Compare commits

..

119 Commits

Author SHA1 Message Date
DevTekVE 10124e8e4e Merge branch 'master-new-ESCC' into mads-new-rework
# Conflicts:
#	panda
2024-11-15 19:53:03 +01:00
DevTekVE 1039cac2fd Refactor ACC command parameters order
Rearrange parameters in the `create_acc_commands` function to prioritize `CS.main_cruise_enabled` over `self.ESCC`. This change aligns with the desired order of priorities and improves readability.
2024-11-15 19:50:31 +01:00
DevTekVE 1700f6cdb0 Refactor type hinting for CarState in update method
Changed the type hinting of the CS parameter from structs.CarState to CarState in the update method. This aligns the code with the current naming conventions and improves readability.
2024-11-15 19:50:31 +01:00
DevTekVE 747db17aa1 Refactor spFlags to safetyParam2DEPRECATED
Updated Hyundai car state and interface files to use `sunnyParams.flags` instead of `spFlags` for consistency. This included changes in the conditional checks and flag assignments. The car.capnp struct was also modified to rename `spFlags` to `safetyParam2DEPRECATED`.
2024-11-15 19:50:30 +01:00
DevTekVE 9be2f5628d Remove MADS components and migrate to Opendbc repo
The Modular Assistive Driving System (MADS) related files and tests have been removed from the sunnypilot directory. MADS functionality has been migrated to the opendbc repository, streamlining its structure and integration.
2024-11-15 19:50:30 +01:00
Jason Wen 60d6e7efce fix panda safety 2024-11-15 12:19:16 -05:00
Jason Wen ba11b97c59 Rename 2024-11-15 12:03:28 -05:00
Jason Wen aaf35b391e check if engagement is from openpilot's state machine 2024-11-15 11:45:11 -05:00
Jason Wen a3c9d72a1e not needed 2024-11-15 11:40:18 -05:00
Jason Wen 6fa78b1db4 more fix 2024-11-15 11:39:13 -05:00
Jason Wen 8f0639ca6c combine 2024-11-15 11:34:01 -05:00
Jason Wen 6a0bc76e63 fix 2024-11-15 11:32:15 -05:00
Jason Wen 23e27bea92 make sure to disengage for allow always cars 2024-11-15 11:29:38 -05:00
Jason Wen 3be1fde36b Fix? 2024-11-15 09:01:12 -05:00
Jason Wen 473349e7b7 rename 2024-11-15 07:32:33 -05:00
Jason Wen 71ffd05027 fix 2024-11-15 07:31:41 -05:00
Jason Wen ab8547d04b bump opendbc 2024-11-15 07:17:21 -05:00
Jason Wen 74eacd2d44 apply pause/resume fix for hyundai (should do this in a separate PR) 2024-11-15 07:17:11 -05:00
Jason Wen 6a059c6877 bump panda 2024-11-15 07:10:14 -05:00
DevTekVE eb9b9a13ff Merge remote-tracking branch 'origin/master-new' into mads-new
# Conflicts:
#	panda
#	selfdrive/ui/qt/offroad/developer_panel.cc
2024-11-15 09:32:22 +01:00
DevTekVE 1d4da71784 bump opendbc 2024-11-15 09:30:50 +01:00
DevTekVE 094b856509 Sync up submodules for ESCC 2024-11-15 08:27:27 +01:00
DevTekVE 3da0dfd47f Updating submodules 2024-11-15 08:16:52 +01:00
Jason Wen 6edaf619bf Add Custom MIT License (#438) 2024-11-15 08:11:51 +01:00
Jason Wen 82510dc48c allow re-regage 2024-11-14 23:41:19 -05:00
Jason Wen 5c6750b2ad bump opendbc 2024-11-14 23:34:07 -05:00
Jason Wen a13e5816bb enforce main 2024-11-14 23:34:02 -05:00
Jason Wen e1b2b10638 add logging for controls allowed lateral 2024-11-14 23:09:11 -05:00
Jason Wen 58fb1b44b6 hyundai: main button heartbeat 2024-11-14 22:29:38 -05:00
Jason Wen d78e66deef hyundai: main button handling 2024-11-14 21:46:47 -05:00
Jason Wen 4b1920ecce handle non drive gear events 2024-11-14 20:24:36 -05:00
Jason Wen dc45bda8b8 no longer needed 2024-11-14 20:00:20 -05:00
Jason Wen b824810be2 bump panda 2024-11-14 20:00:06 -05:00
Jason Wen 08962ad619 hkg always allow 2024-11-14 19:59:52 -05:00
Jason Wen 652a24f13e only allow lateral when cruise main or state is on 2024-11-14 17:19:23 -05:00
Jason Wen ca92ffcb57 rename 2024-11-14 17:05:35 -05:00
Jason Wen 80ebb43365 simply checks 2024-11-14 16:59:56 -05:00
Jason Wen 23f417f450 properly 2024-11-13 23:40:44 -05:00
Jason Wen e63ad5a011 handle available better 2024-11-13 22:44:22 -05:00
Jason Wen b8a82755e6 support toyota and ford 2024-11-13 20:57:38 -05:00
Jason Wen 70e7747f74 cruise main engage 2024-11-13 20:55:14 -05:00
Jason Wen de1b084902 enforce cruise main disengage 2024-11-13 20:39:47 -05:00
Jason Wen 097c976a49 Make sure to disengage with long engaged 2024-11-13 20:21:41 -05:00
Jason Wen 5efd1d63bb Unified Engagement Mode: more 2024-11-13 20:15:02 -05:00
Jason Wen fa3ce0e2a3 add TODO 2024-11-13 20:06:00 -05:00
Jason Wen 835cb71e3b refactor mads params read 2024-11-13 20:04:40 -05:00
Jason Wen 4603fd0f03 Unified Engagement Mode: init 2024-11-13 19:59:19 -05:00
Jason Wen 7f2660d0ad only when mads toggle is enabled 2024-11-13 19:47:51 -05:00
Jason Wen aa0f588248 change events 2024-11-13 19:42:05 -05:00
Jason Wen e3e65de225 add lkas enable and disable events 2024-11-13 19:26:22 -05:00
Jason Wen 37b461a591 unused 2024-11-13 16:57:26 -05:00
Jason Wen 2f09489746 enable should carry over from selfdrived 2024-11-13 13:33:00 -05:00
Jason Wen a9c1e7e277 Expose in settings 2024-11-13 13:25:55 -05:00
Jason Wen ca0020e613 should be the whole class 2024-11-13 13:12:24 -05:00
Jason Wen 5326b18130 set alt experience in helpers 2024-11-13 13:12:18 -05:00
Jason Wen c99299af1f no longer needed 2024-11-13 12:56:42 -05:00
Jason Wen 9422a3cf47 implement params 2024-11-13 12:54:02 -05:00
Jason Wen 872abdda17 this is checked after selfdrived states 2024-11-13 11:16:42 -05:00
Jason Wen 1c2e9bd5b1 inherit in carcontroller properly 2024-11-13 03:07:29 -05:00
Jason Wen 70cf693d15 bump panda 2024-11-13 02:38:25 -05:00
Jason Wen 06dc945b09 consolidate 2024-11-13 02:18:29 -05:00
Jason Wen 8fc21127bd use old copy as checks 2024-11-13 02:15:44 -05:00
Jason Wen eecffb9c8a should be here 2024-11-13 02:08:17 -05:00
Jason Wen 71eb28e1d8 Revert "update in method"
This reverts commit 0403a48e88.
2024-11-13 01:21:12 -05:00
Jason Wen e605398f55 Revert "reorder"
This reverts commit 1a988c716d.
2024-11-13 01:21:12 -05:00
Jason Wen 1a988c716d reorder 2024-11-13 01:18:51 -05:00
Jason Wen 0403a48e88 update in method 2024-11-13 01:15:22 -05:00
Jason Wen d9fb57e5f8 Revert "do it prior"
This reverts commit b38798c1a5.
2024-11-13 00:58:37 -05:00
Jason Wen b38798c1a5 do it prior 2024-11-13 00:00:08 -05:00
Jason Wen 555a753f4c brake check was not handled 2024-11-12 22:52:05 -05:00
Jason Wen 8485cd2013 make sure it's either or 2024-11-12 22:00:44 -05:00
Jason Wen 0fa1ff07f5 try this out 2024-11-12 19:58:22 -05:00
Jason Wen d2cbdeb683 take them out for all modes 2024-11-12 19:14:37 -05:00
Jason Wen 7c633afe7e skip pedal pressed for MADS 2024-11-12 17:53:50 -05:00
Jason Wen e5a34e9023 add always available for hyundai 2024-11-12 17:53:25 -05:00
Jason Wen 81708364b8 new logic 2024-11-12 16:15:27 -05:00
Jason Wen e0e940dd55 do this 2024-11-12 09:17:21 -05:00
Jason Wen c0b92dee04 more fixes 2024-11-11 22:17:11 -05:00
Jason Wen 249e7c2fa2 fixes 2024-11-11 20:46:56 -05:00
Jason Wen fae91beaae better 2024-11-11 20:38:10 -05:00
Jason Wen 376cbbdf83 missed 2024-11-11 20:28:00 -05:00
Jason Wen b497bc607f reset as it should 2024-11-11 09:46:47 -05:00
Jason Wen 90a1ff46b4 Merge branch 'master-new' into mads-new
# Conflicts:
#	cereal/car.capnp
#	cereal/car.capnp~HEAD
#	opendbc_repo
#	panda
2024-11-11 08:23:13 -05:00
DevTekVE c05191949a Updating submodules 2024-11-02 19:15:58 +01:00
Jason Wen 9d5ea83f5a Add Custom MIT License (#438) 2024-11-02 18:53:31 +01:00
Jason Wen 6a74dc253b typo! 2024-09-30 22:47:24 -04:00
Jason Wen 434a89d83e move to card 2024-09-30 18:51:36 -04:00
Jason Wen 20e6dc4246 hkg dbc 2024-09-30 17:03:50 -04:00
Jason Wen 96b5b7caeb more fix 2024-09-30 16:58:25 -04:00
Jason Wen 85cdce477e fix typo 2024-09-30 16:42:59 -04:00
Jason Wen cc06b0271c fix typo 2024-09-30 16:40:13 -04:00
Jason Wen e67833ae7d add events 2024-09-30 16:37:11 -04:00
Jason Wen 42e3061748 Merge branch 'master' into mads-new 2024-09-30 16:31:52 -04:00
Jason Wen 738484e628 some cleanup 2024-09-30 16:28:18 -04:00
Jason Wen 519ab8ec3e traditional state machine with tests 2024-09-30 16:18:59 -04:00
Jason Wen 00bc34b125 test 2024-09-30 15:33:44 -04:00
Jason Wen ff87abb45b comments 2024-09-30 11:04:56 -04:00
Jason Wen 000bb1b5b3 explicit 2024-09-30 10:56:30 -04:00
Jason Wen 7c95b43e1a should append 2024-09-30 10:45:00 -04:00
Jason Wen 9570a9240f fix type hint 2024-09-30 10:42:57 -04:00
Jason Wen 676702ae3c fixes 2024-09-29 22:43:18 -04:00
Jason Wen c27b112bbc misra 2024-09-29 12:27:50 -04:00
Jason Wen 0a1a878897 Merge branch 'master' into mads-new
# Conflicts:
#	opendbc_repo
#	panda
2024-09-29 12:11:54 -04:00
Jason Wen 3a593f85dc more 2024-09-29 12:00:46 -04:00
Jason Wen 6db0d94b83 cleanup 2024-09-29 11:58:38 -04:00
Jason Wen 66b900aea6 clearer 2024-09-29 11:55:36 -04:00
Jason Wen 9c57f6bad0 not really 2024-09-29 11:45:47 -04:00
Jason Wen 1b64a7debd move around 2024-09-29 11:30:39 -04:00
Jason Wen bd19439a4c move around 2024-09-29 11:28:27 -04:00
Jason Wen 18a237c0c0 more update 2024-09-29 11:25:19 -04:00
Jason Wen dd5ff7e1d3 fix 2024-09-29 11:20:30 -04:00
Jason Wen 515c00c379 fix 2024-09-20 00:01:41 -04:00
Jason Wen 7dc4073c9b safety init 2024-09-19 00:46:26 -04:00
Jason Wen a9c775bffe no need 2024-09-18 09:01:13 -04:00
Jason Wen c06d8db015 alternative experience 2024-09-18 08:57:58 -04:00
Jason Wen 8bb6c8fc17 some more infra 2024-09-18 08:22:13 -04:00
Jason Wen d58be609ac more infra 2024-09-18 07:33:23 -04:00
Jason Wen 434fab00f3 more 2024-09-18 07:15:51 -04:00
Jason Wen 8e62914e69 Modified Assist Driving System: init 2024-09-18 07:15:51 -04:00
175 changed files with 3285 additions and 3972 deletions
+3
View File
@@ -0,0 +1,3 @@
.Xauthority
.env
.host/
+18
View File
@@ -0,0 +1,18 @@
FROM ghcr.io/commaai/openpilot-base:latest
RUN apt update && apt install -y vim net-tools usbutils htop ripgrep tmux wget mesa-utils xvfb libxtst6 libxv1 libglu1-mesa gdb bash-completion
RUN python3 -m ensurepip --upgrade
RUN pip3 install ipython jupyter jupyterlab
RUN cd /tmp && \
ARCH=$(arch | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) && \
curl -L -o virtualgl.deb "https://github.com/VirtualGL/virtualgl/releases/download/3.1.1/virtualgl_3.1.1_$ARCH.deb" && \
dpkg -i virtualgl.deb
RUN usermod -aG video batman
USER batman
RUN cd $HOME && \
curl -O https://raw.githubusercontent.com/commaai/agnos-builder/master/userspace/home/.tmux.conf && \
curl -O https://raw.githubusercontent.com/commaai/agnos-builder/master/userspace/home/.vimrc
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
TARGET_USER=batman
source .devcontainer/.host/.env
# override display flag for mac hosts
if [[ $HOST_OS == darwin ]]; then
echo "Setting up DISPLAY override for macOS..."
cat <<EOF >> /home/$TARGET_USER/.bashrc
source .devcontainer/.host/.env
if [ -n "\$HOST_DISPLAY" ]; then
DISPLAY_NUM=\$(echo "\$HOST_DISPLAY" | awk -F: '{print \$NF}')
export DISPLAY=host.docker.internal:\$DISPLAY_NUM
fi
EOF
fi
# setup virtualgl for mac hosts
if [[ $HOST_OS == darwin ]]; then
echo "Setting up virtualgl for macOS..."
cat <<EOF >> /home/$TARGET_USER/.bashrc
if [ -n "\$HOST_DISPLAY" ]; then
export VGL_PORT=10000
export VGL_CLIENT=host.docker.internal
export VGL_COMPRESS=rgb
export VGL_DISPLAY=:99
export VGL_FPS=60
# prevent vglrun from running exec
alias exec=:; source vglrun :; unalias exec
fi
EOF
fi
# These lines are temporary, to remain backwards compatible with old devcontainers
# that were running as root and therefore had their caches written as root
sudo chown -R $TARGET_USER: /tmp/scons_cache
sudo chown -R $TARGET_USER: /tmp/comma_download_cache
sudo chown -R $TARGET_USER: /home/batman/.comma
+15
View File
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
source .devcontainer/.host/.env
# setup safe directories for submodules
SUBMODULE_DIRS=$(git config --file .gitmodules --get-regexp path | awk '{ print $2 }')
for DIR in $SUBMODULE_DIRS; do
git config --global --add safe.directory "$PWD/$DIR"
done
# virtual display for virtualgl
if [[ "$HOST_OS" == "darwin" ]] && [[ -n "$HOST_DISPLAY" ]]; then
echo "Starting virtual display at :99 ..."
tmux new-session -d -s fakedisplay Xvfb :99 -screen 0 1920x1080x24
fi
+53
View File
@@ -0,0 +1,53 @@
{
"name": "openpilot devcontainer",
"build": {
"dockerfile": "Dockerfile"
},
"postCreateCommand": ".devcontainer/container_post_create.sh",
"postStartCommand": ".devcontainer/container_post_start.sh",
"initializeCommand": [".devcontainer/host_setup"],
"privileged": true,
"containerEnv": {
"DISPLAY": "${localEnv:DISPLAY}",
"PYTHONPATH": "${containerWorkspaceFolder}",
"TERM": "xterm-256color",
"force_color_prompt": "1"
},
"runArgs": [
"--volume=/dev:/dev",
"--volume=/tmp/.X11-unix:/tmp/.X11-unix",
"--volume=${localWorkspaceFolder}/.devcontainer/.host/.Xauthority:/home/batman/.Xauthority",
"--volume=${localEnv:HOME}/.comma:/home/batman/.comma",
"--volume=${localEnv:HOME}/.azure:/home/batman/.azure",
"--volume=/tmp/comma_download_cache:/tmp/comma_download_cache",
"--shm-size=1G",
"--add-host=host.docker.internal:host-gateway", // required to use host.docker.internal on linux
"--publish=0.0.0.0:8070-8079:8070-8079" // body ZMQ services
],
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": false,
"installOhMyZsh": false,
"upgradePackages": false,
"username": "batman"
},
"ghcr.io/devcontainers-contrib/features/gh-cli:1": {},
"ghcr.io/devcontainers/features/azure-cli:1": {}
},
"containerUser": "batman",
"remoteUser": "batman",
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-vscode.cpptools",
"ms-toolsai.jupyter",
"guyskk.language-cython",
"lharri73.dbc"
]
}
},
"mounts": [
"type=volume,source=scons_cache,target=/tmp/scons_cache"
]
}
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# pull base image
if [[ -z $USE_LOCAL_IMAGE ]]; then
echo "Updating openpilot_base image if needed..."
docker pull ghcr.io/commaai/openpilot-base:latest
fi
# setup .host dir
mkdir -p .devcontainer/.host
# setup links to Xauthority
XAUTHORITY_LINK=".devcontainer/.host/.Xauthority"
rm -f $XAUTHORITY_LINK
if [[ -z $XAUTHORITY ]]; then
echo "XAUTHORITY not set. Fallback to ~/.Xauthority ..."
if ! [[ -f $HOME/.Xauthority ]]; then
echo "~/.XAuthority file does not exist. GUI tools may not work properly."
touch $XAUTHORITY_LINK # dummy file to satisfy container volume mount
else
ln -sf $HOME/.Xauthority $XAUTHORITY_LINK
fi
else
ln -sf $XAUTHORITY $XAUTHORITY_LINK
fi
# setup host env file
HOST_INFO_FILE=".devcontainer/.host/.env"
SYSTEM=$(uname -s | tr '[:upper:]' '[:lower:]')
echo "HOST_OS=\"$SYSTEM\"" > $HOST_INFO_FILE
echo "HOST_DISPLAY=\"$DISPLAY\"" >> $HOST_INFO_FILE
# run virtualgl if macos
if [[ $SYSTEM == "darwin" ]]; then
echo
if [[ -f /opt/VirtualGL/bin/vglclient ]]; then
echo "Starting VirtualGL client at port 10000..."
VGL_LOG_FILE=".devcontainer/.host/.vgl/vglclient.log"
mkdir -p "$(dirname $VGL_LOG_FILE)"
/opt/VirtualGL/bin/vglclient -l "$VGL_LOG_FILE" -display "$DISPLAY" -port 10000 -detach
else
echo "VirtualGL not found. GUI tools may not work properly. Some GUI tools require OpenGL to work properly. To use them with XQuartz on mac, VirtualGL needs to be installed. To install it run:"
echo
echo " brew install --cask virtualgl"
echo
fi
fi
+10
View File
@@ -0,0 +1,10 @@
:: pull base image
IF NOT DEFINED USE_LOCAL_IMAGE ^
echo "Updating openpilot_base image if needed..." && ^
docker pull ghcr.io/commaai/openpilot-base:latest
:: setup .host dir
mkdir .devcontainer\.host
:: setup host env file
echo "" > .devcontainer\.host\.env
+1 -1
View File
@@ -8,7 +8,7 @@ assignees: ''
**Checklist**
- [ ] added entry to CAR in selfdrive/car/*/values.py and ran `selfdrive/car/docs.py` to generate new docs
- [ ] added entry to CAR in selfdrive/car/*/values.py and ran `selfdrive/opcar/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:
+1 -1
View File
@@ -44,7 +44,7 @@ Explain how you tested this bug fix.
**Checklist**
- [ ] added entry to CAR in selfdrive/car/*/values.py and ran `selfdrive/car/docs.py` to generate new docs
- [ ] added entry to CAR in selfdrive/car/*/values.py and ran `selfdrive/opcar/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:
-9
View File
@@ -14,25 +14,17 @@ inputs:
description: 'whether to save the cache'
default: 'false'
required: false
outputs:
cache-hit:
description: 'cache hit occurred'
value: ${{ (contains(runner.name, 'nsc') && steps.ns-cache.outputs.cache-hit) ||
(!contains(runner.name, 'nsc') && inputs.save != 'false' && steps.gha-cache.outputs.cache-hit) ||
(!contains(runner.name, 'nsc') && inputs.save == 'false' && steps.gha-cache-ro.outputs.cache-hit) }}
runs:
using: "composite"
steps:
- name: setup namespace cache
id: ns-cache
if: ${{ contains(runner.name, 'nsc') }}
uses: namespacelabs/nscloud-cache-action@v1
with:
path: ${{ inputs.path }}
- name: setup github cache
id: gha-cache
if: ${{ !contains(runner.name, 'nsc') && inputs.save != 'false' }}
uses: 'actions/cache@v4'
with:
@@ -41,7 +33,6 @@ runs:
restore-keys: ${{ inputs.restore-keys }}
- name: setup github cache
id: gha-cache-ro
if: ${{ !contains(runner.name, 'nsc') && inputs.save == 'false' }}
uses: 'actions/cache/restore@v4'
with:
+4
View File
@@ -15,3 +15,7 @@ jobs:
uses: commaai/openpilot/.github/workflows/selfdrive_tests.yaml@master
with:
run_number: ${{ inputs.run_number }}
tools_tests:
uses: commaai/openpilot/.github/workflows/tools_tests.yaml@master
with:
run_number: ${{ inputs.run_number }}
+1 -2
View File
@@ -19,9 +19,8 @@ jobs:
docs:
name: build docs
runs-on: ubuntu-latest
timeout-minutes: 1
steps:
- uses: commaai/timeout@v1
- uses: actions/checkout@v4
with:
submodules: true
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
git add .
- name: update car docs
run: |
scons -j$(nproc) --minimal opendbc_repo
scons -j$(nproc) --minimal opendbc
PYTHONPATH=. python selfdrive/car/docs.py
git add docs/CARS.md
- name: Create Pull Request
+68 -32
View File
@@ -32,9 +32,9 @@ env:
jobs:
build_release:
name: build release
runs-on:
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
((github.event_name != 'pull_request') ||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-latest' }}
env:
STRIPPED_DIR: /tmp/releasepilot
steps:
@@ -75,9 +75,15 @@ jobs:
${{ env.RUN }} "scripts/lint/lint.sh --skip check_added_large_files"
build:
runs-on:
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
strategy:
matrix:
arch: ${{ fromJson(
((github.repository == 'commaai/openpilot') &&
((github.event_name != 'pull_request') ||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && '["x86_64", "aarch64"]' || '["x86_64"]' ) }}
runs-on: ${{ ((matrix.arch == 'aarch64') && 'namespace-profile-arm64-2x8') ||
((matrix.arch == 'x86_64') && ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16') ||
'ubuntu-latest'}}
steps:
- uses: actions/checkout@v4
with:
@@ -86,14 +92,17 @@ jobs:
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot'
run: |
echo "PUSH_IMAGE=true" >> "$GITHUB_ENV"
echo "TARGET_ARCHITECTURE=${{ matrix.arch }}" >> "$GITHUB_ENV"
$DOCKER_LOGIN
- uses: ./.github/workflows/setup-with-retry
with:
docker_hub_pat: ${{ secrets.DOCKER_HUB_PAT }}
- uses: ./.github/workflows/compile-openpilot
timeout-minutes: 30
timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 15 || 30) }} # allow more time when we missed the scons cache
build_mac:
name: build macOS
runs-on: ${{ github.repository == 'commaai/openpilot' && 'namespace-profile-macos-8x14' || 'macos-latest' }}
runs-on: namespace-profile-macos-8x14
steps:
- uses: actions/checkout@v4
with:
@@ -116,11 +125,28 @@ jobs:
- name: Building openpilot
run: . .venv/bin/activate && scons -j$(nproc)
docker_push_multiarch:
name: docker push multiarch tag
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot'
needs: [build]
steps:
- uses: actions/checkout@v4
with:
submodules: false
- name: Setup docker
run: |
$DOCKER_LOGIN
- name: Merge x64 and arm64 tags
run: |
export PUSH_IMAGE=true
scripts/retry.sh selfdrive/test/docker_tag_multiarch.sh base x86_64 aarch64
static_analysis:
name: static analysis
runs-on:
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
((github.event_name != 'pull_request') ||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
env:
PYTHONWARNINGS: default
steps:
@@ -134,16 +160,24 @@ jobs:
unit_tests:
name: unit tests
runs-on:
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
((github.event_name != 'pull_request') ||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
with:
docker_hub_pat: ${{ secrets.DOCKER_HUB_PAT }}
- name: Build openpilot
timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 10 || 30) }} # allow more time when we missed the scons cache
run: ${{ env.RUN }} "scons -j$(nproc)"
- name: Setup cache
uses: ./.github/workflows/auto-cache
with:
path: .ci_cache/comma_download_cache
key: unit_tests_${{ hashFiles('.github/workflows/selfdrive_tests.yaml') }}
- name: Run unit tests
timeout-minutes: ${{ contains(runner.name, 'nsc') && 1 || 20 }}
run: |
@@ -161,25 +195,27 @@ jobs:
process_replay:
name: process replay
runs-on:
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
((github.event_name != 'pull_request') ||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
with:
docker_hub_pat: ${{ secrets.DOCKER_HUB_PAT }}
- name: Cache test routes
id: dependency-cache
uses: actions/cache@v4
with:
path: .ci_cache/comma_download_cache
key: proc-replay-${{ hashFiles('selfdrive/test/process_replay/ref_commit', 'selfdrive/test/process_replay/test_processes.py') }}
key: proc-replay-${{ hashFiles('.github/workflows/selfdrive_tests.yaml', 'selfdrive/test/process_replay/ref_commit', 'selfdrive/test/process_replay/test_regen.py') }}
- name: Build openpilot
run: |
${{ env.RUN }} "scons -j$(nproc)"
- name: Run replay
timeout-minutes: ${{ contains(runner.name, 'nsc') && (steps.dependency-cache.outputs.cache-hit == 'true') && 1 || 20 }}
timeout-minutes: ${{ contains(runner.name, 'nsc') && 1 || 20 }}
run: |
${{ env.RUN }} "coverage run selfdrive/test/process_replay/test_processes.py -j$(nproc) && \
chmod -R 777 /tmp/comma_download_cache && \
@@ -214,9 +250,9 @@ jobs:
test_cars:
name: cars
runs-on:
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
((github.event_name != 'pull_request') ||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-latest' }}
strategy:
fail-fast: false
matrix:
@@ -227,17 +263,17 @@ jobs:
submodules: true
- uses: ./.github/workflows/setup-with-retry
- name: Cache test routes
id: routes-cache
uses: actions/cache@v4
id: dependency-cache
uses: ./.github/workflows/auto-cache
with:
path: .ci_cache/comma_download_cache
key: car_models-${{ hashFiles('selfdrive/car/tests/test_models.py', 'selfdrive/car/tests/routes.py') }}-${{ matrix.job }}
- name: Build openpilot
run: ${{ env.RUN }} "scons -j$(nproc)"
- name: Test car models
timeout-minutes: ${{ contains(runner.name, 'nsc') && (steps.routes-cache.outputs.cache-hit == 'true') && 1 || 20 }}
timeout-minutes: ${{ contains(runner.name, 'nsc') && 1 || 20 }}
run: |
${{ env.RUN }} "MAX_EXAMPLES=1 $PYTEST selfdrive/car/tests/test_models.py && \
${{ env.RUN }} "FILEREADER_CACHE=1 MAX_EXAMPLES=1 $PYTEST selfdrive/car/tests/test_models.py && \
chmod -R 777 /tmp/comma_download_cache"
env:
NUM_JOBS: 4
@@ -306,9 +342,9 @@ jobs:
simulator_driving:
name: simulator driving
runs-on:
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
((github.event_name != 'pull_request') ||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
steps:
- uses: actions/checkout@v4
with:
@@ -327,9 +363,9 @@ jobs:
create_ui_report:
# This job name needs to be the same as UI_JOB_NAME in ui_preview.yaml
name: Create UI Report
runs-on:
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
- ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-experiments:docker.builds.local-cache=separate' || 'ubuntu-24.04' }}
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
((github.event_name != 'pull_request') ||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-24.04' }}
steps:
- uses: actions/checkout@v4
with:
@@ -17,6 +17,7 @@ runs:
uses: ./.github/workflows/setup
continue-on-error: true
with:
docker_hub_pat: ${{ inputs.docker_hub_pat }}
is_retried: true
- if: steps.setup1.outcome == 'failure'
shell: bash
@@ -26,6 +27,7 @@ runs:
uses: ./.github/workflows/setup
continue-on-error: true
with:
docker_hub_pat: ${{ inputs.docker_hub_pat }}
is_retried: true
- if: steps.setup2.outcome == 'failure'
shell: bash
@@ -34,4 +36,5 @@ runs:
if: steps.setup2.outcome == 'failure'
uses: ./.github/workflows/setup
with:
docker_hub_pat: ${{ inputs.docker_hub_pat }}
is_retried: true
+22 -3
View File
@@ -1,6 +1,10 @@
name: 'openpilot env setup'
inputs:
docker_hub_pat:
description: 'Auth token for Docker Hub, required for BuildJet jobs'
required: true
default: ''
is_retried:
description: 'A mock param that asserts that we use the setup-with-retry instead of this action directly'
required: false
@@ -20,9 +24,11 @@ runs:
name: No retries!
run: |
if [ "${{ github.run_attempt }}" -gt 1 ]; then
echo -e "\033[0;31m##################################################"
echo -e "\033[0;31m Retries not allowed! Fix the flaky test! "
echo -e "\033[0;31m##################################################\033[0m"
echo -e "\033[31m"
echo "##################################################"
echo " Retries not allowed! Fix the flaky test! "
echo "##################################################"
echo -e "\033[0m"
exit 1
fi
@@ -30,6 +36,19 @@ runs:
- shell: bash
run: git lfs pull
# on BuildJet runners, must be logged into DockerHub to avoid rate limiting
# https://buildjet.com/for-github-actions/docs/guides/docker
- shell: bash
if: ${{ contains(runner.name, 'buildjet') && inputs.docker_hub_pat == '' }}
run: |
echo "Need to set the Docker Hub PAT secret as an input to this action"
exit 1
- name: Login to Docker Hub
if: contains(runner.name, 'buildjet')
shell: bash
run: |
docker login -u adeebshihadeh -p ${{ inputs.docker_hub_pat }}
# build cache
- id: date
shell: bash
+54
View File
@@ -0,0 +1,54 @@
name: tools
on:
push:
branches:
- master
pull_request:
workflow_call:
inputs:
run_number:
default: '1'
required: true
type: string
concurrency:
group: tools-tests-ci-run-${{ inputs.run_number }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.run_id || github.head_ref || github.ref }}-${{ github.workflow }}-${{ github.event_name }}
cancel-in-progress: true
env:
BASE_IMAGE: openpilot-base
DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
BUILD: selfdrive/test/docker_build.sh base
RUN: docker run --shm-size 2G -v $GITHUB_WORKSPACE:/tmp/openpilot -w /tmp/openpilot -e FILEREADER_CACHE=1 -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $BASE_IMAGE /bin/bash -c
jobs:
devcontainer:
name: devcontainer
runs-on: ubuntu-latest
if: false # we can re-enable once this is faster
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
- name: Use local image for testing devcontainer with latest base image
run: |
echo "USE_LOCAL_IMAGE=true" >> "$GITHUB_ENV"
- name: Setup Dev Container CLI
run: npm install -g @devcontainers/cli
- name: Build dev container image
run: ./scripts/retry.sh devcontainer build --workspace-folder .
- name: Run dev container
run: |
mkdir -p /tmp/devcontainer_scons_cache/
cp -r $GITHUB_WORKSPACE/.ci_cache/scons_cache/. /tmp/devcontainer_scons_cache/
devcontainer up --workspace-folder .
- name: Test environment
run: |
devcontainer exec --workspace-folder . scons -j$(nproc) cereal/ common/
devcontainer exec --workspace-folder . pip3 install pip-install-test
devcontainer exec --workspace-folder . touch /home/batman/.comma/auth.json
devcontainer exec --workspace-folder . sudo touch /root/test.txt
+6 -6
View File
@@ -1,18 +1,18 @@
[submodule "panda"]
path = panda
url = ../../commaai/panda.git
url = https://github.com/sunnyhaibin/panda.git
[submodule "opendbc"]
path = opendbc_repo
url = ../../commaai/opendbc.git
url = https://github.com/sunnypilot/opendbc.git
[submodule "msgq"]
path = msgq_repo
url = ../../commaai/msgq.git
url = https://github.com/sunnypilot/msgq.git
[submodule "rednose_repo"]
path = rednose_repo
url = ../../commaai/rednose.git
url = https://github.com/commaai/rednose.git
[submodule "teleoprtc_repo"]
path = teleoprtc_repo
url = ../../commaai/teleoprtc
url = https://github.com/commaai/teleoprtc
[submodule "tinygrad"]
path = tinygrad_repo
url = https://github.com/commaai/tinygrad.git
url = https://github.com/tinygrad/tinygrad.git
+7 -4
View File
@@ -68,14 +68,17 @@ 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/
COPY --chown=$USER pyproject.toml uv.lock /tmp/
COPY --chown=$USER tools/install_python_dependencies.sh /tmp/tools/
ENV VIRTUAL_ENV=/home/$USER/.venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
RUN cd /home/$USER && \
RUN cd /tmp && \
tools/install_python_dependencies.sh && \
rm -rf tools/ pyproject.toml uv.lock .cache
mkdir -p $VIRTUAL_ENV && \
cp -r /tmp/.venv/* $VIRTUAL_ENV && \
rm -rf /tmp/* && \
rm -rf /home/$USER/.cache
USER root
RUN sudo git config --global --add safe.directory /tmp/openpilot
Vendored
+4 -13
View File
@@ -79,10 +79,6 @@ def deviceStage(String stageName, String deviceType, List extra_env, def steps)
return
}
if (isReplay()) {
error("REPLAYING TESTS IS NOT ALLOWED. FIX THEM INSTEAD.")
}
def extra = extra_env.collect { "export ${it}" }.join('\n');
def branch = env.BRANCH_NAME ?: 'master';
def gitDiff = sh returnStdout: true, script: 'curl -s -H "Authorization: Bearer ${GITHUB_COMMENTS_TOKEN}" https://api.github.com/repos/commaai/openpilot/compare/master...${GIT_BRANCH} | jq .files[].filename || echo "/"', label: 'Getting changes'
@@ -127,11 +123,6 @@ def hasPathChanged(String gitDiff, List<String> paths) {
return false
}
def isReplay() {
def replayClass = "org.jenkinsci.plugins.workflow.cps.replay.ReplayCause"
return currentBuild.rawBuild.getCauses().any{ cause -> cause.toString().contains(replayClass) }
}
def setupCredentials() {
withCredentials([
string(credentialsId: 'azure_token', variable: 'AZURE_TOKEN'),
@@ -216,8 +207,8 @@ node {
step("build", "cd system/manager && ./build.py"),
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py", [diffPaths: ["panda", "selfdrive/pandad/"]]),
step("test power draw", "pytest -s system/hardware/tici/tests/test_power_draw.py"),
step("test encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py", [diffPaths: ["system/loggerd/"]]),
step("test pigeond", "pytest system/ubloxd/tests/test_pigeond.py", [diffPaths: ["system/ubloxd/"]]),
step("test encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py"),
step("test pigeond", "pytest system/ubloxd/tests/test_pigeond.py"),
step("test manager", "pytest system/manager/test/test_manager.py"),
])
},
@@ -252,7 +243,7 @@ node {
'replay': {
deviceStage("model-replay", "tici-replay", ["UNSAFE=1"], [
step("build", "cd system/manager && ./build.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]),
step("model replay", "selfdrive/test/process_replay/model_replay.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]),
step("model replay", "selfdrive/test/process_replay/model_replay.py", [diffPaths: ["selfdrive/modeld/"]]),
])
},
'tizi': {
@@ -262,7 +253,7 @@ node {
step("test pandad spi", "pytest selfdrive/pandad/tests/test_pandad_spi.py"),
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py", [diffPaths: ["panda", "selfdrive/pandad/"]]),
step("test amp", "pytest system/hardware/tici/tests/test_amplifier.py"),
step("test qcomgpsd", "pytest system/qcomgpsd/tests/test_qcomgpsd.py", [diffPaths: ["system/qcomgpsd/"]]),
step("test qcomgpsd", "pytest system/qcomgpsd/tests/test_qcomgpsd.py"),
])
},
+21
View File
@@ -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 -2
View File
@@ -349,7 +349,7 @@ Export('common', 'gpucommon')
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(['opendbc/can/SConscript'], exports={'env': env_swaglog})
SConscript(['cereal/SConscript'])
@@ -366,7 +366,6 @@ SConscript(['rednose/SConscript'])
# Build system services
SConscript([
'system/ui/SConscript',
'system/proclogd/SConscript',
'system/ubloxd/SConscript',
'system/loggerd/SConscript',
+17 -1
View File
@@ -8,7 +8,23 @@ $Cxx.namespace("cereal");
# cereal, so use these if you want custom events in your fork.
# you can rename the struct, but don't change the identifier
struct CustomReserved0 @0x81c2f05a394cf4af {
struct SelfdriveStateSP @0x81c2f05a394cf4af {
mads @0 :ModularAssistiveDrivingSystem;
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 {
+13 -5
View File
@@ -126,6 +126,17 @@ struct OnroadEvent @0xc4fa6047f024e718 {
personalityChanged @91;
aeb @92;
# sunnypilot
lkasEnable @93;
lkasDisable @94;
manualSteeringRequired @95;
manualLongitudinalRequired @96;
silentPedalPressed @97;
silentLkasEnable @98;
silentBrakeHold @99;
silentWrongGear @100;
silentReverseGear @101;
soundsUnavailableDEPRECATED @47;
}
}
@@ -486,9 +497,6 @@ struct DeviceState @0xa4d8b5af2aa492eb {
nvmeTempC @35 :List(Float32);
modemTempC @36 :List(Float32);
pmicTempC @39 :List(Float32);
intakeTempC @46 :Float32;
exhaustTempC @47 :Float32;
caseTempC @48 :Float32;
maxTempC @44 :Float32; # max of other temps, used to control fan
thermalZones @38 :List(ThermalZone);
thermalStatus @14 :ThermalStatus;
@@ -589,6 +597,7 @@ struct PandaState @0xa7649e2575e4591e {
# safety stuff
controlsAllowed @3 :Bool;
controlsAllowedLat @5 :Bool;
safetyRxInvalid @19 :UInt32;
safetyTxBlocked @24 :UInt32;
safetyModel @14 :Car.CarParams.SafetyModel;
@@ -696,7 +705,6 @@ struct PandaState @0xa7649e2575e4591e {
}
gasInterceptorDetectedDEPRECATED @4 :Bool;
startedSignalDetectedDEPRECATED @5 :Bool;
hasGpsDEPRECATED @6 :Bool;
gmlanSendErrsDEPRECATED @9 :UInt32;
fanSpeedRpmDEPRECATED @11 :UInt16;
@@ -2547,7 +2555,7 @@ struct Event {
customReservedRawData2 @126 :Data;
# *********** Custom: reserved for forks ***********
customReserved0 @107 :Custom.CustomReserved0;
selfdriveStateSP @107 :Custom.SelfdriveStateSP;
customReserved1 @108 :Custom.CustomReserved1;
customReserved2 @109 :Custom.CustomReserved2;
customReserved3 @110 :Custom.CustomReserved3;
+1 -1
View File
@@ -17,5 +17,5 @@ class TestServices:
def test_generated_header(self):
with tempfile.NamedTemporaryFile(suffix=".h") as f:
ret = os.system(f"python3 {services.__file__} > {f.name} && clang++ {f.name} -std=c++11")
ret = os.system(f"python3 {services.__file__} > {f.name} && clang++ {f.name}")
assert ret == 0, "generated services header is not valid C"
+3
View File
@@ -73,6 +73,9 @@ _services: dict[str, tuple] = {
"userFlag": (True, 0., 1),
"microphone": (True, 10., 10),
# sunnypilot
"selfdriveStateSP": (True, 100., 10),
# debug
"uiDebug": (True, 0., 1),
"testJoystick": (True, 0.),
+7
View File
@@ -112,6 +112,7 @@ std::unordered_map<std::string, uint32_t> keys = {
{"DisablePowerDown", PERSISTENT},
{"DisableUpdates", PERSISTENT},
{"DisengageOnAccelerator", PERSISTENT},
{"DmModelInitialized", CLEAR_ON_ONROAD_TRANSITION},
{"DongleId", PERSISTENT},
{"DoReboot", CLEAR_ON_MANAGER_START},
{"DoShutdown", CLEAR_ON_MANAGER_START},
@@ -200,6 +201,12 @@ std::unordered_map<std::string, uint32_t> keys = {
{"UpdaterTargetBranch", CLEAR_ON_MANAGER_START},
{"UpdaterLastFetchTime", PERSISTENT},
{"Version", PERSISTENT},
// sunnypilot params
{"Mads", PERSISTENT},
{"MadsCruiseMain", PERSISTENT},
{"MadsDisengageLateralOnBrake", PERSISTENT},
{"MadsUnifiedEngagementMode", PERSISTENT},
};
} // namespace
+1 -1
View File
@@ -13,7 +13,7 @@ public:
if (prefix.empty()) {
prefix = util::random_string(15);
}
msgq_path = Path::shm_path() + "/" + prefix;
msgq_path = "/dev/shm/" + prefix;
bool ret = util::create_directories(msgq_path, 0777);
assert(ret);
setenv("OPENPILOT_PREFIX", prefix.c_str(), 1);
+1 -1
View File
@@ -11,7 +11,7 @@ from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
class OpenpilotPrefix:
def __init__(self, prefix: str = None, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False):
self.prefix = prefix if prefix else str(uuid.uuid4().hex[0:15])
self.msgq_path = os.path.join(Paths.shm_path(), self.prefix)
self.msgq_path = os.path.join('/dev/shm', self.prefix)
self.clean_dirs_on_exit = clean_dirs_on_exit
self.shared_download_cache = shared_download_cache
+2 -6
View File
@@ -48,13 +48,13 @@ class Ratekeeper:
def __init__(self, rate: float, print_delay_threshold: float | None = 0.0) -> None:
"""Rate in Hz for ratekeeping. print_delay_threshold must be nonnegative."""
self._interval = 1. / rate
self._next_frame_time = time.monotonic() + self._interval
self._print_delay_threshold = print_delay_threshold
self._frame = 0
self._remaining = 0.0
self._process_name = getproctitle()
self._dts = deque([self._interval], maxlen=100)
self._last_monitor_time = -1.
self._next_frame_time = -1.
self._last_monitor_time = time.monotonic()
@property
def frame(self) -> int:
@@ -79,10 +79,6 @@ class Ratekeeper:
# Monitors the cumulative lag, but does not enforce a rate
def monitor_time(self) -> bool:
if self._last_monitor_time < 0:
self._next_frame_time = time.monotonic() + self._interval
self._last_monitor_time = time.monotonic()
prev = self._last_monitor_time
self._last_monitor_time = time.monotonic()
self._dts.append(self._last_monitor_time - prev)
+1 -2
View File
@@ -2,9 +2,8 @@
#include "common/watchdog.h"
#include "common/util.h"
#include "system/hardware/hw.h"
const std::string watchdog_fn_prefix = Path::shm_path() + "/wd_"; // + <pid>
const std::string watchdog_fn_prefix = "/dev/shm/wd_"; // + <pid>
bool watchdog_kick(uint64_t ts) {
static std::string fn = watchdog_fn_prefix + std::to_string(getpid());
+2 -2
View File
@@ -167,7 +167,7 @@ A supported vehicle is one that just works when you install a comma device. All
|Lexus|ES 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES 2017-18">Buy Here</a></sub></details>||
|Lexus|ES 2019-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES 2019-24">Buy Here</a></sub></details>||
|Lexus|ES Hybrid 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES Hybrid 2017-18">Buy Here</a></sub></details>||
|Lexus|ES Hybrid 2019-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES Hybrid 2019-25">Buy Here</a></sub></details>|<a href="https://youtu.be/BZ29osRVJeg?t=12" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Lexus|ES Hybrid 2019-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES Hybrid 2019-24">Buy Here</a></sub></details>|<a href="https://youtu.be/BZ29osRVJeg?t=12" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Lexus|GS F 2016|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=GS F 2016">Buy Here</a></sub></details>||
|Lexus|IS 2017-19|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=IS 2017-19">Buy Here</a></sub></details>||
|Lexus|IS 2022-23|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=IS 2022-23">Buy Here</a></sub></details>||
@@ -188,7 +188,7 @@ A supported vehicle is one that just works when you install a comma device. All
|Lincoln|Aviator Plug-in Hybrid 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lincoln&model=Aviator Plug-in Hybrid 2020-24">Buy Here</a></sub></details>||
|MAN|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=eTGE 2020-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|MAN|TGE 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=TGE 2017-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Mazda|CX-5 2022-25|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Mazda&model=CX-5 2022-25">Buy Here</a></sub></details>||
|Mazda|CX-5 2022-24|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Mazda&model=CX-5 2022-24">Buy Here</a></sub></details>||
|Mazda|CX-9 2021-23|All|Stock|0 mph|28 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Mazda&model=CX-9 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/dA3duO4a0O4" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Nissan|Altima 2019-20|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Nissan B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Nissan&model=Altima 2019-20">Buy Here</a></sub></details>||
|Nissan|Leaf 2018-23|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Nissan&model=Leaf 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/vaMbtAh_0cY" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
+1 -1
View File
@@ -7,7 +7,7 @@ export OPENBLAS_NUM_THREADS=1
export VECLIB_MAXIMUM_THREADS=1
if [ -z "$AGNOS_VERSION" ]; then
export AGNOS_VERSION="11.3"
export AGNOS_VERSION="11.2"
fi
export STAGING_ROOT="/data/safe_staging"
+1 -1
Submodule panda updated: c7cc2deaf0...1ae97c112e
+1 -4
View File
@@ -31,9 +31,6 @@ dependencies = [
# body / webrtcd
"aiohttp",
"aiortc",
# aiortc does not put an upper bound on pyopenssl and is now incompatible
# with the latest release
"pyopenssl < 24.3.0",
"pyaudio",
# panda
@@ -101,6 +98,7 @@ dev = [
"azure-identity",
"azure-storage-blob",
"dictdiffer",
"flaky",
"lru-dict",
"matplotlib",
"parameterized >=0.8, <0.9",
@@ -241,7 +239,6 @@ exclude = [
"cereal",
"panda",
"opendbc",
"opendbc_repo",
"rednose_repo",
"tinygrad_repo",
"teleoprtc",
+1
View File
@@ -32,6 +32,7 @@ blacklist = [
".git/",
".github/",
".devcontainer/",
"Darwin/",
".vscode",
+5 -5
View File
@@ -37,7 +37,7 @@ for f in sorted(pyf):
lns = len(src.split("\n"))
tree = ast.parse(src)
Analyzer().visit(tree)
print(f"{lns:5d} {f} {xbit}")
print("%5d %s %s" % (lns, f, xbit))
if 'test' in f:
testlns += lns
elif f.startswith(('tools/', 'scripts/', 'selfdrive/debug')):
@@ -47,8 +47,8 @@ for f in sorted(pyf):
else:
tlns += lns
print(f"{tlns} lines of openpilot python")
print(f"{carlns} lines of car ports")
print(f"{scriptlns} lines of tools/scripts/debug")
print(f"{testlns} lines of tests")
print("%d lines of openpilot python" % tlns)
print("%d lines of car ports" % carlns)
print("%d lines of tools/scripts/debug" % scriptlns)
print("%d lines of tests" % testlns)
#print(sorted(list(imps)))
-10
View File
@@ -1,10 +0,0 @@
#!/usr/bin/env bash
FAIL=0
if grep -n '#include "third_party/raylib/include/raylib\.h"' $@ | grep -v '^system/ui/raylib/raylib\.h'; then
echo -e "Bad raylib include found! Use '#include \"system/ui/raylib/raylib.h\"' instead\n"
FAIL=1
fi
exit $FAIL
-1
View File
@@ -53,7 +53,6 @@ function run_tests() {
run "check_shebang_scripts_are_executable" python3 -m pre_commit_hooks.check_shebang_scripts_are_executable $ALL_FILES
run "check_shebang_format" $DIR/check_shebang_format.sh $ALL_FILES
run "check_nomerge_comments" $DIR/check_nomerge_comments.sh $ALL_FILES
run "check_raylib_includes" $DIR/check_raylib_includes.sh $ALL_FILES
if [[ -z "$FAST" ]]; then
run "mypy" mypy $PYTHON_FILES
+2 -2
View File
@@ -16,9 +16,9 @@ def waste(core):
j = 0
while 1:
if (i % 100) == 0:
setproctitle(f"{core:3d}: {i:8d}")
setproctitle("%3d: %8d" % (core, i))
lt = time.monotonic()
print(f"{core:3d}: {i:8d} {lt-st:f} {j:.2f}")
print("%3d: %8d %f %.2f" % (core, i, lt-st, j))
st = lt
i += 1
j = np.sum(np.matmul(m1, m2))
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f7565541b4e6213221174839b9b2b67397ced0b9807ea56413989fd37325b3b6
size 4908
+5 -3
View File
@@ -148,7 +148,8 @@ class CarSpecificEvents:
# To avoid re-engaging when openpilot cancels, check user engagement intention via buttons
# Main button also can trigger an engagement on these cars
self.cruise_buttons.append(any(ev.type in HYUNDAI_ENABLE_BUTTONS for ev in CS.buttonEvents))
events = self.create_common_events(CS, CS_prev, pcm_enable=self.CP.pcmCruise, allow_enable=any(self.cruise_buttons))
events = self.create_common_events(CS, CS_prev, pcm_enable=self.CP.pcmCruise, allow_enable=any(self.cruise_buttons),
allow_cancel=any(self.CP.pcmCruise and b.type == ButtonType.cancel and b.pressed for b in CS.buttonEvents) or not self.CP.pcmCruise)
# low speed steer alert hysteresis logic (only for cars with steer cut off above 10 m/s)
if CS.vEgo < (self.CP.minSteerSpeed + 2.) and self.CP.minSteerSpeed > 10.:
@@ -164,7 +165,8 @@ class CarSpecificEvents:
return events
def create_common_events(self, CS: structs.CarState, CS_prev: car.CarState, extra_gears=None, pcm_enable=True,
allow_enable=True, enable_buttons=(ButtonType.accelCruise, ButtonType.decelCruise)):
allow_enable=True, enable_buttons=(ButtonType.accelCruise, ButtonType.decelCruise),
allow_cancel=True):
events = Events()
if CS.doorOpen:
@@ -215,7 +217,7 @@ class CarSpecificEvents:
if not self.CP.pcmCruise and (b.type in enable_buttons and not b.pressed):
events.add(EventName.buttonEnable)
# Disable on rising and falling edge of cancel for both stock and OP long
if b.type == ButtonType.cancel:
if b.type == ButtonType.cancel and allow_cancel:
events.add(EventName.buttonCancel)
# Handle permanent and temporary steering faults
+7
View File
@@ -22,6 +22,8 @@ from openpilot.selfdrive.pandad import can_capnp_to_list, can_list_to_can_capnp
from openpilot.selfdrive.car.cruise import VCruiseHelper
from openpilot.selfdrive.car.car_specific import MockCarState
from opendbc.sunnypilot.mads.mads import MadsParams
REPLAY = "REPLAY" in os.environ
EventName = log.OnroadEvent.EventName
@@ -113,6 +115,11 @@ class Car:
if not disengage_on_accelerator:
self.CP.alternativeExperience |= ALTERNATIVE_EXPERIENCE.DISABLE_DISENGAGE_ON_GAS
# mads
data_services = list(self.sm.data.keys()) + ['selfdriveStateSP']
self.sm = messaging.SubMaster(data_services, poll='selfdriveStateSP')
MadsParams().set_alternative_experience(self.CP, self.params)
openpilot_enabled_toggle = self.params.get_bool("OpenpilotEnabledToggle")
controller_available = self.CI.CC is not None and openpilot_enabled_toggle and not self.CP.dashcamOnly
+1 -1
View File
@@ -17,7 +17,7 @@ class TestCarDocs:
with open(CARS_MD_OUT) as f:
current_cars_md = f.read()
assert generated_cars_md == current_cars_md, "Run selfdrive/car/docs.py to update the compatibility documentation"
assert generated_cars_md == current_cars_md, "Run selfdrive/opcar/docs.py to update the compatibility documentation"
def test_docs_diff(self):
dump_path = os.path.join(BASEDIR, "selfdrive", "car", "tests", "cars_dump")
+1 -1
View File
@@ -394,7 +394,7 @@ class TestCarModelBase(unittest.TestCase):
for msg in filter(lambda m: m.src in range(64), can.can):
to_send = libpanda_py.make_CANPacket(msg.address, msg.src % 4, msg.dat)
ret = self.safety.safety_rx_hook(to_send)
self.assertEqual(1, ret, f"safety rx failed ({ret=}): {(msg.address, msg.src % 4)}")
self.assertEqual(1, ret, f"safety rx failed ({ret=}): {to_send}")
# Skip first frame so CS_prev is properly initialized
if idx == 0:
+9 -1
View File
@@ -56,6 +56,9 @@ class Controls:
elif self.CP.lateralTuning.which() == 'torque':
self.LaC = LatControlTorque(self.CP, self.CI)
data_services = list(self.sm.data.keys()) + ['selfdriveStateSP']
self.sm = messaging.SubMaster(data_services, poll='selfdriveState')
def update(self):
self.sm.update(15)
if self.sm.updated["liveCalibration"]:
@@ -88,7 +91,12 @@ class Controls:
# Check which actuators can be enabled
standstill = abs(CS.vEgo) <= max(self.CP.minSteerSpeed, MIN_LATERAL_CONTROL_SPEED) or CS.standstill
CC.latActive = self.sm['selfdriveState'].active and not CS.steerFaultTemporary and not CS.steerFaultPermanent and not standstill
ss_sp = self.sm['selfdriveStateSP']
CC.madsActive = ss_sp.mads.available and ss_sp.mads.active
_lat_active = ss_sp.mads.enabled if ss_sp.mads.available else self.sm['selfdriveState'].active
CC.latActive = _lat_active and not CS.steerFaultTemporary and not CS.steerFaultPermanent and not standstill
CC.longActive = CC.enabled and not any(e.overrideLongitudinal for e in self.sm['onroadEvents']) and self.CP.openpilotLongitudinalControl
actuators = CC.actuators
+1 -1
View File
@@ -28,7 +28,7 @@ def can_printer(bus, max_msg, addr, ascii_decode):
x = binascii.hexlify(msgs[_addr][-1]).decode('ascii')
freq = len(msgs[_addr]) / (time.monotonic() - start)
if max_msg is None or _addr < max_msg:
dd += f"{_addr:04X}({_addr:4d})({len(msgs[_addr]):6d})({freq:3}dHz) {x.ljust(20)} {a}\n"
dd += "%04X(%4d)(%6d)(%3dHz) %s %s\n" % (_addr, _addr, len(msgs[_addr]), freq, x.ljust(20), a)
print(dd)
lp = time.monotonic()
@@ -29,7 +29,7 @@ if __name__ == '__main__':
start_t = time.process_time_ns()
for msg in msgs:
can_list = can_capnp_to_list([msg])
for cp in tm.CI.can_parsers.values():
for cp in tm.CI.can_parsers:
if cp is not None:
cp.update_strings(can_list)
ets.append((time.process_time_ns() - start_t) * 1e-6)
+1 -2
View File
@@ -8,7 +8,6 @@ from typing import cast
from cereal.services import SERVICE_LIST
from openpilot.tools.lib.logreader import LogReader, ReadMode
from openpilot.selfdrive.test.process_replay.migration import migrate_all
if __name__ == "__main__":
cnt_events: Counter = Counter()
@@ -21,7 +20,7 @@ if __name__ == "__main__":
start_time = math.inf
end_time = -math.inf
ignition_off = None
for msg in migrate_all(LogReader(sys.argv[1], ReadMode.QLOG)):
for msg in LogReader(sys.argv[1], ReadMode.QLOG):
t = (msg.logMonoTime - start_time) / 1e9
end_time = max(end_time, msg.logMonoTime)
start_time = min(start_time, msg.logMonoTime)
+1 -1
View File
@@ -22,7 +22,7 @@ def get_fingerprint(lr):
msgs[c.address] = len(c.dat)
# show CAN fingerprint
fingerprint = ', '.join(f"{v[0]}: {v[1]}" for v in sorted(msgs.items()))
fingerprint = ', '.join("%d: %d" % v for v in sorted(msgs.items()))
print(f"\nfound {len(msgs)} messages. CAN fingerprint:\n")
print(fingerprint)
+1 -1
View File
@@ -25,7 +25,7 @@ while True:
if c.src % 0x80 == 0 and c.address < 0x800 and c.address not in (0x7df, 0x7e0, 0x7e8):
msgs[c.address] = len(c.dat)
fingerprint = ', '.join(f"{v[0]}: {v[1]}" for v in sorted(msgs.items()))
fingerprint = ', '.join("%d: %d" % v for v in sorted(msgs.items()))
print(f"number of messages {len(msgs)}:")
print(f"fingerprint {fingerprint}")
+9 -18
View File
@@ -8,7 +8,6 @@ from enum import Enum
from collections import defaultdict
from cereal import log, messaging
from cereal.services import SERVICE_LIST
from openpilot.common.transformations.orientation import rot_from_euler
from openpilot.common.realtime import config_realtime_process
from openpilot.common.params import Params
@@ -24,10 +23,8 @@ MIN_STD_SANITY_CHECK = 1e-5 # m or rad
MAX_FILTER_REWIND_TIME = 0.8 # s
MAX_SENSOR_TIME_DIFF = 0.1 # s
YAWRATE_CROSS_ERR_CHECK_FACTOR = 30
INPUT_INVALID_THRESHOLD = 0.5 # 0 bad inputs ignored
TIMING_INVALID_THRESHOLD = 2.5 # 2 bad timings ignored
INPUT_INVALID_DECAY = 0.9993 # ~10 secs to resume after exceeding allowed bad inputs by one (at 100hz)
TIMING_INVALID_DECAY = 0.9990 # ~2 secs to resume after exceeding allowed bad timings by one (at 100hz)
INPUT_INVALID_THRESHOLD = 0.5
INPUT_INVALID_DECAY = 0.9993 # ~10 secs to resume after a bad input
POSENET_STD_INITIAL_VALUE = 10.0
POSENET_STD_HIST_HALF = 20
@@ -268,13 +265,10 @@ def main():
estimator = LocationEstimator(DEBUG)
filter_initialized = False
critcal_services = ["accelerometer", "gyroscope", "cameraOdometry"]
observation_timing_invalid = defaultdict(int)
critcal_services = ["accelerometer", "gyroscope", "liveCalibration", "cameraOdometry"]
observation_timing_invalid = False
observation_input_invalid = defaultdict(int)
input_invalid_decay = {s: INPUT_INVALID_DECAY ** (100. / SERVICE_LIST[s].frequency) for s in critcal_services}
timing_invalid_decay = {s: TIMING_INVALID_DECAY ** (100. / SERVICE_LIST[s].frequency) for s in critcal_services}
initial_pose = params.get("LocationFilterInitialState")
if initial_pose is not None:
initial_pose = json.loads(initial_pose)
@@ -288,6 +282,8 @@ def main():
acc_msgs, gyro_msgs = (messaging.drain_sock(sock) for sock in sensor_sockets)
if filter_initialized:
observation_timing_invalid = False
msgs = []
for msg in acc_msgs + gyro_msgs:
t, valid, which, data = msg.logMonoTime, msg.valid, msg.which(), getattr(msg, msg.which())
@@ -302,23 +298,18 @@ def main():
if valid:
t = log_mono_time * 1e-9
res = estimator.handle_log(t, which, msg)
if which not in critcal_services:
continue
if res == HandleLogResult.TIMING_INVALID:
observation_timing_invalid[which] += 1
observation_timing_invalid = True
elif res == HandleLogResult.INPUT_INVALID:
observation_input_invalid[which] += 1
else:
observation_input_invalid[which] *= input_invalid_decay[which]
observation_timing_invalid[which] *= timing_invalid_decay[which]
observation_input_invalid[which] *= INPUT_INVALID_DECAY
else:
filter_initialized = sm.all_checks() and sensor_all_checks(acc_msgs, gyro_msgs, sensor_valid, sensor_recv_time, sensor_alive, SIMULATION)
if sm.updated["cameraOdometry"]:
critical_service_inputs_valid = all(observation_input_invalid[s] < INPUT_INVALID_THRESHOLD for s in critcal_services)
critical_service_timing_valid = all(observation_timing_invalid[s] < TIMING_INVALID_THRESHOLD for s in critcal_services)
inputs_valid = sm.all_valid() and critical_service_inputs_valid and critical_service_timing_valid
inputs_valid = sm.all_valid() and critical_service_inputs_valid and not observation_timing_invalid
sensors_valid = sensor_all_checks(acc_msgs, gyro_msgs, sensor_valid, sensor_recv_time, sensor_alive, SIMULATION)
msg = estimator.get_msg(sensors_valid, inputs_valid, filter_initialized)
@@ -1,3 +1,4 @@
import pytest
import numpy as np
from collections import defaultdict
from enum import Enum
@@ -16,7 +17,6 @@ SELECT_COMPARE_FIELDS = {
'sensors_flag': ['sensorsOK'],
}
JUNK_IDX = 100
CONSISTENT_SPIKES_COUNT = 10
class Scenario(Enum):
@@ -25,8 +25,6 @@ class Scenario(Enum):
GYRO_SPIKE_MIDWAY = 'gyro_spike_midway'
ACCEL_OFF = 'accel_off'
ACCEL_SPIKE_MIDWAY = 'accel_spike_midway'
SENSOR_TIMING_SPIKE_MIDWAY = 'timing_spikes'
SENSOR_TIMING_CONSISTENT_SPIKES = 'timing_consistent_spikes'
def get_select_fields_data(logs):
@@ -45,17 +43,6 @@ def get_select_fields_data(logs):
return data
def modify_logs_midway(logs, which, count, fn):
non_which = [x for x in logs if x.which() != which]
which = [x for x in logs if x.which() == which]
temps = which[len(which) // 2:len(which) // 2 + count]
for i, temp in enumerate(temps):
temp = temp.as_builder()
fn(temp)
which[len(which) // 2 + i] = temp.as_reader()
return sorted(non_which + which, key=lambda x: x.logMonoTime)
def run_scenarios(scenario, logs):
if scenario == Scenario.BASE:
pass
@@ -64,28 +51,30 @@ def run_scenarios(scenario, logs):
logs = sorted([x for x in logs if x.which() != 'gyroscope'], key=lambda x: x.logMonoTime)
elif scenario == Scenario.GYRO_SPIKE_MIDWAY:
def gyro_spike(msg):
msg.gyroscope.gyroUncalibrated.v[0] += 3.0
logs = modify_logs_midway(logs, 'gyroscope', 1, gyro_spike)
non_gyro = [x for x in logs if x.which() not in 'gyroscope']
gyro = [x for x in logs if x.which() in 'gyroscope']
temp = gyro[len(gyro) // 2].as_builder()
temp.gyroscope.gyroUncalibrated.v[0] += 3.0
gyro[len(gyro) // 2] = temp.as_reader()
logs = sorted(non_gyro + gyro, key=lambda x: x.logMonoTime)
elif scenario == Scenario.ACCEL_OFF:
logs = sorted([x for x in logs if x.which() != 'accelerometer'], key=lambda x: x.logMonoTime)
elif scenario == Scenario.ACCEL_SPIKE_MIDWAY:
def acc_spike(msg):
msg.accelerometer.acceleration.v[0] += 10.0
logs = modify_logs_midway(logs, 'accelerometer', 1, acc_spike)
elif scenario == Scenario.SENSOR_TIMING_SPIKE_MIDWAY or scenario == Scenario.SENSOR_TIMING_CONSISTENT_SPIKES:
def timing_spike(msg):
msg.accelerometer.timestamp -= int(0.150 * 1e9)
count = 1 if scenario == Scenario.SENSOR_TIMING_SPIKE_MIDWAY else CONSISTENT_SPIKES_COUNT
logs = modify_logs_midway(logs, 'accelerometer', count, timing_spike)
non_accel = [x for x in logs if x.which() not in 'accelerometer']
accel = [x for x in logs if x.which() in 'accelerometer']
temp = accel[len(accel) // 2].as_builder()
temp.accelerometer.acceleration.v[0] += 10.0
accel[len(accel) // 2] = temp.as_reader()
logs = sorted(non_accel + accel, key=lambda x: x.logMonoTime)
replayed_logs = replay_process_with_name(name='locationd', lr=logs)
return get_select_fields_data(logs), get_select_fields_data(replayed_logs)
@pytest.mark.xdist_group("test_locationd_scenarios")
@pytest.mark.shared_download_cache
class TestLocationdScenarios:
"""
Test locationd with different scenarios. In all these scenarios, we expect the following:
@@ -133,7 +122,7 @@ class TestLocationdScenarios:
assert np.allclose(orig_data['yaw_rate'], replayed_data['yaw_rate'], atol=np.radians(0.35))
assert np.allclose(orig_data['roll'], replayed_data['roll'], atol=np.radians(0.55))
assert np.diff(replayed_data['inputs_flag'])[499] == -1.0
assert np.diff(replayed_data['inputs_flag'])[704] == 1.0
assert np.diff(replayed_data['inputs_flag'])[696] == 1.0
def test_accel_off(self):
"""
@@ -157,21 +146,3 @@ class TestLocationdScenarios:
orig_data, replayed_data = run_scenarios(Scenario.ACCEL_SPIKE_MIDWAY, self.logs)
assert np.allclose(orig_data['yaw_rate'], replayed_data['yaw_rate'], atol=np.radians(0.35))
assert np.allclose(orig_data['roll'], replayed_data['roll'], atol=np.radians(0.55))
def test_single_timing_spike(self):
"""
Test: timing of 150ms off for the single accelerometer message in the middle of the segment
Expected Result: the message is ignored, and inputsOK is False for that time
"""
orig_data, replayed_data = run_scenarios(Scenario.SENSOR_TIMING_SPIKE_MIDWAY, self.logs)
assert np.all(replayed_data['inputs_flag'] == orig_data['inputs_flag'])
assert np.all(replayed_data['sensors_flag'] == orig_data['sensors_flag'])
def test_consistent_timing_spikes(self):
"""
Test: consistent timing spikes for N accelerometer messages in the middle of the segment
Expected Result: inputsOK becomes False after N of bad measurements
"""
orig_data, replayed_data = run_scenarios(Scenario.SENSOR_TIMING_CONSISTENT_SPIKES, self.logs)
assert np.diff(replayed_data['inputs_flag'])[500] == -1.0
assert np.diff(replayed_data['inputs_flag'])[787] == 1.0
+2
View File
@@ -12,6 +12,7 @@ from cereal import messaging
from cereal.messaging import PubMaster, SubMaster
from msgq.visionipc import VisionIpcClient, VisionStreamType, VisionBuf
from openpilot.common.swaglog import cloudlog
from openpilot.common.params import Params
from openpilot.common.realtime import set_realtime_priority
from openpilot.selfdrive.modeld.runners import ModelRunner, Runtime
from openpilot.selfdrive.modeld.models.commonmodel_pyx import CLContext
@@ -125,6 +126,7 @@ def main():
cl_context = CLContext()
model = ModelState(cl_context)
cloudlog.warning("models loaded, dmonitoringmodeld starting")
Params().put_bool("DmModelInitialized", True)
cloudlog.warning("connecting to driver stream")
vipc_client = VisionIpcClient("camerad", VisionStreamType.VISION_STREAM_DRIVER, True, cl_context)
+2 -2
View File
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9dc64f5d1e7d6b67f1d4659a3483f03b4324b4c7b969a5ba90c4e37e62bf6fce
size 50320584
oid sha256:c829d824ebc73d15da82516592c07d9784369ccbf710698e919e06a702e70924
size 50320138
-4
View File
@@ -145,10 +145,6 @@ void Panda::set_can_speed_kbps(uint16_t bus, uint16_t speed) {
handle->control_write(0xde, bus, (speed * 10));
}
void Panda::set_can_fd_auto(uint16_t bus, bool enabled) {
handle->control_write(0xe8, bus, enabled);
}
void Panda::set_data_speed_kbps(uint16_t bus, uint16_t speed) {
handle->control_write(0xf9, bus, (speed * 10));
}
-1
View File
@@ -77,7 +77,6 @@ public:
void enable_deepsleep();
void send_heartbeat(bool engaged);
void set_can_speed_kbps(uint16_t bus, uint16_t speed);
void set_can_fd_auto(uint16_t bus, bool enabled);
void set_data_speed_kbps(uint16_t bus, uint16_t speed);
void set_canfd_non_iso(uint16_t bus, bool non_iso);
void can_send(const capnp::List<cereal::CanData>::Reader &can_data_list);
+1 -4
View File
@@ -67,10 +67,6 @@ Panda *connect(std::string serial="", uint32_t index=0) {
}
//panda->enable_deepsleep();
for (int i = 0; i < PANDA_BUS_CNT; i++) {
panda->set_can_fd_auto(i, true);
}
if (!panda->up_to_date() && !getenv("BOARDD_SKIP_FW_CHECK")) {
throw std::runtime_error("Panda firmware out of date. Run pandad.py to update.");
}
@@ -144,6 +140,7 @@ void fill_panda_state(cereal::PandaState::Builder &ps, cereal::PandaState::Panda
ps.setIgnitionLine(health.ignition_line_pkt);
ps.setIgnitionCan(health.ignition_can_pkt);
ps.setControlsAllowed(health.controls_allowed_pkt);
ps.setControlsAllowedLat(health.controls_allowed_lat_pkt);
ps.setTxBufferOverflow(health.tx_buffer_overflow_pkt);
ps.setRxBufferOverflow(health.rx_buffer_overflow_pkt);
ps.setPandaType(hw_type);
+2 -2
View File
@@ -239,7 +239,7 @@ int PandaSpiHandle::spi_transfer_retry(uint8_t endpoint, uint8_t *tx_data, uint1
// due to full TX buffers
nack_count += 1;
if (nack_count > 3) {
SPILOG(LOGD, "NACK sleep %d", nack_count);
SPILOG(LOGE, "NACK sleep %d", nack_count);
usleep(std::clamp(nack_count*10, 200, 2000));
}
}
@@ -418,7 +418,7 @@ fail:
}
}
if (ret >= 0) ret = -1;
if (ret > 0) ret = -1;
return ret;
}
#endif
-2
View File
@@ -6,7 +6,6 @@ import cereal.messaging as messaging
from cereal import log
from openpilot.common.gpio import gpio_set, gpio_init
from panda import Panda, PandaDFU, PandaProtocolMismatch
from openpilot.common.retry import retry
from openpilot.system.manager.process_config import managed_processes
from openpilot.system.hardware import HARDWARE
from openpilot.system.hardware.tici.pins import GPIO
@@ -52,7 +51,6 @@ class TestPandad:
assert not Panda.wait_for_dfu(None, 3)
assert not Panda.wait_for_panda(None, 3)
@retry(attempts=3)
def _flash_bootstub_and_test(self, fn, expect_mismatch=False):
self._go_to_dfu()
pd = PandaDFU(None)
@@ -14,7 +14,7 @@ from openpilot.common.params import Params
from openpilot.common.timeout import Timeout
from openpilot.selfdrive.pandad import can_list_to_can_capnp
from openpilot.system.hardware import TICI
from openpilot.selfdrive.test.helpers import with_processes
from openpilot.selfdrive.test.helpers import phone_only, with_processes
@retry(attempts=3)
@@ -72,6 +72,7 @@ class TestBoarddLoopback:
os.environ['STARTED'] = '1'
os.environ['BOARDD_LOOPBACK'] = '1'
@phone_only
@with_processes(['pandad'])
def test_loopback(self):
num_pandas = 2 if TICI and "SINGLE_PANDA" not in os.environ else 1
+2 -1
View File
@@ -7,7 +7,7 @@ import random
import cereal.messaging as messaging
from cereal.services import SERVICE_LIST
from openpilot.system.hardware import HARDWARE
from openpilot.selfdrive.test.helpers import with_processes
from openpilot.selfdrive.test.helpers import phone_only, with_processes
from openpilot.selfdrive.pandad.tests.test_pandad_loopback import setup_pandad, send_random_can_messages
JUNGLE_SPAM = "JUNGLE_SPAM" in os.environ
@@ -23,6 +23,7 @@ class TestBoarddSpi:
if not JUNGLE_SPAM:
os.environ['BOARDD_LOOPBACK'] = '1'
@phone_only
@with_processes(['pandad'])
def test_spi_corruption(self, subtests):
setup_pandad(1)
+90
View File
@@ -105,6 +105,17 @@ class Events:
ret.append(event)
return ret
def has(self, event_name: int) -> bool:
return event_name in self.events
def remove(self, event_name: int, static: bool = False) -> None:
if static and event_name in self.static_events:
self.static_events.remove(event_name)
if event_name in self.events:
self.event_counters[event_name] = self.event_counters[event_name] + 1
self.events.remove(event_name)
class Alert:
def __init__(self,
@@ -951,6 +962,85 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = {
ET.WARNING: personality_changed_alert,
},
# sunnypilot
EventName.lkasEnable: {
ET.ENABLE: EngagementAlert(AudibleAlert.engage),
},
EventName.lkasDisable: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
},
EventName.manualSteeringRequired: {
ET.USER_DISABLE: Alert(
"Automatic Lane Centering is OFF",
"Manual Steering Required",
AlertStatus.normal, AlertSize.mid,
Priority.LOW, VisualAlert.none, AudibleAlert.disengage, 1.),
},
EventName.manualLongitudinalRequired: {
ET.WARNING: Alert(
"Smart/Adaptive Cruise Control is OFF",
"Manual Gas/Brakes Required",
AlertStatus.normal, AlertSize.mid,
Priority.LOW, VisualAlert.none, AudibleAlert.none, 1.),
},
EventName.silentPedalPressed: {
ET.USER_DISABLE: Alert(
"",
"",
AlertStatus.normal, AlertSize.none,
Priority.MID, VisualAlert.none, AudibleAlert.none, .2),
ET.NO_ENTRY: NoEntryAlert("Pedal Pressed During Attempt",
visual_alert=VisualAlert.brakePressed),
},
EventName.silentLkasEnable: {
ET.ENABLE: Alert(
"",
"",
AlertStatus.normal, AlertSize.none,
Priority.MID, VisualAlert.none, AudibleAlert.none, .2, 0.),
},
EventName.silentBrakeHold: {
ET.USER_DISABLE: Alert(
"",
"",
AlertStatus.normal, AlertSize.none,
Priority.MID, VisualAlert.none, AudibleAlert.none, .2, 0.),
ET.NO_ENTRY: NoEntryAlert("Brake Hold Active"),
},
EventName.silentWrongGear: {
ET.USER_DISABLE: Alert(
"Gear not D",
"openpilot Unavailable",
AlertStatus.normal, AlertSize.mid,
Priority.LOW, VisualAlert.none, AudibleAlert.none, 0., 3.),
ET.NO_ENTRY: Alert(
"Gear not D",
"openpilot Unavailable",
AlertStatus.normal, AlertSize.mid,
Priority.LOW, VisualAlert.none, AudibleAlert.none, 0., 3.),
},
EventName.silentReverseGear: {
ET.PERMANENT: Alert(
"Reverse\nGear",
"",
AlertStatus.normal, AlertSize.full,
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2, creation_delay=0.5),
ET.USER_DISABLE: Alert(
"Reverse\nGear",
"",
AlertStatus.normal, AlertSize.full,
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2, creation_delay=0.5),
ET.NO_ENTRY: NoEntryAlert("Reverse Gear"),
},
}
+19
View File
@@ -23,6 +23,8 @@ from openpilot.selfdrive.controls.lib.latcontrol import MIN_LATERAL_CONTROL_SPEE
from openpilot.system.version import get_build_metadata
from opendbc.sunnypilot.mads.mads import ModularAssistiveDrivingSystem
REPLAY = "REPLAY" in os.environ
SIMULATION = "SIMULATION" in os.environ
TESTING_CLOSET = "TESTING_CLOSET" in os.environ
@@ -131,6 +133,10 @@ class SelfdriveD:
elif self.CP.passive:
self.events.add(EventName.dashcamMode, static=True)
self.mads = ModularAssistiveDrivingSystem(self)
sock_services = list(self.pm.sock.keys()) + ['selfdriveStateSP']
self.pm = messaging.PubMaster(sock_services)
def update_events(self, CS):
"""Compute onroadEvents from carState"""
@@ -451,11 +457,24 @@ class SelfdriveD:
self.pm.send('onroadEvents', ce_send)
self.events_prev = self.events.names.copy()
# selfdriveStateSP
ss_sp_msg = messaging.new_message('selfdriveStateSP')
ss_sp_msg.valid = True
ss_sp = ss_sp_msg.selfdriveStateSP
mads = ss_sp.mads
mads.state = self.mads.state_machine.state
mads.enabled = self.mads.enabled
mads.active = self.mads.active
mads.available = self.mads.enabled_toggle
self.pm.send('selfdriveStateSP', ss_sp_msg)
def step(self):
CS = self.data_sample()
self.update_events(CS)
if not self.CP.passive and self.initialized:
self.enabled, self.active = self.state_machine.update(self.events)
self.mads.update(CS)
self.update_alerts(CS)
self.publish_selfdriveState(CS)
+1 -1
View File
@@ -42,7 +42,7 @@ class TestAlerts:
for name, e in events.items():
if not name.endswith("DEPRECATED"):
fail_msg = f"{name} @{e} not in EVENTS"
fail_msg = "%s @%d not in EVENTS" % (name, e)
assert e in EVENTS.keys(), fail_msg
# ensure alert text doesn't exceed allowed width
+9
View File
@@ -10,6 +10,7 @@ from functools import wraps
import cereal.messaging as messaging
from openpilot.common.params import Params
from openpilot.system.manager.process_config import managed_processes
from openpilot.system.hardware import PC
from openpilot.system.version import training_version, terms_version
@@ -28,6 +29,14 @@ def set_params_enabled():
msg.liveCalibration.rpyCalib = [0.0, 0.0, 0.0]
params.put("CalibrationParams", msg.to_bytes())
def phone_only(f):
@wraps(f)
def wrap(self, *args, **kwargs):
if PC:
pytest.skip("This test is not meant to run on PC")
return f(self, *args, **kwargs)
return wrap
def release_only(f):
@wraps(f)
def wrap(self, *args, **kwargs):
+10 -34
View File
@@ -7,20 +7,19 @@ import tempfile
from itertools import zip_longest
import matplotlib.pyplot as plt
import numpy as np
from openpilot.common.git import get_commit
from openpilot.system.hardware import PC
from openpilot.tools.lib.openpilotci import get_url
from openpilot.selfdrive.test.process_replay.compare_logs import compare_logs, format_diff
from openpilot.selfdrive.test.process_replay.process_replay import get_process_config, replay_process
from openpilot.tools.lib.framereader import FrameReader, NumpyFrameReader
from openpilot.tools.lib.framereader import FrameReader
from openpilot.tools.lib.logreader import LogReader, save_log
from openpilot.tools.lib.github_utils import GithubUtils
TEST_ROUTE = "2f4452b03ccb98f0|2022-12-03--13-45-30"
SEGMENT = 6
MAX_FRAMES = 100 if PC else 400
MAX_FRAMES = 100 if PC else 600
NO_MODEL = "NO_MODEL" in os.environ
SEND_EXTRA_INPUTS = bool(int(os.getenv("SEND_EXTRA_INPUTS", "0")))
@@ -32,14 +31,14 @@ GITHUB = GithubUtils(API_TOKEN, DATA_TOKEN)
def get_log_fn(test_route, ref="master"):
return f"{test_route}_model_tici_{ref}.zst"
return f"{test_route}_model_tici_{ref}.bz2"
def plot(proposed, master, title, tmp):
proposed = list(proposed)
master = list(master)
fig, ax = plt.subplots()
ax.plot(master, label='MASTER')
ax.plot(proposed, label='PROPOSED')
ax.plot(master, label='MASTER')
plt.legend(loc='best')
plt.title(title)
plt.savefig(f'{tmp}/{title}.png')
@@ -152,44 +151,21 @@ def model_replay(lr, frs):
dmonitoringmodeld = get_process_config("dmonitoringmodeld")
modeld_msgs = replay_process(modeld, modeld_logs, frs)
if isinstance(frs['roadCameraState'], NumpyFrameReader):
del frs['roadCameraState'].frames
del frs['wideRoadCameraState'].frames
dmonitoringmodeld_msgs = replay_process(dmonitoringmodeld, dmodeld_logs, frs)
return modeld_msgs + dmonitoringmodeld_msgs
def get_frames():
regen_cache = "--regen-cache" in sys.argv
cache = "--cache" in sys.argv or not PC or regen_cache
videos = ('fcamera.hevc', 'dcamera.hevc', 'ecamera.hevc')
cams = ('roadCameraState', 'driverCameraState', 'wideRoadCameraState')
if cache:
frames_cache = '/tmp/model_replay_cache' if PC else '/data/model_replay_cache'
os.makedirs(frames_cache, exist_ok=True)
cache_size = 200
for v in videos:
if not all(os.path.isfile(f'{frames_cache}/{TEST_ROUTE}_{v}_{i}.npy') for i in range(MAX_FRAMES//cache_size)) or regen_cache:
f = FrameReader(get_url(TEST_ROUTE, SEGMENT, v)).get(0, MAX_FRAMES + 1, pix_fmt="nv12")
print(f'Caching {v}...')
for i in range(MAX_FRAMES//cache_size):
np.save(f'{frames_cache}/{TEST_ROUTE}_{v}_{i}', f[(i * cache_size) + 1:((i + 1) * cache_size) + 1])
del f
return {c : NumpyFrameReader(f"{frames_cache}/{TEST_ROUTE}_{v}", 1928, 1208, cache_size) for c,v in zip(cams, videos, strict=True)}
else:
return {c : FrameReader(get_url(TEST_ROUTE, SEGMENT, v), readahead=True) for c,v in zip(cams, videos, strict=True)}
if __name__ == "__main__":
update = "--update" in sys.argv or (os.getenv("GIT_BRANCH", "") == 'master')
replay_dir = os.path.dirname(os.path.abspath(__file__))
# load logs
lr = list(LogReader(get_url(TEST_ROUTE, SEGMENT, "rlog.zst")))
frs = get_frames()
lr = list(LogReader(get_url(TEST_ROUTE, SEGMENT, "rlog.bz2")))
frs = {
'roadCameraState': FrameReader(get_url(TEST_ROUTE, SEGMENT, "fcamera.hevc"), readahead=True),
'driverCameraState': FrameReader(get_url(TEST_ROUTE, SEGMENT, "dcamera.hevc"), readahead=True),
'wideRoadCameraState': FrameReader(get_url(TEST_ROUTE, SEGMENT, "ecamera.hevc"), readahead=True)
}
log_msgs = []
# run replays
@@ -5,13 +5,13 @@ import copy
import json
import heapq
import signal
import platform
from collections import Counter, OrderedDict
from dataclasses import dataclass, field
from typing import Any
from collections.abc import Callable, Iterable
from tqdm import tqdm
import capnp
from openpilot.system.hardware.hw import Paths
import cereal.messaging as messaging
from cereal import car
@@ -780,7 +780,8 @@ def generate_params_config(lr=None, CP=None, fingerprint=None, custom_params=Non
def generate_environ_config(CP=None, fingerprint=None, log_dir=None) -> dict[str, Any]:
environ_dict = {}
environ_dict["PARAMS_ROOT"] = f"{Paths.shm_path()}/params"
if platform.system() != "Darwin":
environ_dict["PARAMS_ROOT"] = "/dev/shm/params"
if log_dir is not None:
environ_dict["LOG_ROOT"] = log_dir
+1 -1
View File
@@ -1 +1 @@
255ceb08c75bc85379da5ec247e612be3716fb43
2fc2e865ab77fd8145feab86d454f2111c5d9871
+2 -12
View File
@@ -72,7 +72,7 @@ PROCS = {
PROCS.update({
"tici": {
"./pandad": 5.0,
"./pandad": 4.0,
"./ubloxd": 1.0,
"system.ubloxd.pigeond": 6.0,
},
@@ -138,7 +138,6 @@ class TestOnroad:
proc = None
try:
manager_path = os.path.join(BASEDIR, "system/manager/manager.py")
cls.manager_st = time.monotonic()
proc = subprocess.Popen(["python", manager_path])
sm = messaging.SubMaster(['carState'])
@@ -203,10 +202,6 @@ class TestOnroad:
with subtests.test(service=s):
assert len(msgs) >= math.floor(SERVICE_LIST[s].frequency*int(TEST_DURATION*0.8))
def test_manager_starting_time(self):
st = self.msgs['managerState'][0].logMonoTime / 1e9
assert (st - self.manager_st) < 10, f"manager.py took {st - self.manager_st}s to publish the first 'managerState' msg"
def test_cloudlog_size(self):
msgs = self.msgs['logMessage']
@@ -300,18 +295,13 @@ class TestOnroad:
assert cpu_ok
def test_memory_usage(self):
print("\n------------------------------------------------")
print("--------------- Memory Usage -------------------")
print("------------------------------------------------")
offset = int(SERVICE_LIST['deviceState'].frequency * LOG_OFFSET)
mems = [m.deviceState.memoryUsagePercent for m in self.msgs['deviceState'][offset:]]
print("Memory usage: ", mems)
# check for big leaks. note that memory usage is
# expected to go up while the MSGQ buffers fill up
assert np.average(mems) <= 65, "Average memory usage above 65%"
assert np.max(np.diff(mems)) <= 4, "Max memory increase too high"
assert np.average(np.diff(mems)) <= 1, "Average memory increase too high"
assert max(mems) - min(mems) <= 3.0
def test_gpu_usage(self):
assert self.gpu_procs == {"weston", "ui", "camerad", "selfdrive.modeld.modeld", "selfdrive.modeld.dmonitoringmodeld"}
+2
View File
@@ -110,3 +110,5 @@ if GetOption('extras') and arch != "Darwin":
# build watch3
if arch in ['x86_64', 'aarch64', 'Darwin'] or GetOption('extras'):
qt_env.Program("watch3", ["watch3.cc"], LIBS=qt_libs + ['common', 'msgq', 'visionipc'])
SConscript(['raylib/SConscript'])
-1
View File
@@ -124,7 +124,6 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) {
// left: PrimeAdWidget
QStackedWidget *left_widget = new QStackedWidget(this);
QVBoxLayout *left_prime_layout = new QVBoxLayout();
left_prime_layout->setContentsMargins(0, 0, 0, 0);
QWidget *prime_user = new PrimeUserWidget();
prime_user->setStyleSheet(R"(
border-radius: 10px;
@@ -49,6 +49,20 @@ void DeveloperPanel::updateToggles(bool _offroad) {
}
offroad = _offroad;
// FIXME-SP: Move to sunnypilot panels before merging
auto madsToggle = new ParamControl("Mads", tr("Modular Assistive Driving System (MADS)"), "", "");
addItem(madsToggle);
// TODO-SP: Rename toggle
auto madsCruiseMainToggle = new ParamControl("MadsCruiseMain", tr("MADS: Cruise Main"), "", "");
addItem(madsCruiseMainToggle);
auto madsDisengageLateralOnBrakeToggle = new ParamControl("MadsDisengageLateralOnBrake", tr("MADS: Disengage Lateral on Brake"), "", "");
addItem(madsDisengageLateralOnBrakeToggle);
auto madsUnifiedEngagementModeToggle = new ParamControl("MadsUnifiedEngagementMode", tr("MADS: Unified Engagement Mode"), "", "");
addItem(madsUnifiedEngagementModeToggle);
}
void DeveloperPanel::showEvent(QShowEvent *event) {
+1 -1
View File
@@ -408,7 +408,7 @@ Setup::Setup(QWidget *parent) : QStackedWidget(parent) {
std::stringstream buffer;
buffer << std::ifstream("/sys/class/hwmon/hwmon1/in1_input").rdbuf();
float voltage = (float)std::atoi(buffer.str().c_str()) / 1000.;
if (voltage < 7) {
if (voltage > 0 && voltage < 7) {
addWidget(low_voltage());
}
+1
View File
@@ -0,0 +1 @@
_spinner
+17
View File
@@ -0,0 +1,17 @@
Import('env', 'arch', 'common')
raylib_env = env.Clone()
raylib_util_lib = env.Library("raylib_util_lib", ['util.cc'], LIBS='raylib')
linked_libs = ['raylib', raylib_util_lib, common]
raylib_env['LIBPATH'] += [f'#third_party/raylib/{arch}/']
mac_frameworks = []
if arch == "Darwin":
mac_frameworks += ['OpenCL', 'CoreVideo', 'Cocoa', 'GLUT', 'CoreFoundation', 'OpenGL', 'IOKit']
elif arch == 'larch64':
linked_libs += []
else:
linked_libs += ['OpenCL', 'dl', 'pthread']
if arch != 'aarch64':
raylib_env.Program("_spinner", ["spinner.cc"], LIBS=linked_libs, FRAMEWORKS=mac_frameworks)
@@ -2,7 +2,8 @@
#include <cmath>
#include <iostream>
#include "system/ui/raylib/util.h"
#include "selfdrive/ui/raylib/util.h"
#include "third_party/raylib/include/raylib.h"
constexpr int kProgressBarWidth = 1000;
constexpr int kProgressBarHeight = 20;
@@ -18,15 +19,15 @@ int main(int argc, char *argv[]) {
std::cin.sync_with_stdio(false);
std::cin.tie(nullptr);
Texture2D commaTexture = LoadTextureResized("../../selfdrive/assets/img_spinner_comma.png", kTextureSize);
Texture2D spinnerTexture = LoadTextureResized("../../selfdrive/assets/img_spinner_track.png", kTextureSize);
Texture2D commaTexture = LoadTextureResized("../../assets/img_spinner_comma.png", kTextureSize);
Texture2D spinnerTexture = LoadTextureResized("../../assets/img_spinner_track.png", kTextureSize);
float rotation = 0.0f;
std::string userInput;
while (!WindowShouldClose()) {
BeginDrawing();
ClearBackground(RAYLIB_BLACK);
ClearBackground(BLACK);
rotation = fmod(rotation + kRotationRate, 360.0f);
Vector2 center = {GetScreenWidth() / 2.0f, GetScreenHeight() / 2.0f};
@@ -36,8 +37,8 @@ int main(int argc, char *argv[]) {
// Draw rotating spinner and static comma logo
DrawTexturePro(spinnerTexture, {0, 0, (float)kTextureSize, (float)kTextureSize},
{center.x, center.y, (float)kTextureSize, (float)kTextureSize},
spinnerOrigin, rotation, RAYLIB_WHITE);
DrawTextureV(commaTexture, commaPosition, RAYLIB_WHITE);
spinnerOrigin, rotation, WHITE);
DrawTextureV(commaTexture, commaPosition, WHITE);
// Check for user input
if (std::cin.rdbuf()->in_avail() > 0) {
@@ -49,14 +50,14 @@ int main(int argc, char *argv[]) {
float yPos = GetScreenHeight() - kMargin - kProgressBarHeight;
if (std::all_of(userInput.begin(), userInput.end(), ::isdigit)) {
Rectangle bar = {center.x - kProgressBarWidth / 2.0f, yPos, kProgressBarWidth, kProgressBarHeight};
DrawRectangleRounded(bar, 0.5f, 10, RAYLIB_GRAY);
DrawRectangleRounded(bar, 0.5f, 10, GRAY);
int progress = std::clamp(std::stoi(userInput), 0, 100);
bar.width *= progress / 100.0f;
DrawRectangleRounded(bar, 0.5f, 10, RAYLIB_RAYWHITE);
DrawRectangleRounded(bar, 0.5f, 10, RAYWHITE);
} else {
Vector2 textSize = MeasureTextEx(getFont(), userInput.c_str(), kFontSize, 1.0);
DrawTextEx(getFont(), userInput.c_str(), {center.x - textSize.x / 2, yPos}, kFontSize, 1.0, RAYLIB_WHITE);
DrawTextEx(getFont(), userInput.c_str(), {center.x - textSize.x / 2, yPos}, kFontSize, 1.0, WHITE);
}
}
@@ -1,4 +1,4 @@
#include "system/ui/raylib/util.h"
#include "selfdrive/ui/raylib/util.h"
#include <array>
@@ -23,6 +23,7 @@ struct FontManager {
FontManager() {
for (int i = 0; i < fonts.size(); ++i) {
fonts[i] = LoadFontEx(FONT_FILE_PATHS[i], 120, nullptr, 250);
SetTextureFilter(fonts[i].texture, TEXTURE_FILTER_TRILINEAR);
}
}
@@ -42,6 +43,7 @@ Texture2D LoadTextureResized(const char *fileName, int size) {
Image img = LoadImage(fileName);
ImageResize(&img, size, size);
Texture2D texture = LoadTextureFromImage(img);
SetTextureFilter(texture, TEXTURE_FILTER_TRILINEAR);
return texture;
}
@@ -49,6 +51,6 @@ void initApp(const char *title, int fps) {
Hardware::set_display_power(true);
Hardware::set_brightness(65);
// SetTraceLogLevel(LOG_NONE);
InitWindow(2160, 1080, title);
InitWindow(0, 0, title);
SetTargetFPS(fps);
}
@@ -2,7 +2,7 @@
#include <string>
#include "system/ui/raylib/raylib.h"
#include "third_party/raylib/include/raylib.h"
enum class FontWeight {
Normal,
+16
View File
@@ -123,6 +123,22 @@
<source>Longitudinal Maneuver Mode</source>
<translation>وضع المناورة الطولية</translation>
</message>
<message>
<source>MADS: Cruise Main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Disengage Lateral on Brake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Modular Assistive Driving System (MADS)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Unified Engagement Mode</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DevicePanel</name>
+16
View File
@@ -123,6 +123,22 @@
<source>Longitudinal Maneuver Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Cruise Main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Disengage Lateral on Brake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Modular Assistive Driving System (MADS)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Unified Engagement Mode</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DevicePanel</name>
+16
View File
@@ -123,6 +123,22 @@
<source>Longitudinal Maneuver Mode</source>
<translation>Modo de maniobra longitudinal</translation>
</message>
<message>
<source>MADS: Cruise Main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Disengage Lateral on Brake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Modular Assistive Driving System (MADS)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Unified Engagement Mode</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DevicePanel</name>
+16
View File
@@ -123,6 +123,22 @@
<source>Longitudinal Maneuver Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Cruise Main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Disengage Lateral on Brake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Modular Assistive Driving System (MADS)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Unified Engagement Mode</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DevicePanel</name>
+16
View File
@@ -123,6 +123,22 @@
<source>Longitudinal Maneuver Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Cruise Main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Disengage Lateral on Brake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Modular Assistive Driving System (MADS)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Unified Engagement Mode</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DevicePanel</name>
+16
View File
@@ -123,6 +123,22 @@
<source>Longitudinal Maneuver Mode</source>
<translation> </translation>
</message>
<message>
<source>MADS: Cruise Main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Disengage Lateral on Brake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Modular Assistive Driving System (MADS)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Unified Engagement Mode</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DevicePanel</name>
+16
View File
@@ -123,6 +123,22 @@
<source>Longitudinal Maneuver Mode</source>
<translation>Modo Longitudinal Maneuver</translation>
</message>
<message>
<source>MADS: Cruise Main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Disengage Lateral on Brake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Modular Assistive Driving System (MADS)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Unified Engagement Mode</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DevicePanel</name>
+16
View File
@@ -123,6 +123,22 @@
<source>Longitudinal Maneuver Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Cruise Main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Disengage Lateral on Brake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Modular Assistive Driving System (MADS)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Unified Engagement Mode</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DevicePanel</name>
+16
View File
@@ -123,6 +123,22 @@
<source>Longitudinal Maneuver Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Cruise Main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Disengage Lateral on Brake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Modular Assistive Driving System (MADS)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Unified Engagement Mode</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DevicePanel</name>
+16
View File
@@ -123,6 +123,22 @@
<source>Longitudinal Maneuver Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Cruise Main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Disengage Lateral on Brake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Modular Assistive Driving System (MADS)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Unified Engagement Mode</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DevicePanel</name>
+16
View File
@@ -123,6 +123,22 @@
<source>Longitudinal Maneuver Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Cruise Main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Disengage Lateral on Brake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Modular Assistive Driving System (MADS)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>MADS: Unified Engagement Mode</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DevicePanel</name>
+38 -49
View File
@@ -54,7 +54,6 @@ RETRY_DELAY = 10 # seconds
MAX_RETRY_COUNT = 30 # Try for at most 5 minutes if upload fails immediately
MAX_AGE = 31 * 24 * 3600 # seconds
WS_FRAME_SIZE = 4096
DEVICE_STATE_UPDATE_INTERVAL = 1.0 # in seconds
NetworkType = log.DeviceState.NetworkType
@@ -100,9 +99,9 @@ send_queue: Queue[str] = queue.Queue()
upload_queue: Queue[UploadItem] = queue.Queue()
low_priority_send_queue: Queue[str] = queue.Queue()
log_recv_queue: Queue[str] = queue.Queue()
cancelled_uploads: set[str] = set()
cur_upload_items: dict[int, UploadItem | None] = {}
cur_upload_items_lock = threading.Lock()
def strip_zst_extension(fn: str) -> str:
@@ -130,9 +129,8 @@ class UploadQueueCache:
@staticmethod
def cache(upload_queue: Queue[UploadItem]) -> None:
try:
with upload_queue.mutex:
items = [asdict(item) for item in upload_queue.queue]
queue: list[UploadItem | None] = list(upload_queue.queue)
items = [asdict(i) for i in queue if i is not None and (i.id not in cancelled_uploads)]
Params().put("AthenadUploadQueue", json.dumps(items))
except Exception:
cloudlog.exception("athena.UploadQueueCache.cache.exception")
@@ -199,13 +197,11 @@ def retry_upload(tid: int, end_event: threading.Event, increase_count: bool = Tr
progress=0,
current=False
)
with cur_upload_items_lock:
upload_queue.put_nowait(item)
cur_upload_items[tid] = None
upload_queue.put_nowait(item)
UploadQueueCache.cache(upload_queue)
cur_upload_items[tid] = None
for _ in range(RETRY_DELAY):
time.sleep(1)
if end_event.is_set():
@@ -215,17 +211,15 @@ def retry_upload(tid: int, end_event: threading.Event, increase_count: bool = Tr
def cb(sm, item, tid, end_event: threading.Event, sz: int, cur: int) -> None:
# Abort transfer if connection changed to metered after starting upload
# or if athenad is shutting down to re-connect the websocket
if not item.allow_cellular:
if (time.monotonic() - sm.recv_time['deviceState']) > DEVICE_STATE_UPDATE_INTERVAL:
sm.update(0)
if sm['deviceState'].networkMetered:
raise AbortTransferException
sm.update(0)
metered = sm['deviceState'].networkMetered
if metered and (not item.allow_cellular):
raise AbortTransferException
if end_event.is_set():
raise AbortTransferException
with cur_upload_items_lock:
cur_upload_items[tid] = replace(item, progress=cur / sz if sz else 1)
cur_upload_items[tid] = replace(item, progress=cur / sz if sz else 1)
def upload_handler(end_event: threading.Event) -> None:
@@ -233,10 +227,14 @@ def upload_handler(end_event: threading.Event) -> None:
tid = threading.get_ident()
while not end_event.is_set():
cur_upload_items[tid] = None
try:
with cur_upload_items_lock:
cur_upload_items[tid] = None
cur_upload_items[tid] = item = replace(upload_queue.get(timeout=1), current=True)
cur_upload_items[tid] = item = replace(upload_queue.get(timeout=1), current=True)
if item.id in cancelled_uploads:
cancelled_uploads.remove(item.id)
continue
# Remove item if too old
age = datetime.now() - datetime.fromtimestamp(item.created_at / 1000)
@@ -260,13 +258,13 @@ def upload_handler(end_event: threading.Event) -> None:
sz = -1
cloudlog.event("athena.upload_handler.upload_start", fn=fn, sz=sz, network_type=network_type, metered=metered, retry_count=item.retry_count)
response = _do_upload(item, partial(cb, sm, item, tid, end_event))
with _do_upload(item, partial(cb, sm, item, tid, end_event)) as response:
if response.status_code not in (200, 201, 401, 403, 412):
cloudlog.event("athena.upload_handler.retry", status_code=response.status_code, fn=fn, sz=sz, network_type=network_type, metered=metered)
retry_upload(tid, end_event)
else:
cloudlog.event("athena.upload_handler.success", fn=fn, sz=sz, network_type=network_type, metered=metered)
if response.status_code not in (200, 201, 401, 403, 412):
cloudlog.event("athena.upload_handler.retry", status_code=response.status_code, fn=fn, sz=sz, network_type=network_type, metered=metered)
retry_upload(tid, end_event)
else:
cloudlog.event("athena.upload_handler.success", fn=fn, sz=sz, network_type=network_type, metered=metered)
UploadQueueCache.cache(upload_queue)
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError, requests.exceptions.SSLError):
@@ -311,16 +309,13 @@ def getMessage(service: str, timeout: int = 1000) -> dict:
raise Exception("invalid service")
socket = messaging.sub_sock(service, timeout=timeout)
try:
ret = messaging.recv_one(socket)
ret = messaging.recv_one(socket)
if ret is None:
raise TimeoutError
if ret is None:
raise TimeoutError
# this is because capnp._DynamicStructReader doesn't have typing information
return cast(dict, ret.to_dict())
finally:
del socket
# this is because capnp._DynamicStructReader doesn't have typing information
return cast(dict, ret.to_dict())
@dispatcher.add_method
@@ -415,10 +410,8 @@ def uploadFilesToUrls(files_data: list[UploadFileDict]) -> UploadFilesToUrlRespo
@dispatcher.add_method
def listUploadQueue() -> list[UploadItemDict]:
with cur_upload_items_lock, upload_queue.mutex:
items = list(upload_queue.queue) + [item for item in cur_upload_items.values() if item is not None]
return [asdict(item) for item in items]
items = list(upload_queue.queue) + list(cur_upload_items.values())
return [asdict(i) for i in items if (i is not None) and (i.id not in cancelled_uploads)]
@dispatcher.add_method
@@ -426,14 +419,13 @@ def cancelUpload(upload_id: str | list[str]) -> dict[str, int | str]:
if not isinstance(upload_id, list):
upload_id = [upload_id]
with upload_queue.mutex:
remaining_items = [item for item in upload_queue.queue if item.id not in upload_id]
if len(remaining_items) == len(upload_queue.queue):
return {"success": 0, "error": "not found"}
uploading_ids = {item.id for item in list(upload_queue.queue)}
cancelled_ids = uploading_ids.intersection(upload_id)
if len(cancelled_ids) == 0:
return {"success": 0, "error": "not found"}
upload_queue.queue.clear()
upload_queue.queue.extend(remaining_items)
return {"success": 1}
cancelled_uploads.update(cancelled_ids)
return {"success": 1}
@dispatcher.add_method
def setRouteViewed(route: str) -> dict[str, int | str]:
@@ -634,9 +626,8 @@ def log_handler(end_event: threading.Event) -> None:
def stat_handler(end_event: threading.Event) -> None:
STATS_DIR = Paths.stats_root()
last_scan = 0.0
while not end_event.is_set():
last_scan = 0.
curr_scan = time.monotonic()
try:
if curr_scan - last_scan > 10:
@@ -810,8 +801,6 @@ def main(exit_event: threading.Event = None):
cur_upload_items.clear()
handle_long_poll(ws, exit_event)
ws.close()
except (KeyboardInterrupt, SystemExit):
break
except (ConnectionError, TimeoutError, WebSocketException):
+7 -3
View File
@@ -78,6 +78,7 @@ class TestAthenadMethods:
athenad.upload_queue = queue.Queue()
athenad.cur_upload_items.clear()
athenad.cancelled_uploads.clear()
for i in os.listdir(Paths.log_root()):
p = os.path.join(Paths.log_root(), i)
@@ -239,7 +240,7 @@ class TestAthenadMethods:
@with_upload_handler
def test_upload_handler_retry(self, mocker, host, status, retry):
mock_put = mocker.patch('requests.put')
mock_put.return_value.__enter__.return_value.status_code = status
mock_put.return_value.status_code = status
fn = self._create_file('qlog.zst')
item = athenad.UploadItem(path=fn, url=f"{host}/qlog.zst", headers={}, created_at=int(time.time()*1000), id='', allow_cellular=True)
@@ -281,10 +282,13 @@ class TestAthenadMethods:
athenad.upload_queue.put_nowait(item)
dispatcher["cancelUpload"](item.id)
assert item.id in athenad.cancelled_uploads
self._wait_for_upload()
time.sleep(0.1)
assert athenad.upload_queue.qsize() == 0
assert len(athenad.cancelled_uploads) == 0
@with_upload_handler
def test_cancel_expiry(self):
@@ -327,7 +331,7 @@ class TestAthenadMethods:
assert items[0] == asdict(item)
assert not items[0]['current']
dispatcher["cancelUpload"](item.id)
athenad.cancelled_uploads.add(item.id)
items = dispatcher["listUploadQueue"]()
assert len(items) == 0
@@ -339,7 +343,7 @@ class TestAthenadMethods:
athenad.upload_queue.put_nowait(item2)
# Ensure canceled items are not persisted
dispatcher["cancelUpload"](item2.id)
athenad.cancelled_uploads.add(item2.id)
# serialize item
athenad.UploadQueueCache.cache(athenad.upload_queue)
+9 -12
View File
@@ -65,19 +65,16 @@ void CameraBuf::init(cl_device_id device_id, cl_context context, SpectraCamera *
const SensorInfo *sensor = cam->sensor.get();
is_raw = cam->is_raw;
camera_bufs_raw = std::make_unique<VisionBuf[]>(frame_buf_count);
frame_metadata = std::make_unique<FrameMetadata[]>(frame_buf_count);
// RAW frames from ISP
if (is_raw) {
camera_bufs_raw = std::make_unique<VisionBuf[]>(frame_buf_count);
const int raw_frame_size = (sensor->frame_height + sensor->extra_height) * sensor->frame_stride;
for (int i = 0; i < frame_buf_count; i++) {
camera_bufs_raw[i].allocate(raw_frame_size);
camera_bufs_raw[i].init_cl(device_id, context);
}
LOGD("allocated %d CL buffers", frame_buf_count);
// RAW + final frames from ISP
const int raw_frame_size = (sensor->frame_height + sensor->extra_height) * sensor->frame_stride;
for (int i = 0; i < frame_buf_count; i++) {
camera_bufs_raw[i].allocate(raw_frame_size);
camera_bufs_raw[i].init_cl(device_id, context);
}
LOGD("allocated %d CL buffers", frame_buf_count);
out_img_width = sensor->frame_width;
out_img_height = sensor->hdr_offset > 0 ? (sensor->frame_height - sensor->hdr_offset) / 2 : sensor->frame_height;
@@ -86,8 +83,8 @@ void CameraBuf::init(cl_device_id device_id, cl_context context, SpectraCamera *
// TODO: VENUS_BUFFER_SIZE should give the size, but it's too small. dependent on encoder settings?
size_t nv12_size = (out_img_width <= 1344 ? 2900 : 2346)*cam->stride;
vipc_server->create_buffers_with_sizes(stream_type, VIPC_BUFFER_COUNT, out_img_width, out_img_height, nv12_size, cam->stride, cam->uv_offset);
LOGD("created %d YUV vipc buffers with size %dx%d", VIPC_BUFFER_COUNT, cam->stride, cam->y_height);
vipc_server->create_buffers_with_sizes(stream_type, YUV_BUFFER_COUNT, out_img_width, out_img_height, nv12_size, cam->stride, cam->uv_offset);
LOGD("created %d YUV vipc buffers with size %dx%d", YUV_BUFFER_COUNT, cam->stride, cam->y_height);
imgproc = new ImgProc(device_id, context, this, sensor, cam->cc.camera_num, cam->stride, cam->uv_offset);
}
+1 -1
View File
@@ -8,7 +8,7 @@
#include "common/util.h"
const int VIPC_BUFFER_COUNT = 18;
const int YUV_BUFFER_COUNT = 20;
typedef struct FrameMetadata {
uint32_t frame_id;
+4 -4
View File
@@ -69,10 +69,10 @@ public:
};
void CameraState::init(VisionIpcServer *v, cl_device_id device_id, cl_context ctx) {
camera.camera_open(v, device_id, ctx);
if (!camera.enabled) return;
camera.camera_open(v, device_id, ctx);
fl_pix = camera.cc.focal_len / camera.sensor->pixel_size_mm;
set_exposure_rect();
@@ -140,14 +140,14 @@ void CameraState::set_camera_exposure(float grey_frac) {
// Therefore we use the target EV from 3 frames ago, the grey fraction that was just measured was the result of that control action.
// TODO: Lower latency to 2 frames, by using the histogram outputted by the sensor we can do AE before the debayering is complete
const float cur_ev_ = cur_ev[camera.buf.cur_frame_data.frame_id % 3];
const auto &sensor = camera.sensor;
const float cur_ev_ = cur_ev[camera.buf.cur_frame_data.frame_id % 3] * sensor->ev_scale;
// Scale target grey between 0.1 and 0.4 depending on lighting conditions
float new_target_grey = std::clamp(0.4 - 0.3 * log2(1.0 + sensor->target_grey_factor*cur_ev_) / log2(6000.0), 0.1, 0.4);
float target_grey = (1.0 - k_grey) * target_grey_fraction + k_grey * new_target_grey;
float desired_ev = std::clamp(cur_ev_ / sensor->ev_scale * target_grey / grey_frac, sensor->min_ev, sensor->max_ev);
float desired_ev = std::clamp(cur_ev_ * target_grey / grey_frac, sensor->min_ev, sensor->max_ev);
float k = (1.0 - k_ev) / 3.0;
desired_ev = (k * cur_ev[0]) + (k * cur_ev[1]) + (k * cur_ev[2]) + (k_ev * desired_ev);
+34 -37
View File
@@ -242,9 +242,6 @@ SpectraCamera::SpectraCamera(SpectraMaster *master, const CameraConfig &config,
cc(config),
is_raw(raw) {
mm.init(m->video0_fd);
ife_buf_depth = is_raw ? 4 : VIPC_BUFFER_COUNT;
assert(ife_buf_depth < MAX_IFE_BUFS);
}
SpectraCamera::~SpectraCamera() {
@@ -264,12 +261,12 @@ int SpectraCamera::clear_req_queue() {
}
void SpectraCamera::camera_open(VisionIpcServer *v, cl_device_id device_id, cl_context ctx) {
if (!enabled) return;
if (!openSensor()) {
return;
}
if (!enabled) return;
// size is driven by all the HW that handles frames,
// the video encoder has certain alignment requirements in this case
stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, sensor->frame_width);
@@ -291,15 +288,14 @@ void SpectraCamera::camera_open(VisionIpcServer *v, cl_device_id device_id, cl_c
linkDevices();
LOGD("camera init %d", cc.camera_num);
buf.init(device_id, ctx, this, v, ife_buf_depth, cc.stream_type);
buf.init(device_id, ctx, this, v, FRAME_BUF_COUNT, cc.stream_type);
camera_map_bufs();
enqueue_req_multi(1, ife_buf_depth, 0);
}
void SpectraCamera::enqueue_req_multi(uint64_t start, int n, bool dp) {
for (uint64_t i = start; i < start + n; ++i) {
request_ids[(i - 1) % ife_buf_depth] = i;
enqueue_buffer((i - 1) % ife_buf_depth, dp);
request_ids[(i - 1) % FRAME_BUF_COUNT] = i;
enqueue_buffer((i - 1) % FRAME_BUF_COUNT, dp);
}
}
@@ -674,7 +670,7 @@ void SpectraCamera::enqueue_buffer(int i, bool dp) {
int ret;
uint64_t request_id = request_ids[i];
if (sync_objs[i]) {
if (buf_handle_raw[i] && sync_objs[i]) {
// wait
struct cam_sync_wait sync_wait = {0};
sync_wait.sync_obj = sync_objs[i];
@@ -737,31 +733,31 @@ void SpectraCamera::enqueue_buffer(int i, bool dp) {
void SpectraCamera::camera_map_bufs() {
int ret;
for (int i = 0; i < ife_buf_depth; i++) {
for (int i = 0; i < FRAME_BUF_COUNT; i++) {
// configure ISP to put the image in place
struct cam_mem_mgr_map_cmd mem_mgr_map_cmd = {0};
mem_mgr_map_cmd.flags = CAM_MEM_FLAG_HW_READ_WRITE;
mem_mgr_map_cmd.mmu_hdls[0] = m->device_iommu;
mem_mgr_map_cmd.num_hdl = 1;
//mem_mgr_map_cmd.mmu_hdls[1] = m->icp_device_iommu;
//mem_mgr_map_cmd.num_hdl = 2;
mem_mgr_map_cmd.num_hdl = 1;
mem_mgr_map_cmd.flags = CAM_MEM_FLAG_HW_READ_WRITE;
if (is_raw) {
// RAW bayer images
mem_mgr_map_cmd.fd = buf.camera_bufs_raw[i].fd;
ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_MAP_BUF, &mem_mgr_map_cmd, sizeof(mem_mgr_map_cmd));
assert(ret == 0);
LOGD("map buf req: (fd: %d) 0x%x %d", buf.camera_bufs_raw[i].fd, mem_mgr_map_cmd.out.buf_handle, ret);
buf_handle_raw[i] = mem_mgr_map_cmd.out.buf_handle;
} else {
// final processed images
VisionBuf *vb = buf.vipc_server->get_buffer(buf.stream_type, i);
mem_mgr_map_cmd.fd = vb->fd;
ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_MAP_BUF, &mem_mgr_map_cmd, sizeof(mem_mgr_map_cmd));
LOGD("map buf req: (fd: %d) 0x%x %d", vb->fd, mem_mgr_map_cmd.out.buf_handle, ret);
buf_handle_yuv[i] = mem_mgr_map_cmd.out.buf_handle;
}
// RAW bayer images
mem_mgr_map_cmd.fd = buf.camera_bufs_raw[i].fd;
ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_MAP_BUF, &mem_mgr_map_cmd, sizeof(mem_mgr_map_cmd));
assert(ret == 0);
LOGD("map buf req: (fd: %d) 0x%x %d", buf.camera_bufs_raw[i].fd, mem_mgr_map_cmd.out.buf_handle, ret);
buf_handle_raw[i] = mem_mgr_map_cmd.out.buf_handle;
// TODO: this needs to match camera bufs length
// final processed images
VisionBuf *vb = buf.vipc_server->get_buffer(buf.stream_type, i);
mem_mgr_map_cmd.fd = vb->fd;
ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_MAP_BUF, &mem_mgr_map_cmd, sizeof(mem_mgr_map_cmd));
LOGD("map buf req: (fd: %d) 0x%x %d", vb->fd, mem_mgr_map_cmd.out.buf_handle, ret);
buf_handle_yuv[i] = mem_mgr_map_cmd.out.buf_handle;
}
enqueue_req_multi(1, FRAME_BUF_COUNT, 0);
}
bool SpectraCamera::openSensor() {
@@ -874,7 +870,7 @@ void SpectraCamera::configISP() {
// allocate IFE memory, then configure it
ife_cmd.init(m, 67984, 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE,
m->device_iommu, m->cdm_iommu, ife_buf_depth);
m->device_iommu, m->cdm_iommu, FRAME_BUF_COUNT);
if (!is_raw) {
ife_gamma_lut.init(m, 64*sizeof(uint32_t), 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE,
@@ -929,7 +925,7 @@ void SpectraCamera::configICP() {
// BPS CMD buffer
unsigned char striping_out[] = "\x00";
bps_cmd.init(m, ife_buf_depth*ALIGNED_SIZE(464, 0x20), 0x20,
bps_cmd.init(m, FRAME_BUF_COUNT*ALIGNED_SIZE(464, 0x20), 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE | CAM_MEM_FLAG_HW_SHARED_ACCESS,
m->icp_device_iommu);
@@ -1050,8 +1046,9 @@ void SpectraCamera::camera_close() {
ret = device_control(csiphy_fd, CAM_RELEASE_DEV, session_handle, csiphy_dev_handle);
LOGD("release csiphy: %d", ret);
for (int i = 0; i < ife_buf_depth; i++) {
release(m->video0_fd, is_raw ? buf_handle_raw[i] : buf_handle_yuv[i]);
for (int i = 0; i < FRAME_BUF_COUNT; i++) {
release(m->video0_fd, buf_handle_yuv[i]);
release(m->video0_fd, buf_handle_raw[i]);
}
LOGD("released buffers");
}
@@ -1074,13 +1071,13 @@ void SpectraCamera::handle_camera_event(const cam_req_mgr_message *event_data) {
if (real_id != 0) { // next ready
if (real_id == 1) {idx_offset = main_id;}
int buf_idx = (real_id - 1) % ife_buf_depth;
int buf_idx = (real_id - 1) % FRAME_BUF_COUNT;
// check for skipped frames
if (main_id > frame_id_last + 1 && !skipped) {
LOGE("camera %d realign", cc.camera_num);
clear_req_queue();
enqueue_req_multi(real_id + 1, ife_buf_depth - 1, 0);
enqueue_req_multi(real_id + 1, FRAME_BUF_COUNT - 1, 0);
skipped = true;
} else if (main_id == frame_id_last + 1) {
skipped = false;
@@ -1089,7 +1086,7 @@ void SpectraCamera::handle_camera_event(const cam_req_mgr_message *event_data) {
// check for dropped requests
if (real_id > request_id_last + 1) {
LOGE("camera %d dropped requests %ld %ld", cc.camera_num, real_id, request_id_last);
enqueue_req_multi(request_id_last + 1 + ife_buf_depth, real_id - (request_id_last + 1), 0);
enqueue_req_multi(request_id_last + 1 + FRAME_BUF_COUNT, real_id - (request_id_last + 1), 0);
}
// metas
@@ -1102,12 +1099,12 @@ void SpectraCamera::handle_camera_event(const cam_req_mgr_message *event_data) {
meta_data.timestamp_sof = timestamp; // this is timestamped in the kernel's SOF IRQ callback
// dispatch
enqueue_req_multi(real_id + ife_buf_depth, 1, 1);
enqueue_req_multi(real_id + FRAME_BUF_COUNT, 1, 1);
} else { // not ready
if (main_id > frame_id_last + 10) {
LOGE("camera %d reset after half second of no response", cc.camera_num);
clear_req_queue();
enqueue_req_multi(request_id_last + 1, ife_buf_depth, 0);
enqueue_req_multi(request_id_last + 1, FRAME_BUF_COUNT, 0);
frame_id_last = main_id;
skipped = true;
}
+6 -7
View File
@@ -12,7 +12,7 @@
#include "system/camerad/cameras/camera_common.h"
#include "system/camerad/sensors/sensor.h"
#define MAX_IFE_BUFS 20
#define FRAME_BUF_COUNT 4
const int MIPI_SETTLE_CNT = 33; // Calculated by camera_freqs.py
@@ -116,7 +116,6 @@ public:
// *** state ***
int ife_buf_depth = -1;
bool open = false;
bool enabled = true;
CameraConfig cc;
@@ -152,11 +151,11 @@ public:
SpectraBuf bps_iq;
SpectraBuf bps_striping;
int buf_handle_yuv[MAX_IFE_BUFS] = {};
int buf_handle_raw[MAX_IFE_BUFS] = {};
int sync_objs[MAX_IFE_BUFS] = {};
int sync_objs_bps_out[MAX_IFE_BUFS] = {};
uint64_t request_ids[MAX_IFE_BUFS] = {};
int buf_handle_yuv[FRAME_BUF_COUNT] = {};
int buf_handle_raw[FRAME_BUF_COUNT] = {};
int sync_objs[FRAME_BUF_COUNT] = {};
int sync_objs_bps_out[FRAME_BUF_COUNT] = {};
uint64_t request_ids[FRAME_BUF_COUNT] = {};
uint64_t request_id_last = 0;
uint64_t frame_id_last = 0;
uint64_t idx_offset = 0;
+4 -5
View File
@@ -43,28 +43,27 @@ OS04C10::OS04C10() {
frame_data_type = 0x2c;
mclk_frequency = 24000000; // Hz
ev_scale = 150.0;
dc_gain_factor = 1;
dc_gain_min_weight = 1; // always on is fine
dc_gain_max_weight = 1;
dc_gain_on_grey = 0.9;
dc_gain_off_grey = 1.0;
exposure_time_min = 2;
exposure_time_max = 1684;
exposure_time_max = 2400;
analog_gain_min_idx = 0x0;
analog_gain_rec_idx = 0x0; // 1x
analog_gain_max_idx = 0x28;
analog_gain_max_idx = 0x36;
analog_gain_cost_delta = -1;
analog_gain_cost_low = 0.4;
analog_gain_cost_high = 6.4;
for (int i = 0; i <= analog_gain_max_idx; i++) {
sensor_analog_gains[i] = sensor_analog_gains_OS04C10[i];
}
min_ev = exposure_time_min * sensor_analog_gains[analog_gain_min_idx];
min_ev = (exposure_time_min) * sensor_analog_gains[analog_gain_min_idx];
max_ev = exposure_time_max * dc_gain_factor * sensor_analog_gains[analog_gain_max_idx];
target_grey_factor = 0.01;
black_level = 48;
black_level = 64;
color_correct_matrix = {
0x000000c2, 0x00000fe0, 0x00000fde,
0x00000fa7, 0x000000d9, 0x00001000,

Some files were not shown because too many files have changed in this diff Show More