Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 14ff1fb436 |
-19
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
Checks: '
|
|
||||||
bugprone-*,
|
|
||||||
-bugprone-integer-division,
|
|
||||||
-bugprone-narrowing-conversions,
|
|
||||||
performance-*,
|
|
||||||
clang-analyzer-*,
|
|
||||||
misc-*,
|
|
||||||
-misc-unused-parameters,
|
|
||||||
modernize-*,
|
|
||||||
-modernize-avoid-c-arrays,
|
|
||||||
-modernize-deprecated-headers,
|
|
||||||
-modernize-use-auto,
|
|
||||||
-modernize-use-using,
|
|
||||||
-modernize-use-nullptr,
|
|
||||||
-modernize-use-trailing-return-type,
|
|
||||||
'
|
|
||||||
CheckOptions:
|
|
||||||
...
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
Wen
|
||||||
|
REGIST
|
||||||
|
PullRequest
|
||||||
|
cancelled
|
||||||
|
FOF
|
||||||
|
NoO
|
||||||
@@ -13,27 +13,6 @@
|
|||||||
*.o-*
|
*.o-*
|
||||||
*.os
|
*.os
|
||||||
*.os-*
|
*.os-*
|
||||||
*.so
|
|
||||||
*.a
|
|
||||||
|
|
||||||
venv/
|
venv/
|
||||||
.venv/
|
.venv/
|
||||||
|
|
||||||
notebooks
|
|
||||||
phone
|
|
||||||
massivemap
|
|
||||||
neos
|
|
||||||
installer
|
|
||||||
chffr/app2
|
|
||||||
chffr/backend/env
|
|
||||||
selfdrive/nav
|
|
||||||
selfdrive/baseui
|
|
||||||
selfdrive/test/simulator2
|
|
||||||
**/cache_data
|
|
||||||
xx/plus
|
|
||||||
xx/community
|
|
||||||
xx/projects
|
|
||||||
!xx/projects/eon_testing_master
|
|
||||||
!xx/projects/map3d
|
|
||||||
xx/ops
|
|
||||||
xx/junk
|
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
---
|
|
||||||
name: Enhancement
|
|
||||||
about: For openpilot enhancement suggestions
|
|
||||||
title: ''
|
|
||||||
labels: 'enhancement'
|
|
||||||
assignees: ''
|
|
||||||
---
|
|
||||||
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
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}"
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
<!-- Please copy and paste the relevant template -->
|
|
||||||
|
|
||||||
<!--- ***** Template: Fingerprint *****
|
|
||||||
|
|
||||||
**Car**
|
|
||||||
Which car (make, model, year) this fingerprint is for
|
|
||||||
|
|
||||||
**Route**
|
|
||||||
A route with the fingerprint
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!--- ***** Template: Car Bugfix *****
|
|
||||||
|
|
||||||
**Description**
|
|
||||||
|
|
||||||
A description of the bug and the fix. Also link the issue if it exists.
|
|
||||||
|
|
||||||
**Verification**
|
|
||||||
|
|
||||||
Explain how you tested this bug fix.
|
|
||||||
|
|
||||||
**Route**
|
|
||||||
|
|
||||||
Route: [a route with the bug fix]
|
|
||||||
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!--- ***** Template: Bugfix *****
|
|
||||||
|
|
||||||
**Description**
|
|
||||||
|
|
||||||
A description of the bug and the fix. Also link the issue if it exists.
|
|
||||||
|
|
||||||
**Verification**
|
|
||||||
|
|
||||||
Explain how you tested this bug fix.
|
|
||||||
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!--- ***** Template: Car Port *****
|
|
||||||
|
|
||||||
**Checklist**
|
|
||||||
|
|
||||||
- [ ] added entry to CAR in selfdrive/car/*/values.py and ran `selfdrive/car/docs.py` to generate new docs
|
|
||||||
- [ ] test route added to [routes.py](https://github.com/commaai/openpilot/blob/master/selfdrive/car/tests/routes.py)
|
|
||||||
- [ ] route with openpilot:
|
|
||||||
- [ ] route with stock system:
|
|
||||||
- [ ] car harness used (if comma doesn't sell it, put N/A):
|
|
||||||
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!--- ***** Template: Refactor *****
|
|
||||||
|
|
||||||
**Description**
|
|
||||||
|
|
||||||
A description of the refactor, including the goals it accomplishes.
|
|
||||||
|
|
||||||
**Verification**
|
|
||||||
|
|
||||||
Explain how you tested the refactor for regressions.
|
|
||||||
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
+26
-34
@@ -7,21 +7,19 @@ venv/
|
|||||||
.tags
|
.tags
|
||||||
.ipynb_checkpoints
|
.ipynb_checkpoints
|
||||||
.idea
|
.idea
|
||||||
*.iml
|
|
||||||
.overlay_init
|
.overlay_init
|
||||||
.overlay_consistent
|
.overlay_consistent
|
||||||
.sconsign.dblite
|
.sconsign.dblite
|
||||||
model2.png
|
|
||||||
a.out
|
a.out
|
||||||
.hypothesis
|
.hypothesis
|
||||||
.cache/
|
.cache/
|
||||||
|
bin/
|
||||||
/docs_site/
|
|
||||||
|
|
||||||
*.mp4
|
*.mp4
|
||||||
*.dylib
|
*.dylib
|
||||||
*.DSYM
|
*.DSYM
|
||||||
*.d
|
*.d
|
||||||
|
*.pem
|
||||||
*.pyc
|
*.pyc
|
||||||
*.pyo
|
*.pyo
|
||||||
.*.swp
|
.*.swp
|
||||||
@@ -38,68 +36,62 @@ a.out
|
|||||||
*.class
|
*.class
|
||||||
*.pyxbldc
|
*.pyxbldc
|
||||||
*.vcd
|
*.vcd
|
||||||
*.qm
|
*.mo
|
||||||
*_pyx.cpp
|
*_pyx.cpp
|
||||||
|
*.stats
|
||||||
|
*.pkl
|
||||||
|
*.pkl*
|
||||||
config.json
|
config.json
|
||||||
clcache
|
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
compare_runtime*.html
|
compare_runtime*.html
|
||||||
|
selfdrive/modeld/models/tg_input_devices.json
|
||||||
|
|
||||||
persist
|
# build artifacts
|
||||||
|
docs_site/
|
||||||
selfdrive/pandad/pandad
|
selfdrive/pandad/pandad
|
||||||
cereal/services.h
|
cereal/services.h
|
||||||
cereal/gen
|
cereal/gen
|
||||||
cereal/messaging/bridge
|
cereal/messaging/bridge
|
||||||
selfdrive/mapd/default_speeds_by_region.json
|
|
||||||
system/proclogd/proclogd
|
|
||||||
selfdrive/ui/translations/tmp
|
selfdrive/ui/translations/tmp
|
||||||
selfdrive/test/longitudinal_maneuvers/out
|
|
||||||
selfdrive/car/tests/cars_dump
|
selfdrive/car/tests/cars_dump
|
||||||
system/camerad/camerad
|
system/camerad/camerad
|
||||||
system/camerad/test/ae_gray_test
|
system/camerad/test/ae_gray_test
|
||||||
|
|
||||||
notebooks
|
|
||||||
hyperthneed
|
|
||||||
provisioning
|
|
||||||
|
|
||||||
.coverage*
|
.coverage*
|
||||||
coverage.xml
|
coverage.xml
|
||||||
htmlcov
|
htmlcov
|
||||||
pandaextra
|
|
||||||
|
|
||||||
.mypy_cache/
|
|
||||||
flycheck_*
|
|
||||||
|
|
||||||
cppcheck_report.txt
|
|
||||||
comma*.sh
|
|
||||||
|
|
||||||
selfdrive/modeld/models/*.pkl
|
|
||||||
|
|
||||||
|
# openpilot log files
|
||||||
*.bz2
|
*.bz2
|
||||||
*.zst
|
*.zst
|
||||||
|
*.rlog
|
||||||
|
|
||||||
build/
|
build/
|
||||||
|
|
||||||
!**/.gitkeep
|
!**/.gitkeep
|
||||||
|
|
||||||
poetry.toml
|
|
||||||
Pipfile
|
|
||||||
|
|
||||||
### VisualStudioCode ###
|
### VisualStudioCode ###
|
||||||
|
*.vsix
|
||||||
|
.history
|
||||||
|
.ionide
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
.history/
|
||||||
!.vscode/settings.json
|
!.vscode/settings.json
|
||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/launch.json
|
!.vscode/launch.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
!.vscode/*.code-snippets
|
!.vscode/*.code-snippets
|
||||||
|
|
||||||
# Local History for Visual Studio Code
|
# agents
|
||||||
.history/
|
.claude/
|
||||||
|
.context/
|
||||||
|
PLAN.md
|
||||||
|
TASK.md
|
||||||
|
CLAUDE.md
|
||||||
|
SKILL.md
|
||||||
|
|
||||||
# Built Visual Studio Code Extensions
|
### JetBrains ###
|
||||||
*.vsix
|
!.idea/customTargets.xml
|
||||||
|
!.idea/tools/*
|
||||||
### VisualStudioCode Patch ###
|
!.run/*
|
||||||
# Ignore all local history of files
|
|
||||||
.history
|
|
||||||
.ionide
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
3.12.13
|
||||||
Vendored
+43
-1
@@ -23,6 +23,11 @@
|
|||||||
"id": "args",
|
"id": "args",
|
||||||
"description": "Arguments to pass to the process",
|
"description": "Arguments to pass to the process",
|
||||||
"type": "promptString"
|
"type": "promptString"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "replayArg",
|
||||||
|
"type": "promptString",
|
||||||
|
"description": "Enter route or segment to replay."
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"configurations": [
|
"configurations": [
|
||||||
@@ -40,7 +45,44 @@
|
|||||||
"type": "cppdbg",
|
"type": "cppdbg",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/${input:cpp_process}",
|
"program": "${workspaceFolder}/${input:cpp_process}",
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Attach LLDB to Replay drive",
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "attach",
|
||||||
|
"pid": "${command:pickMyProcess}",
|
||||||
|
"sourceMap": {
|
||||||
|
".": "${workspaceFolder}/opendbc/safety"
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Vendored
-1
@@ -21,7 +21,6 @@
|
|||||||
"common/**",
|
"common/**",
|
||||||
"selfdrive/**",
|
"selfdrive/**",
|
||||||
"system/**",
|
"system/**",
|
||||||
"third_party/**",
|
|
||||||
"tools/**",
|
"tools/**",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+1291
File diff suppressed because it is too large
Load Diff
+30
-4
@@ -1,12 +1,38 @@
|
|||||||
FROM ghcr.io/commaai/openpilot-base:latest
|
FROM ubuntu:24.04
|
||||||
|
|
||||||
ENV PYTHONUNBUFFERED=1
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
ENV OPENPILOT_PATH=/home/batman/openpilot
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends sudo tzdata locales && \
|
||||||
|
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
|
||||||
|
|
||||||
|
ENV NVIDIA_VISIBLE_DEVICES=all
|
||||||
|
ENV NVIDIA_DRIVER_CAPABILITIES=graphics,utility,compute
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
ENV OPENPILOT_PATH=/home/$USER/openpilot
|
||||||
RUN mkdir -p ${OPENPILOT_PATH}
|
RUN mkdir -p ${OPENPILOT_PATH}
|
||||||
WORKDIR ${OPENPILOT_PATH}
|
WORKDIR ${OPENPILOT_PATH}
|
||||||
|
|
||||||
COPY . ${OPENPILOT_PATH}/
|
COPY --chown=$USER . ${OPENPILOT_PATH}/
|
||||||
|
|
||||||
RUN scons --cache-readonly -j$(nproc)
|
ENV UV_BIN="/home/$USER/.local/bin/"
|
||||||
|
ENV VIRTUAL_ENV=${OPENPILOT_PATH}/.venv
|
||||||
|
ENV PATH="$UV_BIN:$VIRTUAL_ENV/bin:$PATH"
|
||||||
|
RUN tools/setup_dependencies.sh && \
|
||||||
|
sudo rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
USER root
|
||||||
|
RUN git config --global --add safe.directory '*'
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
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
|
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
# Custom MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024, Haibin Wen, SUNNYPILOT LLC
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to view and modify the Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1. **Permission Required**: Permission Required for Commercial, For-Profit, or Closed Source Use: Use of the Software, in whole or in part, for any commercial purposes, for-profit projects, or in closed source projects requires explicit written permission from the original author(s).
|
||||||
|
|
||||||
|
2. **Redistribution**: Any redistribution of the Software, modified or unmodified, must retain this license notice and the following acknowledgment:
|
||||||
|
"This software is licensed under a custom license requiring permission for use."
|
||||||
|
|
||||||
|
3. **Visibility**: Any project that uses the Software must visibly mention the following acknowledgment:
|
||||||
|
"This project uses software from Haibin Wen and SUNNYPILOT LLC and is licensed under a custom license requiring permission for use."
|
||||||
|
|
||||||
|
4. **No Warranty**: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Contact sunnypilot Support <support@sunnypilot.ai> for permission requests.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Haibin Wen, SUNNYPILOT LLC
|
||||||
@@ -1,107 +1,74 @@
|
|||||||
<div align="center" style="text-align: center;">
|

|
||||||
|
|
||||||
<h1>openpilot</h1>
|
## 🌞 What is sunnypilot?
|
||||||
|
[sunnypilot](https://github.com/sunnyhaibin/sunnypilot) is a fork of comma.ai's openpilot, an open source driver assistance system. sunnypilot offers the user a unique driving experience for over 300+ supported car makes and models with modified behaviors of driving assist engagements. sunnypilot complies with comma.ai's safety rules as accurately as possible.
|
||||||
|
|
||||||
<p>
|
## 💭 Join our Community Forum
|
||||||
<b>openpilot is an operating system for robotics.</b>
|
Join the official sunnypilot community forum to stay up to date with all the latest features and be a part of shaping the future of sunnypilot!
|
||||||
<br>
|
* https://community.sunnypilot.ai/
|
||||||
Currently, it upgrades the driver assistance system in 300+ supported cars.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>
|
## Documentation
|
||||||
<a href="https://docs.comma.ai">Docs</a>
|
https://docs.sunnypilot.ai/ is your one stop shop for everything from features to installation to FAQ about the sunnypilot
|
||||||
<span> · </span>
|
|
||||||
<a href="https://docs.comma.ai/contributing/roadmap/">Roadmap</a>
|
|
||||||
<span> · </span>
|
|
||||||
<a href="https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md">Contribute</a>
|
|
||||||
<span> · </span>
|
|
||||||
<a href="https://discord.comma.ai">Community</a>
|
|
||||||
<span> · </span>
|
|
||||||
<a href="https://comma.ai/shop">Try it on a comma 3X</a>
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
Quick start: `bash <(curl -fsSL openpilot.comma.ai)`
|
## 🚘 Running on a dedicated device in a car
|
||||||
|
First, check out this list of items you'll need to [get started](https://community.sunnypilot.ai/t/getting-started-using-sunnypilot-in-your-supported-car/251).
|
||||||
|
|
||||||
[](https://github.com/commaai/openpilot/actions/workflows/selfdrive_tests.yaml)
|
## Installation
|
||||||
[](LICENSE)
|
Next, refer to the sunnypilot community forum for [installation instructions](https://community.sunnypilot.ai/t/read-before-installing-sunnypilot/254), as well as a complete list of [Recommended Branch Installations](https://community.sunnypilot.ai/t/recommended-branch-installations/235).
|
||||||
[](https://x.com/comma_ai)
|
|
||||||
[](https://discord.comma.ai)
|
|
||||||
|
|
||||||
</div>
|
## 🎆 Pull Requests
|
||||||
|
We welcome both pull requests and issues on GitHub. Bug fixes are encouraged.
|
||||||
|
|
||||||
<table>
|
Pull requests should be against the most current `master` branch.
|
||||||
<tr>
|
|
||||||
<td><a href="https://youtu.be/NmBfgOanCyk" title="Video By Greer Viau"><img src="https://github.com/commaai/openpilot/assets/8762862/2f7112ae-f748-4f39-b617-fabd689c3772"></a></td>
|
|
||||||
<td><a href="https://youtu.be/VHKyqZ7t8Gw" title="Video By Logan LeGrand"><img src="https://github.com/commaai/openpilot/assets/8762862/92351544-2833-40d7-9e0b-7ef7ae37ec4c"></a></td>
|
|
||||||
<td><a href="https://youtu.be/SUIZYzxtMQs" title="A drive to Taco Bell"><img src="https://github.com/commaai/openpilot/assets/8762862/05ceefc5-2628-439c-a9b2-89ce77dc6f63"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
## 📊 User Data
|
||||||
|
|
||||||
Using openpilot in a car
|
By default, sunnypilot uploads the driving data to comma servers. You can also access your data through [comma connect](https://connect.comma.ai/).
|
||||||
------
|
|
||||||
|
|
||||||
To use openpilot in a car, you need four things:
|
sunnypilot is open source software. The user is free to disable data collection if they wish to do so.
|
||||||
1. **Supported Device:** a comma 3/3X, available at [comma.ai/shop](https://comma.ai/shop/comma-3x).
|
|
||||||
2. **Software:** The setup procedure for the comma 3/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 3/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.
|
sunnypilot logs the road-facing camera, CAN, GPS, IMU, magnetometer, thermal sensors, crashes, and operating system logs.
|
||||||
|
|
||||||
### 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.
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>MIT Licensed</summary>
|
|
||||||
|
|
||||||
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.**
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>User Data and comma Account</summary>
|
|
||||||
|
|
||||||
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.
|
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.
|
By using this software, 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.
|
||||||
</details>
|
|
||||||
|
## Licensing
|
||||||
|
|
||||||
|
sunnypilot is released under the [MIT License](LICENSE). This repository includes original work as well as significant portions of code derived from [openpilot by comma.ai](https://github.com/commaai/openpilot), which is also released under the MIT license with additional disclaimers.
|
||||||
|
|
||||||
|
The original openpilot license notice, including comma.ai’s indemnification and alpha software disclaimer, is reproduced below as required:
|
||||||
|
|
||||||
|
> 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.**
|
||||||
|
|
||||||
|
For full license terms, please see the [`LICENSE`](LICENSE) file.
|
||||||
|
|
||||||
|
## 💰 Support sunnypilot
|
||||||
|
If you find any of the features useful, consider becoming a [sponsor on GitHub](https://github.com/sponsors/sunnyhaibin) to support future feature development and improvements.
|
||||||
|
|
||||||
|
|
||||||
|
By becoming a sponsor, you will gain access to exclusive content, early access to new features, and the opportunity to directly influence the project's development.
|
||||||
|
|
||||||
|
|
||||||
|
<h3>GitHub Sponsor</h3>
|
||||||
|
|
||||||
|
<a href="https://github.com/sponsors/sunnyhaibin">
|
||||||
|
<img src="https://user-images.githubusercontent.com/47793918/244135584-9800acbd-69fd-4b2b-bec9-e5fa2d85c817.png" alt="Become a Sponsor" width="300" style="max-width: 100%; height: auto;">
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<h3>PayPal</h3>
|
||||||
|
|
||||||
|
<a href="https://paypal.me/sunnyhaibin0850" target="_blank">
|
||||||
|
<img src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" alt="PayPal this" title="PayPal - The safer, easier way to pay online!" border="0" />
|
||||||
|
</a>
|
||||||
|
<br></br>
|
||||||
|
|
||||||
|
Your continuous love and support are greatly appreciated! Enjoy 🥰
|
||||||
|
|
||||||
|
<span>-</span> Jason, Founder of sunnypilot
|
||||||
|
|||||||
+46
-2
@@ -1,7 +1,51 @@
|
|||||||
|
Version 0.11.2 (2026-06-15)
|
||||||
|
========================
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.11.1 (2026-05-18)
|
||||||
|
========================
|
||||||
|
* New driver monitoring model
|
||||||
|
* Improved image processing pipeline for driver camera
|
||||||
|
* Improved thermal policy for comma four
|
||||||
|
* Acura MDX 2022-24 support thanks to mvl-boston!
|
||||||
|
* Rivian R1S and R1T 2025 support thanks to lukasloetkolben!
|
||||||
|
|
||||||
|
Version 0.11.0 (2026-03-17)
|
||||||
|
========================
|
||||||
|
* New driving model #36798
|
||||||
|
* Fully trained using a learned simulator
|
||||||
|
* Improved longitudinal performance in Experimental mode
|
||||||
|
* Reduce comma four standby power usage by 77% to 52 mW
|
||||||
|
* Kia K7 2017 support thanks to royjr!
|
||||||
|
* Lexus LS 2018 support thanks to Hacheoy!
|
||||||
|
|
||||||
|
Version 0.10.3 (2025-12-17)
|
||||||
|
========================
|
||||||
|
* New driving model #36249
|
||||||
|
* New temporal policy architecture
|
||||||
|
* New on-policy training physics noise model
|
||||||
|
* New driver monitoring model #36409
|
||||||
|
* Trained on a new dataset, including comma four data
|
||||||
|
* Improved inter-process communication memory efficiency
|
||||||
|
|
||||||
|
Version 0.10.2 (2025-11-19)
|
||||||
|
========================
|
||||||
|
* comma four support
|
||||||
|
|
||||||
Version 0.10.1 (2025-09-08)
|
Version 0.10.1 (2025-09-08)
|
||||||
========================
|
========================
|
||||||
* Record driving feedback using LKAS button
|
* New driving model #36276
|
||||||
* Honda City 2023 support thanks to drFritz!
|
* 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)
|
Version 0.10.0 (2025-08-05)
|
||||||
========================
|
========================
|
||||||
|
|||||||
-362
@@ -1,362 +0,0 @@
|
|||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import sysconfig
|
|
||||||
import platform
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
import SCons.Errors
|
|
||||||
|
|
||||||
SCons.Warnings.warningAsException(True)
|
|
||||||
|
|
||||||
# pending upstream fix - https://github.com/SCons/scons/issues/4461
|
|
||||||
#SetOption('warn', 'all')
|
|
||||||
|
|
||||||
TICI = os.path.isfile('/TICI')
|
|
||||||
AGNOS = TICI
|
|
||||||
|
|
||||||
Decider('MD5-timestamp')
|
|
||||||
|
|
||||||
SetOption('num_jobs', 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('--coverage',
|
|
||||||
action='store_true',
|
|
||||||
help='build with test coverage options')
|
|
||||||
|
|
||||||
AddOption('--clazy',
|
|
||||||
action='store_true',
|
|
||||||
help='build with clazy')
|
|
||||||
|
|
||||||
AddOption('--ccflags',
|
|
||||||
action='store',
|
|
||||||
type='string',
|
|
||||||
default='',
|
|
||||||
help='pass arbitrary flags over the command line')
|
|
||||||
|
|
||||||
AddOption('--external-sconscript',
|
|
||||||
action='store',
|
|
||||||
metavar='FILE',
|
|
||||||
dest='external_sconscript',
|
|
||||||
help='add an external SConscript to the build')
|
|
||||||
|
|
||||||
AddOption('--mutation',
|
|
||||||
action='store_true',
|
|
||||||
help='generate mutation-ready code')
|
|
||||||
|
|
||||||
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.')
|
|
||||||
|
|
||||||
## Architecture name breakdown (arch)
|
|
||||||
## - larch64: linux tici aarch64
|
|
||||||
## - aarch64: linux pc aarch64
|
|
||||||
## - x86_64: linux pc x64
|
|
||||||
## - Darwin: mac x64 or arm64
|
|
||||||
real_arch = arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
|
|
||||||
if platform.system() == "Darwin":
|
|
||||||
arch = "Darwin"
|
|
||||||
brew_prefix = subprocess.check_output(['brew', '--prefix'], encoding='utf8').strip()
|
|
||||||
elif arch == "aarch64" and AGNOS:
|
|
||||||
arch = "larch64"
|
|
||||||
assert arch in ["larch64", "aarch64", "x86_64", "Darwin"]
|
|
||||||
|
|
||||||
lenv = {
|
|
||||||
"PATH": os.environ['PATH'],
|
|
||||||
"PYTHONPATH": Dir("#").abspath + ':' + Dir(f"#third_party/acados").abspath,
|
|
||||||
|
|
||||||
"ACADOS_SOURCE_DIR": Dir("#third_party/acados").abspath,
|
|
||||||
"ACADOS_PYTHON_INTERFACE_PATH": Dir("#third_party/acados/acados_template").abspath,
|
|
||||||
"TERA_PATH": Dir("#").abspath + f"/third_party/acados/{arch}/t_renderer"
|
|
||||||
}
|
|
||||||
|
|
||||||
rpath = []
|
|
||||||
|
|
||||||
if arch == "larch64":
|
|
||||||
cpppath = [
|
|
||||||
"#third_party/opencl/include",
|
|
||||||
]
|
|
||||||
|
|
||||||
libpath = [
|
|
||||||
"/usr/local/lib",
|
|
||||||
"/system/vendor/lib64",
|
|
||||||
f"#third_party/acados/{arch}/lib",
|
|
||||||
]
|
|
||||||
|
|
||||||
libpath += [
|
|
||||||
"#third_party/libyuv/larch64/lib",
|
|
||||||
"/usr/lib/aarch64-linux-gnu"
|
|
||||||
]
|
|
||||||
cflags = ["-DQCOM2", "-mcpu=cortex-a57"]
|
|
||||||
cxxflags = ["-DQCOM2", "-mcpu=cortex-a57"]
|
|
||||||
rpath += ["/usr/local/lib"]
|
|
||||||
else:
|
|
||||||
cflags = []
|
|
||||||
cxxflags = []
|
|
||||||
cpppath = []
|
|
||||||
rpath += []
|
|
||||||
|
|
||||||
# MacOS
|
|
||||||
if arch == "Darwin":
|
|
||||||
libpath = [
|
|
||||||
f"#third_party/libyuv/{arch}/lib",
|
|
||||||
f"#third_party/acados/{arch}/lib",
|
|
||||||
f"{brew_prefix}/lib",
|
|
||||||
f"{brew_prefix}/opt/openssl@3.0/lib",
|
|
||||||
"/System/Library/Frameworks/OpenGL.framework/Libraries",
|
|
||||||
]
|
|
||||||
|
|
||||||
cflags += ["-DGL_SILENCE_DEPRECATION"]
|
|
||||||
cxxflags += ["-DGL_SILENCE_DEPRECATION"]
|
|
||||||
cpppath += [
|
|
||||||
f"{brew_prefix}/include",
|
|
||||||
f"{brew_prefix}/opt/openssl@3.0/include",
|
|
||||||
]
|
|
||||||
# Linux
|
|
||||||
else:
|
|
||||||
libpath = [
|
|
||||||
f"#third_party/acados/{arch}/lib",
|
|
||||||
f"#third_party/libyuv/{arch}/lib",
|
|
||||||
"/usr/lib",
|
|
||||||
"/usr/local/lib",
|
|
||||||
]
|
|
||||||
|
|
||||||
if GetOption('asan'):
|
|
||||||
ccflags = ["-fsanitize=address", "-fno-omit-frame-pointer"]
|
|
||||||
ldflags = ["-fsanitize=address"]
|
|
||||||
elif GetOption('ubsan'):
|
|
||||||
ccflags = ["-fsanitize=undefined"]
|
|
||||||
ldflags = ["-fsanitize=undefined"]
|
|
||||||
else:
|
|
||||||
ccflags = []
|
|
||||||
ldflags = []
|
|
||||||
|
|
||||||
# no --as-needed on mac linker
|
|
||||||
if arch != "Darwin":
|
|
||||||
ldflags += ["-Wl,--as-needed", "-Wl,--no-undefined"]
|
|
||||||
|
|
||||||
ccflags_option = GetOption('ccflags')
|
|
||||||
if ccflags_option:
|
|
||||||
ccflags += ccflags_option.split(' ')
|
|
||||||
|
|
||||||
env = Environment(
|
|
||||||
ENV=lenv,
|
|
||||||
CCFLAGS=[
|
|
||||||
"-g",
|
|
||||||
"-fPIC",
|
|
||||||
"-O2",
|
|
||||||
"-Wunused",
|
|
||||||
"-Werror",
|
|
||||||
"-Wshadow",
|
|
||||||
"-Wno-unknown-warning-option",
|
|
||||||
"-Wno-inconsistent-missing-override",
|
|
||||||
"-Wno-c99-designator",
|
|
||||||
"-Wno-reorder-init-list",
|
|
||||||
"-Wno-vla-cxx-extension",
|
|
||||||
] + cflags + ccflags,
|
|
||||||
|
|
||||||
CPPPATH=cpppath + [
|
|
||||||
"#",
|
|
||||||
"#third_party/acados/include",
|
|
||||||
"#third_party/acados/include/blasfeo/include",
|
|
||||||
"#third_party/acados/include/hpipm/include",
|
|
||||||
"#third_party/catch2/include",
|
|
||||||
"#third_party/libyuv/include",
|
|
||||||
"#third_party/json11",
|
|
||||||
"#third_party/linux/include",
|
|
||||||
"#third_party",
|
|
||||||
"#msgq",
|
|
||||||
],
|
|
||||||
|
|
||||||
CC='clang',
|
|
||||||
CXX='clang++',
|
|
||||||
LINKFLAGS=ldflags,
|
|
||||||
|
|
||||||
RPATH=rpath,
|
|
||||||
|
|
||||||
CFLAGS=["-std=gnu11"] + cflags,
|
|
||||||
CXXFLAGS=["-std=c++1z"] + cxxflags,
|
|
||||||
LIBPATH=libpath + [
|
|
||||||
"#msgq_repo",
|
|
||||||
"#third_party",
|
|
||||||
"#selfdrive/pandad",
|
|
||||||
"#common",
|
|
||||||
"#rednose/helpers",
|
|
||||||
],
|
|
||||||
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"],
|
|
||||||
)
|
|
||||||
|
|
||||||
if arch == "Darwin":
|
|
||||||
# RPATH is not supported on macOS, instead use the linker flags
|
|
||||||
darwin_rpath_link_flags = [f"-Wl,-rpath,{path}" for path in env["RPATH"]]
|
|
||||||
env["LINKFLAGS"] += darwin_rpath_link_flags
|
|
||||||
|
|
||||||
env.CompilationDatabase('compile_commands.json')
|
|
||||||
|
|
||||||
# Setup cache dir
|
|
||||||
cache_dir = '/data/scons_cache' if AGNOS else '/tmp/scons_cache'
|
|
||||||
CacheDir(cache_dir)
|
|
||||||
Clean(["."], cache_dir)
|
|
||||||
|
|
||||||
node_interval = 5
|
|
||||||
node_count = 0
|
|
||||||
def progress_function(node):
|
|
||||||
global node_count
|
|
||||||
node_count += node_interval
|
|
||||||
sys.stderr.write("progress: %d\n" % node_count)
|
|
||||||
|
|
||||||
if os.environ.get('SCONS_PROGRESS'):
|
|
||||||
Progress(progress_function, interval=node_interval)
|
|
||||||
|
|
||||||
# Cython build environment
|
|
||||||
py_include = sysconfig.get_paths()['include']
|
|
||||||
envCython = env.Clone()
|
|
||||||
envCython["CPPPATH"] += [py_include, np.get_include()]
|
|
||||||
envCython["CCFLAGS"] += ["-Wno-#warnings", "-Wno-shadow", "-Wno-deprecated-declarations"]
|
|
||||||
envCython["CCFLAGS"].remove("-Werror")
|
|
||||||
|
|
||||||
envCython["LIBS"] = []
|
|
||||||
if arch == "Darwin":
|
|
||||||
envCython["LINKFLAGS"] = ["-bundle", "-undefined", "dynamic_lookup"] + darwin_rpath_link_flags
|
|
||||||
else:
|
|
||||||
envCython["LINKFLAGS"] = ["-pthread", "-shared"]
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
if GetOption("clazy"):
|
|
||||||
checks = [
|
|
||||||
"level0",
|
|
||||||
"level1",
|
|
||||||
"no-range-loop",
|
|
||||||
"no-non-pod-global-static",
|
|
||||||
]
|
|
||||||
qt_env['CXX'] = 'clazy'
|
|
||||||
qt_env['ENV']['CLAZY_IGNORE_DIRS'] = qt_dirs[0]
|
|
||||||
qt_env['ENV']['CLAZY_CHECKS'] = ','.join(checks)
|
|
||||||
|
|
||||||
Export('env', 'qt_env', 'arch', 'real_arch')
|
|
||||||
|
|
||||||
# Build common module
|
|
||||||
SConscript(['common/SConscript'])
|
|
||||||
Import('_common', '_gpucommon')
|
|
||||||
|
|
||||||
common = [_common, 'json11', 'zmq']
|
|
||||||
gpucommon = [_gpucommon]
|
|
||||||
|
|
||||||
Export('common', 'gpucommon')
|
|
||||||
|
|
||||||
# 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 != "Darwin":
|
|
||||||
SConscript([
|
|
||||||
'system/logcatd/SConscript',
|
|
||||||
'system/proclogd/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'])
|
|
||||||
|
|
||||||
external_sconscript = GetOption('external_sconscript')
|
|
||||||
if external_sconscript:
|
|
||||||
SConscript([external_sconscript])
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
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')
|
|
||||||
+426
-10
@@ -10,34 +10,450 @@ $Cxx.namespace("cereal");
|
|||||||
# DO rename the structs
|
# DO rename the structs
|
||||||
# DON'T change the identifier (e.g. @0x81c2f05a394cf4af)
|
# DON'T change the identifier (e.g. @0x81c2f05a394cf4af)
|
||||||
|
|
||||||
struct CustomReserved0 @0x81c2f05a394cf4af {
|
struct ModularAssistiveDrivingSystem {
|
||||||
|
state @0 :ModularAssistiveDrivingSystemState;
|
||||||
|
enabled @1 :Bool;
|
||||||
|
active @2 :Bool;
|
||||||
|
available @3 :Bool;
|
||||||
|
|
||||||
|
enum ModularAssistiveDrivingSystemState {
|
||||||
|
disabled @0;
|
||||||
|
paused @1;
|
||||||
|
enabled @2;
|
||||||
|
softDisabling @3;
|
||||||
|
overriding @4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved1 @0xaedffd8f31e7b55d {
|
struct IntelligentCruiseButtonManagement {
|
||||||
|
state @0 :IntelligentCruiseButtonManagementState;
|
||||||
|
sendButton @1 :SendButtonState;
|
||||||
|
vTarget @2 :Float32;
|
||||||
|
|
||||||
|
enum IntelligentCruiseButtonManagementState {
|
||||||
|
inactive @0; # No button press or default state
|
||||||
|
preActive @1; # Pre-active state before transitioning to increasing or decreasing
|
||||||
|
increasing @2; # Increasing speed
|
||||||
|
decreasing @3; # Decreasing speed
|
||||||
|
holding @4; # Holding steady speed
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SendButtonState {
|
||||||
|
none @0;
|
||||||
|
increase @1;
|
||||||
|
decrease @2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved2 @0xf35cc4560bbf6ec2 {
|
# Same struct as Log.RadarState.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;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved3 @0xda96579883444c35 {
|
struct SelfdriveStateSP @0x81c2f05a394cf4af {
|
||||||
|
mads @0 :ModularAssistiveDrivingSystem;
|
||||||
|
intelligentCruiseButtonManagement @1 :IntelligentCruiseButtonManagement;
|
||||||
|
|
||||||
|
enum AudibleAlert {
|
||||||
|
none @0;
|
||||||
|
|
||||||
|
engage @1;
|
||||||
|
disengage @2;
|
||||||
|
refuse @3;
|
||||||
|
|
||||||
|
warningSoft @4;
|
||||||
|
warningImmediate @5;
|
||||||
|
|
||||||
|
prompt @6;
|
||||||
|
promptRepeat @7;
|
||||||
|
promptDistracted @8;
|
||||||
|
|
||||||
|
# unused, these are reserved for upstream events so we don't collide
|
||||||
|
reserved9 @9;
|
||||||
|
reserved10 @10;
|
||||||
|
reserved11 @11;
|
||||||
|
reserved12 @12;
|
||||||
|
reserved13 @13;
|
||||||
|
reserved14 @14;
|
||||||
|
reserved15 @15;
|
||||||
|
reserved16 @16;
|
||||||
|
reserved17 @17;
|
||||||
|
reserved18 @18;
|
||||||
|
reserved19 @19;
|
||||||
|
reserved20 @20;
|
||||||
|
reserved21 @21;
|
||||||
|
reserved22 @22;
|
||||||
|
reserved23 @23;
|
||||||
|
reserved24 @24;
|
||||||
|
reserved25 @25;
|
||||||
|
reserved26 @26;
|
||||||
|
reserved27 @27;
|
||||||
|
reserved28 @28;
|
||||||
|
reserved29 @29;
|
||||||
|
reserved30 @30;
|
||||||
|
|
||||||
|
promptSingleLow @31;
|
||||||
|
promptSingleHigh @32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved4 @0x80ae746ee2596b11 {
|
struct ModelManagerSP @0xaedffd8f31e7b55d {
|
||||||
|
activeBundle @0 :ModelBundle;
|
||||||
|
selectedBundle @1 :ModelBundle;
|
||||||
|
availableBundles @2 :List(ModelBundle);
|
||||||
|
|
||||||
|
struct DownloadUri {
|
||||||
|
uri @0 :Text;
|
||||||
|
sha256 @1 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DownloadStatus {
|
||||||
|
notDownloading @0;
|
||||||
|
downloading @1;
|
||||||
|
downloaded @2;
|
||||||
|
cached @3;
|
||||||
|
failed @4;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DownloadProgress {
|
||||||
|
status @0 :DownloadStatus;
|
||||||
|
progress @1 :Float32;
|
||||||
|
eta @2 :UInt32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Artifact {
|
||||||
|
fileName @0 :Text;
|
||||||
|
downloadUri @1 :DownloadUri;
|
||||||
|
downloadProgress @2 :DownloadProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Model {
|
||||||
|
type @0 :Type;
|
||||||
|
artifact @1 :Artifact; # Main artifact
|
||||||
|
metadata @2 :Artifact; # Metadata artifact
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
supercombo @0;
|
||||||
|
navigation @1;
|
||||||
|
vision @2;
|
||||||
|
policy @3;
|
||||||
|
offPolicy @4;
|
||||||
|
onPolicy @5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Runner {
|
||||||
|
snpe @0;
|
||||||
|
tinygrad @1;
|
||||||
|
stock @2;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Override {
|
||||||
|
key @0 :Text;
|
||||||
|
value @1 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ModelBundle {
|
||||||
|
index @0 :UInt32;
|
||||||
|
internalName @1 :Text;
|
||||||
|
displayName @2 :Text;
|
||||||
|
models @3 :List(Model);
|
||||||
|
status @4 :DownloadStatus;
|
||||||
|
generation @5 :UInt32;
|
||||||
|
environment @6 :Text;
|
||||||
|
runner @7 :Runner;
|
||||||
|
is20hz @8 :Bool;
|
||||||
|
ref @9 :Text;
|
||||||
|
minimumSelectorVersion @10 :UInt32;
|
||||||
|
overrides @11 :List(Override);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved5 @0xa5cd762cd951a455 {
|
struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 {
|
||||||
|
dec @0 :DynamicExperimentalControl;
|
||||||
|
longitudinalPlanSource @1 :LongitudinalPlanSource;
|
||||||
|
smartCruiseControl @2 :SmartCruiseControl;
|
||||||
|
speedLimit @3 :SpeedLimit;
|
||||||
|
vTarget @4 :Float32;
|
||||||
|
aTarget @5 :Float32;
|
||||||
|
events @6 :List(OnroadEventSP.Event);
|
||||||
|
e2eAlerts @7 :E2eAlerts;
|
||||||
|
|
||||||
|
struct DynamicExperimentalControl {
|
||||||
|
state @0 :DynamicExperimentalControlState;
|
||||||
|
enabled @1 :Bool;
|
||||||
|
active @2 :Bool;
|
||||||
|
|
||||||
|
enum DynamicExperimentalControlState {
|
||||||
|
acc @0;
|
||||||
|
blended @1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SmartCruiseControl {
|
||||||
|
vision @0 :Vision;
|
||||||
|
map @1 :Map;
|
||||||
|
|
||||||
|
struct Vision {
|
||||||
|
state @0 :VisionState;
|
||||||
|
vTarget @1 :Float32;
|
||||||
|
aTarget @2 :Float32;
|
||||||
|
currentLateralAccel @3 :Float32;
|
||||||
|
maxPredictedLateralAccel @4 :Float32;
|
||||||
|
enabled @5 :Bool;
|
||||||
|
active @6 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map {
|
||||||
|
state @0 :MapState;
|
||||||
|
vTarget @1 :Float32;
|
||||||
|
aTarget @2 :Float32;
|
||||||
|
enabled @3 :Bool;
|
||||||
|
active @4 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum VisionState {
|
||||||
|
disabled @0; # System disabled or inactive.
|
||||||
|
enabled @1; # No predicted substantial turn on vision range.
|
||||||
|
entering @2; # A substantial turn is predicted ahead, adapting speed to turn comfort levels.
|
||||||
|
turning @3; # Actively turning. Managing acceleration to provide a roll on turn feeling.
|
||||||
|
leaving @4; # Road ahead straightens. Start to allow positive acceleration.
|
||||||
|
overriding @5; # System overriding with manual control.
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MapState {
|
||||||
|
disabled @0; # System disabled or inactive.
|
||||||
|
enabled @1; # No predicted substantial turn on map range.
|
||||||
|
turning @2; # Actively turning. Managing acceleration to provide a roll on turn feeling.
|
||||||
|
overriding @3; # System overriding with manual control.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SpeedLimit {
|
||||||
|
resolver @0 :Resolver;
|
||||||
|
assist @1 :Assist;
|
||||||
|
|
||||||
|
struct Resolver {
|
||||||
|
speedLimit @0 :Float32;
|
||||||
|
distToSpeedLimit @1 :Float32;
|
||||||
|
source @2 :Source;
|
||||||
|
speedLimitOffset @3 :Float32;
|
||||||
|
speedLimitLast @4 :Float32;
|
||||||
|
speedLimitFinal @5 :Float32;
|
||||||
|
speedLimitFinalLast @6 :Float32;
|
||||||
|
speedLimitValid @7 :Bool;
|
||||||
|
speedLimitLastValid @8 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Assist {
|
||||||
|
state @0 :AssistState;
|
||||||
|
enabled @1 :Bool;
|
||||||
|
active @2 :Bool;
|
||||||
|
vTarget @3 :Float32;
|
||||||
|
aTarget @4 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Source {
|
||||||
|
none @0;
|
||||||
|
car @1;
|
||||||
|
map @2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AssistState {
|
||||||
|
disabled @0;
|
||||||
|
inactive @1; # No speed limit set or not enabled by parameter.
|
||||||
|
preActive @2;
|
||||||
|
pending @3; # Awaiting new speed limit.
|
||||||
|
adapting @4; # Reducing speed to match new speed limit.
|
||||||
|
active @5; # Cruising at speed limit.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LongitudinalPlanSource {
|
||||||
|
cruise @0;
|
||||||
|
sccVision @1;
|
||||||
|
sccMap @2;
|
||||||
|
speedLimitAssist @3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct E2eAlerts {
|
||||||
|
greenLightAlert @0 :Bool;
|
||||||
|
leadDepartAlert @1 :Bool;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved6 @0xf98d843bfd7004a3 {
|
struct OnroadEventSP @0xda96579883444c35 {
|
||||||
|
events @0 :List(Event);
|
||||||
|
|
||||||
|
struct Event {
|
||||||
|
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 {
|
||||||
|
lkasEnable @0;
|
||||||
|
lkasDisable @1;
|
||||||
|
manualSteeringRequired @2;
|
||||||
|
manualLongitudinalRequired @3;
|
||||||
|
silentLkasEnable @4;
|
||||||
|
silentLkasDisable @5;
|
||||||
|
silentBrakeHold @6;
|
||||||
|
silentWrongGear @7;
|
||||||
|
silentReverseGear @8;
|
||||||
|
silentDoorOpen @9;
|
||||||
|
silentSeatbeltNotLatched @10;
|
||||||
|
silentParkBrake @11;
|
||||||
|
controlsMismatchLateral @12;
|
||||||
|
hyundaiRadarTracksConfirmed @13;
|
||||||
|
experimentalModeSwitched @14;
|
||||||
|
wrongCarModeAlertOnly @15;
|
||||||
|
pedalPressedAlertOnly @16;
|
||||||
|
laneTurnLeft @17;
|
||||||
|
laneTurnRight @18;
|
||||||
|
speedLimitPreActive @19;
|
||||||
|
speedLimitActive @20;
|
||||||
|
speedLimitChanged @21;
|
||||||
|
speedLimitPending @22;
|
||||||
|
e2eChime @23;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved7 @0xb86e6369214c01c8 {
|
struct CarParamsSP @0x80ae746ee2596b11 {
|
||||||
|
flags @0 :UInt32; # flags for car specific quirks in sunnypilot
|
||||||
|
safetyParam @1 : Int16; # flags for sunnypilot's custom safety flags
|
||||||
|
pcmCruiseSpeed @3 :Bool;
|
||||||
|
intelligentCruiseButtonManagementAvailable @4 :Bool;
|
||||||
|
enableGasInterceptor @5 :Bool;
|
||||||
|
|
||||||
|
neuralNetworkLateralControl @2 :NeuralNetworkLateralControl;
|
||||||
|
|
||||||
|
struct NeuralNetworkLateralControl {
|
||||||
|
model @0 :Model;
|
||||||
|
fuzzyFingerprint @1 :Bool;
|
||||||
|
|
||||||
|
struct Model {
|
||||||
|
path @0 :Text;
|
||||||
|
name @1 :Text;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved8 @0xf416ec09499d9d19 {
|
struct CarControlSP @0xa5cd762cd951a455 {
|
||||||
|
mads @0 :ModularAssistiveDrivingSystem;
|
||||||
|
params @1 :List(Param);
|
||||||
|
leadOne @2 :LeadData;
|
||||||
|
leadTwo @3 :LeadData;
|
||||||
|
intelligentCruiseButtonManagement @4 :IntelligentCruiseButtonManagement;
|
||||||
|
|
||||||
|
struct Param {
|
||||||
|
key @0 :Text;
|
||||||
|
type @2 :ParamType;
|
||||||
|
value @3 :Data;
|
||||||
|
|
||||||
|
valueDEPRECATED @1 :Text; # The data type change may cause issues with backwards compatibility.
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ParamType {
|
||||||
|
string @0;
|
||||||
|
bool @1;
|
||||||
|
int @2;
|
||||||
|
float @3;
|
||||||
|
time @4;
|
||||||
|
json @5;
|
||||||
|
bytes @6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved9 @0xa1680744031fdb2d {
|
struct BackupManagerSP @0xf98d843bfd7004a3 {
|
||||||
|
backupStatus @0 :Status;
|
||||||
|
restoreStatus @1 :Status;
|
||||||
|
backupProgress @2 :Float32;
|
||||||
|
restoreProgress @3 :Float32;
|
||||||
|
lastError @4 :Text;
|
||||||
|
currentBackup @5 :BackupInfo;
|
||||||
|
backupHistory @6 :List(BackupInfo);
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
idle @0;
|
||||||
|
inProgress @1;
|
||||||
|
completed @2;
|
||||||
|
failed @3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Version {
|
||||||
|
major @0 :UInt16;
|
||||||
|
minor @1 :UInt16;
|
||||||
|
patch @2 :UInt16;
|
||||||
|
build @3 :UInt16;
|
||||||
|
branch @4 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MetadataEntry {
|
||||||
|
key @0 :Text;
|
||||||
|
value @1 :Text;
|
||||||
|
tags @2 :List(Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BackupInfo {
|
||||||
|
deviceId @0 :Text;
|
||||||
|
version @1 :UInt32;
|
||||||
|
config @2 :Text;
|
||||||
|
isEncrypted @3 :Bool;
|
||||||
|
createdAt @4 :Text; # ISO timestamp
|
||||||
|
updatedAt @5 :Text; # ISO timestamp
|
||||||
|
sunnypilotVersion @6 :Version;
|
||||||
|
backupMetadata @7 :List(MetadataEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CarStateSP @0xb86e6369214c01c8 {
|
||||||
|
speedLimit @0 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LiveMapDataSP @0xf416ec09499d9d19 {
|
||||||
|
speedLimitValid @0 :Bool;
|
||||||
|
speedLimit @1 :Float32;
|
||||||
|
speedLimitAheadValid @2 :Bool;
|
||||||
|
speedLimitAhead @3 :Float32;
|
||||||
|
speedLimitAheadDistance @4 :Float32;
|
||||||
|
roadName @5 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ModelDataV2SP @0xa1680744031fdb2d {
|
||||||
|
laneTurnDirection @0 :TurnDirection;
|
||||||
|
|
||||||
|
enum TurnDirection {
|
||||||
|
none @0;
|
||||||
|
turnLeft @1;
|
||||||
|
turnRight @2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved10 @0xcb9fd56c7057593a {
|
struct CustomReserved10 @0xcb9fd56c7057593a {
|
||||||
|
|||||||
@@ -0,0 +1,789 @@
|
|||||||
|
using Cxx = import "./include/c++.capnp";
|
||||||
|
$Cxx.namespace("cereal");
|
||||||
|
|
||||||
|
@0x80ef1ec4889c2a63;
|
||||||
|
|
||||||
|
# deprecated.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LiveTracksDEPRECATED @0xb16f60103159415a {
|
||||||
|
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 LiveMpcData @0x92a5e332a85f32a0 {
|
||||||
|
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 @0xe7e17c434f865ae2 {
|
||||||
|
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 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 NavModelData @0xac3de5c437be057a {
|
||||||
|
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 @0xbe09e615b2507e26 {
|
||||||
|
x @0 :List(Float32);
|
||||||
|
y @1 :List(Float32);
|
||||||
|
xStd @2 :List(Float32);
|
||||||
|
yStd @3 :List(Float32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AndroidBuildInfo @0xfe2919d5c21f426c {
|
||||||
|
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 @0x9b513b93a887dbcd {
|
||||||
|
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 IosBuildInfo @0xd97e3b28239f5580 {
|
||||||
|
appVersion @0 :Text;
|
||||||
|
appBuild @1 :UInt32;
|
||||||
|
osVersion @2 :Text;
|
||||||
|
deviceModel @3 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FrameTypeDEPRECATED @0xa37f0d8558e193fd {
|
||||||
|
unknown @0;
|
||||||
|
neo @1;
|
||||||
|
chffrAndroid @2;
|
||||||
|
front @3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AndroidCaptureResult @0xbcc3efbac41d2048 {
|
||||||
|
sensitivity @0 :Int32;
|
||||||
|
frameDuration @1 :Int64;
|
||||||
|
exposureTime @2 :Int64;
|
||||||
|
rollingShutterSkew @3 :UInt64;
|
||||||
|
colorCorrectionTransform @4 :List(Int32);
|
||||||
|
colorCorrectionGains @5 :List(Float32);
|
||||||
|
displayRotation @6 :Int8;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UsbPowerModeDEPRECATED @0xa8883583b32c9877 {
|
||||||
|
none @0;
|
||||||
|
client @1;
|
||||||
|
cdp @2;
|
||||||
|
dcp @3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LateralINDIState @0x939463348632375e {
|
||||||
|
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 LateralLQRState @0x9024e2d790c82ade {
|
||||||
|
active @0 :Bool;
|
||||||
|
steeringAngleDeg @1 :Float32;
|
||||||
|
i @2 :Float32;
|
||||||
|
output @3 :Float32;
|
||||||
|
lqrOutput @4 :Float32;
|
||||||
|
saturated @5 :Bool;
|
||||||
|
steeringAngleDesiredDeg @6 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LateralCurvatureState @0xad9d8095c06f7c61 {
|
||||||
|
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 LateralPlannerSolution @0x84caeca5a6b4acfe {
|
||||||
|
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 GpsTrajectory @0x8cfeb072f5301000 {
|
||||||
|
x @0 :List(Float32);
|
||||||
|
y @1 :List(Float32);
|
||||||
|
}
|
||||||
+593
-571
File diff suppressed because it is too large
Load Diff
+57
-38
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#ifndef CAPNP_VERSION
|
#ifndef CAPNP_VERSION
|
||||||
#error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?"
|
#error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?"
|
||||||
#elif CAPNP_VERSION != 1000002
|
#elif CAPNP_VERSION != 1000001
|
||||||
#error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library."
|
#error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -650,7 +650,7 @@ struct CarParams::LateralTorqueTuning {
|
|||||||
class Pipeline;
|
class Pipeline;
|
||||||
|
|
||||||
struct _capnpPrivate {
|
struct _capnpPrivate {
|
||||||
CAPNP_DECLARE_STRUCT_HEADER(80366e0e804ecc1d, 4, 0)
|
CAPNP_DECLARE_STRUCT_HEADER(80366e0e804ecc1d, 5, 0)
|
||||||
#if !CAPNP_LITE
|
#if !CAPNP_LITE
|
||||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||||
#endif // !CAPNP_LITE
|
#endif // !CAPNP_LITE
|
||||||
@@ -895,7 +895,7 @@ public:
|
|||||||
|
|
||||||
inline bool getGasPressed() const;
|
inline bool getGasPressed() const;
|
||||||
|
|
||||||
inline float getBrake() const;
|
inline float getBrakeDEPRECATED() const;
|
||||||
|
|
||||||
inline bool getBrakePressed() const;
|
inline bool getBrakePressed() const;
|
||||||
|
|
||||||
@@ -1063,8 +1063,8 @@ public:
|
|||||||
inline bool getGasPressed();
|
inline bool getGasPressed();
|
||||||
inline void setGasPressed(bool value);
|
inline void setGasPressed(bool value);
|
||||||
|
|
||||||
inline float getBrake();
|
inline float getBrakeDEPRECATED();
|
||||||
inline void setBrake(float value);
|
inline void setBrakeDEPRECATED(float value);
|
||||||
|
|
||||||
inline bool getBrakePressed();
|
inline bool getBrakePressed();
|
||||||
inline void setBrakePressed(bool value);
|
inline void setBrakePressed(bool value);
|
||||||
@@ -2511,7 +2511,7 @@ public:
|
|||||||
|
|
||||||
inline bool getEnableCameraDEPRECATED() const;
|
inline bool getEnableCameraDEPRECATED() const;
|
||||||
|
|
||||||
inline bool getEnableDsu() const;
|
inline bool getEnableDsuDEPRECATED() const;
|
||||||
|
|
||||||
inline bool getEnableApgsDEPRECATED() const;
|
inline bool getEnableApgsDEPRECATED() const;
|
||||||
|
|
||||||
@@ -2713,8 +2713,8 @@ public:
|
|||||||
inline bool getEnableCameraDEPRECATED();
|
inline bool getEnableCameraDEPRECATED();
|
||||||
inline void setEnableCameraDEPRECATED(bool value);
|
inline void setEnableCameraDEPRECATED(bool value);
|
||||||
|
|
||||||
inline bool getEnableDsu();
|
inline bool getEnableDsuDEPRECATED();
|
||||||
inline void setEnableDsu(bool value);
|
inline void setEnableDsuDEPRECATED(bool value);
|
||||||
|
|
||||||
inline bool getEnableApgsDEPRECATED();
|
inline bool getEnableApgsDEPRECATED();
|
||||||
inline void setEnableApgsDEPRECATED(bool value);
|
inline void setEnableApgsDEPRECATED(bool value);
|
||||||
@@ -3325,13 +3325,13 @@ public:
|
|||||||
|
|
||||||
inline bool getUseSteeringAngleDEPRECATED() const;
|
inline bool getUseSteeringAngleDEPRECATED() const;
|
||||||
|
|
||||||
inline float getKp() const;
|
inline float getKpDEPRECATED() const;
|
||||||
|
|
||||||
inline float getKi() const;
|
inline float getKiDEPRECATED() const;
|
||||||
|
|
||||||
inline float getFriction() const;
|
inline float getFriction() const;
|
||||||
|
|
||||||
inline float getKf() const;
|
inline float getKfDEPRECATED() const;
|
||||||
|
|
||||||
inline float getSteeringAngleDeadzoneDeg() const;
|
inline float getSteeringAngleDeadzoneDeg() const;
|
||||||
|
|
||||||
@@ -3339,6 +3339,8 @@ public:
|
|||||||
|
|
||||||
inline float getLatAccelOffset() const;
|
inline float getLatAccelOffset() const;
|
||||||
|
|
||||||
|
inline float getKdDEPRECATED() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::capnp::_::StructReader _reader;
|
::capnp::_::StructReader _reader;
|
||||||
template <typename, ::capnp::Kind>
|
template <typename, ::capnp::Kind>
|
||||||
@@ -3370,17 +3372,17 @@ public:
|
|||||||
inline bool getUseSteeringAngleDEPRECATED();
|
inline bool getUseSteeringAngleDEPRECATED();
|
||||||
inline void setUseSteeringAngleDEPRECATED(bool value);
|
inline void setUseSteeringAngleDEPRECATED(bool value);
|
||||||
|
|
||||||
inline float getKp();
|
inline float getKpDEPRECATED();
|
||||||
inline void setKp(float value);
|
inline void setKpDEPRECATED(float value);
|
||||||
|
|
||||||
inline float getKi();
|
inline float getKiDEPRECATED();
|
||||||
inline void setKi(float value);
|
inline void setKiDEPRECATED(float value);
|
||||||
|
|
||||||
inline float getFriction();
|
inline float getFriction();
|
||||||
inline void setFriction(float value);
|
inline void setFriction(float value);
|
||||||
|
|
||||||
inline float getKf();
|
inline float getKfDEPRECATED();
|
||||||
inline void setKf(float value);
|
inline void setKfDEPRECATED(float value);
|
||||||
|
|
||||||
inline float getSteeringAngleDeadzoneDeg();
|
inline float getSteeringAngleDeadzoneDeg();
|
||||||
inline void setSteeringAngleDeadzoneDeg(float value);
|
inline void setSteeringAngleDeadzoneDeg(float value);
|
||||||
@@ -3391,6 +3393,9 @@ public:
|
|||||||
inline float getLatAccelOffset();
|
inline float getLatAccelOffset();
|
||||||
inline void setLatAccelOffset(float value);
|
inline void setLatAccelOffset(float value);
|
||||||
|
|
||||||
|
inline float getKdDEPRECATED();
|
||||||
|
inline void setKdDEPRECATED(float value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::capnp::_::StructBuilder _builder;
|
::capnp::_::StructBuilder _builder;
|
||||||
template <typename, ::capnp::Kind>
|
template <typename, ::capnp::Kind>
|
||||||
@@ -3452,7 +3457,7 @@ public:
|
|||||||
inline bool hasDeadzoneVDEPRECATED() const;
|
inline bool hasDeadzoneVDEPRECATED() const;
|
||||||
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader getDeadzoneVDEPRECATED() const;
|
inline ::capnp::List<float, ::capnp::Kind::PRIMITIVE>::Reader getDeadzoneVDEPRECATED() const;
|
||||||
|
|
||||||
inline float getKf() const;
|
inline float getKfDEPRECATED() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::capnp::_::StructReader _reader;
|
::capnp::_::StructReader _reader;
|
||||||
@@ -3530,8 +3535,8 @@ public:
|
|||||||
inline void adoptDeadzoneVDEPRECATED(::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>&& value);
|
inline void adoptDeadzoneVDEPRECATED(::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>>&& value);
|
||||||
inline ::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>> disownDeadzoneVDEPRECATED();
|
inline ::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>> disownDeadzoneVDEPRECATED();
|
||||||
|
|
||||||
inline float getKf();
|
inline float getKfDEPRECATED();
|
||||||
inline void setKf(float value);
|
inline void setKfDEPRECATED(float value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::capnp::_::StructBuilder _builder;
|
::capnp::_::StructBuilder _builder;
|
||||||
@@ -4412,16 +4417,16 @@ inline void CarState::Builder::setGasPressed(bool value) {
|
|||||||
::capnp::bounded<64>() * ::capnp::ELEMENTS, value);
|
::capnp::bounded<64>() * ::capnp::ELEMENTS, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float CarState::Reader::getBrake() const {
|
inline float CarState::Reader::getBrakeDEPRECATED() const {
|
||||||
return _reader.getDataField<float>(
|
return _reader.getDataField<float>(
|
||||||
::capnp::bounded<3>() * ::capnp::ELEMENTS);
|
::capnp::bounded<3>() * ::capnp::ELEMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float CarState::Builder::getBrake() {
|
inline float CarState::Builder::getBrakeDEPRECATED() {
|
||||||
return _builder.getDataField<float>(
|
return _builder.getDataField<float>(
|
||||||
::capnp::bounded<3>() * ::capnp::ELEMENTS);
|
::capnp::bounded<3>() * ::capnp::ELEMENTS);
|
||||||
}
|
}
|
||||||
inline void CarState::Builder::setBrake(float value) {
|
inline void CarState::Builder::setBrakeDEPRECATED(float value) {
|
||||||
_builder.setDataField<float>(
|
_builder.setDataField<float>(
|
||||||
::capnp::bounded<3>() * ::capnp::ELEMENTS, value);
|
::capnp::bounded<3>() * ::capnp::ELEMENTS, value);
|
||||||
}
|
}
|
||||||
@@ -6669,16 +6674,16 @@ inline void CarParams::Builder::setEnableCameraDEPRECATED(bool value) {
|
|||||||
::capnp::bounded<2>() * ::capnp::ELEMENTS, value);
|
::capnp::bounded<2>() * ::capnp::ELEMENTS, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool CarParams::Reader::getEnableDsu() const {
|
inline bool CarParams::Reader::getEnableDsuDEPRECATED() const {
|
||||||
return _reader.getDataField<bool>(
|
return _reader.getDataField<bool>(
|
||||||
::capnp::bounded<3>() * ::capnp::ELEMENTS);
|
::capnp::bounded<3>() * ::capnp::ELEMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool CarParams::Builder::getEnableDsu() {
|
inline bool CarParams::Builder::getEnableDsuDEPRECATED() {
|
||||||
return _builder.getDataField<bool>(
|
return _builder.getDataField<bool>(
|
||||||
::capnp::bounded<3>() * ::capnp::ELEMENTS);
|
::capnp::bounded<3>() * ::capnp::ELEMENTS);
|
||||||
}
|
}
|
||||||
inline void CarParams::Builder::setEnableDsu(bool value) {
|
inline void CarParams::Builder::setEnableDsuDEPRECATED(bool value) {
|
||||||
_builder.setDataField<bool>(
|
_builder.setDataField<bool>(
|
||||||
::capnp::bounded<3>() * ::capnp::ELEMENTS, value);
|
::capnp::bounded<3>() * ::capnp::ELEMENTS, value);
|
||||||
}
|
}
|
||||||
@@ -8217,30 +8222,30 @@ inline void CarParams::LateralTorqueTuning::Builder::setUseSteeringAngleDEPRECAT
|
|||||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
|
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float CarParams::LateralTorqueTuning::Reader::getKp() const {
|
inline float CarParams::LateralTorqueTuning::Reader::getKpDEPRECATED() const {
|
||||||
return _reader.getDataField<float>(
|
return _reader.getDataField<float>(
|
||||||
::capnp::bounded<1>() * ::capnp::ELEMENTS);
|
::capnp::bounded<1>() * ::capnp::ELEMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float CarParams::LateralTorqueTuning::Builder::getKp() {
|
inline float CarParams::LateralTorqueTuning::Builder::getKpDEPRECATED() {
|
||||||
return _builder.getDataField<float>(
|
return _builder.getDataField<float>(
|
||||||
::capnp::bounded<1>() * ::capnp::ELEMENTS);
|
::capnp::bounded<1>() * ::capnp::ELEMENTS);
|
||||||
}
|
}
|
||||||
inline void CarParams::LateralTorqueTuning::Builder::setKp(float value) {
|
inline void CarParams::LateralTorqueTuning::Builder::setKpDEPRECATED(float value) {
|
||||||
_builder.setDataField<float>(
|
_builder.setDataField<float>(
|
||||||
::capnp::bounded<1>() * ::capnp::ELEMENTS, value);
|
::capnp::bounded<1>() * ::capnp::ELEMENTS, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float CarParams::LateralTorqueTuning::Reader::getKi() const {
|
inline float CarParams::LateralTorqueTuning::Reader::getKiDEPRECATED() const {
|
||||||
return _reader.getDataField<float>(
|
return _reader.getDataField<float>(
|
||||||
::capnp::bounded<2>() * ::capnp::ELEMENTS);
|
::capnp::bounded<2>() * ::capnp::ELEMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float CarParams::LateralTorqueTuning::Builder::getKi() {
|
inline float CarParams::LateralTorqueTuning::Builder::getKiDEPRECATED() {
|
||||||
return _builder.getDataField<float>(
|
return _builder.getDataField<float>(
|
||||||
::capnp::bounded<2>() * ::capnp::ELEMENTS);
|
::capnp::bounded<2>() * ::capnp::ELEMENTS);
|
||||||
}
|
}
|
||||||
inline void CarParams::LateralTorqueTuning::Builder::setKi(float value) {
|
inline void CarParams::LateralTorqueTuning::Builder::setKiDEPRECATED(float value) {
|
||||||
_builder.setDataField<float>(
|
_builder.setDataField<float>(
|
||||||
::capnp::bounded<2>() * ::capnp::ELEMENTS, value);
|
::capnp::bounded<2>() * ::capnp::ELEMENTS, value);
|
||||||
}
|
}
|
||||||
@@ -8259,16 +8264,16 @@ inline void CarParams::LateralTorqueTuning::Builder::setFriction(float value) {
|
|||||||
::capnp::bounded<3>() * ::capnp::ELEMENTS, value);
|
::capnp::bounded<3>() * ::capnp::ELEMENTS, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float CarParams::LateralTorqueTuning::Reader::getKf() const {
|
inline float CarParams::LateralTorqueTuning::Reader::getKfDEPRECATED() const {
|
||||||
return _reader.getDataField<float>(
|
return _reader.getDataField<float>(
|
||||||
::capnp::bounded<4>() * ::capnp::ELEMENTS);
|
::capnp::bounded<4>() * ::capnp::ELEMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float CarParams::LateralTorqueTuning::Builder::getKf() {
|
inline float CarParams::LateralTorqueTuning::Builder::getKfDEPRECATED() {
|
||||||
return _builder.getDataField<float>(
|
return _builder.getDataField<float>(
|
||||||
::capnp::bounded<4>() * ::capnp::ELEMENTS);
|
::capnp::bounded<4>() * ::capnp::ELEMENTS);
|
||||||
}
|
}
|
||||||
inline void CarParams::LateralTorqueTuning::Builder::setKf(float value) {
|
inline void CarParams::LateralTorqueTuning::Builder::setKfDEPRECATED(float value) {
|
||||||
_builder.setDataField<float>(
|
_builder.setDataField<float>(
|
||||||
::capnp::bounded<4>() * ::capnp::ELEMENTS, value);
|
::capnp::bounded<4>() * ::capnp::ELEMENTS, value);
|
||||||
}
|
}
|
||||||
@@ -8315,6 +8320,20 @@ inline void CarParams::LateralTorqueTuning::Builder::setLatAccelOffset(float val
|
|||||||
::capnp::bounded<7>() * ::capnp::ELEMENTS, value);
|
::capnp::bounded<7>() * ::capnp::ELEMENTS, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline float CarParams::LateralTorqueTuning::Reader::getKdDEPRECATED() const {
|
||||||
|
return _reader.getDataField<float>(
|
||||||
|
::capnp::bounded<8>() * ::capnp::ELEMENTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float CarParams::LateralTorqueTuning::Builder::getKdDEPRECATED() {
|
||||||
|
return _builder.getDataField<float>(
|
||||||
|
::capnp::bounded<8>() * ::capnp::ELEMENTS);
|
||||||
|
}
|
||||||
|
inline void CarParams::LateralTorqueTuning::Builder::setKdDEPRECATED(float value) {
|
||||||
|
_builder.setDataField<float>(
|
||||||
|
::capnp::bounded<8>() * ::capnp::ELEMENTS, value);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool CarParams::LongitudinalPIDTuning::Reader::hasKpBP() const {
|
inline bool CarParams::LongitudinalPIDTuning::Reader::hasKpBP() const {
|
||||||
return !_reader.getPointerField(
|
return !_reader.getPointerField(
|
||||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||||
@@ -8543,16 +8562,16 @@ inline ::capnp::Orphan< ::capnp::List<float, ::capnp::Kind::PRIMITIVE>> CarPara
|
|||||||
::capnp::bounded<5>() * ::capnp::POINTERS));
|
::capnp::bounded<5>() * ::capnp::POINTERS));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float CarParams::LongitudinalPIDTuning::Reader::getKf() const {
|
inline float CarParams::LongitudinalPIDTuning::Reader::getKfDEPRECATED() const {
|
||||||
return _reader.getDataField<float>(
|
return _reader.getDataField<float>(
|
||||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float CarParams::LongitudinalPIDTuning::Builder::getKf() {
|
inline float CarParams::LongitudinalPIDTuning::Builder::getKfDEPRECATED() {
|
||||||
return _builder.getDataField<float>(
|
return _builder.getDataField<float>(
|
||||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||||
}
|
}
|
||||||
inline void CarParams::LongitudinalPIDTuning::Builder::setKf(float value) {
|
inline void CarParams::LongitudinalPIDTuning::Builder::setKfDEPRECATED(float value) {
|
||||||
_builder.setDataField<float>(
|
_builder.setDataField<float>(
|
||||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
|
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
|
||||||
}
|
}
|
||||||
|
|||||||
+5137
-170
File diff suppressed because it is too large
Load Diff
+6976
-91
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+7949
-8750
File diff suppressed because it is too large
Load Diff
+9670
-10741
File diff suppressed because it is too large
Load Diff
@@ -1,574 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
+426
-489
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,8 @@
|
|||||||
# must be built with scons
|
# must be built with scons
|
||||||
from msgq.ipc_pyx import Context, Poller, SubSocket, PubSocket, SocketEventHandle, toggle_fake_events, \
|
from msgq import fake_event_handle, drain_sock_raw, MultiplePublishersError, IpcError, \
|
||||||
set_fake_prefix, get_fake_prefix, delete_fake_prefix, wait_for_one_event
|
Context, Poller, SubSocket, PubSocket, SocketEventHandle, toggle_fake_events, \
|
||||||
from msgq.ipc_pyx import MultiplePublishersError, IpcError
|
set_fake_prefix, get_fake_prefix, delete_fake_prefix, wait_for_one_event
|
||||||
from msgq import fake_event_handle, pub_sock, sub_sock, drain_sock_raw
|
|
||||||
import msgq
|
import msgq
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import capnp
|
import capnp
|
||||||
import time
|
import time
|
||||||
@@ -13,11 +11,25 @@ from typing import Optional, List, Union, Dict
|
|||||||
|
|
||||||
from cereal import log
|
from cereal import log
|
||||||
from cereal.services import SERVICE_LIST
|
from cereal.services import SERVICE_LIST
|
||||||
from openpilot.common.util import MovingAverage
|
from openpilot.common.utils import MovingAverage
|
||||||
|
|
||||||
NO_TRAVERSAL_LIMIT = 2**64-1
|
NO_TRAVERSAL_LIMIT = 2**64-1
|
||||||
|
|
||||||
|
|
||||||
|
def pub_sock(endpoint: str) -> PubSocket:
|
||||||
|
service = SERVICE_LIST.get(endpoint)
|
||||||
|
segment_size = service.queue_size if service else 0
|
||||||
|
return msgq.pub_sock(endpoint, segment_size)
|
||||||
|
|
||||||
|
|
||||||
|
def sub_sock(endpoint: str, poller: Optional[Poller] = None, addr: str = "127.0.0.1",
|
||||||
|
conflate: bool = False, timeout: Optional[int] = None) -> SubSocket:
|
||||||
|
service = SERVICE_LIST.get(endpoint)
|
||||||
|
segment_size = service.queue_size if service else 0
|
||||||
|
return msgq.sub_sock(endpoint, poller=poller, addr=addr, conflate=conflate,
|
||||||
|
timeout=timeout, segment_size=segment_size)
|
||||||
|
|
||||||
|
|
||||||
def reset_context():
|
def reset_context():
|
||||||
msgq.context = Context()
|
msgq.context = Context()
|
||||||
|
|
||||||
@@ -247,11 +259,11 @@ class PubMaster:
|
|||||||
self.sock[s].send(dat)
|
self.sock[s].send(dat)
|
||||||
|
|
||||||
def wait_for_readers_to_update(self, s: str, timeout: int, dt: float = 0.05) -> bool:
|
def wait_for_readers_to_update(self, s: str, timeout: int, dt: float = 0.05) -> bool:
|
||||||
for _ in range(int(timeout*(1./dt))):
|
try:
|
||||||
if self.sock[s].all_readers_updated():
|
self.sock[s].wait_for_readers(timeout=timeout, interval=dt)
|
||||||
return True
|
return True
|
||||||
time.sleep(dt)
|
except TimeoutError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def all_readers_updated(self, s: str) -> bool:
|
def all_readers_updated(self, s: str) -> bool:
|
||||||
return self.sock[s].all_readers_updated() # type: ignore
|
return self.sock[s].all_readers_updated()
|
||||||
|
|||||||
Binary file not shown.
@@ -25,15 +25,16 @@ void msgq_to_zmq(const std::vector<std::string> &endpoints, const std::string &i
|
|||||||
}
|
}
|
||||||
|
|
||||||
void zmq_to_msgq(const std::vector<std::string> &endpoints, const std::string &ip) {
|
void zmq_to_msgq(const std::vector<std::string> &endpoints, const std::string &ip) {
|
||||||
auto poller = std::make_unique<ZMQPoller>();
|
auto poller = std::make_unique<BridgeZmqPoller>();
|
||||||
auto pub_context = std::make_unique<MSGQContext>();
|
auto pub_context = std::make_unique<Context>();
|
||||||
auto sub_context = std::make_unique<ZMQContext>();
|
auto sub_context = std::make_unique<BridgeZmqContext>();
|
||||||
std::map<SubSocket *, PubSocket *> sub2pub;
|
std::map<BridgeZmqSubSocket *, PubSocket *> sub2pub;
|
||||||
|
|
||||||
for (auto endpoint : endpoints) {
|
for (auto endpoint : endpoints) {
|
||||||
auto pub_sock = new MSGQPubSocket();
|
auto pub_sock = new PubSocket();
|
||||||
auto sub_sock = new ZMQSubSocket();
|
auto sub_sock = new BridgeZmqSubSocket();
|
||||||
pub_sock->connect(pub_context.get(), endpoint);
|
size_t queue_size = services.at(endpoint).queue_size;
|
||||||
|
pub_sock->connect(pub_context.get(), endpoint, true, queue_size);
|
||||||
sub_sock->connect(sub_context.get(), endpoint, ip, false);
|
sub_sock->connect(sub_context.get(), endpoint, ip, false);
|
||||||
|
|
||||||
poller->registerSocket(sub_sock);
|
poller->registerSocket(sub_sock);
|
||||||
|
|||||||
@@ -0,0 +1,170 @@
|
|||||||
|
#include "cereal/messaging/bridge_zmq.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
#include <unistd.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;
|
||||||
|
return start_port + (hash_value % (max_port - start_port));
|
||||||
|
}
|
||||||
|
|
||||||
|
BridgeZmqContext::BridgeZmqContext() {
|
||||||
|
context = zmq_ctx_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
BridgeZmqContext::~BridgeZmqContext() {
|
||||||
|
if (context != nullptr) {
|
||||||
|
zmq_ctx_term(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BridgeZmqMessage::init(size_t sz) {
|
||||||
|
size = sz;
|
||||||
|
data = new char[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
void BridgeZmqMessage::init(char *d, size_t sz) {
|
||||||
|
size = sz;
|
||||||
|
data = new char[size];
|
||||||
|
memcpy(data, d, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BridgeZmqMessage::close() {
|
||||||
|
if (size > 0) {
|
||||||
|
delete[] data;
|
||||||
|
}
|
||||||
|
data = nullptr;
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BridgeZmqMessage::~BridgeZmqMessage() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int BridgeZmqSubSocket::connect(BridgeZmqContext *context, std::string endpoint, std::string address, bool conflate, bool check_endpoint) {
|
||||||
|
sock = zmq_socket(context->getRawContext(), ZMQ_SUB);
|
||||||
|
if (sock == nullptr) {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
void BridgeZmqSubSocket::setTimeout(int timeout) {
|
||||||
|
zmq_setsockopt(sock, ZMQ_RCVTIMEO, &timeout, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
Message *BridgeZmqSubSocket::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 *ret = nullptr;
|
||||||
|
if (rc >= 0) {
|
||||||
|
ret = new BridgeZmqMessage;
|
||||||
|
ret->init((char *)zmq_msg_data(&msg), zmq_msg_size(&msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
zmq_msg_close(&msg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
BridgeZmqSubSocket::~BridgeZmqSubSocket() {
|
||||||
|
if (sock != nullptr) {
|
||||||
|
zmq_close(sock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int BridgeZmqPubSocket::connect(BridgeZmqContext *context, std::string endpoint, bool check_endpoint) {
|
||||||
|
sock = zmq_socket(context->getRawContext(), ZMQ_PUB);
|
||||||
|
if (sock == nullptr) {
|
||||||
|
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 BridgeZmqPubSocket::sendMessage(Message *message) {
|
||||||
|
assert(pid == getpid());
|
||||||
|
return zmq_send(sock, message->getData(), message->getSize(), ZMQ_DONTWAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BridgeZmqPubSocket::send(char *data, size_t size) {
|
||||||
|
assert(pid == getpid());
|
||||||
|
return zmq_send(sock, data, size, ZMQ_DONTWAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
BridgeZmqPubSocket::~BridgeZmqPubSocket() {
|
||||||
|
if (sock != nullptr) {
|
||||||
|
zmq_close(sock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BridgeZmqPoller::registerSocket(BridgeZmqSubSocket *socket) {
|
||||||
|
assert(num_polls + 1 < (sizeof(polls) / sizeof(polls[0])));
|
||||||
|
polls[num_polls].socket = socket->getRawSocket();
|
||||||
|
polls[num_polls].events = ZMQ_POLLIN;
|
||||||
|
|
||||||
|
sockets.push_back(socket);
|
||||||
|
num_polls++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<BridgeZmqSubSocket *> BridgeZmqPoller::poll(int timeout) {
|
||||||
|
std::vector<BridgeZmqSubSocket *> ret;
|
||||||
|
|
||||||
|
int rc = zmq_poll(polls, num_polls, timeout);
|
||||||
|
if (rc < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num_polls; i++) {
|
||||||
|
if (polls[i].revents) {
|
||||||
|
ret.push_back(sockets[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <zmq.h>
|
||||||
|
|
||||||
|
#include "msgq/ipc.h"
|
||||||
|
|
||||||
|
class BridgeZmqContext {
|
||||||
|
public:
|
||||||
|
BridgeZmqContext();
|
||||||
|
void *getRawContext() { return context; }
|
||||||
|
~BridgeZmqContext();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *context = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BridgeZmqMessage : public Message {
|
||||||
|
public:
|
||||||
|
void init(size_t size);
|
||||||
|
void init(char *data, size_t size);
|
||||||
|
void close();
|
||||||
|
size_t getSize() { return size; }
|
||||||
|
char *getData() { return data; }
|
||||||
|
~BridgeZmqMessage();
|
||||||
|
|
||||||
|
private:
|
||||||
|
char *data = nullptr;
|
||||||
|
size_t size = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BridgeZmqSubSocket {
|
||||||
|
public:
|
||||||
|
int connect(BridgeZmqContext *context, std::string endpoint, std::string address, bool conflate = false, bool check_endpoint = true);
|
||||||
|
void setTimeout(int timeout);
|
||||||
|
Message *receive(bool non_blocking = false);
|
||||||
|
void *getRawSocket() { return sock; }
|
||||||
|
~BridgeZmqSubSocket();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *sock = nullptr;
|
||||||
|
std::string full_endpoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BridgeZmqPubSocket {
|
||||||
|
public:
|
||||||
|
int connect(BridgeZmqContext *context, std::string endpoint, bool check_endpoint = true);
|
||||||
|
int sendMessage(Message *message);
|
||||||
|
int send(char *data, size_t size);
|
||||||
|
void *getRawSocket() { return sock; }
|
||||||
|
~BridgeZmqPubSocket();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *sock = nullptr;
|
||||||
|
std::string full_endpoint;
|
||||||
|
int pid = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BridgeZmqPoller {
|
||||||
|
public:
|
||||||
|
void registerSocket(BridgeZmqSubSocket *socket);
|
||||||
|
std::vector<BridgeZmqSubSocket *> poll(int timeout);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr size_t MAX_BRIDGE_ZMQ_POLLERS = 128;
|
||||||
|
std::vector<BridgeZmqSubSocket *> sockets;
|
||||||
|
zmq_pollitem_t polls[MAX_BRIDGE_ZMQ_POLLERS] = {};
|
||||||
|
size_t num_polls = 0;
|
||||||
|
};
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "cereal/services.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
|
||||||
extern ExitHandler do_exit;
|
extern ExitHandler do_exit;
|
||||||
@@ -21,14 +22,14 @@ static std::string recv_zmq_msg(void *sock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MsgqToZmq::run(const std::vector<std::string> &endpoints, const std::string &ip) {
|
void MsgqToZmq::run(const std::vector<std::string> &endpoints, const std::string &ip) {
|
||||||
zmq_context = std::make_unique<ZMQContext>();
|
zmq_context = std::make_unique<BridgeZmqContext>();
|
||||||
msgq_context = std::make_unique<MSGQContext>();
|
msgq_context = std::make_unique<Context>();
|
||||||
|
|
||||||
// Create ZMQPubSockets for each endpoint
|
// Create ZMQPubSockets for each endpoint
|
||||||
for (const auto &endpoint : endpoints) {
|
for (const auto &endpoint : endpoints) {
|
||||||
auto &socket_pair = socket_pairs.emplace_back();
|
auto &socket_pair = socket_pairs.emplace_back();
|
||||||
socket_pair.endpoint = endpoint;
|
socket_pair.endpoint = endpoint;
|
||||||
socket_pair.pub_sock = std::make_unique<ZMQPubSocket>();
|
socket_pair.pub_sock = std::make_unique<BridgeZmqPubSocket>();
|
||||||
int ret = socket_pair.pub_sock->connect(zmq_context.get(), endpoint);
|
int ret = socket_pair.pub_sock->connect(zmq_context.get(), endpoint);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
printf("Failed to create ZMQ publisher for [%s]: %s\n", endpoint.c_str(), zmq_strerror(zmq_errno()));
|
printf("Failed to create ZMQ publisher for [%s]: %s\n", endpoint.c_str(), zmq_strerror(zmq_errno()));
|
||||||
@@ -48,7 +49,7 @@ void MsgqToZmq::run(const std::vector<std::string> &endpoints, const std::string
|
|||||||
|
|
||||||
for (auto sub_sock : msgq_poller->poll(100)) {
|
for (auto sub_sock : msgq_poller->poll(100)) {
|
||||||
// Process messages for each socket
|
// Process messages for each socket
|
||||||
ZMQPubSocket *pub_sock = sub2pub.at(sub_sock);
|
BridgeZmqPubSocket *pub_sock = sub2pub.at(sub_sock);
|
||||||
for (int i = 0; i < MAX_MESSAGES_PER_SOCKET; ++i) {
|
for (int i = 0; i < MAX_MESSAGES_PER_SOCKET; ++i) {
|
||||||
auto msg = std::unique_ptr<Message>(sub_sock->receive(true));
|
auto msg = std::unique_ptr<Message>(sub_sock->receive(true));
|
||||||
if (!msg) break;
|
if (!msg) break;
|
||||||
@@ -71,7 +72,7 @@ void MsgqToZmq::zmqMonitorThread() {
|
|||||||
// Set up ZMQ monitor for each pub socket
|
// Set up ZMQ monitor for each pub socket
|
||||||
for (int i = 0; i < socket_pairs.size(); ++i) {
|
for (int i = 0; i < socket_pairs.size(); ++i) {
|
||||||
std::string addr = "inproc://op-bridge-monitor-" + std::to_string(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);
|
zmq_socket_monitor(socket_pairs[i].pub_sock->getRawSocket(), addr.c_str(), ZMQ_EVENT_ACCEPTED | ZMQ_EVENT_DISCONNECTED);
|
||||||
|
|
||||||
void *monitor_socket = zmq_socket(zmq_context->getRawContext(), ZMQ_PAIR);
|
void *monitor_socket = zmq_socket(zmq_context->getRawContext(), ZMQ_PAIR);
|
||||||
zmq_connect(monitor_socket, addr.c_str());
|
zmq_connect(monitor_socket, addr.c_str());
|
||||||
@@ -108,7 +109,8 @@ void MsgqToZmq::zmqMonitorThread() {
|
|||||||
if (++pair.connected_clients == 1) {
|
if (++pair.connected_clients == 1) {
|
||||||
// Create new MSGQ subscriber socket and map to ZMQ publisher
|
// Create new MSGQ subscriber socket and map to ZMQ publisher
|
||||||
pair.sub_sock = std::make_unique<MSGQSubSocket>();
|
pair.sub_sock = std::make_unique<MSGQSubSocket>();
|
||||||
pair.sub_sock->connect(msgq_context.get(), pair.endpoint, "127.0.0.1");
|
size_t queue_size = services.at(pair.endpoint).queue_size;
|
||||||
|
pair.sub_sock->connect(msgq_context.get(), pair.endpoint, "127.0.0.1", false, true, queue_size);
|
||||||
sub2pub[pair.sub_sock.get()] = pair.pub_sock.get();
|
sub2pub[pair.sub_sock.get()] = pair.pub_sock.get();
|
||||||
registerSockets();
|
registerSockets();
|
||||||
}
|
}
|
||||||
@@ -128,7 +130,7 @@ void MsgqToZmq::zmqMonitorThread() {
|
|||||||
|
|
||||||
// Clean up monitor sockets
|
// Clean up monitor sockets
|
||||||
for (int i = 0; i < pollitems.size(); ++i) {
|
for (int i = 0; i < pollitems.size(); ++i) {
|
||||||
zmq_socket_monitor(socket_pairs[i].pub_sock->sock, nullptr, 0);
|
zmq_socket_monitor(socket_pairs[i].pub_sock->getRawSocket(), nullptr, 0);
|
||||||
zmq_close(pollitems[i].socket);
|
zmq_close(pollitems[i].socket);
|
||||||
}
|
}
|
||||||
cv.notify_one();
|
cv.notify_one();
|
||||||
|
|||||||
@@ -7,9 +7,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#define private public
|
|
||||||
#include "msgq/impl_msgq.h"
|
#include "msgq/impl_msgq.h"
|
||||||
#include "msgq/impl_zmq.h"
|
#include "cereal/messaging/bridge_zmq.h"
|
||||||
|
|
||||||
class MsgqToZmq {
|
class MsgqToZmq {
|
||||||
public:
|
public:
|
||||||
@@ -22,16 +21,16 @@ protected:
|
|||||||
|
|
||||||
struct SocketPair {
|
struct SocketPair {
|
||||||
std::string endpoint;
|
std::string endpoint;
|
||||||
std::unique_ptr<ZMQPubSocket> pub_sock;
|
std::unique_ptr<BridgeZmqPubSocket> pub_sock;
|
||||||
std::unique_ptr<MSGQSubSocket> sub_sock;
|
std::unique_ptr<MSGQSubSocket> sub_sock;
|
||||||
int connected_clients = 0;
|
int connected_clients = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<MSGQContext> msgq_context;
|
std::unique_ptr<Context> msgq_context;
|
||||||
std::unique_ptr<ZMQContext> zmq_context;
|
std::unique_ptr<BridgeZmqContext> zmq_context;
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
std::unique_ptr<MSGQPoller> msgq_poller;
|
std::unique_ptr<MSGQPoller> msgq_poller;
|
||||||
std::map<SubSocket *, ZMQPubSocket *> sub2pub;
|
std::map<SubSocket *, BridgeZmqPubSocket *> sub2pub;
|
||||||
std::vector<SocketPair> socket_pairs;
|
std::vector<SocketPair> socket_pairs;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ MessageContext message_context;
|
|||||||
struct SubMaster::SubMessage {
|
struct SubMaster::SubMessage {
|
||||||
std::string name;
|
std::string name;
|
||||||
SubSocket *socket = nullptr;
|
SubSocket *socket = nullptr;
|
||||||
int freq = 0;
|
float freq = 0.0f;
|
||||||
bool updated = false, alive = false, valid = false, ignore_alive;
|
bool updated = false, alive = false, valid = false, ignore_alive;
|
||||||
uint64_t rcv_time = 0, rcv_frame = 0;
|
uint64_t rcv_time = 0, rcv_frame = 0;
|
||||||
void *allocated_msg_reader = nullptr;
|
void *allocated_msg_reader = nullptr;
|
||||||
@@ -50,7 +50,7 @@ SubMaster::SubMaster(const std::vector<const char *> &service_list, const std::v
|
|||||||
assert(services.count(std::string(name)) > 0);
|
assert(services.count(std::string(name)) > 0);
|
||||||
|
|
||||||
service serv = services.at(std::string(name));
|
service serv = services.at(std::string(name));
|
||||||
SubSocket *socket = SubSocket::create(message_context.context(), name, address ? address : "127.0.0.1", true);
|
SubSocket *socket = SubSocket::create(message_context.context(), name, address ? address : "127.0.0.1", true, true, serv.queue_size);
|
||||||
assert(socket != 0);
|
assert(socket != 0);
|
||||||
bool is_polled = inList(poll, name) || poll.empty();
|
bool is_polled = inList(poll, name) || poll.empty();
|
||||||
if (is_polled) poller_->registerSocket(socket);
|
if (is_polled) poller_->registerSocket(socket);
|
||||||
@@ -187,7 +187,8 @@ SubMaster::~SubMaster() {
|
|||||||
PubMaster::PubMaster(const std::vector<const char *> &service_list) {
|
PubMaster::PubMaster(const std::vector<const char *> &service_list) {
|
||||||
for (auto name : service_list) {
|
for (auto name : service_list) {
|
||||||
assert(services.count(name) > 0);
|
assert(services.count(name) > 0);
|
||||||
PubSocket *socket = PubSocket::create(message_context.context(), name);
|
service serv = services.at(std::string(name));
|
||||||
|
PubSocket *socket = PubSocket::create(message_context.context(), name, true, serv.queue_size);
|
||||||
assert(socket);
|
assert(socket);
|
||||||
sockets_[name] = socket;
|
sockets_[name] = socket;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import numbers
|
|||||||
import random
|
import random
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from parameterized import parameterized
|
from openpilot.common.parameterized import parameterized
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from cereal import log, car
|
from cereal import log, car
|
||||||
@@ -30,7 +30,7 @@ def zmq_sleep(t=1):
|
|||||||
|
|
||||||
# TODO: this should take any capnp struct and returrn a msg with random populated data
|
# TODO: this should take any capnp struct and returrn a msg with random populated data
|
||||||
def random_carstate():
|
def random_carstate():
|
||||||
fields = ["vEgo", "aEgo", "brake", "steeringAngleDeg"]
|
fields = ["vEgo", "aEgo", "steeringTorque", "steeringAngleDeg"]
|
||||||
msg = messaging.new_message("carState")
|
msg = messaging.new_message("carState")
|
||||||
cs = msg.carState
|
cs = msg.carState
|
||||||
for f in fields:
|
for f in fields:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from parameterized import parameterized
|
from openpilot.common.parameterized import parameterized
|
||||||
|
|
||||||
import cereal.services as services
|
import cereal.services as services
|
||||||
from cereal.services import SERVICE_LIST
|
from cereal.services import SERVICE_LIST
|
||||||
|
|||||||
+256
@@ -0,0 +1,256 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Schema-level cereal compat check between sunnypilot and upstream openpilot.
|
||||||
|
|
||||||
|
Rules (per struct matched across sides by typeId):
|
||||||
|
R1 shared ordinal must reference the same type.
|
||||||
|
R2 sunnypilot-only ordinal in a union -> FAIL (unknown discriminant upstream).
|
||||||
|
R3 sunnypilot-only ordinal on a regular field -> OK (additive struct evolution).
|
||||||
|
R4 upstream-only ordinal -> OK.
|
||||||
|
R5 sunnypilot-only struct referenced via an upstream-shared field -> FAIL.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
NO_DISCRIMINANT = 0xFFFF
|
||||||
|
|
||||||
|
|
||||||
|
def hex_id(value: int) -> str:
|
||||||
|
return f"0x{value:016x}"
|
||||||
|
|
||||||
|
|
||||||
|
def encode_type(type_node: Any) -> dict:
|
||||||
|
which = type_node.which()
|
||||||
|
if which == "struct":
|
||||||
|
return {"kind": "struct", "typeId": hex_id(type_node.struct.typeId)}
|
||||||
|
if which == "enum":
|
||||||
|
return {"kind": "enum", "typeId": hex_id(type_node.enum.typeId)}
|
||||||
|
if which == "interface":
|
||||||
|
return {"kind": "interface", "typeId": hex_id(type_node.interface.typeId)}
|
||||||
|
if which == "list":
|
||||||
|
return {"kind": "list", "element": encode_type(type_node.list.elementType)}
|
||||||
|
if which == "anyPointer":
|
||||||
|
return {"kind": "anyPointer"}
|
||||||
|
return {"kind": which}
|
||||||
|
|
||||||
|
|
||||||
|
def encode_field(name: str, field: Any) -> dict:
|
||||||
|
proto = field.proto
|
||||||
|
ordinal = proto.ordinal.explicit if proto.ordinal.which() == "explicit" else None
|
||||||
|
discriminant = proto.discriminantValue if proto.discriminantValue != NO_DISCRIMINANT else None
|
||||||
|
|
||||||
|
if proto.which() == "group":
|
||||||
|
type_desc = {"kind": "group", "typeId": hex_id(proto.group.typeId)}
|
||||||
|
else:
|
||||||
|
type_desc = encode_type(proto.slot.type)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"name": name,
|
||||||
|
"ordinal": ordinal,
|
||||||
|
"discriminant": discriminant,
|
||||||
|
"type": type_desc,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def encode_struct(schema: Any) -> dict:
|
||||||
|
node = schema.node
|
||||||
|
return {
|
||||||
|
"typeId": hex_id(node.id),
|
||||||
|
"displayName": node.displayName,
|
||||||
|
"hasUnion": node.struct.discriminantCount > 0,
|
||||||
|
"fields": [encode_field(name, field) for name, field in schema.fields.items()],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _child_struct_schema(field: Any) -> Any:
|
||||||
|
proto = field.proto
|
||||||
|
if proto.which() == "group":
|
||||||
|
return field.schema
|
||||||
|
type_node = proto.slot.type
|
||||||
|
which = type_node.which()
|
||||||
|
if which == "struct":
|
||||||
|
return field.schema
|
||||||
|
if which == "list":
|
||||||
|
container = field.schema
|
||||||
|
element_type = type_node.list.elementType
|
||||||
|
while element_type.which() == "list":
|
||||||
|
container = container.elementType
|
||||||
|
element_type = element_type.list.elementType
|
||||||
|
if element_type.which() == "struct":
|
||||||
|
return container.elementType
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def collect_schema(root: Any) -> dict[str, dict]:
|
||||||
|
structs: dict[str, dict] = {}
|
||||||
|
stack = [root]
|
||||||
|
while stack:
|
||||||
|
schema = stack.pop()
|
||||||
|
type_id = hex_id(schema.node.id)
|
||||||
|
if type_id in structs:
|
||||||
|
continue
|
||||||
|
structs[type_id] = encode_struct(schema)
|
||||||
|
for _name, field in schema.fields.items():
|
||||||
|
try:
|
||||||
|
child = _child_struct_schema(field)
|
||||||
|
except Exception:
|
||||||
|
child = None
|
||||||
|
if child is not None:
|
||||||
|
stack.append(child)
|
||||||
|
return structs
|
||||||
|
|
||||||
|
|
||||||
|
def load_log(cereal_dir: str) -> Any:
|
||||||
|
import capnp
|
||||||
|
cereal_dir = os.path.abspath(cereal_dir)
|
||||||
|
capnp.remove_import_hook()
|
||||||
|
return capnp.load(os.path.join(cereal_dir, "log.capnp"), imports=[cereal_dir])
|
||||||
|
|
||||||
|
|
||||||
|
def dump_schema(cereal_dir: str, path: str) -> None:
|
||||||
|
log = load_log(cereal_dir)
|
||||||
|
payload = {
|
||||||
|
"root": hex_id(log.Event.schema.node.id),
|
||||||
|
"structs": collect_schema(log.Event.schema),
|
||||||
|
}
|
||||||
|
with open(path, "w", encoding="utf-8") as handle:
|
||||||
|
json.dump(payload, handle, indent=2, sort_keys=True)
|
||||||
|
print(f"wrote schema dump with {len(payload['structs'])} structs to {path}")
|
||||||
|
|
||||||
|
|
||||||
|
def types_equal(a: dict, b: dict) -> bool:
|
||||||
|
if a.get("kind") != b.get("kind"):
|
||||||
|
return False
|
||||||
|
kind = a["kind"]
|
||||||
|
if kind in ("struct", "enum", "interface", "group"):
|
||||||
|
return a.get("typeId") == b.get("typeId")
|
||||||
|
if kind == "list":
|
||||||
|
return types_equal(a["element"], b["element"])
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def type_repr(t: dict) -> str:
|
||||||
|
kind = t.get("kind", "?")
|
||||||
|
if kind in ("struct", "enum", "interface", "group"):
|
||||||
|
return f"{kind}({t.get('typeId')})"
|
||||||
|
if kind == "list":
|
||||||
|
return f"list<{type_repr(t['element'])}>"
|
||||||
|
return kind
|
||||||
|
|
||||||
|
|
||||||
|
def field_is_union_variant(field: dict) -> bool:
|
||||||
|
return field.get("discriminant") is not None
|
||||||
|
|
||||||
|
|
||||||
|
def index_fields_by_ordinal(struct: dict) -> dict[int, dict]:
|
||||||
|
indexed: dict[int, dict] = {}
|
||||||
|
for field in struct["fields"]:
|
||||||
|
ordinal = field.get("ordinal")
|
||||||
|
if ordinal is None:
|
||||||
|
continue
|
||||||
|
indexed[ordinal] = field
|
||||||
|
return indexed
|
||||||
|
|
||||||
|
|
||||||
|
def compare(sunnypilot_dump: dict, upstream_dump: dict) -> list[str]:
|
||||||
|
violations: list[str] = []
|
||||||
|
sunnypilot_structs: dict[str, dict] = sunnypilot_dump["structs"]
|
||||||
|
upstream_structs: dict[str, dict] = upstream_dump["structs"]
|
||||||
|
|
||||||
|
sunnypilot_struct_referenced_from_shared: set[str] = set()
|
||||||
|
|
||||||
|
for type_id, sunnypilot_struct in sunnypilot_structs.items():
|
||||||
|
upstream_struct = upstream_structs.get(type_id)
|
||||||
|
if upstream_struct is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
sunnypilot_fields = index_fields_by_ordinal(sunnypilot_struct)
|
||||||
|
upstream_fields = index_fields_by_ordinal(upstream_struct)
|
||||||
|
display = sunnypilot_struct["displayName"]
|
||||||
|
|
||||||
|
for ordinal, sunnypilot_field in sunnypilot_fields.items():
|
||||||
|
upstream_field = upstream_fields.get(ordinal)
|
||||||
|
if upstream_field is None:
|
||||||
|
if field_is_union_variant(sunnypilot_field):
|
||||||
|
violations.append(
|
||||||
|
f"[R2] {display} @{ordinal} ('{sunnypilot_field['name']}', {type_repr(sunnypilot_field['type'])}): "
|
||||||
|
f"union variant not present upstream. upstream cannot parse this discriminant."
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not types_equal(sunnypilot_field["type"], upstream_field["type"]):
|
||||||
|
violations.append(
|
||||||
|
f"[R1] {display} @{ordinal}: type mismatch. "
|
||||||
|
f"sunnypilot='{sunnypilot_field['name']}' {type_repr(sunnypilot_field['type'])} vs "
|
||||||
|
f"upstream='{upstream_field['name']}' {type_repr(upstream_field['type'])}."
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
cursor = sunnypilot_field["type"]
|
||||||
|
while cursor.get("kind") == "list":
|
||||||
|
cursor = cursor["element"]
|
||||||
|
if cursor.get("kind") in ("struct", "group", "interface") and cursor.get("typeId"):
|
||||||
|
sunnypilot_struct_referenced_from_shared.add(cursor["typeId"])
|
||||||
|
|
||||||
|
for type_id, sunnypilot_struct in sunnypilot_structs.items():
|
||||||
|
if type_id in upstream_structs:
|
||||||
|
continue
|
||||||
|
if type_id in sunnypilot_struct_referenced_from_shared:
|
||||||
|
violations.append(
|
||||||
|
f"[R5] struct {sunnypilot_struct['displayName']} ({type_id}) exists only on sunnypilot "
|
||||||
|
f"but is referenced from an upstream-shared field. upstream cannot resolve this type."
|
||||||
|
)
|
||||||
|
|
||||||
|
return violations
|
||||||
|
|
||||||
|
|
||||||
|
def load_peer(path: str) -> dict:
|
||||||
|
with open(path, "r", encoding="utf-8") as handle:
|
||||||
|
return json.load(handle)
|
||||||
|
|
||||||
|
|
||||||
|
def run_read(cereal_dir: str, peer_path: str) -> int:
|
||||||
|
log = load_log(cereal_dir)
|
||||||
|
peer_dump = load_peer(peer_path)
|
||||||
|
local_dump = {
|
||||||
|
"root": hex_id(log.Event.schema.node.id),
|
||||||
|
"structs": collect_schema(log.Event.schema),
|
||||||
|
}
|
||||||
|
violations = compare(sunnypilot_dump=peer_dump, upstream_dump=local_dump)
|
||||||
|
|
||||||
|
if not violations:
|
||||||
|
print("cereal compat OK: upstream openpilot can parse sunnypilot routes "
|
||||||
|
"(no leaked structs, no ordinal collisions).")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
print(f"cereal compat FAIL: upstream openpilot would misparse sunnypilot routes "
|
||||||
|
f"({len(violations)} violation(s)):")
|
||||||
|
for v in violations:
|
||||||
|
print(f" {v}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="sunnypilot <-> upstream cereal compatibility validator (schema-level)."
|
||||||
|
)
|
||||||
|
mode = parser.add_mutually_exclusive_group(required=True)
|
||||||
|
mode.add_argument("-g", "--generate", action="store_true", help="dump local schema to JSON")
|
||||||
|
mode.add_argument("-r", "--read", action="store_true", help="load peer JSON and diff against local")
|
||||||
|
parser.add_argument("-f", "--file", default="schema.json", help="JSON file path (default: schema.json)")
|
||||||
|
parser.add_argument("--cereal-dir", required=True, help="path to cereal directory containing log.capnp")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.generate:
|
||||||
|
dump_schema(args.cereal_dir, args.file)
|
||||||
|
return 0
|
||||||
|
return run_read(args.cereal_dir, args.file)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
+81
-82
@@ -3,89 +3,88 @@
|
|||||||
#define __SERVICES_H
|
#define __SERVICES_H
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
struct service { std::string name; bool should_log; int frequency; int decimation; };
|
struct service { std::string name; bool should_log; float frequency; int decimation; size_t queue_size; };
|
||||||
static std::map<std::string, service> services = {
|
static std::map<std::string, service> services = {
|
||||||
{ "gyroscope", {"gyroscope", true, 104, 104}},
|
{ "gyroscope", {"gyroscope", true, 104.000000, 104, 256000}},
|
||||||
{ "gyroscope2", {"gyroscope2", true, 100, 100}},
|
{ "accelerometer", {"accelerometer", true, 104.000000, 104, 256000}},
|
||||||
{ "accelerometer", {"accelerometer", true, 104, 104}},
|
{ "temperatureSensor", {"temperatureSensor", true, 2.000000, 200, 256000}},
|
||||||
{ "accelerometer2", {"accelerometer2", true, 100, 100}},
|
{ "deviceState", {"deviceState", true, 2.000000, 1, 256000}},
|
||||||
{ "magnetometer", {"magnetometer", true, 25, -1}},
|
{ "touch", {"touch", true, 20.000000, 1, 256000}},
|
||||||
{ "lightSensor", {"lightSensor", true, 100, 100}},
|
{ "can", {"can", true, 100.000000, 2053, 10485760}},
|
||||||
{ "temperatureSensor", {"temperatureSensor", true, 2, 200}},
|
{ "controlsState", {"controlsState", true, 100.000000, 10, 2097152}},
|
||||||
{ "temperatureSensor2", {"temperatureSensor2", true, 2, 200}},
|
{ "selfdriveState", {"selfdriveState", true, 100.000000, 10, 256000}},
|
||||||
{ "gpsNMEA", {"gpsNMEA", true, 9, -1}},
|
{ "pandaStates", {"pandaStates", true, 10.000000, 1, 256000}},
|
||||||
{ "deviceState", {"deviceState", true, 2, 1}},
|
{ "peripheralState", {"peripheralState", true, 2.000000, 1, 256000}},
|
||||||
{ "touch", {"touch", true, 20, 1}},
|
{ "radarState", {"radarState", true, 20.000000, 5, 256000}},
|
||||||
{ "can", {"can", true, 100, 2053}},
|
{ "roadEncodeIdx", {"roadEncodeIdx", false, 20.000000, 1, 256000}},
|
||||||
{ "controlsState", {"controlsState", true, 100, 10}},
|
{ "liveTracks", {"liveTracks", true, 20.000000, -1, 256000}},
|
||||||
{ "selfdriveState", {"selfdriveState", true, 100, 10}},
|
{ "sendcan", {"sendcan", true, 100.000000, 139, 2097152}},
|
||||||
{ "pandaStates", {"pandaStates", true, 10, 1}},
|
{ "logMessage", {"logMessage", true, 0.000000, -1, 10485760}},
|
||||||
{ "peripheralState", {"peripheralState", true, 2, 1}},
|
{ "errorLogMessage", {"errorLogMessage", true, 0.000000, 1, 10485760}},
|
||||||
{ "radarState", {"radarState", true, 20, 5}},
|
{ "liveCalibration", {"liveCalibration", true, 4.000000, 4, 256000}},
|
||||||
{ "roadEncodeIdx", {"roadEncodeIdx", false, 20, 1}},
|
{ "liveTorqueParameters", {"liveTorqueParameters", true, 4.000000, 1, 256000}},
|
||||||
{ "liveTracks", {"liveTracks", true, 20, -1}},
|
{ "liveDelay", {"liveDelay", true, 4.000000, 1, 256000}},
|
||||||
{ "sendcan", {"sendcan", true, 100, 139}},
|
{ "androidLog", {"androidLog", true, 0.000000, -1, 256000}},
|
||||||
{ "logMessage", {"logMessage", true, 0, -1}},
|
{ "carState", {"carState", true, 100.000000, 10, 256000}},
|
||||||
{ "errorLogMessage", {"errorLogMessage", true, 0, 1}},
|
{ "carControl", {"carControl", true, 100.000000, 10, 256000}},
|
||||||
{ "liveCalibration", {"liveCalibration", true, 4, 4}},
|
{ "carOutput", {"carOutput", true, 100.000000, 10, 256000}},
|
||||||
{ "liveTorqueParameters", {"liveTorqueParameters", true, 4, 1}},
|
{ "longitudinalPlan", {"longitudinalPlan", true, 20.000000, 10, 256000}},
|
||||||
{ "liveDelay", {"liveDelay", true, 4, 1}},
|
{ "lateralManeuverPlan", {"lateralManeuverPlan", true, 20.000000, -1, 256000}},
|
||||||
{ "androidLog", {"androidLog", true, 0, -1}},
|
{ "driverAssistance", {"driverAssistance", true, 20.000000, 20, 256000}},
|
||||||
{ "carState", {"carState", true, 100, 10}},
|
{ "procLog", {"procLog", true, 0.500000, 15, 10485760}},
|
||||||
{ "carControl", {"carControl", true, 100, 10}},
|
{ "gpsLocationExternal", {"gpsLocationExternal", true, 10.000000, 10, 256000}},
|
||||||
{ "carOutput", {"carOutput", true, 100, 10}},
|
{ "gpsLocation", {"gpsLocation", true, 1.000000, 1, 256000}},
|
||||||
{ "longitudinalPlan", {"longitudinalPlan", true, 20, 10}},
|
{ "ubloxGnss", {"ubloxGnss", true, 10.000000, -1, 256000}},
|
||||||
{ "driverAssistance", {"driverAssistance", true, 20, 20}},
|
{ "qcomGnss", {"qcomGnss", true, 2.000000, -1, 256000}},
|
||||||
{ "procLog", {"procLog", true, 0, 15}},
|
{ "clocks", {"clocks", true, 0.100000, 1, 256000}},
|
||||||
{ "gpsLocationExternal", {"gpsLocationExternal", true, 10, 10}},
|
{ "ubloxRaw", {"ubloxRaw", true, 20.000000, -1, 256000}},
|
||||||
{ "gpsLocation", {"gpsLocation", true, 1, 1}},
|
{ "livePose", {"livePose", true, 20.000000, 4, 256000}},
|
||||||
{ "ubloxGnss", {"ubloxGnss", true, 10, -1}},
|
{ "liveParameters", {"liveParameters", true, 20.000000, 5, 256000}},
|
||||||
{ "qcomGnss", {"qcomGnss", true, 2, -1}},
|
{ "cameraOdometry", {"cameraOdometry", true, 20.000000, 10, 256000}},
|
||||||
{ "gnssMeasurements", {"gnssMeasurements", true, 10, 10}},
|
{ "thumbnail", {"thumbnail", true, 0.016667, 1, 256000}},
|
||||||
{ "clocks", {"clocks", true, 0, 1}},
|
{ "onroadEvents", {"onroadEvents", true, 1.000000, 1, 256000}},
|
||||||
{ "ubloxRaw", {"ubloxRaw", true, 20, -1}},
|
{ "carParams", {"carParams", true, 0.020000, 1, 256000}},
|
||||||
{ "livePose", {"livePose", true, 20, 4}},
|
{ "roadCameraState", {"roadCameraState", true, 20.000000, 20, 256000}},
|
||||||
{ "liveParameters", {"liveParameters", true, 20, 5}},
|
{ "driverCameraState", {"driverCameraState", true, 20.000000, 20, 256000}},
|
||||||
{ "cameraOdometry", {"cameraOdometry", true, 20, 10}},
|
{ "driverEncodeIdx", {"driverEncodeIdx", false, 20.000000, 1, 256000}},
|
||||||
{ "thumbnail", {"thumbnail", true, 0, 1}},
|
{ "driverStateV2", {"driverStateV2", true, 20.000000, 10, 256000}},
|
||||||
{ "onroadEvents", {"onroadEvents", true, 1, 1}},
|
{ "driverMonitoringState", {"driverMonitoringState", true, 20.000000, 10, 256000}},
|
||||||
{ "carParams", {"carParams", true, 0, 1}},
|
{ "wideRoadEncodeIdx", {"wideRoadEncodeIdx", false, 20.000000, 1, 256000}},
|
||||||
{ "roadCameraState", {"roadCameraState", true, 20, 20}},
|
{ "wideRoadCameraState", {"wideRoadCameraState", true, 20.000000, 20, 256000}},
|
||||||
{ "driverCameraState", {"driverCameraState", true, 20, 20}},
|
{ "drivingModelData", {"drivingModelData", true, 20.000000, 10, 256000}},
|
||||||
{ "driverEncodeIdx", {"driverEncodeIdx", false, 20, 1}},
|
{ "modelV2", {"modelV2", true, 20.000000, -1, 10485760}},
|
||||||
{ "driverStateV2", {"driverStateV2", true, 20, 10}},
|
{ "managerState", {"managerState", true, 2.000000, 1, 256000}},
|
||||||
{ "driverMonitoringState", {"driverMonitoringState", true, 20, 10}},
|
{ "qRoadEncodeIdx", {"qRoadEncodeIdx", false, 20.000000, -1, 256000}},
|
||||||
{ "wideRoadEncodeIdx", {"wideRoadEncodeIdx", false, 20, 1}},
|
{ "userBookmark", {"userBookmark", true, 0.000000, 1, 256000}},
|
||||||
{ "wideRoadCameraState", {"wideRoadCameraState", true, 20, 20}},
|
{ "soundPressure", {"soundPressure", true, 10.000000, 10, 256000}},
|
||||||
{ "drivingModelData", {"drivingModelData", true, 20, 10}},
|
{ "rawAudioData", {"rawAudioData", false, 20.000000, -1, 256000}},
|
||||||
{ "modelV2", {"modelV2", true, 20, -1}},
|
{ "bookmarkButton", {"bookmarkButton", true, 0.000000, 1, 256000}},
|
||||||
{ "managerState", {"managerState", true, 2, 1}},
|
{ "audioFeedback", {"audioFeedback", true, 0.000000, 1, 256000}},
|
||||||
{ "uploaderState", {"uploaderState", true, 0, 1}},
|
{ "roadEncodeData", {"roadEncodeData", false, 20.000000, -1, 10485760}},
|
||||||
{ "navInstruction", {"navInstruction", true, 1, 10}},
|
{ "driverEncodeData", {"driverEncodeData", false, 20.000000, -1, 10485760}},
|
||||||
{ "navRoute", {"navRoute", true, 0, -1}},
|
{ "wideRoadEncodeData", {"wideRoadEncodeData", false, 20.000000, -1, 10485760}},
|
||||||
{ "navThumbnail", {"navThumbnail", true, 0, -1}},
|
{ "qRoadEncodeData", {"qRoadEncodeData", false, 20.000000, -1, 10485760}},
|
||||||
{ "qRoadEncodeIdx", {"qRoadEncodeIdx", false, 20, -1}},
|
{ "modelManagerSP", {"modelManagerSP", false, 1.000000, 1, 10485760}},
|
||||||
{ "userBookmark", {"userBookmark", true, 0, 1}},
|
{ "backupManagerSP", {"backupManagerSP", false, 1.000000, 1, 10485760}},
|
||||||
{ "soundPressure", {"soundPressure", true, 10, 10}},
|
{ "selfdriveStateSP", {"selfdriveStateSP", true, 100.000000, 10, 256000}},
|
||||||
{ "rawAudioData", {"rawAudioData", false, 20, -1}},
|
{ "longitudinalPlanSP", {"longitudinalPlanSP", true, 20.000000, 10, 256000}},
|
||||||
{ "bookmarkButton", {"bookmarkButton", true, 0, 1}},
|
{ "onroadEventsSP", {"onroadEventsSP", true, 1.000000, 1, 256000}},
|
||||||
{ "audioFeedback", {"audioFeedback", true, 0, 1}},
|
{ "carParamsSP", {"carParamsSP", true, 0.020000, 1, 256000}},
|
||||||
{ "uiDebug", {"uiDebug", true, 0, 1}},
|
{ "carControlSP", {"carControlSP", true, 100.000000, 10, 256000}},
|
||||||
{ "testJoystick", {"testJoystick", true, 0, -1}},
|
{ "carStateSP", {"carStateSP", true, 100.000000, 10, 256000}},
|
||||||
{ "alertDebug", {"alertDebug", true, 20, 5}},
|
{ "liveMapDataSP", {"liveMapDataSP", true, 1.000000, 1, 256000}},
|
||||||
{ "roadEncodeData", {"roadEncodeData", false, 20, -1}},
|
{ "modelDataV2SP", {"modelDataV2SP", true, 20.000000, -1, 10485760}},
|
||||||
{ "driverEncodeData", {"driverEncodeData", false, 20, -1}},
|
{ "liveLocationKalman", {"liveLocationKalman", true, 20.000000, -1, 256000}},
|
||||||
{ "wideRoadEncodeData", {"wideRoadEncodeData", false, 20, -1}},
|
{ "uiDebug", {"uiDebug", true, 0.000000, 1, 256000}},
|
||||||
{ "qRoadEncodeData", {"qRoadEncodeData", false, 20, -1}},
|
{ "testJoystick", {"testJoystick", true, 0.000000, -1, 256000}},
|
||||||
{ "livestreamWideRoadEncodeIdx", {"livestreamWideRoadEncodeIdx", false, 20, -1}},
|
{ "alertDebug", {"alertDebug", true, 20.000000, 5, 256000}},
|
||||||
{ "livestreamRoadEncodeIdx", {"livestreamRoadEncodeIdx", false, 20, -1}},
|
{ "livestreamWideRoadEncodeIdx", {"livestreamWideRoadEncodeIdx", false, 20.000000, -1, 256000}},
|
||||||
{ "livestreamDriverEncodeIdx", {"livestreamDriverEncodeIdx", false, 20, -1}},
|
{ "livestreamRoadEncodeIdx", {"livestreamRoadEncodeIdx", false, 20.000000, -1, 256000}},
|
||||||
{ "livestreamWideRoadEncodeData", {"livestreamWideRoadEncodeData", false, 20, -1}},
|
{ "livestreamDriverEncodeIdx", {"livestreamDriverEncodeIdx", false, 20.000000, -1, 256000}},
|
||||||
{ "livestreamRoadEncodeData", {"livestreamRoadEncodeData", false, 20, -1}},
|
{ "livestreamWideRoadEncodeData", {"livestreamWideRoadEncodeData", false, 20.000000, -1, 2097152}},
|
||||||
{ "livestreamDriverEncodeData", {"livestreamDriverEncodeData", false, 20, -1}},
|
{ "livestreamRoadEncodeData", {"livestreamRoadEncodeData", false, 20.000000, -1, 2097152}},
|
||||||
{ "customReservedRawData0", {"customReservedRawData0", true, 0, -1}},
|
{ "livestreamDriverEncodeData", {"livestreamDriverEncodeData", false, 20.000000, -1, 2097152}},
|
||||||
{ "customReservedRawData1", {"customReservedRawData1", true, 0, -1}},
|
{ "customReservedRawData0", {"customReservedRawData0", true, 0.000000, -1, 256000}},
|
||||||
{ "customReservedRawData2", {"customReservedRawData2", true, 0, -1}},
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+42
-31
@@ -1,39 +1,43 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
from enum import IntEnum
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: this should be automatically determined using the capnp schema
|
||||||
|
class QueueSize(IntEnum):
|
||||||
|
BIG = 10 * 1024 * 1024 # 10MB - video frames, large AI outputs
|
||||||
|
MEDIUM = 2 * 1024 * 1024 # 2MB - high freq (CAN), livestream
|
||||||
|
SMALL = 250 * 1024 # 250KB - most services
|
||||||
|
|
||||||
|
|
||||||
class Service:
|
class Service:
|
||||||
def __init__(self, should_log: bool, frequency: float, decimation: Optional[int] = None):
|
def __init__(self, should_log: bool, frequency: float, decimation: Optional[int] = None,
|
||||||
|
queue_size: QueueSize = QueueSize.SMALL):
|
||||||
self.should_log = should_log
|
self.should_log = should_log
|
||||||
self.frequency = frequency
|
self.frequency = frequency
|
||||||
self.decimation = decimation
|
self.decimation = decimation
|
||||||
|
self.queue_size = queue_size
|
||||||
|
|
||||||
|
|
||||||
_services: dict[str, tuple] = {
|
_services: dict[str, tuple] = {
|
||||||
# service: (should_log, frequency, qlog decimation (optional))
|
# service: (should_log, frequency, qlog decimation (optional))
|
||||||
# note: the "EncodeIdx" packets will still be in the log
|
# note: the "EncodeIdx" packets will still be in the log
|
||||||
"gyroscope": (True, 104., 104),
|
"gyroscope": (True, 104., 104),
|
||||||
"gyroscope2": (True, 100., 100),
|
|
||||||
"accelerometer": (True, 104., 104),
|
"accelerometer": (True, 104., 104),
|
||||||
"accelerometer2": (True, 100., 100),
|
|
||||||
"magnetometer": (True, 25.),
|
|
||||||
"lightSensor": (True, 100., 100),
|
|
||||||
"temperatureSensor": (True, 2., 200),
|
"temperatureSensor": (True, 2., 200),
|
||||||
"temperatureSensor2": (True, 2., 200),
|
|
||||||
"gpsNMEA": (True, 9.),
|
|
||||||
"deviceState": (True, 2., 1),
|
"deviceState": (True, 2., 1),
|
||||||
"touch": (True, 20., 1),
|
"touch": (True, 20., 1),
|
||||||
"can": (True, 100., 2053), # decimation gives ~3 msgs in a full segment
|
"can": (True, 100., 2053, QueueSize.BIG), # decimation gives ~3 msgs in a full segment
|
||||||
"controlsState": (True, 100., 10),
|
"controlsState": (True, 100., 10, QueueSize.MEDIUM),
|
||||||
"selfdriveState": (True, 100., 10),
|
"selfdriveState": (True, 100., 10),
|
||||||
"pandaStates": (True, 10., 1),
|
"pandaStates": (True, 10., 1),
|
||||||
"peripheralState": (True, 2., 1),
|
"peripheralState": (True, 2., 1),
|
||||||
"radarState": (True, 20., 5),
|
"radarState": (True, 20., 5),
|
||||||
"roadEncodeIdx": (False, 20., 1),
|
"roadEncodeIdx": (False, 20., 1),
|
||||||
"liveTracks": (True, 20.),
|
"liveTracks": (True, 20.),
|
||||||
"sendcan": (True, 100., 139),
|
"sendcan": (True, 100., 139, QueueSize.MEDIUM),
|
||||||
"logMessage": (True, 0.),
|
"logMessage": (True, 0., None, QueueSize.BIG),
|
||||||
"errorLogMessage": (True, 0., 1),
|
"errorLogMessage": (True, 0., 1, QueueSize.BIG),
|
||||||
"liveCalibration": (True, 4., 4),
|
"liveCalibration": (True, 4., 4),
|
||||||
"liveTorqueParameters": (True, 4., 1),
|
"liveTorqueParameters": (True, 4., 1),
|
||||||
"liveDelay": (True, 4., 1),
|
"liveDelay": (True, 4., 1),
|
||||||
@@ -42,13 +46,13 @@ _services: dict[str, tuple] = {
|
|||||||
"carControl": (True, 100., 10),
|
"carControl": (True, 100., 10),
|
||||||
"carOutput": (True, 100., 10),
|
"carOutput": (True, 100., 10),
|
||||||
"longitudinalPlan": (True, 20., 10),
|
"longitudinalPlan": (True, 20., 10),
|
||||||
|
"lateralManeuverPlan": (True, 20.),
|
||||||
"driverAssistance": (True, 20., 20),
|
"driverAssistance": (True, 20., 20),
|
||||||
"procLog": (True, 0.5, 15),
|
"procLog": (True, 0.5, 15, QueueSize.BIG),
|
||||||
"gpsLocationExternal": (True, 10., 10),
|
"gpsLocationExternal": (True, 10., 10),
|
||||||
"gpsLocation": (True, 1., 1),
|
"gpsLocation": (True, 1., 1),
|
||||||
"ubloxGnss": (True, 10.),
|
"ubloxGnss": (True, 10.),
|
||||||
"qcomGnss": (True, 2.),
|
"qcomGnss": (True, 2.),
|
||||||
"gnssMeasurements": (True, 10., 10),
|
|
||||||
"clocks": (True, 0.1, 1),
|
"clocks": (True, 0.1, 1),
|
||||||
"ubloxRaw": (True, 20.),
|
"ubloxRaw": (True, 20.),
|
||||||
"livePose": (True, 20., 4),
|
"livePose": (True, 20., 4),
|
||||||
@@ -65,36 +69,43 @@ _services: dict[str, tuple] = {
|
|||||||
"wideRoadEncodeIdx": (False, 20., 1),
|
"wideRoadEncodeIdx": (False, 20., 1),
|
||||||
"wideRoadCameraState": (True, 20., 20),
|
"wideRoadCameraState": (True, 20., 20),
|
||||||
"drivingModelData": (True, 20., 10),
|
"drivingModelData": (True, 20., 10),
|
||||||
"modelV2": (True, 20.),
|
"modelV2": (True, 20., None, QueueSize.BIG),
|
||||||
"managerState": (True, 2., 1),
|
"managerState": (True, 2., 1),
|
||||||
"uploaderState": (True, 0., 1),
|
|
||||||
"navInstruction": (True, 1., 10),
|
|
||||||
"navRoute": (True, 0.),
|
|
||||||
"navThumbnail": (True, 0.),
|
|
||||||
"qRoadEncodeIdx": (False, 20.),
|
"qRoadEncodeIdx": (False, 20.),
|
||||||
"userBookmark": (True, 0., 1),
|
"userBookmark": (True, 0., 1),
|
||||||
"soundPressure": (True, 10., 10),
|
"soundPressure": (True, 10., 10),
|
||||||
"rawAudioData": (False, 20.),
|
"rawAudioData": (False, 20.),
|
||||||
"bookmarkButton": (True, 0., 1),
|
"bookmarkButton": (True, 0., 1),
|
||||||
"audioFeedback": (True, 0., 1),
|
"audioFeedback": (True, 0., 1),
|
||||||
|
"roadEncodeData": (False, 20., None, QueueSize.BIG),
|
||||||
|
"driverEncodeData": (False, 20., None, QueueSize.BIG),
|
||||||
|
"wideRoadEncodeData": (False, 20., None, QueueSize.BIG),
|
||||||
|
"qRoadEncodeData": (False, 20., None, QueueSize.BIG),
|
||||||
|
|
||||||
|
# sunnypilot
|
||||||
|
"modelManagerSP": (False, 1., 1, QueueSize.BIG),
|
||||||
|
"backupManagerSP": (False, 1., 1, QueueSize.BIG),
|
||||||
|
"selfdriveStateSP": (True, 100., 10),
|
||||||
|
"longitudinalPlanSP": (True, 20., 10),
|
||||||
|
"onroadEventsSP": (True, 1., 1),
|
||||||
|
"carParamsSP": (True, 0.02, 1),
|
||||||
|
"carControlSP": (True, 100., 10),
|
||||||
|
"carStateSP": (True, 100., 10),
|
||||||
|
"liveMapDataSP": (True, 1., 1),
|
||||||
|
"modelDataV2SP": (True, 20., None, QueueSize.BIG),
|
||||||
|
"liveLocationKalman": (True, 20.),
|
||||||
|
|
||||||
# debug
|
# debug
|
||||||
"uiDebug": (True, 0., 1),
|
"uiDebug": (True, 0., 1),
|
||||||
"testJoystick": (True, 0.),
|
"testJoystick": (True, 0.),
|
||||||
"alertDebug": (True, 20., 5),
|
"alertDebug": (True, 20., 5),
|
||||||
"roadEncodeData": (False, 20.),
|
|
||||||
"driverEncodeData": (False, 20.),
|
|
||||||
"wideRoadEncodeData": (False, 20.),
|
|
||||||
"qRoadEncodeData": (False, 20.),
|
|
||||||
"livestreamWideRoadEncodeIdx": (False, 20.),
|
"livestreamWideRoadEncodeIdx": (False, 20.),
|
||||||
"livestreamRoadEncodeIdx": (False, 20.),
|
"livestreamRoadEncodeIdx": (False, 20.),
|
||||||
"livestreamDriverEncodeIdx": (False, 20.),
|
"livestreamDriverEncodeIdx": (False, 20.),
|
||||||
"livestreamWideRoadEncodeData": (False, 20.),
|
"livestreamWideRoadEncodeData": (False, 20., None, QueueSize.MEDIUM),
|
||||||
"livestreamRoadEncodeData": (False, 20.),
|
"livestreamRoadEncodeData": (False, 20., None, QueueSize.MEDIUM),
|
||||||
"livestreamDriverEncodeData": (False, 20.),
|
"livestreamDriverEncodeData": (False, 20., None, QueueSize.MEDIUM),
|
||||||
"customReservedRawData0": (True, 0.),
|
"customReservedRawData0": (True, 0.),
|
||||||
"customReservedRawData1": (True, 0.),
|
|
||||||
"customReservedRawData2": (True, 0.),
|
|
||||||
}
|
}
|
||||||
SERVICE_LIST = {name: Service(*vals) for
|
SERVICE_LIST = {name: Service(*vals) for
|
||||||
idx, (name, vals) in enumerate(_services.items())}
|
idx, (name, vals) in enumerate(_services.items())}
|
||||||
@@ -109,13 +120,13 @@ def build_header():
|
|||||||
h += "#include <map>\n"
|
h += "#include <map>\n"
|
||||||
h += "#include <string>\n"
|
h += "#include <string>\n"
|
||||||
|
|
||||||
h += "struct service { std::string name; bool should_log; int frequency; int decimation; };\n"
|
h += "struct service { std::string name; bool should_log; float frequency; int decimation; size_t queue_size; };\n"
|
||||||
h += "static std::map<std::string, service> services = {\n"
|
h += "static std::map<std::string, service> services = {\n"
|
||||||
for k, v in SERVICE_LIST.items():
|
for k, v in SERVICE_LIST.items():
|
||||||
should_log = "true" if v.should_log else "false"
|
should_log = "true" if v.should_log else "false"
|
||||||
decimation = -1 if v.decimation is None else v.decimation
|
decimation = -1 if v.decimation is None else v.decimation
|
||||||
h += ' { "%s", {"%s", %s, %d, %d}},\n' % \
|
h += ' { "%s", {"%s", %s, %f, %d, %d}},\n' % \
|
||||||
(k, k, should_log, v.frequency, decimation)
|
(k, k, should_log, v.frequency, decimation, v.queue_size)
|
||||||
h += "};\n"
|
h += "};\n"
|
||||||
|
|
||||||
h += "#endif\n"
|
h += "#endif\n"
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
*.cpp
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
Import('env', 'envCython', 'arch')
|
|
||||||
|
|
||||||
common_libs = [
|
|
||||||
'params.cc',
|
|
||||||
'swaglog.cc',
|
|
||||||
'util.cc',
|
|
||||||
'watchdog.cc',
|
|
||||||
'ratekeeper.cc'
|
|
||||||
]
|
|
||||||
|
|
||||||
_common = env.Library('common', common_libs, LIBS="json11")
|
|
||||||
|
|
||||||
files = [
|
|
||||||
'clutil.cc',
|
|
||||||
]
|
|
||||||
|
|
||||||
_gpucommon = env.Library('gpucommon', files)
|
|
||||||
Export('_common', '_gpucommon')
|
|
||||||
|
|
||||||
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')
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
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, 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)
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
from openpilot.common.api.comma_connect import CommaConnectApi
|
||||||
|
|
||||||
|
|
||||||
|
class Api:
|
||||||
|
def __init__(self, dongle_id):
|
||||||
|
self.service = CommaConnectApi(dongle_id)
|
||||||
|
|
||||||
|
def request(self, method, endpoint, **params):
|
||||||
|
return self.service.request(method, endpoint, **params)
|
||||||
|
|
||||||
|
def get(self, *args, **kwargs):
|
||||||
|
return self.service.get(*args, **kwargs)
|
||||||
|
|
||||||
|
def post(self, *args, **kwargs):
|
||||||
|
return self.service.post(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_token(self, payload_extra=None, expiry_hours=1):
|
||||||
|
return self.service.get_token(payload_extra, expiry_hours)
|
||||||
|
|
||||||
|
|
||||||
|
def api_get(endpoint, method='GET', timeout=None, access_token=None, session=None, **params):
|
||||||
|
return CommaConnectApi(None).api_get(endpoint, method, timeout, access_token, session, **params)
|
||||||
|
|
||||||
|
|
||||||
|
def get_key_pair() -> tuple[str, str, str] | tuple[None, None, None]:
|
||||||
|
return CommaConnectApi(None).get_key_pair()
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import jwt
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
import unicodedata
|
||||||
|
from datetime import datetime, timedelta, UTC
|
||||||
|
from openpilot.system.hardware.hw import Paths
|
||||||
|
from openpilot.system.version import get_version
|
||||||
|
|
||||||
|
# name: jwt signature algorithm
|
||||||
|
KEYS = {"id_rsa": "RS256",
|
||||||
|
"id_ecdsa": "ES256"}
|
||||||
|
|
||||||
|
|
||||||
|
class BaseApi:
|
||||||
|
def __init__(self, dongle_id, api_host, user_agent="openpilot-"):
|
||||||
|
self.dongle_id = dongle_id
|
||||||
|
self.api_host = api_host
|
||||||
|
self.user_agent = user_agent
|
||||||
|
self.jwt_algorithm, self.private_key, _ = self.get_key_pair()
|
||||||
|
|
||||||
|
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 self.api_get(endpoint, method=method, timeout=timeout, access_token=access_token, **params)
|
||||||
|
|
||||||
|
def _get_token(self, payload_extra=None, expiry_hours=1, **extra_payload):
|
||||||
|
now = datetime.now(UTC).replace(tzinfo=None)
|
||||||
|
payload = {
|
||||||
|
'identity': self.dongle_id,
|
||||||
|
'nbf': now,
|
||||||
|
'iat': now,
|
||||||
|
'exp': now + timedelta(hours=expiry_hours),
|
||||||
|
**extra_payload
|
||||||
|
}
|
||||||
|
if payload_extra is not None:
|
||||||
|
payload.update(payload_extra)
|
||||||
|
token = jwt.encode(payload, self.private_key, algorithm=self.jwt_algorithm)
|
||||||
|
if isinstance(token, bytes):
|
||||||
|
token = token.decode('utf8')
|
||||||
|
return token
|
||||||
|
|
||||||
|
def get_token(self, payload_extra=None, expiry_hours=1):
|
||||||
|
return self._get_token(payload_extra, expiry_hours)
|
||||||
|
|
||||||
|
def remove_non_ascii_chars(self, text):
|
||||||
|
normalized_text = unicodedata.normalize('NFD', text)
|
||||||
|
ascii_encoded_text = normalized_text.encode('ascii', 'ignore')
|
||||||
|
return ascii_encoded_text.decode()
|
||||||
|
|
||||||
|
def api_get(self, endpoint, method='GET', timeout=None, access_token=None, session=None, json=None, **params):
|
||||||
|
headers = {}
|
||||||
|
if access_token is not None:
|
||||||
|
headers['Authorization'] = "JWT " + access_token
|
||||||
|
|
||||||
|
version = self.remove_non_ascii_chars(get_version())
|
||||||
|
headers['User-Agent'] = self.user_agent + version
|
||||||
|
|
||||||
|
# TODO: add session to Api
|
||||||
|
req = requests if session is None else session
|
||||||
|
return req.request(method, f"{self.api_host}/{endpoint}", timeout=timeout, headers=headers, json=json, params=params)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_key_pair() -> tuple[str, str, str] | tuple[None, None, None]:
|
||||||
|
for key in KEYS:
|
||||||
|
if os.path.isfile(Paths.persist_root() + f'/comma/{key}') and os.path.isfile(Paths.persist_root() + f'/comma/{key}.pub'):
|
||||||
|
with open(Paths.persist_root() + f'/comma/{key}') as private, open(Paths.persist_root() + f'/comma/{key}.pub') as public:
|
||||||
|
return KEYS[key], private.read(), public.read()
|
||||||
|
return None, None, None
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from openpilot.common.api.base import BaseApi
|
||||||
|
|
||||||
|
API_HOST = os.getenv('API_HOST', 'https://api.commadotai.com')
|
||||||
|
|
||||||
|
|
||||||
|
class CommaConnectApi(BaseApi):
|
||||||
|
def __init__(self, dongle_id):
|
||||||
|
super().__init__(dongle_id, API_HOST)
|
||||||
|
self.user_agent = "openpilot-"
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
#include "common/clutil.h"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "common/util.h"
|
|
||||||
#include "common/swaglog.h"
|
|
||||||
|
|
||||||
namespace { // helper functions
|
|
||||||
|
|
||||||
template <typename Func, typename Id, typename Name>
|
|
||||||
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<cl_platform_id[]> platform_ids = std::make_unique<cl_platform_id[]>(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;
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include <OpenCL/cl.h>
|
|
||||||
#else
|
|
||||||
#include <CL/cl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#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);
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# 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
|
|
||||||
Executable
+55
@@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import sys
|
||||||
|
import math
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
CHUNK_SIZE = 45 * 1024 * 1024 # 45MB, under GitHub's 50MB limit
|
||||||
|
|
||||||
|
def get_chunk_name(name, idx, num_chunks):
|
||||||
|
return f"{name}.chunk{idx+1:02d}of{num_chunks:02d}"
|
||||||
|
|
||||||
|
def get_manifest_path(name):
|
||||||
|
return f"{name}.chunkmanifest"
|
||||||
|
|
||||||
|
def _chunk_paths(path, num_chunks):
|
||||||
|
return [get_manifest_path(path)] + [get_chunk_name(path, i, num_chunks) for i in range(num_chunks)]
|
||||||
|
|
||||||
|
def get_chunk_targets(path, file_size):
|
||||||
|
num_chunks = math.ceil(file_size / CHUNK_SIZE)
|
||||||
|
return _chunk_paths(path, num_chunks)
|
||||||
|
|
||||||
|
def chunk_file(path, targets):
|
||||||
|
manifest_path, *chunk_paths = targets
|
||||||
|
with open(path, 'rb') as f:
|
||||||
|
data = f.read()
|
||||||
|
actual_num_chunks = max(1, math.ceil(len(data) / CHUNK_SIZE))
|
||||||
|
assert len(chunk_paths) >= actual_num_chunks, f"Allowed {len(chunk_paths)} chunks but needs at least {actual_num_chunks}, for path {path}"
|
||||||
|
for i, chunk_path in enumerate(chunk_paths):
|
||||||
|
with open(chunk_path, 'wb') as f:
|
||||||
|
f.write(data[i * CHUNK_SIZE:(i + 1) * CHUNK_SIZE])
|
||||||
|
Path(manifest_path).write_text(str(len(chunk_paths)))
|
||||||
|
os.remove(path)
|
||||||
|
|
||||||
|
def get_existing_chunks(path):
|
||||||
|
if os.path.isfile(path):
|
||||||
|
return [path]
|
||||||
|
if os.path.isfile(manifest := get_manifest_path(path)):
|
||||||
|
num_chunks = int(Path(manifest).read_text().strip())
|
||||||
|
return _chunk_paths(path, num_chunks)
|
||||||
|
raise FileNotFoundError(path)
|
||||||
|
|
||||||
|
def read_file_chunked(path):
|
||||||
|
manifest_path = get_manifest_path(path)
|
||||||
|
if os.path.isfile(manifest_path):
|
||||||
|
num_chunks = int(Path(manifest_path).read_text().strip())
|
||||||
|
return b''.join(Path(get_chunk_name(path, i, num_chunks)).read_bytes() for i in range(num_chunks))
|
||||||
|
if os.path.isfile(path):
|
||||||
|
return Path(path).read_bytes()
|
||||||
|
raise FileNotFoundError(path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
path = sys.argv[1]
|
||||||
|
chunk_paths = get_chunk_targets(path, os.path.getsize(path))
|
||||||
|
chunk_file(path, chunk_paths)
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -15,3 +15,20 @@ class FirstOrderFilter:
|
|||||||
self.initialized = True
|
self.initialized = True
|
||||||
self.x = x
|
self.x = x
|
||||||
return self.x
|
return self.x
|
||||||
|
|
||||||
|
|
||||||
|
class BounceFilter(FirstOrderFilter):
|
||||||
|
def __init__(self, x0, rc, dt, initialized=True, bounce=2):
|
||||||
|
self.velocity = FirstOrderFilter(0.0, 0.15, dt)
|
||||||
|
self.bounce = bounce
|
||||||
|
super().__init__(x0, rc, dt, initialized)
|
||||||
|
|
||||||
|
def update(self, x):
|
||||||
|
super().update(x)
|
||||||
|
scale = self.dt / (1.0 / 60.0) # tuned at 60 fps
|
||||||
|
self.velocity.x += (x - self.x) * self.bounce * scale * self.dt
|
||||||
|
self.velocity.update(0.0)
|
||||||
|
if abs(self.velocity.x) < 1e-3:
|
||||||
|
self.velocity.x = 0.0
|
||||||
|
self.x += self.velocity.x
|
||||||
|
return self.x
|
||||||
|
|||||||
+7
-7
@@ -1,30 +1,30 @@
|
|||||||
from functools import cache
|
from functools import cache
|
||||||
import subprocess
|
import subprocess
|
||||||
from openpilot.common.run import run_cmd, run_cmd_default
|
from openpilot.common.utils import run_cmd, run_cmd_default
|
||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_commit(cwd: str = None, branch: str = "HEAD") -> str:
|
def get_commit(cwd: str | None = None, branch: str = "HEAD") -> str:
|
||||||
return run_cmd_default(["git", "rev-parse", branch], cwd=cwd)
|
return run_cmd_default(["git", "rev-parse", branch], cwd=cwd)
|
||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_commit_date(cwd: str = None, commit: str = "HEAD") -> str:
|
def get_commit_date(cwd: str | None = None, commit: str = "HEAD") -> str:
|
||||||
return run_cmd_default(["git", "show", "--no-patch", "--format='%ct %ci'", commit], cwd=cwd)
|
return run_cmd_default(["git", "show", "--no-patch", "--format='%ct %ci'", commit], cwd=cwd)
|
||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_short_branch(cwd: str = None) -> str:
|
def get_short_branch(cwd: str | None = None) -> str:
|
||||||
return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=cwd)
|
return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=cwd)
|
||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_branch(cwd: str = None) -> str:
|
def get_branch(cwd: str | None = None) -> str:
|
||||||
return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], cwd=cwd)
|
return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], cwd=cwd)
|
||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_origin(cwd: str = None) -> str:
|
def get_origin(cwd: str | None = None) -> str:
|
||||||
try:
|
try:
|
||||||
local_branch = run_cmd(["git", "name-rev", "--name-only", "HEAD"], cwd=cwd)
|
local_branch = run_cmd(["git", "name-rev", "--name-only", "HEAD"], cwd=cwd)
|
||||||
tracking_remote = run_cmd(["git", "config", "branch." + local_branch + ".remote"], cwd=cwd)
|
tracking_remote = run_cmd(["git", "config", "branch." + local_branch + ".remote"], cwd=cwd)
|
||||||
@@ -34,7 +34,7 @@ def get_origin(cwd: str = None) -> str:
|
|||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def get_normalized_origin(cwd: str = None) -> str:
|
def get_normalized_origin(cwd: str | None = None) -> str:
|
||||||
return get_origin(cwd) \
|
return get_origin(cwd) \
|
||||||
.replace("git@", "", 1) \
|
.replace("git@", "", 1) \
|
||||||
.replace(".git", "", 1) \
|
.replace(".git", "", 1) \
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import os
|
||||||
|
import fcntl
|
||||||
|
import ctypes
|
||||||
|
|
||||||
|
# I2C constants from /usr/include/linux/i2c-dev.h
|
||||||
|
I2C_SLAVE = 0x0703
|
||||||
|
I2C_SLAVE_FORCE = 0x0706
|
||||||
|
I2C_SMBUS = 0x0720
|
||||||
|
|
||||||
|
# SMBus transfer types
|
||||||
|
I2C_SMBUS_READ = 1
|
||||||
|
I2C_SMBUS_WRITE = 0
|
||||||
|
I2C_SMBUS_BYTE_DATA = 2
|
||||||
|
I2C_SMBUS_I2C_BLOCK_DATA = 8
|
||||||
|
|
||||||
|
I2C_SMBUS_BLOCK_MAX = 32
|
||||||
|
|
||||||
|
|
||||||
|
class _I2cSmbusData(ctypes.Union):
|
||||||
|
_fields_ = [
|
||||||
|
("byte", ctypes.c_uint8),
|
||||||
|
("word", ctypes.c_uint16),
|
||||||
|
("block", ctypes.c_uint8 * (I2C_SMBUS_BLOCK_MAX + 2)),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class _I2cSmbusIoctlData(ctypes.Structure):
|
||||||
|
_fields_ = [
|
||||||
|
("read_write", ctypes.c_uint8),
|
||||||
|
("command", ctypes.c_uint8),
|
||||||
|
("size", ctypes.c_uint32),
|
||||||
|
("data", ctypes.POINTER(_I2cSmbusData)),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class SMBus:
|
||||||
|
def __init__(self, bus: int):
|
||||||
|
self._fd = os.open(f'/dev/i2c-{bus}', os.O_RDWR)
|
||||||
|
|
||||||
|
def __enter__(self) -> 'SMBus':
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, *args) -> None:
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
def close(self) -> None:
|
||||||
|
if hasattr(self, '_fd') and self._fd >= 0:
|
||||||
|
os.close(self._fd)
|
||||||
|
self._fd = -1
|
||||||
|
|
||||||
|
def _set_address(self, addr: int, force: bool = False) -> None:
|
||||||
|
ioctl_arg = I2C_SLAVE_FORCE if force else I2C_SLAVE
|
||||||
|
fcntl.ioctl(self._fd, ioctl_arg, addr)
|
||||||
|
|
||||||
|
def _smbus_access(self, read_write: int, command: int, size: int, data: _I2cSmbusData) -> None:
|
||||||
|
ioctl_data = _I2cSmbusIoctlData(read_write, command, size, ctypes.pointer(data))
|
||||||
|
fcntl.ioctl(self._fd, I2C_SMBUS, ioctl_data)
|
||||||
|
|
||||||
|
def read_byte_data(self, addr: int, register: int, force: bool = False) -> int:
|
||||||
|
self._set_address(addr, force)
|
||||||
|
data = _I2cSmbusData()
|
||||||
|
self._smbus_access(I2C_SMBUS_READ, register, I2C_SMBUS_BYTE_DATA, data)
|
||||||
|
return int(data.byte)
|
||||||
|
|
||||||
|
def write_byte_data(self, addr: int, register: int, value: int, force: bool = False) -> None:
|
||||||
|
self._set_address(addr, force)
|
||||||
|
data = _I2cSmbusData()
|
||||||
|
data.byte = value & 0xFF
|
||||||
|
self._smbus_access(I2C_SMBUS_WRITE, register, I2C_SMBUS_BYTE_DATA, data)
|
||||||
|
|
||||||
|
def read_i2c_block_data(self, addr: int, register: int, length: int, force: bool = False) -> list[int]:
|
||||||
|
self._set_address(addr, force)
|
||||||
|
if not (0 <= length <= I2C_SMBUS_BLOCK_MAX):
|
||||||
|
raise ValueError(f"length must be 0..{I2C_SMBUS_BLOCK_MAX}")
|
||||||
|
|
||||||
|
data = _I2cSmbusData()
|
||||||
|
data.block[0] = length
|
||||||
|
self._smbus_access(I2C_SMBUS_READ, register, I2C_SMBUS_I2C_BLOCK_DATA, data)
|
||||||
|
read_len = int(data.block[0]) or length
|
||||||
|
read_len = min(read_len, length)
|
||||||
|
return [int(b) for b in data.block[1 : read_len + 1]]
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
#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));
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import pytest
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
|
||||||
|
def _to_safe_name(s):
|
||||||
|
return re.sub(r"[^a-zA-Z0-9_]+", "_", str(s)).strip("_")
|
||||||
|
|
||||||
|
|
||||||
|
class parameterized:
|
||||||
|
@staticmethod
|
||||||
|
def expand(cases):
|
||||||
|
cases = list(cases)
|
||||||
|
|
||||||
|
if not cases:
|
||||||
|
return lambda func: pytest.mark.skip("no parameterized cases")(func)
|
||||||
|
|
||||||
|
def decorator(func):
|
||||||
|
params = [p for p in inspect.signature(func).parameters if p != 'self']
|
||||||
|
normalized = [c if isinstance(c, tuple) else (c,) for c in cases]
|
||||||
|
# Infer arg count from first case so extra params (e.g. from @given) are left untouched
|
||||||
|
expand_params = params[: len(normalized[0])]
|
||||||
|
if len(expand_params) == 1:
|
||||||
|
return pytest.mark.parametrize(expand_params[0], [c[0] for c in normalized])(func)
|
||||||
|
return pytest.mark.parametrize(', '.join(expand_params), normalized)(func)
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def parameterized_class(attrs, input_list=None):
|
||||||
|
if isinstance(attrs, list) and (not attrs or isinstance(attrs[0], dict)):
|
||||||
|
params_list = attrs
|
||||||
|
else:
|
||||||
|
assert input_list is not None
|
||||||
|
attr_names = (attrs,) if isinstance(attrs, str) else tuple(attrs)
|
||||||
|
params_list = [dict(zip(attr_names, v if isinstance(v, (tuple, list)) else (v,), strict=False)) for v in input_list]
|
||||||
|
|
||||||
|
def decorator(cls):
|
||||||
|
globs = sys._getframe(1).f_globals
|
||||||
|
for i, params in enumerate(params_list):
|
||||||
|
# append sanitized string param values so pytest -k can filter by them
|
||||||
|
suffix = "_".join(filter(None, (_to_safe_name(v) for v in params.values() if isinstance(v, str))))
|
||||||
|
name = f"{cls.__name__}_{i}" + (f"_{suffix}" if suffix else "")
|
||||||
|
new_cls = type(name, (cls,), dict(params))
|
||||||
|
new_cls.__module__ = cls.__module__
|
||||||
|
new_cls.__test__ = True # override inherited False so pytest collects this subclass
|
||||||
|
globs[name] = new_cls
|
||||||
|
# Don't collect the un-parametrised base, but return it so outer decorators
|
||||||
|
# (e.g. @pytest.mark.skip) land on it and propagate to subclasses via MRO.
|
||||||
|
cls.__test__ = False
|
||||||
|
return cls
|
||||||
|
|
||||||
|
return decorator
|
||||||
+4
-2
@@ -103,10 +103,12 @@ Params::~Params() {
|
|||||||
assert(queue.empty());
|
assert(queue.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Params::allKeys() const {
|
std::vector<std::string> Params::allKeys(ParamKeyFlag flag) const {
|
||||||
std::vector<std::string> ret;
|
std::vector<std::string> ret;
|
||||||
for (auto &p : keys) {
|
for (auto &p : keys) {
|
||||||
ret.push_back(p.first);
|
if (flag == ALL || (p.second.flags & flag)) {
|
||||||
|
ret.push_back(p.first);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -18,6 +18,7 @@ enum ParamKeyFlag {
|
|||||||
DONT_LOG = 0x20,
|
DONT_LOG = 0x20,
|
||||||
DEVELOPMENT_ONLY = 0x40,
|
DEVELOPMENT_ONLY = 0x40,
|
||||||
CLEAR_ON_IGNITION_ON = 0x80,
|
CLEAR_ON_IGNITION_ON = 0x80,
|
||||||
|
BACKUP = 0x100,
|
||||||
ALL = 0xFFFFFFFF
|
ALL = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@ public:
|
|||||||
Params(const Params&) = delete;
|
Params(const Params&) = delete;
|
||||||
Params& operator=(const Params&) = delete;
|
Params& operator=(const Params&) = delete;
|
||||||
|
|
||||||
std::vector<std::string> allKeys() const;
|
std::vector<std::string> allKeys(ParamKeyFlag flag = ALL) const;
|
||||||
bool checkKey(const std::string &key);
|
bool checkKey(const std::string &key);
|
||||||
ParamKeyFlag getKeyFlag(const std::string &key);
|
ParamKeyFlag getKeyFlag(const std::string &key);
|
||||||
ParamKeyType getKeyType(const std::string &key);
|
ParamKeyType getKeyType(const std::string &key);
|
||||||
|
|||||||
+1
-1
@@ -14,6 +14,6 @@ if __name__ == "__main__":
|
|||||||
if len(sys.argv) == 3:
|
if len(sys.argv) == 3:
|
||||||
val = sys.argv[2]
|
val = sys.argv[2]
|
||||||
print(f"SET: {key} = {val}")
|
print(f"SET: {key} = {val}")
|
||||||
params.put(key, val)
|
params.put(key, val, block=True)
|
||||||
elif len(sys.argv) == 2:
|
elif len(sys.argv) == 2:
|
||||||
print(f"GET: {key} = {params.get(key)}")
|
print(f"GET: {key} = {params.get(key)}")
|
||||||
|
|||||||
+177
-28
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||||
{"AccessToken", {CLEAR_ON_MANAGER_START | DONT_LOG, STRING}},
|
{"AccessToken", {CLEAR_ON_MANAGER_START | DONT_LOG, STRING}},
|
||||||
{"AdbEnabled", {PERSISTENT, BOOL}},
|
{"AdbEnabled", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"AlwaysOnDM", {PERSISTENT, BOOL}},
|
{"AlwaysOnDM", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"ApiCache_Device", {PERSISTENT, STRING}},
|
{"ApiCache_Device", {PERSISTENT, STRING}},
|
||||||
{"ApiCache_FirehoseStats", {PERSISTENT, JSON}},
|
{"ApiCache_FirehoseStats", {PERSISTENT, JSON}},
|
||||||
{"AssistNowToken", {PERSISTENT, STRING}},
|
{"AssistNowToken", {PERSISTENT, STRING}},
|
||||||
@@ -29,36 +29,36 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"CurrentBootlog", {PERSISTENT, STRING}},
|
{"CurrentBootlog", {PERSISTENT, STRING}},
|
||||||
{"CurrentRoute", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, STRING}},
|
{"CurrentRoute", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, STRING}},
|
||||||
{"DisableLogging", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
{"DisableLogging", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
{"DisablePowerDown", {PERSISTENT, BOOL}},
|
{"DisablePowerDown", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"DisableUpdates", {PERSISTENT, BOOL}},
|
{"DisableUpdates", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"DisengageOnAccelerator", {PERSISTENT, BOOL, "0"}},
|
{"DisengageOnAccelerator", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"DongleId", {PERSISTENT, STRING}},
|
{"DongleId", {PERSISTENT, STRING}},
|
||||||
{"DoReboot", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"DoReboot", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"DoShutdown", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"DoShutdown", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"DoUninstall", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"DoUninstall", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"DriverTooDistracted", {CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON, BOOL}},
|
{"DriverTooDistracted", {CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON, BOOL}},
|
||||||
{"AlphaLongitudinalEnabled", {PERSISTENT | DEVELOPMENT_ONLY, BOOL}},
|
{"AlphaLongitudinalEnabled", {PERSISTENT | DEVELOPMENT_ONLY | BACKUP, BOOL}},
|
||||||
{"ExperimentalMode", {PERSISTENT, BOOL}},
|
{"ExperimentalMode", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"ExperimentalModeConfirmed", {PERSISTENT, BOOL}},
|
{"ExperimentalModeConfirmed", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"FirmwareQueryDone", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
{"FirmwareQueryDone", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
{"ForcePowerDown", {PERSISTENT, BOOL}},
|
{"ForcePowerDown", {PERSISTENT, BOOL}},
|
||||||
{"GitBranch", {PERSISTENT, STRING}},
|
{"GitBranch", {PERSISTENT, STRING}},
|
||||||
{"GitCommit", {PERSISTENT, STRING}},
|
{"GitCommit", {PERSISTENT, STRING}},
|
||||||
{"GitCommitDate", {PERSISTENT, STRING}},
|
{"GitCommitDate", {PERSISTENT, STRING}},
|
||||||
{"GitDiff", {PERSISTENT, STRING}},
|
{"GitDiff", {PERSISTENT, STRING}},
|
||||||
{"GithubSshKeys", {PERSISTENT, STRING}},
|
{"GithubSshKeys", {PERSISTENT | BACKUP, STRING}},
|
||||||
{"GithubUsername", {PERSISTENT, STRING}},
|
{"GithubUsername", {PERSISTENT | BACKUP, STRING}},
|
||||||
{"GitRemote", {PERSISTENT, STRING}},
|
{"GitRemote", {PERSISTENT, STRING}},
|
||||||
{"GsmApn", {PERSISTENT, STRING}},
|
{"GsmApn", {PERSISTENT | BACKUP, STRING}},
|
||||||
{"GsmMetered", {PERSISTENT, BOOL, "1"}},
|
{"GsmMetered", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"GsmRoaming", {PERSISTENT, BOOL}},
|
{"GsmRoaming", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"HardwareSerial", {PERSISTENT, STRING}},
|
{"HardwareSerial", {PERSISTENT, STRING}},
|
||||||
{"HasAcceptedTerms", {PERSISTENT, STRING, "0"}},
|
{"HasAcceptedTerms", {PERSISTENT, STRING, "0"}},
|
||||||
{"InstallDate", {PERSISTENT, TIME}},
|
{"InstallDate", {PERSISTENT, TIME}},
|
||||||
{"IsDriverViewEnabled", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"IsDriverViewEnabled", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"IsEngaged", {PERSISTENT, BOOL}},
|
{"IsEngaged", {PERSISTENT, BOOL}},
|
||||||
{"IsLdwEnabled", {PERSISTENT, BOOL}},
|
{"IsLdwEnabled", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"IsMetric", {PERSISTENT, BOOL}},
|
{"IsMetric", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"IsOffroad", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"IsOffroad", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"IsOnroad", {PERSISTENT, BOOL}},
|
{"IsOnroad", {PERSISTENT, BOOL}},
|
||||||
{"IsRhdDetected", {PERSISTENT, BOOL}},
|
{"IsRhdDetected", {PERSISTENT, BOOL}},
|
||||||
@@ -66,24 +66,27 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"IsTakingSnapshot", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"IsTakingSnapshot", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"IsTestedBranch", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"IsTestedBranch", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"JoystickDebugMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
{"JoystickDebugMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"LanguageSetting", {PERSISTENT, STRING, "main_en"}},
|
{"LanguageSetting", {PERSISTENT | BACKUP, STRING, "en"}},
|
||||||
{"LastAthenaPingTime", {CLEAR_ON_MANAGER_START, INT}},
|
{"LastAthenaPingTime", {CLEAR_ON_MANAGER_START, INT}},
|
||||||
{"LastGPSPosition", {PERSISTENT, STRING}},
|
{"LastGPSPosition", {PERSISTENT, STRING}},
|
||||||
{"LastManagerExitReason", {CLEAR_ON_MANAGER_START, STRING}},
|
{"LastManagerExitReason", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"LastOffroadStatusPacket", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, JSON}},
|
{"LastOffroadStatusPacket", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, JSON}},
|
||||||
|
{"LastAgnosPowerMonitorShutdown", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"LastPowerDropDetected", {CLEAR_ON_MANAGER_START, STRING}},
|
{"LastPowerDropDetected", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"LastUpdateException", {CLEAR_ON_MANAGER_START, STRING}},
|
{"LastUpdateException", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"LastUpdateRouteCount", {PERSISTENT, INT, "0"}},
|
{"LastUpdateRouteCount", {PERSISTENT, INT, "0"}},
|
||||||
{"LastUpdateTime", {PERSISTENT, TIME}},
|
{"LastUpdateTime", {PERSISTENT, TIME}},
|
||||||
{"LastUpdateUptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
|
{"LastUpdateUptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
|
||||||
{"LiveDelay", {PERSISTENT, BYTES}},
|
{"LiveDelay", {PERSISTENT | BACKUP, BYTES}},
|
||||||
{"LiveParameters", {PERSISTENT, JSON}},
|
{"LiveParameters", {PERSISTENT, JSON}},
|
||||||
{"LiveParametersV2", {PERSISTENT, BYTES}},
|
{"LiveParametersV2", {PERSISTENT, BYTES}},
|
||||||
|
{"LivestreamEncoderBitrate", {CLEAR_ON_MANAGER_START | DONT_LOG, INT}},
|
||||||
{"LiveTorqueParameters", {PERSISTENT | DONT_LOG, BYTES}},
|
{"LiveTorqueParameters", {PERSISTENT | DONT_LOG, BYTES}},
|
||||||
{"LocationFilterInitialState", {PERSISTENT, BYTES}},
|
{"LocationFilterInitialState", {PERSISTENT, BYTES}},
|
||||||
|
{"LateralManeuverMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"LongitudinalManeuverMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
{"LongitudinalManeuverMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"LongitudinalPersonality", {PERSISTENT, INT, std::to_string(static_cast<int>(cereal::LongitudinalPersonality::STANDARD))}},
|
{"LongitudinalPersonality", {PERSISTENT | BACKUP, INT, std::to_string(static_cast<int>(cereal::LongitudinalPersonality::STANDARD))}},
|
||||||
{"NetworkMetered", {PERSISTENT, BOOL}},
|
{"NetworkMetered", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"ObdMultiplexingChanged", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
{"ObdMultiplexingChanged", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
{"ObdMultiplexingEnabled", {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_CarUnrecognized", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
@@ -94,25 +97,25 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"Offroad_NeosUpdate", {CLEAR_ON_MANAGER_START, JSON}},
|
{"Offroad_NeosUpdate", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"Offroad_NoFirmware", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
{"Offroad_NoFirmware", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
{"Offroad_Recalibration", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
{"Offroad_Recalibration", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
{"Offroad_StorageMissing", {CLEAR_ON_MANAGER_START, JSON}},
|
|
||||||
{"Offroad_TemperatureTooHigh", {CLEAR_ON_MANAGER_START, JSON}},
|
{"Offroad_TemperatureTooHigh", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"Offroad_UnregisteredHardware", {CLEAR_ON_MANAGER_START, JSON}},
|
{"Offroad_UnregisteredHardware", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"Offroad_UpdateFailed", {CLEAR_ON_MANAGER_START, JSON}},
|
{"Offroad_UpdateFailed", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
|
{"Offroad_DriverMonitoringUncertain", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
{"OnroadCycleRequested", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"OnroadCycleRequested", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"OpenpilotEnabledToggle", {PERSISTENT, BOOL, "1"}},
|
{"OpenpilotEnabledToggle", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"PandaHeartbeatLost", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
{"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}},
|
{"PrimeType", {PERSISTENT, INT}},
|
||||||
{"RecordAudio", {PERSISTENT, BOOL}},
|
{"RecordAudio", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"RecordAudioFeedback", {PERSISTENT, BOOL, "0"}},
|
{"RecordAudioFeedback", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"RecordFront", {PERSISTENT, BOOL}},
|
{"RecordFront", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"RecordFrontLock", {PERSISTENT, BOOL}}, // for the internal fleet
|
{"RecordFrontLock", {PERSISTENT, BOOL}}, // for the internal fleet
|
||||||
{"SecOCKey", {PERSISTENT | DONT_LOG, STRING}},
|
{"SecOCKey", {PERSISTENT | DONT_LOG | BACKUP, STRING}},
|
||||||
|
{"ShowDebugInfo", {PERSISTENT, BOOL}},
|
||||||
{"RouteCount", {PERSISTENT, INT, "0"}},
|
{"RouteCount", {PERSISTENT, INT, "0"}},
|
||||||
{"SnoozeUpdate", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
{"SnoozeUpdate", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"SshEnabled", {PERSISTENT, BOOL}},
|
{"SshEnabled", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"TermsVersion", {PERSISTENT, STRING}},
|
{"TermsVersion", {PERSISTENT, STRING}},
|
||||||
|
{"TorqueBar", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"TrainingVersion", {PERSISTENT, STRING}},
|
{"TrainingVersion", {PERSISTENT, STRING}},
|
||||||
{"UbloxAvailable", {PERSISTENT, BOOL}},
|
{"UbloxAvailable", {PERSISTENT, BOOL}},
|
||||||
{"UpdateAvailable", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
{"UpdateAvailable", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
@@ -128,5 +131,151 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"UpdaterLastFetchTime", {PERSISTENT, TIME}},
|
{"UpdaterLastFetchTime", {PERSISTENT, TIME}},
|
||||||
{"UptimeOffroad", {PERSISTENT, FLOAT, "0.0"}},
|
{"UptimeOffroad", {PERSISTENT, FLOAT, "0.0"}},
|
||||||
{"UptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
|
{"UptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
|
||||||
|
{"UsbGpuPresent", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
|
{"UsbGpuCompiled", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"Version", {PERSISTENT, STRING}},
|
{"Version", {PERSISTENT, STRING}},
|
||||||
|
|
||||||
|
// --- sunnypilot params --- //
|
||||||
|
{"ApiCache_DriveStats", {PERSISTENT, JSON}},
|
||||||
|
{"AutoLaneChangeBsmDelay", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"AutoLaneChangeTimer", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"BlinkerLateralReengageDelay", {PERSISTENT | BACKUP, INT, "0"}}, // seconds
|
||||||
|
{"BlinkerMinLateralControlSpeed", {PERSISTENT | BACKUP, INT, "20"}}, // MPH or km/h
|
||||||
|
{"BlinkerPauseLateralControl", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"Brightness", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"CarList", {PERSISTENT, JSON}},
|
||||||
|
{"CarParamsSP", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BYTES}},
|
||||||
|
{"CarParamsSPCache", {CLEAR_ON_MANAGER_START, BYTES}},
|
||||||
|
{"CarParamsSPPersistent", {PERSISTENT, BYTES}},
|
||||||
|
{"CarPlatformBundle", {PERSISTENT | BACKUP, JSON}},
|
||||||
|
{"ChevronInfo", {PERSISTENT | BACKUP, INT, "4"}},
|
||||||
|
{"CompletedSunnylinkConsentVersion", {PERSISTENT, STRING, "0"}},
|
||||||
|
{"CustomAccIncrementsEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"CustomAccLongPressIncrement", {PERSISTENT | BACKUP, INT, "5"}},
|
||||||
|
{"CustomAccShortPressIncrement", {PERSISTENT | BACKUP, INT, "1"}},
|
||||||
|
{"DeviceBootMode", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"DevUIInfo", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"EnableCopyparty", {PERSISTENT | BACKUP, BOOL}},
|
||||||
|
{"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}},
|
||||||
|
{"GreenLightAlert", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}},
|
||||||
|
{"HasAcceptedTermsSP", {PERSISTENT, STRING, "0"}},
|
||||||
|
{"HideVEgoUI", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"IntelligentCruiseButtonManagement", {PERSISTENT | BACKUP , BOOL}},
|
||||||
|
{"InteractivityTimeout", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"IsDevelopmentBranch", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
|
{"IsReleaseSpBranch", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
|
{"LastGPSPositionLLK", {PERSISTENT, STRING}},
|
||||||
|
{"LeadDepartAlert", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"MaxTimeOffroad", {PERSISTENT | BACKUP, INT, "1800"}},
|
||||||
|
{"ModelRunnerTypeCache", {CLEAR_ON_ONROAD_TRANSITION, INT}},
|
||||||
|
{"OffroadMode", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
|
{"Offroad_TiciSupport", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
|
{"OnroadScreenOffBrightness", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"OnroadScreenOffBrightnessMigrated", {PERSISTENT | BACKUP, STRING, "0.0"}},
|
||||||
|
{"OnroadScreenOffTimer", {PERSISTENT | BACKUP, INT, "15"}},
|
||||||
|
{"OnroadScreenOffTimerMigrated", {PERSISTENT | BACKUP, STRING, "0.0"}},
|
||||||
|
{"OnroadUploads", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
|
{"QuickBootToggle", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"RocketFuel", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"ShowAdvancedControls", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"ShowTurnSignals", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"TrueVEgoUI", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
|
// MADS params
|
||||||
|
{"Mads", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
|
{"MadsMainCruiseAllowed", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
|
{"MadsSteeringMode", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"MadsUnifiedEngagementMode", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
|
|
||||||
|
// Model Manager params
|
||||||
|
{"ModelManager_ActiveBundle", {PERSISTENT, JSON}},
|
||||||
|
{"ModelManager_ClearCache", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
|
{"ModelManager_DownloadIndex", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, INT}},
|
||||||
|
{"ModelManager_Favs", {PERSISTENT | BACKUP, STRING}},
|
||||||
|
{"ModelManager_LastSyncTime", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, INT, "0"}},
|
||||||
|
{"ModelManager_ModelsCache", {PERSISTENT | BACKUP, JSON}},
|
||||||
|
|
||||||
|
// Neural Network Lateral Control
|
||||||
|
{"NeuralNetworkLateralControl", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
|
// sunnylink params
|
||||||
|
{"EnableSunnylinkUploader", {PERSISTENT | BACKUP, BOOL}},
|
||||||
|
{"LastSunnylinkPingTime", {CLEAR_ON_MANAGER_START, INT}},
|
||||||
|
{"ParamsVersion", {PERSISTENT, INT}},
|
||||||
|
{"SunnylinkCache_Roles", {PERSISTENT, STRING}},
|
||||||
|
{"SunnylinkCache_Users", {PERSISTENT, STRING}},
|
||||||
|
{"SunnylinkDongleId", {PERSISTENT, STRING}},
|
||||||
|
{"SunnylinkdPid", {PERSISTENT, INT}},
|
||||||
|
{"SunnylinkEnabled", {PERSISTENT, BOOL, "1"}},
|
||||||
|
{"SunnylinkTempFault", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL, "0"}},
|
||||||
|
|
||||||
|
// Backup Manager params
|
||||||
|
{"BackupManager_CreateBackup", {PERSISTENT, BOOL}},
|
||||||
|
{"BackupManager_RestoreVersion", {PERSISTENT, STRING}},
|
||||||
|
|
||||||
|
// sunnypilot car specific params
|
||||||
|
{"HyundaiLongitudinalTuning", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"SubaruStopAndGo", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"SubaruStopAndGoManualParkingBrake", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"TeslaCoopSteering", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"ToyotaEnforceStockLongitudinal", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"ToyotaStopAndGoHack", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
|
{"DynamicExperimentalControl", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"BlindSpot", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
|
// sunnypilot model params
|
||||||
|
{"CameraOffset", {PERSISTENT | BACKUP, FLOAT, "0.0"}},
|
||||||
|
{"LagdToggle", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
|
{"LagdToggleDelay", {PERSISTENT | BACKUP, FLOAT, "0.2"}},
|
||||||
|
{"LagdValueCache", {PERSISTENT, FLOAT, "0.2"}},
|
||||||
|
{"LaneTurnDesire", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"LaneTurnValue", {PERSISTENT | BACKUP, FLOAT, "19.0"}},
|
||||||
|
{"PlanplusControl", {PERSISTENT | BACKUP, FLOAT, "1.0"}},
|
||||||
|
|
||||||
|
// mapd
|
||||||
|
{"MapAdvisorySpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, FLOAT}},
|
||||||
|
{"MapdVersion", {PERSISTENT, STRING}},
|
||||||
|
{"MapSpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, FLOAT, "0.0"}},
|
||||||
|
{"NextMapSpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
|
{"Offroad_OSMUpdateRequired", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
|
{"OsmDbUpdatesCheck", {CLEAR_ON_MANAGER_START, BOOL}}, // mapd database update happens with device ON, reset on boot
|
||||||
|
{"OSMDownloadBounds", {PERSISTENT, STRING}},
|
||||||
|
{"OsmDownloadedDate", {PERSISTENT, STRING, "0.0"}},
|
||||||
|
{"OSMDownloadLocations", {PERSISTENT, JSON}},
|
||||||
|
{"OSMDownloadProgress", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
|
{"OsmLocal", {PERSISTENT, BOOL}},
|
||||||
|
{"OsmLocationName", {PERSISTENT, STRING}},
|
||||||
|
{"OsmLocationTitle", {PERSISTENT, STRING}},
|
||||||
|
{"OsmLocationUrl", {PERSISTENT, STRING}},
|
||||||
|
{"OsmStateName", {PERSISTENT, STRING, "All"}},
|
||||||
|
{"OsmStateTitle", {PERSISTENT, STRING}},
|
||||||
|
{"OsmWayTest", {PERSISTENT, STRING}},
|
||||||
|
{"RoadName", {CLEAR_ON_ONROAD_TRANSITION, STRING}},
|
||||||
|
{"RoadNameToggle", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
|
// Speed Limit
|
||||||
|
{"SpeedLimitMode", {PERSISTENT | BACKUP, INT, "1"}},
|
||||||
|
{"SpeedLimitOffsetType", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"SpeedLimitPolicy", {PERSISTENT | BACKUP, INT, "3"}},
|
||||||
|
{"SpeedLimitValueOffset", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
|
||||||
|
// Smart Cruise Control
|
||||||
|
{"MapTargetVelocities", {CLEAR_ON_ONROAD_TRANSITION, STRING}},
|
||||||
|
{"SmartCruiseControlMap", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"SmartCruiseControlVision", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
|
// Torque lateral control custom params
|
||||||
|
{"CustomTorqueParams", {PERSISTENT | BACKUP , BOOL}},
|
||||||
|
{"EnforceTorqueControl", {PERSISTENT | BACKUP, BOOL}},
|
||||||
|
{"LiveTorqueParamsToggle", {PERSISTENT | BACKUP , BOOL}},
|
||||||
|
{"LiveTorqueParamsRelaxedToggle", {PERSISTENT | BACKUP , BOOL}},
|
||||||
|
{"TorqueControlTune", {PERSISTENT | BACKUP, FLOAT, "0.0"}},
|
||||||
|
{"TorqueParamsOverrideEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"TorqueParamsOverrideFriction", {PERSISTENT | BACKUP, FLOAT, "0.1"}},
|
||||||
|
{"TorqueParamsOverrideLatAccelFactor", {PERSISTENT | BACKUP, FLOAT, "2.5"}},
|
||||||
};
|
};
|
||||||
|
|||||||
+3172
-3275
File diff suppressed because it is too large
Load Diff
+17
-21
@@ -18,6 +18,7 @@ cdef extern from "common/params.h":
|
|||||||
CLEAR_ON_OFFROAD_TRANSITION
|
CLEAR_ON_OFFROAD_TRANSITION
|
||||||
DEVELOPMENT_ONLY
|
DEVELOPMENT_ONLY
|
||||||
CLEAR_ON_IGNITION_ON
|
CLEAR_ON_IGNITION_ON
|
||||||
|
BACKUP
|
||||||
ALL
|
ALL
|
||||||
|
|
||||||
cpdef enum ParamKeyType:
|
cpdef enum ParamKeyType:
|
||||||
@@ -43,7 +44,7 @@ cdef extern from "common/params.h":
|
|||||||
optional[string] getKeyDefaultValue(string) nogil
|
optional[string] getKeyDefaultValue(string) nogil
|
||||||
string getParamPath(string) nogil
|
string getParamPath(string) nogil
|
||||||
void clearAll(ParamKeyFlag)
|
void clearAll(ParamKeyFlag)
|
||||||
vector[string] allKeys()
|
vector[string] allKeys(ParamKeyFlag)
|
||||||
|
|
||||||
PYTHON_2_CPP = {
|
PYTHON_2_CPP = {
|
||||||
(str, STRING): lambda v: v,
|
(str, STRING): lambda v: v,
|
||||||
@@ -141,33 +142,28 @@ cdef class Params:
|
|||||||
cdef ParamKeyType t = self.p.getKeyType(k)
|
cdef ParamKeyType t = self.p.getKeyType(k)
|
||||||
return ensure_bytes(self.python2cpp(type(dat), t, dat, key))
|
return ensure_bytes(self.python2cpp(type(dat), t, dat, key))
|
||||||
|
|
||||||
def put(self, key, dat):
|
def put(self, key, dat, bool block = False):
|
||||||
"""
|
"""
|
||||||
Warning: This function blocks until the param is written to disk!
|
Warning: block=True blocks until the param is written to disk!
|
||||||
In very rare cases this can take over a second, and your code will hang.
|
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
|
Use block=False in time sensitive code, but in general try to avoid
|
||||||
in general try to avoid writing params as much as possible.
|
writing params as much as possible.
|
||||||
"""
|
"""
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
cdef string dat_bytes = self._put_cast(key, dat)
|
cdef string dat_bytes = self._put_cast(key, dat)
|
||||||
with nogil:
|
with nogil:
|
||||||
self.p.put(k, dat_bytes)
|
if block:
|
||||||
|
self.p.put(k, dat_bytes)
|
||||||
|
else:
|
||||||
|
self.p.putNonBlocking(k, dat_bytes)
|
||||||
|
|
||||||
def put_bool(self, key, bool val):
|
def put_bool(self, key, bool val, bool block = False):
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
with nogil:
|
with nogil:
|
||||||
self.p.putBool(k, val)
|
if block:
|
||||||
|
self.p.putBool(k, val)
|
||||||
def put_nonblocking(self, key, dat):
|
else:
|
||||||
cdef string k = self.check_key(key)
|
self.p.putBoolNonBlocking(k, val)
|
||||||
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):
|
def remove(self, key):
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
@@ -181,8 +177,8 @@ cdef class Params:
|
|||||||
def get_type(self, key):
|
def get_type(self, key):
|
||||||
return self.p.getKeyType(self.check_key(key))
|
return self.p.getKeyType(self.check_key(key))
|
||||||
|
|
||||||
def all_keys(self):
|
def all_keys(self, flag=ParamKeyFlag.ALL):
|
||||||
return self.p.allKeys()
|
return self.p.allKeys(flag)
|
||||||
|
|
||||||
def get_default_value(self, key):
|
def get_default_value(self, key):
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
|
|||||||
Binary file not shown.
+9
-16
@@ -2,21 +2,14 @@ import numpy as np
|
|||||||
from numbers import Number
|
from numbers import Number
|
||||||
|
|
||||||
class PIDController:
|
class PIDController:
|
||||||
def __init__(self, k_p, k_i, k_f=0., k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100):
|
def __init__(self, k_p, k_i, k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100):
|
||||||
self._k_p = k_p
|
self._k_p: list[list[float]] = [[0], [k_p]] if isinstance(k_p, Number) else k_p
|
||||||
self._k_i = k_i
|
self._k_i: list[list[float]] = [[0], [k_i]] if isinstance(k_i, Number) else k_i
|
||||||
self._k_d = k_d
|
self._k_d: list[list[float]] = [[0], [k_d]] if isinstance(k_d, Number) else 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.set_limits(pos_limit, neg_limit)
|
||||||
|
|
||||||
self.i_rate = 1.0 / rate
|
self.i_dt = 1.0 / rate
|
||||||
self.speed = 0.0
|
self.speed = 0.0
|
||||||
|
|
||||||
self.reset()
|
self.reset()
|
||||||
@@ -46,12 +39,12 @@ class PIDController:
|
|||||||
|
|
||||||
def update(self, error, error_rate=0.0, speed=0.0, feedforward=0., freeze_integrator=False):
|
def update(self, error, error_rate=0.0, speed=0.0, feedforward=0., freeze_integrator=False):
|
||||||
self.speed = speed
|
self.speed = speed
|
||||||
self.p = float(error) * self.k_p
|
self.p = self.k_p * float(error)
|
||||||
self.f = feedforward * self.k_f
|
self.d = self.k_d * error_rate
|
||||||
self.d = error_rate * self.k_d
|
self.f = feedforward
|
||||||
|
|
||||||
if not freeze_integrator:
|
if not freeze_integrator:
|
||||||
i = self.i + error * self.k_i * self.i_rate
|
i = self.i + self.k_i * self.i_dt * error
|
||||||
|
|
||||||
# Don't allow windup if already clipping
|
# Don't allow windup if already clipping
|
||||||
test_control = self.p + i + self.d + self.f
|
test_control = self.p + i + self.d + self.f
|
||||||
|
|||||||
+9
-5
@@ -13,7 +13,11 @@ public:
|
|||||||
if (prefix.empty()) {
|
if (prefix.empty()) {
|
||||||
prefix = util::random_string(15);
|
prefix = util::random_string(15);
|
||||||
}
|
}
|
||||||
msgq_path = Path::shm_path() + "/" + prefix;
|
#ifdef __APPLE__
|
||||||
|
msgq_path = "/tmp/msgq_" + prefix;
|
||||||
|
#else
|
||||||
|
msgq_path = "/dev/shm/msgq_" + prefix;
|
||||||
|
#endif
|
||||||
bool ret = util::create_directories(msgq_path, 0777);
|
bool ret = util::create_directories(msgq_path, 0777);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
setenv("OPENPILOT_PREFIX", prefix.c_str(), 1);
|
setenv("OPENPILOT_PREFIX", prefix.c_str(), 1);
|
||||||
@@ -23,14 +27,14 @@ public:
|
|||||||
auto param_path = Params().getParamPath();
|
auto param_path = Params().getParamPath();
|
||||||
if (util::file_exists(param_path)) {
|
if (util::file_exists(param_path)) {
|
||||||
std::string real_path = util::readlink(param_path);
|
std::string real_path = util::readlink(param_path);
|
||||||
system(util::string_format("rm %s -rf", real_path.c_str()).c_str());
|
util::check_system(util::string_format("rm %s -rf", real_path.c_str()));
|
||||||
unlink(param_path.c_str());
|
unlink(param_path.c_str());
|
||||||
}
|
}
|
||||||
if (getenv("COMMA_CACHE") == nullptr) {
|
if (getenv("COMMA_CACHE") == nullptr) {
|
||||||
system(util::string_format("rm %s -rf", Path::download_cache_root().c_str()).c_str());
|
util::check_system(util::string_format("rm %s -rf", Path::download_cache_root().c_str()));
|
||||||
}
|
}
|
||||||
system(util::string_format("rm %s -rf", Path::comma_home().c_str()).c_str());
|
util::check_system(util::string_format("rm %s -rf", Path::comma_home().c_str()));
|
||||||
system(util::string_format("rm %s -rf", msgq_path.c_str()).c_str());
|
util::check_system(util::string_format("rm %s -rf", msgq_path.c_str()));
|
||||||
unsetenv("OPENPILOT_PREFIX");
|
unsetenv("OPENPILOT_PREFIX");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
@@ -9,9 +10,10 @@ from openpilot.system.hardware.hw import Paths
|
|||||||
from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
|
from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
|
||||||
|
|
||||||
class OpenpilotPrefix:
|
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):
|
def __init__(self, prefix: str | None = 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.prefix = prefix if prefix else str(uuid.uuid4().hex[0:15])
|
||||||
self.msgq_path = os.path.join(Paths.shm_path(), self.prefix)
|
shm_path = "/tmp" if platform.system() == "Darwin" else "/dev/shm"
|
||||||
|
self.msgq_path = os.path.join(shm_path, "msgq_" + self.prefix)
|
||||||
self.create_dirs_on_enter = create_dirs_on_enter
|
self.create_dirs_on_enter = create_dirs_on_enter
|
||||||
self.clean_dirs_on_exit = clean_dirs_on_exit
|
self.clean_dirs_on_exit = clean_dirs_on_exit
|
||||||
self.shared_download_cache = shared_download_cache
|
self.shared_download_cache = shared_download_cache
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
#include "common/timing.h"
|
#include "common/timing.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
|
||||||
RateKeeper::RateKeeper(const std::string &name, float rate, float print_delay_threshold)
|
RateKeeper::RateKeeper(const std::string &name_, float rate, float print_delay_threshold_)
|
||||||
: name(name),
|
: name(name_),
|
||||||
print_delay_threshold(std::max(0.f, print_delay_threshold)) {
|
print_delay_threshold(std::max(0.f, print_delay_threshold_)) {
|
||||||
interval = 1 / rate;
|
interval = 1 / rate;
|
||||||
last_monitor_time = seconds_since_boot();
|
last_monitor_time = seconds_since_boot();
|
||||||
next_frame_time = last_monitor_time + interval;
|
next_frame_time = last_monitor_time + interval;
|
||||||
|
|||||||
+6
-1
@@ -6,7 +6,7 @@ import time
|
|||||||
|
|
||||||
from setproctitle import getproctitle
|
from setproctitle import getproctitle
|
||||||
|
|
||||||
from openpilot.common.util import MovingAverage
|
from openpilot.common.utils import MovingAverage
|
||||||
from openpilot.system.hardware import PC
|
from openpilot.system.hardware import PC
|
||||||
|
|
||||||
|
|
||||||
@@ -28,6 +28,11 @@ class Priority:
|
|||||||
CTRL_HIGH = 53
|
CTRL_HIGH = 53
|
||||||
|
|
||||||
|
|
||||||
|
def drop_realtime() -> None:
|
||||||
|
if sys.platform == 'linux' and not PC:
|
||||||
|
os.sched_setscheduler(0, os.SCHED_OTHER, os.sched_param(0))
|
||||||
|
|
||||||
|
|
||||||
def set_core_affinity(cores: list[int]) -> None:
|
def set_core_affinity(cores: list[int]) -> None:
|
||||||
if sys.platform == 'linux' and not PC:
|
if sys.platform == 'linux' and not PC:
|
||||||
os.sched_setaffinity(0, cores)
|
os.sched_setaffinity(0, cores)
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
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()
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
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()
|
|
||||||
+4
-2
@@ -11,10 +11,12 @@
|
|||||||
|
|
||||||
#include <zmq.h>
|
#include <zmq.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "third_party/json11/json11.hpp"
|
#include "json11/json11.hpp"
|
||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
#include "system/hardware/hw.h"
|
#include "system/hardware/hw.h"
|
||||||
|
|
||||||
|
#include "sunnypilot/common/version.h"
|
||||||
|
|
||||||
class SwaglogState {
|
class SwaglogState {
|
||||||
public:
|
public:
|
||||||
SwaglogState() {
|
SwaglogState() {
|
||||||
@@ -56,7 +58,7 @@ public:
|
|||||||
if (char* daemon_name = getenv("MANAGER_DAEMON")) {
|
if (char* daemon_name = getenv("MANAGER_DAEMON")) {
|
||||||
ctx_j["daemon"] = daemon_name;
|
ctx_j["daemon"] = daemon_name;
|
||||||
}
|
}
|
||||||
ctx_j["version"] = COMMA_VERSION;
|
ctx_j["version"] = SUNNYPILOT_VERSION;
|
||||||
ctx_j["dirty"] = !getenv("CLEAN");
|
ctx_j["dirty"] = !getenv("CLEAN");
|
||||||
ctx_j["device"] = Hardware::get_name();
|
ctx_j["device"] = Hardware::get_name();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from openpilot.common.file_helpers import atomic_write_in_dir
|
from openpilot.common.utils import atomic_write
|
||||||
|
|
||||||
|
|
||||||
class TestFileHelpers:
|
class TestFileHelpers:
|
||||||
@@ -15,5 +15,5 @@ class TestFileHelpers:
|
|||||||
assert f.read() == "test"
|
assert f.read() == "test"
|
||||||
os.remove(path)
|
os.remove(path)
|
||||||
|
|
||||||
def test_atomic_write_in_dir(self):
|
def test_atomic_write(self):
|
||||||
self.run_atomic_write_func(atomic_write_in_dir)
|
self.run_atomic_write_func(atomic_write)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from openpilot.common.markdown import parse_markdown
|
|||||||
|
|
||||||
class TestMarkdown:
|
class TestMarkdown:
|
||||||
def test_all_release_notes(self):
|
def test_all_release_notes(self):
|
||||||
with open(os.path.join(BASEDIR, "RELEASES.md")) as f:
|
with open(os.path.join(BASEDIR, "CHANGELOG.md")) as f:
|
||||||
release_notes = f.read().split("\n\n")
|
release_notes = f.read().split("\n\n")
|
||||||
assert len(release_notes) > 10
|
assert len(release_notes) > 10
|
||||||
|
|
||||||
|
|||||||
+19
-19
@@ -12,17 +12,17 @@ class TestParams:
|
|||||||
self.params = Params()
|
self.params = Params()
|
||||||
|
|
||||||
def test_params_put_and_get(self):
|
def test_params_put_and_get(self):
|
||||||
self.params.put("DongleId", "cb38263377b873ee")
|
self.params.put("DongleId", "cb38263377b873ee", block=True)
|
||||||
assert self.params.get("DongleId") == "cb38263377b873ee"
|
assert self.params.get("DongleId") == "cb38263377b873ee"
|
||||||
|
|
||||||
def test_params_non_ascii(self):
|
def test_params_non_ascii(self):
|
||||||
st = b"\xe1\x90\xff"
|
st = b"\xe1\x90\xff"
|
||||||
self.params.put("CarParams", st)
|
self.params.put("CarParams", st, block=True)
|
||||||
assert self.params.get("CarParams") == st
|
assert self.params.get("CarParams") == st
|
||||||
|
|
||||||
def test_params_get_cleared_manager_start(self):
|
def test_params_get_cleared_manager_start(self):
|
||||||
self.params.put("CarParams", b"test")
|
self.params.put("CarParams", b"test", block=True)
|
||||||
self.params.put("DongleId", "cb38263377b873ee")
|
self.params.put("DongleId", "cb38263377b873ee", block=True)
|
||||||
assert self.params.get("CarParams") == b"test"
|
assert self.params.get("CarParams") == b"test"
|
||||||
|
|
||||||
undefined_param = self.params.get_param_path(uuid.uuid4().hex)
|
undefined_param = self.params.get_param_path(uuid.uuid4().hex)
|
||||||
@@ -36,15 +36,15 @@ class TestParams:
|
|||||||
assert not os.path.isfile(undefined_param)
|
assert not os.path.isfile(undefined_param)
|
||||||
|
|
||||||
def test_params_two_things(self):
|
def test_params_two_things(self):
|
||||||
self.params.put("DongleId", "bob")
|
self.params.put("DongleId", "bob", block=True)
|
||||||
self.params.put("AthenadPid", 123)
|
self.params.put("AthenadPid", 123, block=True)
|
||||||
assert self.params.get("DongleId") == "bob"
|
assert self.params.get("DongleId") == "bob"
|
||||||
assert self.params.get("AthenadPid") == 123
|
assert self.params.get("AthenadPid") == 123
|
||||||
|
|
||||||
def test_params_get_block(self):
|
def test_params_get_block(self):
|
||||||
def _delayed_writer():
|
def _delayed_writer():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
self.params.put("CarParams", b"test")
|
self.params.put("CarParams", b"test", block=True)
|
||||||
threading.Thread(target=_delayed_writer).start()
|
threading.Thread(target=_delayed_writer).start()
|
||||||
assert self.params.get("CarParams") is None
|
assert self.params.get("CarParams") is None
|
||||||
assert self.params.get("CarParams", block=True) == b"test"
|
assert self.params.get("CarParams", block=True) == b"test"
|
||||||
@@ -57,10 +57,10 @@ class TestParams:
|
|||||||
self.params.get_bool("swag")
|
self.params.get_bool("swag")
|
||||||
|
|
||||||
with pytest.raises(UnknownKeyName):
|
with pytest.raises(UnknownKeyName):
|
||||||
self.params.put("swag", "abc")
|
self.params.put("swag", "abc", block=True)
|
||||||
|
|
||||||
with pytest.raises(UnknownKeyName):
|
with pytest.raises(UnknownKeyName):
|
||||||
self.params.put_bool("swag", True)
|
self.params.put_bool("swag", True, block=True)
|
||||||
|
|
||||||
def test_remove_not_there(self):
|
def test_remove_not_there(self):
|
||||||
assert self.params.get("CarParams") is None
|
assert self.params.get("CarParams") is None
|
||||||
@@ -71,23 +71,23 @@ class TestParams:
|
|||||||
self.params.remove("IsMetric")
|
self.params.remove("IsMetric")
|
||||||
assert not self.params.get_bool("IsMetric")
|
assert not self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put_bool("IsMetric", True)
|
self.params.put_bool("IsMetric", True, block=True)
|
||||||
assert self.params.get_bool("IsMetric")
|
assert self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put_bool("IsMetric", False)
|
self.params.put_bool("IsMetric", False, block=True)
|
||||||
assert not self.params.get_bool("IsMetric")
|
assert not self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put("IsMetric", True)
|
self.params.put("IsMetric", True, block=True)
|
||||||
assert self.params.get_bool("IsMetric")
|
assert self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put("IsMetric", False)
|
self.params.put("IsMetric", False, block=True)
|
||||||
assert not self.params.get_bool("IsMetric")
|
assert not self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
def test_put_non_blocking_with_get_block(self):
|
def test_put_non_blocking_with_get_block(self):
|
||||||
q = Params()
|
q = Params()
|
||||||
def _delayed_writer():
|
def _delayed_writer():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
Params().put_nonblocking("CarParams", b"test")
|
Params().put("CarParams", b"test")
|
||||||
threading.Thread(target=_delayed_writer).start()
|
threading.Thread(target=_delayed_writer).start()
|
||||||
assert q.get("CarParams") is None
|
assert q.get("CarParams") is None
|
||||||
assert q.get("CarParams", True) == b"test"
|
assert q.get("CarParams", True) == b"test"
|
||||||
@@ -96,7 +96,7 @@ class TestParams:
|
|||||||
q = Params()
|
q = Params()
|
||||||
def _delayed_writer():
|
def _delayed_writer():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
Params().put_bool_nonblocking("CarParams", True)
|
Params().put_bool("CarParams", True)
|
||||||
threading.Thread(target=_delayed_writer).start()
|
threading.Thread(target=_delayed_writer).start()
|
||||||
assert q.get("CarParams") is None
|
assert q.get("CarParams") is None
|
||||||
assert q.get("CarParams", True) == b"1"
|
assert q.get("CarParams", True) == b"1"
|
||||||
@@ -123,19 +123,19 @@ class TestParams:
|
|||||||
|
|
||||||
def test_params_get_type(self):
|
def test_params_get_type(self):
|
||||||
# json
|
# json
|
||||||
self.params.put("ApiCache_FirehoseStats", {"a": 0})
|
self.params.put("ApiCache_FirehoseStats", {"a": 0}, block=True)
|
||||||
assert self.params.get("ApiCache_FirehoseStats") == {"a": 0}
|
assert self.params.get("ApiCache_FirehoseStats") == {"a": 0}
|
||||||
|
|
||||||
# int
|
# int
|
||||||
self.params.put("BootCount", 1441)
|
self.params.put("BootCount", 1441, block=True)
|
||||||
assert self.params.get("BootCount") == 1441
|
assert self.params.get("BootCount") == 1441
|
||||||
|
|
||||||
# bool
|
# bool
|
||||||
self.params.put("AdbEnabled", True)
|
self.params.put("AdbEnabled", True, block=True)
|
||||||
assert self.params.get("AdbEnabled")
|
assert self.params.get("AdbEnabled")
|
||||||
assert isinstance(self.params.get("AdbEnabled"), bool)
|
assert isinstance(self.params.get("AdbEnabled"), bool)
|
||||||
|
|
||||||
# time
|
# time
|
||||||
now = datetime.datetime.now(datetime.UTC)
|
now = datetime.datetime.now(datetime.UTC)
|
||||||
self.params.put("InstallDate", now)
|
self.params.put("InstallDate", now, block=True)
|
||||||
assert self.params.get("InstallDate") == now
|
assert self.params.get("InstallDate") == now
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
#include "system/hardware/hw.h"
|
#include "system/hardware/hw.h"
|
||||||
#include "third_party/json11/json11.hpp"
|
#include "json11/json11.hpp"
|
||||||
|
|
||||||
|
#include "sunnypilot/common/version.h"
|
||||||
|
|
||||||
std::string daemon_name = "testy";
|
std::string daemon_name = "testy";
|
||||||
std::string dongle_id = "test_dongle_id";
|
std::string dongle_id = "test_dongle_id";
|
||||||
@@ -53,7 +55,7 @@ void recv_log(int thread_cnt, int thread_msg_cnt) {
|
|||||||
REQUIRE(ctx["dongle_id"].string_value() == dongle_id);
|
REQUIRE(ctx["dongle_id"].string_value() == dongle_id);
|
||||||
REQUIRE(ctx["dirty"].bool_value() == true);
|
REQUIRE(ctx["dirty"].bool_value() == true);
|
||||||
|
|
||||||
REQUIRE(ctx["version"].string_value() == COMMA_VERSION);
|
REQUIRE(ctx["version"].string_value() == SUNNYPILOT_VERSION);
|
||||||
|
|
||||||
std::string device = Hardware::get_name();
|
std::string device = Hardware::get_name();
|
||||||
REQUIRE(ctx["device"].string_value() == device);
|
REQUIRE(ctx["device"].string_value() == device);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ TEST_CASE("util::read_file") {
|
|||||||
REQUIRE(util::read_file(filename).empty());
|
REQUIRE(util::read_file(filename).empty());
|
||||||
|
|
||||||
std::string content = random_bytes(64 * 1024);
|
std::string content = random_bytes(64 * 1024);
|
||||||
write(fd, content.c_str(), content.size());
|
REQUIRE(write(fd, content.c_str(), content.size()) == (ssize_t)content.size());
|
||||||
std::string ret = util::read_file(filename);
|
std::string ret = util::read_file(filename);
|
||||||
bool equal = (ret == content);
|
bool equal = (ret == content);
|
||||||
REQUIRE(equal);
|
REQUIRE(equal);
|
||||||
@@ -114,12 +114,12 @@ TEST_CASE("util::safe_fwrite") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("util::create_directories") {
|
TEST_CASE("util::create_directories") {
|
||||||
system("rm /tmp/test_create_directories -rf");
|
REQUIRE(system("rm /tmp/test_create_directories -rf") == 0);
|
||||||
std::string dir = "/tmp/test_create_directories/a/b/c/d/e/f";
|
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 {
|
auto check_dir_permissions = [](const std::string &path, mode_t mode) -> bool {
|
||||||
struct stat st = {};
|
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;
|
return stat(path.c_str(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR && (st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) == mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
SECTION("create_directories") {
|
SECTION("create_directories") {
|
||||||
@@ -132,7 +132,7 @@ TEST_CASE("util::create_directories") {
|
|||||||
}
|
}
|
||||||
SECTION("a file exists with the same name") {
|
SECTION("a file exists with the same name") {
|
||||||
REQUIRE(util::create_directories(dir, 0755));
|
REQUIRE(util::create_directories(dir, 0755));
|
||||||
int f = open((dir + "/file").c_str(), O_RDWR | O_CREAT);
|
int f = open((dir + "/file").c_str(), O_RDWR | O_CREAT, 0644);
|
||||||
REQUIRE(f != -1);
|
REQUIRE(f != -1);
|
||||||
close(f);
|
close(f);
|
||||||
REQUIRE(util::create_directories(dir + "/file", 0755) == false);
|
REQUIRE(util::create_directories(dir + "/file", 0755) == false);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import datetime
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
MIN_DATE = datetime.datetime(year=2025, month=2, day=21)
|
MIN_DATE = datetime.datetime(year=2025, month=2, day=21)
|
||||||
|
MAX_DATE = datetime.datetime(year=2035, month=1, day=1)
|
||||||
|
|
||||||
def min_date():
|
def min_date():
|
||||||
# on systemd systems, the default time is the systemd build time
|
# on systemd systems, the default time is the systemd build time
|
||||||
@@ -12,4 +13,4 @@ def min_date():
|
|||||||
return MIN_DATE
|
return MIN_DATE
|
||||||
|
|
||||||
def system_time_valid():
|
def system_time_valid():
|
||||||
return datetime.datetime.now() > min_date()
|
return min_date() < datetime.datetime.now() < MAX_DATE
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
transformations
|
|
||||||
transformations.cpp
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Import('env', 'envCython')
|
|
||||||
|
|
||||||
transformations = env.Library('transformations', ['orientation.cc', 'coordinates.cc'])
|
|
||||||
transformations_python = envCython.Program('transformations.so', 'transformations.pyx')
|
|
||||||
Export('transformations', 'transformations_python')
|
|
||||||
@@ -102,3 +102,36 @@ class TestNED:
|
|||||||
np.testing.assert_allclose(converter.ned2ecef(ned_offsets_batch),
|
np.testing.assert_allclose(converter.ned2ecef(ned_offsets_batch),
|
||||||
ecef_positions_offset_batch,
|
ecef_positions_offset_batch,
|
||||||
rtol=1e-9, atol=1e-7)
|
rtol=1e-9, atol=1e-7)
|
||||||
|
|
||||||
|
def test_errors(self):
|
||||||
|
# Test wrong shape/type for geodetic2ecef
|
||||||
|
# numpy_wrap raises IndexError for scalar input
|
||||||
|
with np.testing.assert_raises(IndexError):
|
||||||
|
coord.geodetic2ecef(1.0)
|
||||||
|
|
||||||
|
with np.testing.assert_raises_regex(ValueError, "Geodetic must be size 3"):
|
||||||
|
coord.geodetic2ecef([0, 0])
|
||||||
|
|
||||||
|
with np.testing.assert_raises_regex(ValueError, "Geodetic must be size 3"):
|
||||||
|
coord.geodetic2ecef([0, 0, 0, 0])
|
||||||
|
|
||||||
|
with np.testing.assert_raises(TypeError):
|
||||||
|
coord.geodetic2ecef(['a', 'b', 'c'])
|
||||||
|
|
||||||
|
# Test LocalCoord constructor errors
|
||||||
|
with np.testing.assert_raises(ValueError):
|
||||||
|
coord.LocalCoord.from_geodetic([0, 0])
|
||||||
|
|
||||||
|
with np.testing.assert_raises(ValueError):
|
||||||
|
coord.LocalCoord.from_geodetic(1)
|
||||||
|
|
||||||
|
with np.testing.assert_raises(TypeError):
|
||||||
|
coord.LocalCoord.from_geodetic(['a', 'b', 'c'])
|
||||||
|
|
||||||
|
# Test wrong shape/type for ecef2geodetic
|
||||||
|
with np.testing.assert_raises(ValueError):
|
||||||
|
coord.ecef2geodetic([1, 2])
|
||||||
|
with np.testing.assert_raises(ValueError):
|
||||||
|
coord.ecef2geodetic([1, 2, 3, 4])
|
||||||
|
with np.testing.assert_raises(IndexError):
|
||||||
|
coord.ecef2geodetic(1.0)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
import pytest
|
||||||
|
|
||||||
from openpilot.common.transformations.orientation import euler2quat, quat2euler, euler2rot, rot2euler, \
|
from openpilot.common.transformations.orientation import euler2quat, quat2euler, euler2rot, rot2euler, \
|
||||||
rot2quat, quat2rot, \
|
rot2quat, quat2rot, \
|
||||||
@@ -59,3 +60,32 @@ class TestOrientation:
|
|||||||
np.testing.assert_allclose(ned_eulers[i], ned_euler_from_ecef(ecef_positions[i], eulers[i]), rtol=1e-7)
|
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(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)
|
# np.testing.assert_allclose(ned_eulers, ned_euler_from_ecef(ecef_positions, eulers), rtol=1e-7)
|
||||||
|
|
||||||
|
def test_inputs(self):
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
euler2quat([1, 2])
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
quat2rot([1, 2, 3])
|
||||||
|
|
||||||
|
with pytest.raises(IndexError):
|
||||||
|
rot2quat(np.zeros((2, 2)))
|
||||||
|
|
||||||
|
def test_euler_rot_consistency(self):
|
||||||
|
rpy = [0.1, 0.2, 0.3]
|
||||||
|
R = euler2rot(rpy)
|
||||||
|
|
||||||
|
# R -> q -> R
|
||||||
|
q = rot2quat(R)
|
||||||
|
R_new = quat2rot(q)
|
||||||
|
np.testing.assert_allclose(R, R_new, atol=1e-15)
|
||||||
|
|
||||||
|
# q -> R -> Euler (quat2euler) -> R
|
||||||
|
rpy_new = quat2euler(q)
|
||||||
|
R_new2 = euler2rot(rpy_new)
|
||||||
|
np.testing.assert_allclose(R, R_new2, atol=1e-15)
|
||||||
|
|
||||||
|
# R -> Euler (rot2euler) -> R
|
||||||
|
rpy_from_rot = rot2euler(R)
|
||||||
|
R_new3 = euler2rot(rpy_from_rot)
|
||||||
|
np.testing.assert_allclose(R, R_new3, atol=1e-15)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,72 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -0,0 +1,342 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
# Constants
|
||||||
|
a = 6378137.0
|
||||||
|
b = 6356752.3142
|
||||||
|
esq = 6.69437999014e-3
|
||||||
|
e1sq = 6.73949674228e-3
|
||||||
|
|
||||||
|
|
||||||
|
def geodetic2ecef_single(g):
|
||||||
|
"""
|
||||||
|
Convert geodetic coordinates (latitude, longitude, altitude) to ECEF.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if len(g) != 3:
|
||||||
|
raise ValueError("Geodetic must be size 3")
|
||||||
|
except TypeError:
|
||||||
|
raise ValueError("Geodetic must be a sequence of length 3") from None
|
||||||
|
|
||||||
|
lat, lon, alt = g
|
||||||
|
lat = np.radians(lat)
|
||||||
|
lon = np.radians(lon)
|
||||||
|
xi = np.sqrt(1.0 - esq * np.sin(lat)**2)
|
||||||
|
x = (a / xi + alt) * np.cos(lat) * np.cos(lon)
|
||||||
|
y = (a / xi + alt) * np.cos(lat) * np.sin(lon)
|
||||||
|
z = (a / xi * (1.0 - esq) + alt) * np.sin(lat)
|
||||||
|
return np.array([x, y, z])
|
||||||
|
|
||||||
|
|
||||||
|
def ecef2geodetic_single(e):
|
||||||
|
"""
|
||||||
|
Convert ECEF to geodetic coordinates using Ferrari's solution.
|
||||||
|
"""
|
||||||
|
x, y, z = e
|
||||||
|
r = np.sqrt(x**2 + y**2)
|
||||||
|
Esq = a**2 - b**2
|
||||||
|
F = 54 * b**2 * z**2
|
||||||
|
G = r**2 + (1 - esq) * z**2 - esq * Esq
|
||||||
|
C = (esq**2 * F * r**2) / (G**3)
|
||||||
|
S = np.cbrt(1 + C + np.sqrt(C**2 + 2 * C))
|
||||||
|
P = F / (3 * (S + 1 / S + 1)**2 * G**2)
|
||||||
|
Q = np.sqrt(1 + 2 * esq**2 * P)
|
||||||
|
r_0 = -(P * esq * r) / (1 + Q) + np.sqrt(0.5 * a**2 * (1 + 1.0 / Q) - P * (1 - esq) * z**2 / (Q * (1 + Q)) - 0.5 * P * r**2)
|
||||||
|
U = np.sqrt((r - esq * r_0)**2 + z**2)
|
||||||
|
V = np.sqrt((r - esq * r_0)**2 + (1 - esq) * z**2)
|
||||||
|
Z_0 = b**2 * z / (a * V)
|
||||||
|
h = U * (1 - b**2 / (a * V))
|
||||||
|
lat = np.arctan((z + e1sq * Z_0) / r)
|
||||||
|
lon = np.arctan2(y, x)
|
||||||
|
return np.array([np.degrees(lat), np.degrees(lon), h])
|
||||||
|
|
||||||
|
|
||||||
|
def euler2quat_single(euler):
|
||||||
|
"""
|
||||||
|
Convert Euler angles (roll, pitch, yaw) to a quaternion.
|
||||||
|
Rotation order: Z-Y-X (yaw, pitch, roll).
|
||||||
|
"""
|
||||||
|
phi, theta, psi = euler
|
||||||
|
|
||||||
|
c_phi, s_phi = np.cos(phi / 2), np.sin(phi / 2)
|
||||||
|
c_theta, s_theta = np.cos(theta / 2), np.sin(theta / 2)
|
||||||
|
c_psi, s_psi = np.cos(psi / 2), np.sin(psi / 2)
|
||||||
|
|
||||||
|
w = c_phi * c_theta * c_psi + s_phi * s_theta * s_psi
|
||||||
|
x = s_phi * c_theta * c_psi - c_phi * s_theta * s_psi
|
||||||
|
y = c_phi * s_theta * c_psi + s_phi * c_theta * s_psi
|
||||||
|
z = c_phi * c_theta * s_psi - s_phi * s_theta * c_psi
|
||||||
|
|
||||||
|
if w < 0:
|
||||||
|
return np.array([-w, -x, -y, -z])
|
||||||
|
return np.array([w, x, y, z])
|
||||||
|
|
||||||
|
|
||||||
|
def quat2euler_single(q):
|
||||||
|
"""
|
||||||
|
Convert a quaternion to Euler angles (roll, pitch, yaw).
|
||||||
|
"""
|
||||||
|
w, x, y, z = q
|
||||||
|
gamma = np.arctan2(2 * (w * x + y * z), 1 - 2 * (x**2 + y**2))
|
||||||
|
sin_arg = 2 * (w * y - z * x)
|
||||||
|
sin_arg = np.clip(sin_arg, -1.0, 1.0)
|
||||||
|
theta = np.arcsin(sin_arg)
|
||||||
|
psi = np.arctan2(2 * (w * z + x * y), 1 - 2 * (y**2 + z**2))
|
||||||
|
return np.array([gamma, theta, psi])
|
||||||
|
|
||||||
|
|
||||||
|
def quat2rot_single(q):
|
||||||
|
"""
|
||||||
|
Convert a quaternion to a 3x3 rotation matrix.
|
||||||
|
"""
|
||||||
|
w, x, y, z = q
|
||||||
|
xx, yy, zz = x * x, y * y, z * z
|
||||||
|
xy, xz, yz = x * y, x * z, y * z
|
||||||
|
wx, wy, wz = w * x, w * y, w * z
|
||||||
|
|
||||||
|
mat = np.array([
|
||||||
|
[1 - 2 * (yy + zz), 2 * (xy - wz), 2 * (xz + wy)],
|
||||||
|
[2 * (xy + wz), 1 - 2 * (xx + zz), 2 * (yz - wx)],
|
||||||
|
[2 * (xz - wy), 2 * (yz + wx), 1 - 2 * (xx + yy)]
|
||||||
|
])
|
||||||
|
return mat
|
||||||
|
|
||||||
|
|
||||||
|
def rot2quat_single(rot):
|
||||||
|
"""
|
||||||
|
Convert a 3x3 rotation matrix to a quaternion.
|
||||||
|
"""
|
||||||
|
trace = np.trace(rot)
|
||||||
|
if trace > 0:
|
||||||
|
s = 0.5 / np.sqrt(trace + 1.0)
|
||||||
|
w = 0.25 / s
|
||||||
|
x = (rot[2, 1] - rot[1, 2]) * s
|
||||||
|
y = (rot[0, 2] - rot[2, 0]) * s
|
||||||
|
z = (rot[1, 0] - rot[0, 1]) * s
|
||||||
|
else:
|
||||||
|
if rot[0, 0] > rot[1, 1] and rot[0, 0] > rot[2, 2]:
|
||||||
|
s = 2.0 * np.sqrt(1.0 + rot[0, 0] - rot[1, 1] - rot[2, 2])
|
||||||
|
w = (rot[2, 1] - rot[1, 2]) / s
|
||||||
|
x = 0.25 * s
|
||||||
|
y = (rot[0, 1] + rot[1, 0]) / s
|
||||||
|
z = (rot[0, 2] + rot[2, 0]) / s
|
||||||
|
elif rot[1, 1] > rot[2, 2]:
|
||||||
|
s = 2.0 * np.sqrt(1.0 + rot[1, 1] - rot[0, 0] - rot[2, 2])
|
||||||
|
w = (rot[0, 2] - rot[2, 0]) / s
|
||||||
|
x = (rot[0, 1] + rot[1, 0]) / s
|
||||||
|
y = 0.25 * s
|
||||||
|
z = (rot[1, 2] + rot[2, 1]) / s
|
||||||
|
else:
|
||||||
|
s = 2.0 * np.sqrt(1.0 + rot[2, 2] - rot[0, 0] - rot[1, 1])
|
||||||
|
w = (rot[1, 0] - rot[0, 1]) / s
|
||||||
|
x = (rot[0, 2] + rot[2, 0]) / s
|
||||||
|
y = (rot[1, 2] + rot[2, 1]) / s
|
||||||
|
z = 0.25 * s
|
||||||
|
|
||||||
|
if w < 0:
|
||||||
|
return np.array([-w, -x, -y, -z])
|
||||||
|
return np.array([w, x, y, z])
|
||||||
|
|
||||||
|
|
||||||
|
def euler2rot_single(euler):
|
||||||
|
"""
|
||||||
|
Convert Euler angles (roll, pitch, yaw) to a 3x3 rotation matrix.
|
||||||
|
Rotation order: Z-Y-X (yaw, pitch, roll).
|
||||||
|
"""
|
||||||
|
phi, theta, psi = euler
|
||||||
|
|
||||||
|
cx, sx = np.cos(phi), np.sin(phi)
|
||||||
|
cy, sy = np.cos(theta), np.sin(theta)
|
||||||
|
cz, sz = np.cos(psi), np.sin(psi)
|
||||||
|
|
||||||
|
Rx = np.array([[1, 0, 0], [0, cx, -sx], [0, sx, cx]])
|
||||||
|
Ry = np.array([[cy, 0, sy], [0, 1, 0], [-sy, 0, cy]])
|
||||||
|
Rz = np.array([[cz, -sz, 0], [sz, cz, 0], [0, 0, 1]])
|
||||||
|
|
||||||
|
return Rz @ Ry @ Rx
|
||||||
|
|
||||||
|
|
||||||
|
def rot2euler_single(rot):
|
||||||
|
"""
|
||||||
|
Convert a 3x3 rotation matrix to Euler angles (roll, pitch, yaw).
|
||||||
|
"""
|
||||||
|
return quat2euler_single(rot2quat_single(rot))
|
||||||
|
|
||||||
|
|
||||||
|
def rot_matrix(roll, pitch, yaw):
|
||||||
|
"""
|
||||||
|
Create a 3x3 rotation matrix from roll, pitch, and yaw angles.
|
||||||
|
"""
|
||||||
|
return euler2rot_single([roll, pitch, yaw])
|
||||||
|
|
||||||
|
|
||||||
|
def axis_angle_to_rot(axis, angle):
|
||||||
|
"""
|
||||||
|
Convert an axis-angle representation to a 3x3 rotation matrix.
|
||||||
|
"""
|
||||||
|
c = np.cos(angle / 2)
|
||||||
|
s = np.sin(angle / 2)
|
||||||
|
q = np.array([c, s*axis[0], s*axis[1], s*axis[2]])
|
||||||
|
return quat2rot_single(q)
|
||||||
|
|
||||||
|
|
||||||
|
class LocalCoord:
|
||||||
|
"""
|
||||||
|
A class to handle conversions between ECEF and local NED coordinates.
|
||||||
|
"""
|
||||||
|
def __init__(self, geodetic=None, ecef=None):
|
||||||
|
"""
|
||||||
|
Initialize LocalCoord with either geodetic or ECEF coordinates.
|
||||||
|
"""
|
||||||
|
if geodetic is not None:
|
||||||
|
self.init_ecef = geodetic2ecef_single(geodetic)
|
||||||
|
lat, lon, _ = geodetic
|
||||||
|
elif ecef is not None:
|
||||||
|
self.init_ecef = np.array(ecef)
|
||||||
|
lat, lon, _ = ecef2geodetic_single(ecef)
|
||||||
|
else:
|
||||||
|
raise ValueError("Must provide geodetic or ecef")
|
||||||
|
|
||||||
|
lat = np.radians(lat)
|
||||||
|
lon = np.radians(lon)
|
||||||
|
|
||||||
|
self.ned2ecef_matrix = np.array([
|
||||||
|
[-np.sin(lat) * np.cos(lon), -np.sin(lon), -np.cos(lat) * np.cos(lon)],
|
||||||
|
[-np.sin(lat) * np.sin(lon), np.cos(lon), -np.cos(lat) * np.sin(lon)],
|
||||||
|
[np.cos(lat), 0, -np.sin(lat)]
|
||||||
|
])
|
||||||
|
self.ecef2ned_matrix = self.ned2ecef_matrix.T
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_geodetic(cls, geodetic):
|
||||||
|
"""
|
||||||
|
Create a LocalCoord instance from geodetic coordinates.
|
||||||
|
"""
|
||||||
|
return cls(geodetic=geodetic)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_ecef(cls, ecef):
|
||||||
|
"""
|
||||||
|
Create a LocalCoord instance from ECEF coordinates.
|
||||||
|
"""
|
||||||
|
return cls(ecef=ecef)
|
||||||
|
|
||||||
|
def ecef2ned_single(self, ecef):
|
||||||
|
"""
|
||||||
|
Convert a single ECEF point to NED coordinates relative to the origin.
|
||||||
|
"""
|
||||||
|
return self.ecef2ned_matrix @ (ecef - self.init_ecef)
|
||||||
|
|
||||||
|
def ned2ecef_single(self, ned):
|
||||||
|
"""
|
||||||
|
Convert a single NED point to ECEF coordinates.
|
||||||
|
"""
|
||||||
|
return self.ned2ecef_matrix @ ned + self.init_ecef
|
||||||
|
|
||||||
|
def geodetic2ned_single(self, geodetic):
|
||||||
|
"""
|
||||||
|
Convert a single geodetic point to NED coordinates.
|
||||||
|
"""
|
||||||
|
ecef = geodetic2ecef_single(geodetic)
|
||||||
|
return self.ecef2ned_single(ecef)
|
||||||
|
|
||||||
|
def ned2geodetic_single(self, ned):
|
||||||
|
"""
|
||||||
|
Convert a single NED point to geodetic coordinates.
|
||||||
|
"""
|
||||||
|
ecef = self.ned2ecef_single(ned)
|
||||||
|
return ecef2geodetic_single(ecef)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ned_from_ecef_matrix(self):
|
||||||
|
"""
|
||||||
|
Returns the rotation matrix from ECEF to NED coordinates.
|
||||||
|
"""
|
||||||
|
return self.ecef2ned_matrix
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ecef_from_ned_matrix(self):
|
||||||
|
"""
|
||||||
|
Returns the rotation matrix from NED to ECEF coordinates.
|
||||||
|
"""
|
||||||
|
return self.ned2ecef_matrix
|
||||||
|
|
||||||
|
|
||||||
|
def ecef_euler_from_ned_single(ecef_init, ned_pose):
|
||||||
|
"""
|
||||||
|
Convert NED Euler angles (roll, pitch, yaw) at a given ECEF origin
|
||||||
|
to equivalent ECEF Euler angles.
|
||||||
|
"""
|
||||||
|
converter = LocalCoord(ecef=ecef_init)
|
||||||
|
zero = np.array(ecef_init)
|
||||||
|
|
||||||
|
x0 = converter.ned2ecef_single([1, 0, 0]) - zero
|
||||||
|
y0 = converter.ned2ecef_single([0, 1, 0]) - zero
|
||||||
|
z0 = converter.ned2ecef_single([0, 0, 1]) - zero
|
||||||
|
|
||||||
|
phi, theta, psi = ned_pose
|
||||||
|
|
||||||
|
x1 = axis_angle_to_rot(z0, psi) @ x0
|
||||||
|
y1 = axis_angle_to_rot(z0, psi) @ y0
|
||||||
|
z1 = axis_angle_to_rot(z0, psi) @ z0
|
||||||
|
|
||||||
|
x2 = axis_angle_to_rot(y1, theta) @ x1
|
||||||
|
y2 = axis_angle_to_rot(y1, theta) @ y1
|
||||||
|
z2 = axis_angle_to_rot(y1, theta) @ z1
|
||||||
|
|
||||||
|
x3 = axis_angle_to_rot(x2, phi) @ x2
|
||||||
|
y3 = axis_angle_to_rot(x2, phi) @ y2
|
||||||
|
|
||||||
|
x0 = np.array([1.0, 0, 0])
|
||||||
|
y0 = np.array([0, 1.0, 0])
|
||||||
|
z0 = np.array([0, 0, 1.0])
|
||||||
|
|
||||||
|
psi_out = np.arctan2(np.dot(x3, y0), np.dot(x3, x0))
|
||||||
|
theta_out = np.arctan2(-np.dot(x3, z0), np.sqrt(np.dot(x3, x0)**2 + np.dot(x3, y0)**2))
|
||||||
|
|
||||||
|
y2 = axis_angle_to_rot(z0, psi_out) @ y0
|
||||||
|
z2 = axis_angle_to_rot(y2, theta_out) @ z0
|
||||||
|
|
||||||
|
phi_out = np.arctan2(np.dot(y3, z2), np.dot(y3, y2))
|
||||||
|
|
||||||
|
return np.array([phi_out, theta_out, psi_out])
|
||||||
|
|
||||||
|
|
||||||
|
def ned_euler_from_ecef_single(ecef_init, ecef_pose):
|
||||||
|
"""
|
||||||
|
Convert ECEF Euler angles (roll, pitch, yaw) at a given ECEF origin
|
||||||
|
to equivalent NED Euler angles.
|
||||||
|
"""
|
||||||
|
converter = LocalCoord(ecef=ecef_init)
|
||||||
|
|
||||||
|
x0 = np.array([1.0, 0, 0])
|
||||||
|
y0 = np.array([0, 1.0, 0])
|
||||||
|
z0 = np.array([0, 0, 1.0])
|
||||||
|
|
||||||
|
phi, theta, psi = ecef_pose
|
||||||
|
|
||||||
|
x1 = axis_angle_to_rot(z0, psi) @ x0
|
||||||
|
y1 = axis_angle_to_rot(z0, psi) @ y0
|
||||||
|
z1 = axis_angle_to_rot(z0, psi) @ z0
|
||||||
|
|
||||||
|
x2 = axis_angle_to_rot(y1, theta) @ x1
|
||||||
|
y2 = axis_angle_to_rot(y1, theta) @ y1
|
||||||
|
z2 = axis_angle_to_rot(y1, theta) @ z1
|
||||||
|
|
||||||
|
x3 = axis_angle_to_rot(x2, phi) @ x2
|
||||||
|
y3 = axis_angle_to_rot(x2, phi) @ y2
|
||||||
|
|
||||||
|
zero = np.array(ecef_init)
|
||||||
|
x0 = converter.ned2ecef_single([1, 0, 0]) - zero
|
||||||
|
y0 = converter.ned2ecef_single([0, 1, 0]) - zero
|
||||||
|
z0 = converter.ned2ecef_single([0, 0, 1]) - zero
|
||||||
|
|
||||||
|
psi_out = np.arctan2(np.dot(x3, y0), np.dot(x3, x0))
|
||||||
|
theta_out = np.arctan2(-np.dot(x3, z0), np.sqrt(np.dot(x3, x0)**2 + np.dot(x3, y0)**2))
|
||||||
|
|
||||||
|
y2 = axis_angle_to_rot(z0, psi_out) @ y0
|
||||||
|
z2 = axis_angle_to_rot(y2, theta_out) @ z0
|
||||||
|
|
||||||
|
phi_out = np.arctan2(np.dot(y3, z2), np.dot(y3, y2))
|
||||||
|
|
||||||
|
return np.array([phi_out, theta_out, psi_out])
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
# 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(<double*>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
|
|
||||||
Binary file not shown.
+4
-4
@@ -181,9 +181,9 @@ bool file_exists(const std::string& fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool createDirectory(std::string dir, mode_t mode) {
|
static bool createDirectory(std::string dir, mode_t mode) {
|
||||||
auto verify_dir = [](const std::string& dir) -> bool {
|
auto verify_dir = [](const std::string& path) -> bool {
|
||||||
struct stat st = {};
|
struct stat st = {};
|
||||||
return (stat(dir.c_str(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR);
|
return (stat(path.c_str(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR);
|
||||||
};
|
};
|
||||||
// remove trailing /'s
|
// remove trailing /'s
|
||||||
while (dir.size() > 1 && dir.back() == '/') {
|
while (dir.size() > 1 && dir.back() == '/') {
|
||||||
@@ -288,7 +288,7 @@ std::string strip(const std::string &str) {
|
|||||||
std::string check_output(const std::string& command) {
|
std::string check_output(const std::string& command) {
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
std::string result;
|
std::string result;
|
||||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(command.c_str(), "r"), pclose);
|
std::unique_ptr<FILE, int(*)(FILE*)> pipe(popen(command.c_str(), "r"), pclose);
|
||||||
|
|
||||||
if (!pipe) {
|
if (!pipe) {
|
||||||
return "";
|
return "";
|
||||||
@@ -303,7 +303,7 @@ std::string check_output(const std::string& command) {
|
|||||||
|
|
||||||
bool system_time_valid() {
|
bool system_time_valid() {
|
||||||
// Default to August 26, 2024
|
// Default to August 26, 2024
|
||||||
tm min_tm = {.tm_year = 2024 - 1900, .tm_mon = 7, .tm_mday = 26};
|
tm min_tm = {.tm_mday = 26, .tm_mon = 7, .tm_year = 2024 - 1900};
|
||||||
time_t min_date = mktime(&min_tm);
|
time_t min_date = mktime(&min_tm);
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ const double MS_TO_KPH = 3.6;
|
|||||||
const double MS_TO_MPH = MS_TO_KPH * KM_TO_MILE;
|
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_MILE = KM_TO_MILE / 1000.0;
|
||||||
const double METER_TO_FOOT = 3.28084;
|
const double METER_TO_FOOT = 3.28084;
|
||||||
|
const double METER_TO_KM = 1. / 1000.0;
|
||||||
|
|
||||||
#define ALIGNED_SIZE(x, align) (((x) + (align)-1) & ~((align)-1))
|
#define ALIGNED_SIZE(x, align) (((x) + (align)-1) & ~((align)-1))
|
||||||
|
|
||||||
@@ -96,6 +97,13 @@ bool create_directories(const std::string &dir, mode_t mode);
|
|||||||
|
|
||||||
std::string check_output(const std::string& command);
|
std::string check_output(const std::string& command);
|
||||||
|
|
||||||
|
inline void check_system(const std::string& cmd) {
|
||||||
|
int ret = std::system(cmd.c_str());
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "system command failed (%d): %s\n", ret, cmd.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool system_time_valid();
|
bool system_time_valid();
|
||||||
|
|
||||||
inline void sleep_for(const int milliseconds) {
|
inline void sleep_for(const int milliseconds) {
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
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
|
|
||||||
+272
@@ -0,0 +1,272 @@
|
|||||||
|
import io
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
import contextlib
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
import functools
|
||||||
|
from subprocess import Popen, PIPE, TimeoutExpired
|
||||||
|
import zstandard as zstd
|
||||||
|
|
||||||
|
LOG_COMPRESSION_LEVEL = 10 # little benefit up to level 15. level ~17 is a small step change
|
||||||
|
|
||||||
|
class Timer:
|
||||||
|
"""Simple lap timer for profiling sequential operations."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._start = self._lap = time.monotonic()
|
||||||
|
self._sections = {}
|
||||||
|
|
||||||
|
def lap(self, name):
|
||||||
|
now = time.monotonic()
|
||||||
|
self._sections[name] = now - self._lap
|
||||||
|
self._lap = now
|
||||||
|
|
||||||
|
@property
|
||||||
|
def total(self):
|
||||||
|
return time.monotonic() - self._start
|
||||||
|
|
||||||
|
def fmt(self, duration):
|
||||||
|
parts = ", ".join(f"{k}={v:.2f}s" + (f" ({duration/v:.0f}x)" if k == 'render' and v > 0 else "") for k, v in self._sections.items())
|
||||||
|
total = self.total
|
||||||
|
realtime = f"{duration/total:.1f}x realtime" if total > 0 else "N/A"
|
||||||
|
return f"{duration}s in {total:.1f}s ({realtime}) | {parts}"
|
||||||
|
|
||||||
|
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(["sudo", "cat", "--", path], 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
|
||||||
|
|
||||||
|
|
||||||
|
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(path: str, mode: str = 'w', buffering: int = -1, encoding: str | None = None, newline: str | None = 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
|
||||||
|
|
||||||
|
|
||||||
|
# remove all keys that end in DEPRECATED, plus any "deprecated" group
|
||||||
|
def strip_deprecated_keys(d):
|
||||||
|
for k in list(d.keys()):
|
||||||
|
if isinstance(k, str):
|
||||||
|
if k.endswith('DEPRECATED') or k == 'deprecated':
|
||||||
|
d.pop(k)
|
||||||
|
elif isinstance(d[k], dict):
|
||||||
|
strip_deprecated_keys(d[k])
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.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()
|
||||||
|
|
||||||
|
|
||||||
|
def tabulate(tabular_data, headers=(), tablefmt="simple", floatfmt="g", stralign="left", numalign=None):
|
||||||
|
rows = [list(row) for row in tabular_data]
|
||||||
|
|
||||||
|
def fmt(val):
|
||||||
|
if isinstance(val, str):
|
||||||
|
return val
|
||||||
|
if isinstance(val, (bool, int)):
|
||||||
|
return str(val)
|
||||||
|
try:
|
||||||
|
return format(val, floatfmt)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return str(val)
|
||||||
|
|
||||||
|
formatted = [[fmt(c) for c in row] for row in rows]
|
||||||
|
hdrs = [str(h) for h in headers] if headers else None
|
||||||
|
|
||||||
|
ncols = max((len(r) for r in formatted), default=0)
|
||||||
|
if hdrs:
|
||||||
|
ncols = max(ncols, len(hdrs))
|
||||||
|
if ncols == 0:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
for r in formatted:
|
||||||
|
r.extend([""] * (ncols - len(r)))
|
||||||
|
if hdrs:
|
||||||
|
hdrs.extend([""] * (ncols - len(hdrs)))
|
||||||
|
|
||||||
|
widths = [0] * ncols
|
||||||
|
if hdrs:
|
||||||
|
for i in range(ncols):
|
||||||
|
widths[i] = len(hdrs[i])
|
||||||
|
for row in formatted:
|
||||||
|
for i in range(ncols):
|
||||||
|
widths[i] = max(widths[i], max(len(ln) for ln in row[i].split('\n')))
|
||||||
|
|
||||||
|
def _align(s, w):
|
||||||
|
if stralign == "center":
|
||||||
|
return s.center(w)
|
||||||
|
return s.ljust(w)
|
||||||
|
|
||||||
|
if tablefmt == "html":
|
||||||
|
parts = ["<table>"]
|
||||||
|
if hdrs:
|
||||||
|
parts.append("<thead>")
|
||||||
|
parts.append("<tr>" + "".join(f"<th>{h}</th>" for h in hdrs) + "</tr>")
|
||||||
|
parts.append("</thead>")
|
||||||
|
parts.append("<tbody>")
|
||||||
|
for row in formatted:
|
||||||
|
parts.append("<tr>" + "".join(f"<td>{c}</td>" for c in row) + "</tr>")
|
||||||
|
parts.append("</tbody>")
|
||||||
|
parts.append("</table>")
|
||||||
|
return "\n".join(parts)
|
||||||
|
|
||||||
|
if tablefmt == "simple_grid":
|
||||||
|
def _sep(left, mid, right):
|
||||||
|
return left + mid.join("\u2500" * (w + 2) for w in widths) + right
|
||||||
|
|
||||||
|
top, mid_sep, bot = _sep("\u250c", "\u252c", "\u2510"), _sep("\u251c", "\u253c", "\u2524"), _sep("\u2514", "\u2534", "\u2518")
|
||||||
|
|
||||||
|
def _fmt_row(cells):
|
||||||
|
split = [c.split('\n') for c in cells]
|
||||||
|
nlines = max(len(s) for s in split)
|
||||||
|
for s in split:
|
||||||
|
s.extend([""] * (nlines - len(s)))
|
||||||
|
return ["\u2502" + "\u2502".join(f" {_align(split[i][li], widths[i])} " for i in range(ncols)) + "\u2502" for li in range(nlines)]
|
||||||
|
|
||||||
|
lines = [top]
|
||||||
|
if hdrs:
|
||||||
|
lines.extend(_fmt_row(hdrs))
|
||||||
|
lines.append(mid_sep)
|
||||||
|
for ri, row in enumerate(formatted):
|
||||||
|
lines.extend(_fmt_row(row))
|
||||||
|
lines.append(mid_sep if ri < len(formatted) - 1 else bot)
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
# simple
|
||||||
|
gap = " "
|
||||||
|
lines = []
|
||||||
|
if hdrs:
|
||||||
|
lines.append(gap.join(h.ljust(w) for h, w in zip(hdrs, widths, strict=True)))
|
||||||
|
lines.append(gap.join("-" * w for w in widths))
|
||||||
|
for row in formatted:
|
||||||
|
lines.append(gap.join(_align(row[i], widths[i]) for i in range(ncols)))
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
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:
|
||||||
|
print(f"{func.__name__} failed, trying again")
|
||||||
|
time.sleep(delay)
|
||||||
|
|
||||||
|
if ignore_failure:
|
||||||
|
print(f"{func.__name__} failed after retry")
|
||||||
|
else:
|
||||||
|
raise Exception(f"{func.__name__} failed after retry")
|
||||||
|
return wrapper
|
||||||
|
return decorator
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
#define COMMA_VERSION "0.10.1"
|
#define COMMA_VERSION "0.11.2"
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
#include <string>
|
|
||||||
|
|
||||||
#include "common/watchdog.h"
|
|
||||||
#include "common/util.h"
|
|
||||||
#include "system/hardware/hw.h"
|
|
||||||
|
|
||||||
const std::string watchdog_fn_prefix = Path::shm_path() + "/wd_"; // + <pid>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user