Merge remote-tracking branch 'upstream/master' into toyota-fuzzy-v2

pull/28641/head
Shane Smiskol 2 years ago
commit 6538b2774e
  1. 7
      .devcontainer/Dockerfile
  2. 23
      .devcontainer/container_post_create.sh
  3. 8
      .devcontainer/container_post_start.sh
  4. 5
      .devcontainer/devcontainer.json
  5. 18
      .devcontainer/host_setup
  6. 10
      .devcontainer/host_setup.cmd
  7. 3
      .dir-locals.el
  8. 2
      .gitattributes
  9. 10
      .github/labeler.yaml
  10. 1
      .github/workflows/prebuilt.yaml
  11. 6
      .pre-commit-config.yaml
  12. 3
      Dockerfile.openpilot_base
  13. 11
      RELEASES.md
  14. 1
      common/params.cc
  15. 2
      common/transformations/README.md
  16. 2
      common/version.h
  17. 20
      conftest.py
  18. 6
      docs/CARS.md
  19. 2
      panda
  20. 747
      poetry.lock
  21. 12
      pyproject.toml
  22. 3
      release/files_common
  23. 59
      scripts/dump_pll.c
  24. 2
      selfdrive/athena/athenad.py
  25. 2
      selfdrive/athena/tests/test_athenad.py
  26. 48
      selfdrive/boardd/pandad.py
  27. 29
      selfdrive/boardd/tests/test_pandad.py
  28. 3
      selfdrive/car/body/values.py
  29. 5
      selfdrive/car/car_helpers.py
  30. 4
      selfdrive/car/chrysler/values.py
  31. 4
      selfdrive/car/ford/values.py
  32. 4
      selfdrive/car/gm/values.py
  33. 4
      selfdrive/car/honda/values.py
  34. 10
      selfdrive/car/hyundai/interface.py
  35. 12
      selfdrive/car/hyundai/values.py
  36. 7
      selfdrive/car/mazda/values.py
  37. 3
      selfdrive/car/mock/values.py
  38. 3
      selfdrive/car/nissan/values.py
  39. 6
      selfdrive/car/subaru/values.py
  40. 3
      selfdrive/car/tesla/values.py
  41. 14
      selfdrive/car/toyota/values.py
  42. 7
      selfdrive/car/volkswagen/values.py
  43. 105
      selfdrive/debug/auto_fingerprint.py
  44. 4
      selfdrive/debug/hyundai_enable_radar_points.py
  45. 1
      selfdrive/debug/vw_mqb_config.py
  46. 1
      selfdrive/hardware
  47. 2
      selfdrive/modeld/modeld.py
  48. 4
      selfdrive/modeld/models/supercombo.onnx
  49. 21
      selfdrive/rtshield.py
  50. 48
      selfdrive/test/process_replay/compare_logs.py
  51. 86
      selfdrive/test/process_replay/migration.py
  52. 3
      selfdrive/test/process_replay/model_replay.py
  53. 2
      selfdrive/test/process_replay/model_replay_ref_commit
  54. 26
      selfdrive/test/process_replay/process_replay.py
  55. 76
      selfdrive/test/process_replay/regen.py
  56. 41
      selfdrive/test/process_replay/test_processes.py
  57. 4
      selfdrive/test/process_replay/vision_meta.py
  58. 2
      selfdrive/ui/qt/widgets/cameraview.cc
  59. 2
      selfdrive/ui/qt/widgets/input.h
  60. 7
      selfdrive/ui/tests/test_translations.py
  61. 398
      selfdrive/ui/translations/main_ar.ts
  62. 2
      system/hardware/hw.py
  63. 105
      system/hardware/tici/power_draw_test.py
  64. 2
      system/loggerd/config.py
  65. 2
      system/loggerd/tests/test_encoder.py
  66. 4
      system/sensord/pigeond.py
  67. 268
      third_party/acados/include/qpOASES_e/Constants.h
  68. 124
      third_party/acados/include/qpOASES_e/ConstraintProduct.h
  69. 442
      third_party/acados/include/qpOASES_e/Indexlist.h
  70. 574
      third_party/acados/include/qpOASES_e/Matrices.h
  71. 306
      third_party/acados/include/qpOASES_e/Options.h
  72. 4738
      third_party/acados/include/qpOASES_e/QProblem.h
  73. 620
      third_party/acados/include/qpOASES_e/Types.h
  74. 158
      third_party/acados/include/qpOASES_e/UnitTesting.h
  75. 124
      third_party/catch2/include/catch2/catch_reporter_automake.hpp
  76. 360
      third_party/catch2/include/catch2/catch_reporter_sonarqube.hpp
  77. 508
      third_party/catch2/include/catch2/catch_reporter_tap.hpp
  78. 438
      third_party/catch2/include/catch2/catch_reporter_teamcity.hpp
  79. 254
      third_party/snpe/include/DlSystem/IOBufferDataTypeMap.hpp
  80. 2
      tools/cabana/chart/chart.cc
  81. 2
      tools/cabana/signalview.cc
  82. 13
      tools/camerastream/compressed_vipc.py
  83. 34
      tools/lib/tests/test_caching.py
  84. 2
      tools/lib/url_file.py
  85. 2
      tools/replay/replay.cc
  86. 26
      tools/scripts/fetch_image_from_route.py
  87. 104
      tools/sim/README.md
  88. 4
      tools/sim/bridge/carla/carla_bridge.py
  89. 4
      tools/sim/bridge/carla/carla_world.py
  90. 19
      tools/sim/bridge/common.py
  91. 153
      tools/sim/bridge/metadrive/metadrive_bridge.py
  92. 99
      tools/sim/bridge/metadrive/metadrive_process.py
  93. 80
      tools/sim/bridge/metadrive/metadrive_world.py
  94. 4
      tools/sim/lib/common.py
  95. 22
      tools/sim/lib/keyboard_ctrl.py
  96. 9
      tools/sim/lib/simulated_car.py
  97. 4
      tools/sim/lib/simulated_sensors.py
  98. 4
      tools/sim/run_bridge.py
  99. 2
      tools/sim/tmux_script.sh

@ -1,8 +1,13 @@
FROM ghcr.io/commaai/openpilot-base:latest FROM ghcr.io/commaai/openpilot-base:latest
RUN apt update && apt install -y vim net-tools usbutils htop ripgrep tmux RUN apt update && apt install -y vim net-tools usbutils htop ripgrep tmux wget mesa-utils xvfb libxtst6 libxv1 libglu1-mesa libegl1-mesa
RUN pip install ipython jupyter jupyterlab RUN pip install ipython jupyter jupyterlab
RUN cd /tmp && \
ARCH=$(arch | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) && \
curl -L -o virtualgl.deb "https://downloads.sourceforge.net/project/virtualgl/3.1/virtualgl_3.1_$ARCH.deb" && \
dpkg -i virtualgl.deb
USER batman USER batman
RUN cd $HOME && \ RUN cd $HOME && \

@ -3,17 +3,34 @@
TARGET_USER=batman TARGET_USER=batman
source .devcontainer/.host/.env source .devcontainer/.host/.env
# override display flag for mac # override display flag for mac hosts
if [[ $HOST_OS == darwin ]]; then if [[ $HOST_OS == darwin ]]; then
echo "Setting up DISPLAY override for macOS..." echo "Setting up DISPLAY override for macOS..."
cat <<EOF >> /home/$TARGET_USER/.bashrc cat <<EOF >> /home/$TARGET_USER/.bashrc
if [ -n "\$DISPLAY" ]; then source .devcontainer/.host/.env
DISPLAY_NUM=\$(echo "\$DISPLAY" | awk -F: '{print \$NF}') if [ -n "\$HOST_DISPLAY" ]; then
DISPLAY_NUM=\$(echo "\$HOST_DISPLAY" | awk -F: '{print \$NF}')
export DISPLAY=host.docker.internal:\$DISPLAY_NUM export DISPLAY=host.docker.internal:\$DISPLAY_NUM
fi fi
EOF EOF
fi 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 # These lines are temporary, to remain backwards compatible with old devcontainers
# that were running as root and therefore had their caches written as root # 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/scons_cache

@ -1,7 +1,15 @@
#!/usr/bin/env bash #!/usr/bin/env bash
source .devcontainer/.host/.env
# setup safe directories for submodules # setup safe directories for submodules
SUBMODULE_DIRS=$(git config --file .gitmodules --get-regexp path | awk '{ print $2 }') SUBMODULE_DIRS=$(git config --file .gitmodules --get-regexp path | awk '{ print $2 }')
for DIR in $SUBMODULE_DIRS; do for DIR in $SUBMODULE_DIRS; do
git config --global --add safe.directory "$PWD/$DIR" git config --global --add safe.directory "$PWD/$DIR"
done 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

@ -5,7 +5,7 @@
}, },
"postCreateCommand": ".devcontainer/container_post_create.sh", "postCreateCommand": ".devcontainer/container_post_create.sh",
"postStartCommand": ".devcontainer/container_post_start.sh", "postStartCommand": ".devcontainer/container_post_start.sh",
"initializeCommand": ".devcontainer/host_setup.sh", "initializeCommand": [".devcontainer/host_setup"],
"privileged": true, "privileged": true,
"containerEnv": { "containerEnv": {
"DISPLAY": "${localEnv:DISPLAY}", "DISPLAY": "${localEnv:DISPLAY}",
@ -21,7 +21,8 @@
"--volume=/tmp/comma_download_cache:/tmp/comma_download_cache", "--volume=/tmp/comma_download_cache:/tmp/comma_download_cache",
"--volume=/tmp/devcontainer_scons_cache:/tmp/scons_cache", "--volume=/tmp/devcontainer_scons_cache:/tmp/scons_cache",
"--shm-size=1G", "--shm-size=1G",
"--add-host=host.docker.internal:host-gateway" // required to use host.docker.internal on linux "--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": { "features": {
"ghcr.io/devcontainers/features/common-utils:2": { "ghcr.io/devcontainers/features/common-utils:2": {

@ -2,6 +2,7 @@
# pull base image # pull base image
if [[ -z $USE_LOCAL_IMAGE ]]; then if [[ -z $USE_LOCAL_IMAGE ]]; then
echo "Updating openpilot_base image if needed..."
docker pull ghcr.io/commaai/openpilot-base:latest docker pull ghcr.io/commaai/openpilot-base:latest
fi fi
@ -27,3 +28,20 @@ fi
HOST_INFO_FILE=".devcontainer/.host/.env" HOST_INFO_FILE=".devcontainer/.host/.env"
SYSTEM=$(uname -s | tr '[:upper:]' '[:lower:]') SYSTEM=$(uname -s | tr '[:upper:]' '[:lower:]')
echo "HOST_OS=\"$SYSTEM\"" > $HOST_INFO_FILE 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

@ -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,3 +0,0 @@
((c++-mode (flycheck-gcc-language-standard . "c++11")
(flycheck-clang-language-standard . "c++11")
))

2
.gitattributes vendored

@ -1,3 +1,5 @@
* text=auto
*.dlc filter=lfs diff=lfs merge=lfs -text *.dlc filter=lfs diff=lfs merge=lfs -text
*.onnx filter=lfs diff=lfs merge=lfs -text *.onnx filter=lfs diff=lfs merge=lfs -text
selfdrive/car/tests/test_models_segs.txt filter=lfs diff=lfs merge=lfs -text selfdrive/car/tests/test_models_segs.txt filter=lfs diff=lfs merge=lfs -text

@ -1,8 +1,6 @@
CI / testing: CI / testing:
- all: - all:
- changed-files: ['.github/**'] - changed-files: ['.github/**', '**/test_*', 'Jenkinsfile']
- all:
- changed-files: ['**/test_*']
car: car:
- all: - all:
@ -59,3 +57,9 @@ multilanguage:
- all: - all:
- changed-files: ['selfdrive/ui/translations/**'] - changed-files: ['selfdrive/ui/translations/**']
research:
- all:
- changed-files: [
'selfdrive/modeld/models/**',
'selfdrive/test/process_replay/model_replay_ref_commit',
]

@ -27,6 +27,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
submodules: true submodules: true
- run: git lfs pull
- name: Build and Push docker image - name: Build and Push docker image
run: | run: |
$DOCKER_LOGIN $DOCKER_LOGIN

@ -23,13 +23,13 @@ repos:
- --maxkb=500 - --maxkb=500
- --enforce-all - --enforce-all
- repo: https://github.com/codespell-project/codespell - repo: https://github.com/codespell-project/codespell
rev: v2.2.5 rev: v2.2.6
hooks: hooks:
- id: codespell - id: codespell
exclude: '^(third_party/)|(body/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(opendbc/)|(laika_repo/)|(rednose_repo/)|(selfdrive/ui/translations/.*.ts)|(poetry.lock)' exclude: '^(third_party/)|(body/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(opendbc/)|(laika_repo/)|(rednose_repo/)|(selfdrive/ui/translations/.*.ts)|(poetry.lock)'
args: args:
# if you've got a short variable name that's getting flagged, add it here # if you've got a short variable name that's getting flagged, add it here
- -L bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie - -L bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints
- --builtins clear,rare,informal,usage,code,names,en-GB_to_en-US - --builtins clear,rare,informal,usage,code,names,en-GB_to_en-US
- repo: local - repo: local
hooks: hooks:
@ -41,7 +41,7 @@ repos:
args: ['--explicit-package-bases'] args: ['--explicit-package-bases']
exclude: '^(third_party/)|(cereal/)|(opendbc/)|(panda/)|(laika/)|(laika_repo/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(xx/)' exclude: '^(third_party/)|(cereal/)|(opendbc/)|(panda/)|(laika/)|(laika_repo/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(xx/)'
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.291 rev: v0.0.292
hooks: hooks:
- id: ruff - id: ruff
exclude: '^(third_party/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(laika_repo/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)' exclude: '^(third_party/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(laika_repo/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)'

@ -38,8 +38,7 @@ COPY --chown=$USER tools/install_python_dependencies.sh /tmp/tools/
RUN cd /tmp && \ RUN cd /tmp && \
tools/install_python_dependencies.sh && \ tools/install_python_dependencies.sh && \
rm -rf /tmp/* && \ rm -rf /tmp/* && \
rm -rf /home/$USER/.cache && \ rm -rf /home/$USER/.cache
pip uninstall -y poetry
USER root USER root
RUN sudo git config --global --add safe.directory /tmp/openpilot RUN sudo git config --global --add safe.directory /tmp/openpilot

@ -1,18 +1,15 @@
Version 0.9.6 (2023-XX-XX) Version 0.9.5 (2023-XX-XX)
========================
* Hyundai Azera Hybrid 2020 support thanks to chanhojung and haram-KONA!
* Hyundai Custin 2023 support thanks to sunnyhaibin and Saber422!
* Kia Optima Hybrid 2019 support
Version 0.9.5 (2023-09-27)
======================== ========================
* New driving model * New driving model
* Improved navigate on openpilot performance using navigation instructions as an additional model input * Improved navigate on openpilot performance using navigation instructions as an additional model input
* Hyundai Azera 2022 support thanks to sunnyhaibin! * Hyundai Azera 2022 support thanks to sunnyhaibin!
* Hyundai Azera Hybrid 2020 support thanks to chanhojung and haram-KONA!
* Hyundai Custin 2023 support thanks to sunnyhaibin and Saber422!
* Hyundai Ioniq 6 2023 support thanks to sunnyhaibin, alamo3, and sshane! * Hyundai Ioniq 6 2023 support thanks to sunnyhaibin, alamo3, and sshane!
* Hyundai Kona Electric 2023 (Korean version) support thanks to sunnyhaibin and haram-KONA! * Hyundai Kona Electric 2023 (Korean version) support thanks to sunnyhaibin and haram-KONA!
* Kia K8 Hybrid (with HDA II) 2023 support thanks to sunnyhaibin! * Kia K8 Hybrid (with HDA II) 2023 support thanks to sunnyhaibin!
* Kia Sorento Hybrid 2023 support thanks to sunnyhaibin! * Kia Sorento Hybrid 2023 support thanks to sunnyhaibin!
* Kia Optima Hybrid 2019 support
* Lexus IS 2023 support thanks to L3R5! * Lexus IS 2023 support thanks to L3R5!
Version 0.9.4 (2023-07-27) Version 0.9.4 (2023-07-27)

@ -181,7 +181,6 @@ std::unordered_map<std::string, uint32_t> keys = {
{"Offroad_UpdateFailed", CLEAR_ON_MANAGER_START}, {"Offroad_UpdateFailed", CLEAR_ON_MANAGER_START},
{"OpenpilotEnabledToggle", PERSISTENT}, {"OpenpilotEnabledToggle", PERSISTENT},
{"PandaHeartbeatLost", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION}, {"PandaHeartbeatLost", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
{"PandaLogState", PERSISTENT},
{"PandaSignatures", CLEAR_ON_MANAGER_START}, {"PandaSignatures", CLEAR_ON_MANAGER_START},
{"Passive", PERSISTENT}, {"Passive", PERSISTENT},
{"PrimeType", PERSISTENT}, {"PrimeType", PERSISTENT},

@ -11,7 +11,7 @@ by generating a rotation matrix and multiplying.
| :-------------: |:-------------:| :-----:| :----: | | :-------------: |:-------------:| :-----:| :----: |
| Geodetic | [Latitude, Longitude, Altitude] | geodetic coordinates | Sometimes used as [lon, lat, alt], avoid this frame. | | Geodetic | [Latitude, Longitude, Altitude] | geodetic coordinates | Sometimes used as [lon, lat, alt], avoid this frame. |
| ECEF | [x, y, z] | meters | We use **ITRF14 (IGS14)**, NOT NAD83. <br> This is the global Mesh3D frame. | | ECEF | [x, y, z] | meters | We use **ITRF14 (IGS14)**, NOT NAD83. <br> This is the global Mesh3D frame. |
| NED | [North, East, Down] | meters | Relative to earth's surface, useful for vizualizing. | | NED | [North, East, Down] | meters | Relative to earth's surface, useful for visualizing. |
| Device | [Forward, Right, Down] | meters | This is the Mesh3D local frame. <br> Relative to camera, **not imu.** <br> ![img](http://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/RPY_angles_of_airplanes.png/440px-RPY_angles_of_airplanes.png)| | Device | [Forward, Right, Down] | meters | This is the Mesh3D local frame. <br> Relative to camera, **not imu.** <br> ![img](http://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/RPY_angles_of_airplanes.png/440px-RPY_angles_of_airplanes.png)|
| Calibrated | [Forward, Right, Down] | meters | This is the frame the model outputs are in. <br> More details below. <br>| | Calibrated | [Forward, Right, Down] | meters | This is the frame the model outputs are in. <br> More details below. <br>|
| Car | [Forward, Right, Down] | meters | This is useful for estimating position of points on the road. <br> More details below. <br>| | Car | [Forward, Right, Down] | meters | This is useful for estimating position of points on the road. <br> More details below. <br>|

@ -1 +1 @@
#define COMMA_VERSION "0.9.6" #define COMMA_VERSION "0.9.5"

@ -1,10 +1,28 @@
import os
import pytest import pytest
from openpilot.common.prefix import OpenpilotPrefix from openpilot.common.prefix import OpenpilotPrefix
@pytest.fixture(scope="function", autouse=True) @pytest.fixture(scope="function", autouse=True)
def global_setup_and_teardown(): def openpilot_function_fixture():
starting_env = dict(os.environ)
# setup a clean environment for each test # setup a clean environment for each test
with OpenpilotPrefix(): with OpenpilotPrefix():
yield yield
os.environ.clear()
os.environ.update(starting_env)
# If you use setUpClass, the environment variables won't be cleared properly,
# so we need to hook both the function and class pytest fixtures
@pytest.fixture(scope="class", autouse=True)
def openpilot_class_fixture():
starting_env = dict(os.environ)
yield
os.environ.clear()
os.environ.update(starting_env)

@ -136,7 +136,7 @@ A supported vehicle is one that just works when you install a comma device. All
|Kia|Optima 2019-20|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G 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=Kia&model=Optima 2019-20">Buy Here</a></sub></details>|| |Kia|Optima 2019-20|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G 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=Kia&model=Optima 2019-20">Buy Here</a></sub></details>||
|Kia|Optima Hybrid 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H 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=Kia&model=Optima Hybrid 2019">Buy Here</a></sub></details>|| |Kia|Optima Hybrid 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H 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=Kia&model=Optima Hybrid 2019">Buy Here</a></sub></details>||
|Kia|Seltos 2021|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A 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=Kia&model=Seltos 2021">Buy Here</a></sub></details>|| |Kia|Seltos 2021|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A 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=Kia&model=Seltos 2021">Buy Here</a></sub></details>||
|Kia|Sorento 2018|Advanced Smart Cruise Control|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C 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=Kia&model=Sorento 2018">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Fkh3s6WHJz8" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>| |Kia|Sorento 2018|Advanced Smart Cruise Control & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E 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=Kia&model=Sorento 2018">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Fkh3s6WHJz8" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Kia|Sorento 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E 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=Kia&model=Sorento 2019">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Fkh3s6WHJz8" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>| |Kia|Sorento 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E 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=Kia&model=Sorento 2019">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Fkh3s6WHJz8" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Kia|Sorento 2021-23[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K 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=Kia&model=Sorento 2021-23">Buy Here</a></sub></details>|| |Kia|Sorento 2021-23[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K 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=Kia&model=Sorento 2021-23">Buy Here</a></sub></details>||
|Kia|Sorento Hybrid 2023[<sup>6</sup>](#footnotes)|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A 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=Kia&model=Sorento Hybrid 2023">Buy Here</a></sub></details>|| |Kia|Sorento Hybrid 2023[<sup>6</sup>](#footnotes)|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A 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=Kia&model=Sorento Hybrid 2023">Buy Here</a></sub></details>||
@ -168,7 +168,7 @@ A supported vehicle is one that just works when you install a comma device. All
|Lincoln|Aviator 2020-21|Co-Pilot360 Plus|openpilot available[<sup>1</sup>](#footnotes)|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 2020-21">Buy Here</a></sub></details>|| |Lincoln|Aviator 2020-21|Co-Pilot360 Plus|openpilot available[<sup>1</sup>](#footnotes)|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 2020-21">Buy Here</a></sub></details>||
|MAN|eTGE 2020-23|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 J533 connector<br>- 1 USB-C coupler<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-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>| |MAN|eTGE 2020-23|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 J533 connector<br>- 1 USB-C coupler<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-23">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-23|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 J533 connector<br>- 1 USB-C coupler<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-23">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-23|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 J533 connector<br>- 1 USB-C coupler<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-23">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-23|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-23">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>| |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|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>| |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>|
@ -210,7 +210,7 @@ A supported vehicle is one that just works when you install a comma device. All
|Toyota|Camry 2018-20|All|Stock|0 mph[<sup>8</sup>](#footnotes)|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=Toyota&model=Camry 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=fkcjviZY9CM" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>| |Toyota|Camry 2018-20|All|Stock|0 mph[<sup>8</sup>](#footnotes)|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=Toyota&model=Camry 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=fkcjviZY9CM" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Toyota|Camry 2021-23|All|openpilot|0 mph[<sup>8</sup>](#footnotes)|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=Toyota&model=Camry 2021-23">Buy Here</a></sub></details>|| |Toyota|Camry 2021-23|All|openpilot|0 mph[<sup>8</sup>](#footnotes)|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=Toyota&model=Camry 2021-23">Buy Here</a></sub></details>||
|Toyota|Camry Hybrid 2018-20|All|Stock|0 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=Toyota&model=Camry Hybrid 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Q2DYY0AWKgk" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>| |Toyota|Camry Hybrid 2018-20|All|Stock|0 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=Toyota&model=Camry Hybrid 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Q2DYY0AWKgk" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Toyota|Camry Hybrid 2021-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=Toyota&model=Camry Hybrid 2021-23">Buy Here</a></sub></details>|| |Toyota|Camry Hybrid 2021-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=Toyota&model=Camry Hybrid 2021-24">Buy Here</a></sub></details>||
|Toyota|Corolla 2017-19|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=Toyota&model=Corolla 2017-19">Buy Here</a></sub></details>|| |Toyota|Corolla 2017-19|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=Toyota&model=Corolla 2017-19">Buy Here</a></sub></details>||
|Toyota|Corolla 2020-22|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=Toyota&model=Corolla 2020-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=_66pXk0CBYA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>| |Toyota|Corolla 2020-22|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=Toyota&model=Corolla 2020-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=_66pXk0CBYA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Toyota|Corolla Cross (Non-US only) 2020-23|All|openpilot|17 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=Toyota&model=Corolla Cross (Non-US only) 2020-23">Buy Here</a></sub></details>|| |Toyota|Corolla Cross (Non-US only) 2020-23|All|openpilot|17 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=Toyota&model=Corolla Cross (Non-US only) 2020-23">Buy Here</a></sub></details>||

@ -1 +1 @@
Subproject commit 62db60595bb5129cc2f295fdc42f2cda473777fd Subproject commit 6bf6ba773ea4174c702ac9c4af4e8a6fd3cef655

747
poetry.lock generated

@ -370,15 +370,18 @@ aio = ["azure-core[aio] (>=1.28.0,<2.0.0)"]
[[package]] [[package]]
name = "babel" name = "babel"
version = "2.12.1" version = "2.13.0"
description = "Internationalization utilities" description = "Internationalization utilities"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"}, {file = "Babel-2.13.0-py3-none-any.whl", hash = "sha256:fbfcae1575ff78e26c7449136f1abbefc3c13ce542eeb13d43d50d8b047216ec"},
{file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"}, {file = "Babel-2.13.0.tar.gz", hash = "sha256:04c3e2d28d2b7681644508f836be388ae49e0cfe91465095340395b60d00f210"},
] ]
[package.extras]
dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
[[package]] [[package]]
name = "breathe" name = "breathe"
version = "4.35.0" version = "4.35.0"
@ -476,75 +479,63 @@ files = [
[[package]] [[package]]
name = "cffi" name = "cffi"
version = "1.15.1" version = "1.16.0"
description = "Foreign Function Interface for Python calling C code." description = "Foreign Function Interface for Python calling C code."
optional = false optional = false
python-versions = "*" python-versions = ">=3.8"
files = [ files = [
{file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"},
{file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"},
{file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"},
{file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"},
{file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"},
{file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"},
{file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"},
{file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"},
{file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"},
{file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"},
{file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"},
{file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"},
{file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"},
{file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"},
{file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"},
{file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"},
{file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"},
{file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"},
{file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"},
{file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"},
{file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"},
{file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"},
{file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"},
{file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"},
{file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"},
{file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"},
{file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"},
{file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"},
{file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"},
{file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"},
{file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"},
{file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"},
{file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"},
{file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"},
{file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"},
{file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"},
{file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"},
{file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"},
{file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"},
{file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"},
] ]
[package.dependencies] [package.dependencies]
@ -563,86 +554,101 @@ files = [
[[package]] [[package]]
name = "charset-normalizer" name = "charset-normalizer"
version = "3.2.0" version = "3.3.0"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
optional = false optional = false
python-versions = ">=3.7.0" python-versions = ">=3.7.0"
files = [ files = [
{file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, {file = "charset-normalizer-3.3.0.tar.gz", hash = "sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6"},
{file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe"},
{file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4162918ef3098851fcd8a628bf9b6a98d10c380725df9e04caf5ca6dd48c847a"},
{file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0570d21da019941634a531444364f2482e8db0b3425fcd5ac0c36565a64142c8"},
{file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5707a746c6083a3a74b46b3a631d78d129edab06195a92a8ece755aac25a3f3d"},
{file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:278c296c6f96fa686d74eb449ea1697f3c03dc28b75f873b65b5201806346a69"},
{file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a4b71f4d1765639372a3b32d2638197f5cd5221b19531f9245fcc9ee62d38f56"},
{file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5969baeaea61c97efa706b9b107dcba02784b1601c74ac84f2a532ea079403e"},
{file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3f93dab657839dfa61025056606600a11d0b696d79386f974e459a3fbc568ec"},
{file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:db756e48f9c5c607b5e33dd36b1d5872d0422e960145b08ab0ec7fd420e9d649"},
{file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:232ac332403e37e4a03d209a3f92ed9071f7d3dbda70e2a5e9cff1c4ba9f0678"},
{file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e5c1502d4ace69a179305abb3f0bb6141cbe4714bc9b31d427329a95acfc8bdd"},
{file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:2502dd2a736c879c0f0d3e2161e74d9907231e25d35794584b1ca5284e43f596"},
{file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23e8565ab7ff33218530bc817922fae827420f143479b753104ab801145b1d5b"},
{file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, {file = "charset_normalizer-3.3.0-cp310-cp310-win32.whl", hash = "sha256:1872d01ac8c618a8da634e232f24793883d6e456a66593135aeafe3784b0848d"},
{file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, {file = "charset_normalizer-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:557b21a44ceac6c6b9773bc65aa1b4cc3e248a5ad2f5b914b91579a32e22204d"},
{file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d7eff0f27edc5afa9e405f7165f85a6d782d308f3b6b9d96016c010597958e63"},
{file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a685067d05e46641d5d1623d7c7fdf15a357546cbb2f71b0ebde91b175ffc3e"},
{file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3d5b7db9ed8a2b11a774db2bbea7ba1884430a205dbd54a32d61d7c2a190fa"},
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2935ffc78db9645cb2086c2f8f4cfd23d9b73cc0dc80334bc30aac6f03f68f8c"},
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fe359b2e3a7729010060fbca442ca225280c16e923b37db0e955ac2a2b72a05"},
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:380c4bde80bce25c6e4f77b19386f5ec9db230df9f2f2ac1e5ad7af2caa70459"},
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0d1e3732768fecb052d90d62b220af62ead5748ac51ef61e7b32c266cac9293"},
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b2919306936ac6efb3aed1fbf81039f7087ddadb3160882a57ee2ff74fd2382"},
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f8888e31e3a85943743f8fc15e71536bda1c81d5aa36d014a3c0c44481d7db6e"},
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:82eb849f085624f6a607538ee7b83a6d8126df6d2f7d3b319cb837b289123078"},
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7b8b8bf1189b3ba9b8de5c8db4d541b406611a71a955bbbd7385bbc45fcb786c"},
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5adf257bd58c1b8632046bbe43ee38c04e1038e9d37de9c57a94d6bd6ce5da34"},
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c350354efb159b8767a6244c166f66e67506e06c8924ed74669b2c70bc8735b1"},
{file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, {file = "charset_normalizer-3.3.0-cp311-cp311-win32.whl", hash = "sha256:02af06682e3590ab952599fbadac535ede5d60d78848e555aa58d0c0abbde786"},
{file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, {file = "charset_normalizer-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:86d1f65ac145e2c9ed71d8ffb1905e9bba3a91ae29ba55b4c46ae6fc31d7c0d4"},
{file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3b447982ad46348c02cb90d230b75ac34e9886273df3a93eec0539308a6296d7"},
{file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:abf0d9f45ea5fb95051c8bfe43cb40cda383772f7e5023a83cc481ca2604d74e"},
{file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b09719a17a2301178fac4470d54b1680b18a5048b481cb8890e1ef820cb80455"},
{file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3d9b48ee6e3967b7901c052b670c7dda6deb812c309439adaffdec55c6d7b78"},
{file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:edfe077ab09442d4ef3c52cb1f9dab89bff02f4524afc0acf2d46be17dc479f5"},
{file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3debd1150027933210c2fc321527c2299118aa929c2f5a0a80ab6953e3bd1908"},
{file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86f63face3a527284f7bb8a9d4f78988e3c06823f7bea2bd6f0e0e9298ca0403"},
{file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24817cb02cbef7cd499f7c9a2735286b4782bd47a5b3516a0e84c50eab44b98e"},
{file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c71f16da1ed8949774ef79f4a0260d28b83b3a50c6576f8f4f0288d109777989"},
{file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9cf3126b85822c4e53aa28c7ec9869b924d6fcfb76e77a45c44b83d91afd74f9"},
{file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:b3b2316b25644b23b54a6f6401074cebcecd1244c0b8e80111c9a3f1c8e83d65"},
{file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:03680bb39035fbcffe828eae9c3f8afc0428c91d38e7d61aa992ef7a59fb120e"},
{file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cc152c5dd831641e995764f9f0b6589519f6f5123258ccaca8c6d34572fefa8"},
{file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, {file = "charset_normalizer-3.3.0-cp312-cp312-win32.whl", hash = "sha256:b8f3307af845803fb0b060ab76cf6dd3a13adc15b6b451f54281d25911eb92df"},
{file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, {file = "charset_normalizer-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:8eaf82f0eccd1505cf39a45a6bd0a8cf1c70dcfc30dba338207a969d91b965c0"},
{file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, {file = "charset_normalizer-3.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dc45229747b67ffc441b3de2f3ae5e62877a282ea828a5bdb67883c4ee4a8810"},
{file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4a0033ce9a76e391542c182f0d48d084855b5fcba5010f707c8e8c34663d77"},
{file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ada214c6fa40f8d800e575de6b91a40d0548139e5dc457d2ebb61470abf50186"},
{file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1121de0e9d6e6ca08289583d7491e7fcb18a439305b34a30b20d8215922d43c"},
{file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1063da2c85b95f2d1a430f1c33b55c9c17ffaf5e612e10aeaad641c55a9e2b9d"},
{file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70f1d09c0d7748b73290b29219e854b3207aea922f839437870d8cc2168e31cc"},
{file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:250c9eb0f4600361dd80d46112213dff2286231d92d3e52af1e5a6083d10cad9"},
{file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:750b446b2ffce1739e8578576092179160f6d26bd5e23eb1789c4d64d5af7dc7"},
{file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:fc52b79d83a3fe3a360902d3f5d79073a993597d48114c29485e9431092905d8"},
{file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:588245972aca710b5b68802c8cad9edaa98589b1b42ad2b53accd6910dad3545"},
{file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e39c7eb31e3f5b1f88caff88bcff1b7f8334975b46f6ac6e9fc725d829bc35d4"},
{file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, {file = "charset_normalizer-3.3.0-cp37-cp37m-win32.whl", hash = "sha256:abecce40dfebbfa6abf8e324e1860092eeca6f7375c8c4e655a8afb61af58f2c"},
{file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, {file = "charset_normalizer-3.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a91a981f185721542a0b7c92e9054b7ab4fea0508a795846bc5b0abf8118d4"},
{file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:67b8cc9574bb518ec76dc8e705d4c39ae78bb96237cb533edac149352c1f39fe"},
{file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac71b2977fb90c35d41c9453116e283fac47bb9096ad917b8819ca8b943abecd"},
{file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3ae38d325b512f63f8da31f826e6cb6c367336f95e418137286ba362925c877e"},
{file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:542da1178c1c6af8873e143910e2269add130a299c9106eef2594e15dae5e482"},
{file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30a85aed0b864ac88309b7d94be09f6046c834ef60762a8833b660139cfbad13"},
{file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aae32c93e0f64469f74ccc730a7cb21c7610af3a775157e50bbd38f816536b38"},
{file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b26ddf78d57f1d143bdf32e820fd8935d36abe8a25eb9ec0b5a71c82eb3895"},
{file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f5d10bae5d78e4551b7be7a9b29643a95aded9d0f602aa2ba584f0388e7a557"},
{file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:249c6470a2b60935bafd1d1d13cd613f8cd8388d53461c67397ee6a0f5dce741"},
{file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c5a74c359b2d47d26cdbbc7845e9662d6b08a1e915eb015d044729e92e7050b7"},
{file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b5bcf60a228acae568e9911f410f9d9e0d43197d030ae5799e20dca8df588287"},
{file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:187d18082694a29005ba2944c882344b6748d5be69e3a89bf3cc9d878e548d5a"},
{file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81bf654678e575403736b85ba3a7867e31c2c30a69bc57fe88e3ace52fb17b89"},
{file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, {file = "charset_normalizer-3.3.0-cp38-cp38-win32.whl", hash = "sha256:85a32721ddde63c9df9ebb0d2045b9691d9750cb139c161c80e500d210f5e26e"},
{file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, {file = "charset_normalizer-3.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:468d2a840567b13a590e67dd276c570f8de00ed767ecc611994c301d0f8c014f"},
{file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e0fc42822278451bc13a2e8626cf2218ba570f27856b536e00cfa53099724828"},
{file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:09c77f964f351a7369cc343911e0df63e762e42bac24cd7d18525961c81754f4"},
{file = "charset_normalizer-3.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:12ebea541c44fdc88ccb794a13fe861cc5e35d64ed689513a5c03d05b53b7c82"},
{file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:805dfea4ca10411a5296bcc75638017215a93ffb584c9e344731eef0dcfb026a"},
{file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96c2b49eb6a72c0e4991d62406e365d87067ca14c1a729a870d22354e6f68115"},
{file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaf7b34c5bc56b38c931a54f7952f1ff0ae77a2e82496583b247f7c969eb1479"},
{file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:619d1c96099be5823db34fe89e2582b336b5b074a7f47f819d6b3a57ff7bdb86"},
{file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0ac5e7015a5920cfce654c06618ec40c33e12801711da6b4258af59a8eff00a"},
{file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93aa7eef6ee71c629b51ef873991d6911b906d7312c6e8e99790c0f33c576f89"},
{file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7966951325782121e67c81299a031f4c115615e68046f79b85856b86ebffc4cd"},
{file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:02673e456dc5ab13659f85196c534dc596d4ef260e4d86e856c3b2773ce09843"},
{file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:c2af80fb58f0f24b3f3adcb9148e6203fa67dd3f61c4af146ecad033024dde43"},
{file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:153e7b6e724761741e0974fc4dcd406d35ba70b92bfe3fedcb497226c93b9da7"},
{file = "charset_normalizer-3.3.0-cp39-cp39-win32.whl", hash = "sha256:d47ecf253780c90ee181d4d871cd655a789da937454045b17b5798da9393901a"},
{file = "charset_normalizer-3.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d97d85fa63f315a8bdaba2af9a6a686e0eceab77b3089af45133252618e70884"},
{file = "charset_normalizer-3.3.0-py3-none-any.whl", hash = "sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2"},
] ]
[[package]] [[package]]
@ -826,63 +832,63 @@ test = ["pytest", "pytest-timeout"]
[[package]] [[package]]
name = "coverage" name = "coverage"
version = "7.3.1" version = "7.3.2"
description = "Code coverage measurement for Python" description = "Code coverage measurement for Python"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "coverage-7.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cd0f7429ecfd1ff597389907045ff209c8fdb5b013d38cfa7c60728cb484b6e3"}, {file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"},
{file = "coverage-7.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:966f10df9b2b2115da87f50f6a248e313c72a668248be1b9060ce935c871f276"}, {file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"},
{file = "coverage-7.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0575c37e207bb9b98b6cf72fdaaa18ac909fb3d153083400c2d48e2e6d28bd8e"}, {file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"},
{file = "coverage-7.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:245c5a99254e83875c7fed8b8b2536f040997a9b76ac4c1da5bff398c06e860f"}, {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"},
{file = "coverage-7.3.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c96dd7798d83b960afc6c1feb9e5af537fc4908852ef025600374ff1a017392"}, {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"},
{file = "coverage-7.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:de30c1aa80f30af0f6b2058a91505ea6e36d6535d437520067f525f7df123887"}, {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"},
{file = "coverage-7.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:50dd1e2dd13dbbd856ffef69196781edff26c800a74f070d3b3e3389cab2600d"}, {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"},
{file = "coverage-7.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9c0c19f70d30219113b18fe07e372b244fb2a773d4afde29d5a2f7930765136"}, {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"},
{file = "coverage-7.3.1-cp310-cp310-win32.whl", hash = "sha256:770f143980cc16eb601ccfd571846e89a5fe4c03b4193f2e485268f224ab602f"}, {file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"},
{file = "coverage-7.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:cdd088c00c39a27cfa5329349cc763a48761fdc785879220d54eb785c8a38520"}, {file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"},
{file = "coverage-7.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:74bb470399dc1989b535cb41f5ca7ab2af561e40def22d7e188e0a445e7639e3"}, {file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"},
{file = "coverage-7.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:025ded371f1ca280c035d91b43252adbb04d2aea4c7105252d3cbc227f03b375"}, {file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"},
{file = "coverage-7.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6191b3a6ad3e09b6cfd75b45c6aeeffe7e3b0ad46b268345d159b8df8d835f9"}, {file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"},
{file = "coverage-7.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7eb0b188f30e41ddd659a529e385470aa6782f3b412f860ce22b2491c89b8593"}, {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"},
{file = "coverage-7.3.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c8f0df9dfd8ff745bccff75867d63ef336e57cc22b2908ee725cc552689ec8"}, {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"},
{file = "coverage-7.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7eb3cd48d54b9bd0e73026dedce44773214064be93611deab0b6a43158c3d5a0"}, {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"},
{file = "coverage-7.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ac3c5b7e75acac31e490b7851595212ed951889918d398b7afa12736c85e13ce"}, {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"},
{file = "coverage-7.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5b4ee7080878077af0afa7238df1b967f00dc10763f6e1b66f5cced4abebb0a3"}, {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"},
{file = "coverage-7.3.1-cp311-cp311-win32.whl", hash = "sha256:229c0dd2ccf956bf5aeede7e3131ca48b65beacde2029f0361b54bf93d36f45a"}, {file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"},
{file = "coverage-7.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:c6f55d38818ca9596dc9019eae19a47410d5322408140d9a0076001a3dcb938c"}, {file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"},
{file = "coverage-7.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5289490dd1c3bb86de4730a92261ae66ea8d44b79ed3cc26464f4c2cde581fbc"}, {file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"},
{file = "coverage-7.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ca833941ec701fda15414be400c3259479bfde7ae6d806b69e63b3dc423b1832"}, {file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"},
{file = "coverage-7.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd694e19c031733e446c8024dedd12a00cda87e1c10bd7b8539a87963685e969"}, {file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"},
{file = "coverage-7.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aab8e9464c00da5cb9c536150b7fbcd8850d376d1151741dd0d16dfe1ba4fd26"}, {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"},
{file = "coverage-7.3.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87d38444efffd5b056fcc026c1e8d862191881143c3aa80bb11fcf9dca9ae204"}, {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"},
{file = "coverage-7.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8a07b692129b8a14ad7a37941a3029c291254feb7a4237f245cfae2de78de037"}, {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"},
{file = "coverage-7.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2829c65c8faaf55b868ed7af3c7477b76b1c6ebeee99a28f59a2cb5907a45760"}, {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"},
{file = "coverage-7.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1f111a7d85658ea52ffad7084088277135ec5f368457275fc57f11cebb15607f"}, {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"},
{file = "coverage-7.3.1-cp312-cp312-win32.whl", hash = "sha256:c397c70cd20f6df7d2a52283857af622d5f23300c4ca8e5bd8c7a543825baa5a"}, {file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"},
{file = "coverage-7.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:5ae4c6da8b3d123500f9525b50bf0168023313963e0e2e814badf9000dd6ef92"}, {file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"},
{file = "coverage-7.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca70466ca3a17460e8fc9cea7123c8cbef5ada4be3140a1ef8f7b63f2f37108f"}, {file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"},
{file = "coverage-7.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f2781fd3cabc28278dc982a352f50c81c09a1a500cc2086dc4249853ea96b981"}, {file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"},
{file = "coverage-7.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6407424621f40205bbe6325686417e5e552f6b2dba3535dd1f90afc88a61d465"}, {file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"},
{file = "coverage-7.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:04312b036580ec505f2b77cbbdfb15137d5efdfade09156961f5277149f5e344"}, {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"},
{file = "coverage-7.3.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac9ad38204887349853d7c313f53a7b1c210ce138c73859e925bc4e5d8fc18e7"}, {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"},
{file = "coverage-7.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:53669b79f3d599da95a0afbef039ac0fadbb236532feb042c534fbb81b1a4e40"}, {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"},
{file = "coverage-7.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:614f1f98b84eb256e4f35e726bfe5ca82349f8dfa576faabf8a49ca09e630086"}, {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"},
{file = "coverage-7.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f1a317fdf5c122ad642db8a97964733ab7c3cf6009e1a8ae8821089993f175ff"}, {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"},
{file = "coverage-7.3.1-cp38-cp38-win32.whl", hash = "sha256:defbbb51121189722420a208957e26e49809feafca6afeef325df66c39c4fdb3"}, {file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"},
{file = "coverage-7.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:f4f456590eefb6e1b3c9ea6328c1e9fa0f1006e7481179d749b3376fc793478e"}, {file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"},
{file = "coverage-7.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f12d8b11a54f32688b165fd1a788c408f927b0960984b899be7e4c190ae758f1"}, {file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"},
{file = "coverage-7.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f09195dda68d94a53123883de75bb97b0e35f5f6f9f3aa5bf6e496da718f0cb6"}, {file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"},
{file = "coverage-7.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6601a60318f9c3945be6ea0f2a80571f4299b6801716f8a6e4846892737ebe4"}, {file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"},
{file = "coverage-7.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07d156269718670d00a3b06db2288b48527fc5f36859425ff7cec07c6b367745"}, {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"},
{file = "coverage-7.3.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:636a8ac0b044cfeccae76a36f3b18264edcc810a76a49884b96dd744613ec0b7"}, {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"},
{file = "coverage-7.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5d991e13ad2ed3aced177f524e4d670f304c8233edad3210e02c465351f785a0"}, {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"},
{file = "coverage-7.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:586649ada7cf139445da386ab6f8ef00e6172f11a939fc3b2b7e7c9082052fa0"}, {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"},
{file = "coverage-7.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4aba512a15a3e1e4fdbfed2f5392ec221434a614cc68100ca99dcad7af29f3f8"}, {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"},
{file = "coverage-7.3.1-cp39-cp39-win32.whl", hash = "sha256:6bc6f3f4692d806831c136c5acad5ccedd0262aa44c087c46b7101c77e139140"}, {file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"},
{file = "coverage-7.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:553d7094cb27db58ea91332e8b5681bac107e7242c23f7629ab1316ee73c4981"}, {file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"},
{file = "coverage-7.3.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:220eb51f5fb38dfdb7e5d54284ca4d0cd70ddac047d750111a68ab1798945194"}, {file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"},
{file = "coverage-7.3.1.tar.gz", hash = "sha256:6cb7fe1581deb67b782c153136541e20901aa312ceedaf1467dcb35255787952"}, {file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"},
] ]
[package.extras] [package.extras]
@ -945,15 +951,19 @@ test-randomorder = ["pytest-randomly"]
[[package]] [[package]]
name = "cycler" name = "cycler"
version = "0.11.0" version = "0.12.0"
description = "Composable style cycles" description = "Composable style cycles"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.8"
files = [ files = [
{file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"}, {file = "cycler-0.12.0-py3-none-any.whl", hash = "sha256:7896994252d006771357777d0251f3e34d266f4fa5f2c572247a80ab01440947"},
{file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"}, {file = "cycler-0.12.0.tar.gz", hash = "sha256:8cc3a7b4861f91b1095157f9916f748549a617046e67eb7619abed9b34d2c94a"},
] ]
[package.extras]
docs = ["ipython", "matplotlib", "numpydoc", "sphinx"]
tests = ["pytest", "pytest-cov", "pytest-xdist"]
[[package]] [[package]]
name = "cython" name = "cython"
version = "3.0.2" version = "3.0.2"
@ -1176,45 +1186,53 @@ files = [
[[package]] [[package]]
name = "fonttools" name = "fonttools"
version = "4.42.1" version = "4.43.0"
description = "Tools to manipulate font files" description = "Tools to manipulate font files"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "fonttools-4.42.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ed1a13a27f59d1fc1920394a7f596792e9d546c9ca5a044419dca70c37815d7c"}, {file = "fonttools-4.43.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ab80e7d6bb01316d5fc8161a2660ca2e9e597d0880db4927bc866c76474472ef"},
{file = "fonttools-4.42.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c9b1ce7a45978b821a06d375b83763b27a3a5e8a2e4570b3065abad240a18760"}, {file = "fonttools-4.43.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82d8e687a42799df5325e7ee12977b74738f34bf7fde1c296f8140efd699a213"},
{file = "fonttools-4.42.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f720fa82a11c0f9042376fd509b5ed88dab7e3cd602eee63a1af08883b37342b"}, {file = "fonttools-4.43.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d08a694b280d615460563a6b4e2afb0b1b9df708c799ec212bf966652b94fc84"},
{file = "fonttools-4.42.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db55cbaea02a20b49fefbd8e9d62bd481aaabe1f2301dabc575acc6b358874fa"}, {file = "fonttools-4.43.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d654d3e780e0ceabb1f4eff5a3c042c67d4428d0fe1ea3afd238a721cf171b3"},
{file = "fonttools-4.42.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a35981d90feebeaef05e46e33e6b9e5b5e618504672ca9cd0ff96b171e4bfff"}, {file = "fonttools-4.43.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:20fc43783c432862071fa76da6fa714902ae587bc68441e12ff4099b94b1fcef"},
{file = "fonttools-4.42.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:68a02bbe020dc22ee0540e040117535f06df9358106d3775e8817d826047f3fd"}, {file = "fonttools-4.43.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:33c40a657fb87ff83185828c0323032d63a4df1279d5c1c38e21f3ec56327803"},
{file = "fonttools-4.42.1-cp310-cp310-win32.whl", hash = "sha256:12a7c247d1b946829bfa2f331107a629ea77dc5391dfd34fdcd78efa61f354ca"}, {file = "fonttools-4.43.0-cp310-cp310-win32.whl", hash = "sha256:b3813f57f85bbc0e4011a0e1e9211f9ee52f87f402e41dc05bc5135f03fa51c1"},
{file = "fonttools-4.42.1-cp310-cp310-win_amd64.whl", hash = "sha256:a398bdadb055f8de69f62b0fc70625f7cbdab436bbb31eef5816e28cab083ee8"}, {file = "fonttools-4.43.0-cp310-cp310-win_amd64.whl", hash = "sha256:05056a8c9af048381fdb17e89b17d45f6c8394176d01e8c6fef5ac96ea950d38"},
{file = "fonttools-4.42.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:689508b918332fb40ce117131633647731d098b1b10d092234aa959b4251add5"}, {file = "fonttools-4.43.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:da78f39b601ed0b4262929403186d65cf7a016f91ff349ab18fdc5a7080af465"},
{file = "fonttools-4.42.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e36344e48af3e3bde867a1ca54f97c308735dd8697005c2d24a86054a114a71"}, {file = "fonttools-4.43.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5056f69a18f3f28ab5283202d1efcfe011585d31de09d8560f91c6c88f041e92"},
{file = "fonttools-4.42.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19b7db825c8adee96fac0692e6e1ecd858cae9affb3b4812cdb9d934a898b29e"}, {file = "fonttools-4.43.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcc01cea0a121fb0c009993497bad93cae25e77db7dee5345fec9cce1aaa09cd"},
{file = "fonttools-4.42.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:113337c2d29665839b7d90b39f99b3cac731f72a0eda9306165a305c7c31d341"}, {file = "fonttools-4.43.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee728d5af70f117581712966a21e2e07031e92c687ef1fdc457ac8d281016f64"},
{file = "fonttools-4.42.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:37983b6bdab42c501202500a2be3a572f50d4efe3237e0686ee9d5f794d76b35"}, {file = "fonttools-4.43.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b5e760198f0b87e42478bb35a6eae385c636208f6f0d413e100b9c9c5efafb6a"},
{file = "fonttools-4.42.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6ed2662a3d9c832afa36405f8748c250be94ae5dfc5283d668308391f2102861"}, {file = "fonttools-4.43.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:af38f5145258e9866da5881580507e6d17ff7756beef175d13213a43a84244e9"},
{file = "fonttools-4.42.1-cp311-cp311-win32.whl", hash = "sha256:179737095eb98332a2744e8f12037b2977f22948cf23ff96656928923ddf560a"}, {file = "fonttools-4.43.0-cp311-cp311-win32.whl", hash = "sha256:25620b738d4533cfc21fd2a4f4b667e481f7cb60e86b609799f7d98af657854e"},
{file = "fonttools-4.42.1-cp311-cp311-win_amd64.whl", hash = "sha256:f2b82f46917d8722e6b5eafeefb4fb585d23babd15d8246c664cd88a5bddd19c"}, {file = "fonttools-4.43.0-cp311-cp311-win_amd64.whl", hash = "sha256:635658464dccff6fa5c3b43fe8f818ae2c386ee6a9e1abc27359d1e255528186"},
{file = "fonttools-4.42.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:62f481ac772fd68901573956231aea3e4b1ad87b9b1089a61613a91e2b50bb9b"}, {file = "fonttools-4.43.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a682fb5cbf8837d1822b80acc0be5ff2ea0c49ca836e468a21ffd388ef280fd3"},
{file = "fonttools-4.42.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f2f806990160d1ce42d287aa419df3ffc42dfefe60d473695fb048355fe0c6a0"}, {file = "fonttools-4.43.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3d7adfa342e6b3a2b36960981f23f480969f833d565a4eba259c2e6f59d2674f"},
{file = "fonttools-4.42.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db372213d39fa33af667c2aa586a0c1235e88e9c850f5dd5c8e1f17515861868"}, {file = "fonttools-4.43.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5aa67d1e720fdd902fde4a59d0880854ae9f19fc958f3e1538bceb36f7f4dc92"},
{file = "fonttools-4.42.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d18fc642fd0ac29236ff88ecfccff229ec0386090a839dd3f1162e9a7944a40"}, {file = "fonttools-4.43.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77e5113233a2df07af9dbf493468ce526784c3b179c0e8b9c7838ced37c98b69"},
{file = "fonttools-4.42.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8708b98c278012ad267ee8a7433baeb809948855e81922878118464b274c909d"}, {file = "fonttools-4.43.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:57c22e5f9f53630d458830f710424dce4f43c5f0d95cb3368c0f5178541e4db7"},
{file = "fonttools-4.42.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c95b0724a6deea2c8c5d3222191783ced0a2f09bd6d33f93e563f6f1a4b3b3a4"}, {file = "fonttools-4.43.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:206808f9717c9b19117f461246372a2c160fa12b9b8dbdfb904ab50ca235ba0a"},
{file = "fonttools-4.42.1-cp38-cp38-win32.whl", hash = "sha256:4aa79366e442dbca6e2c8595645a3a605d9eeabdb7a094d745ed6106816bef5d"}, {file = "fonttools-4.43.0-cp312-cp312-win32.whl", hash = "sha256:f19c2b1c65d57cbea25cabb80941fea3fbf2625ff0cdcae8900b5fb1c145704f"},
{file = "fonttools-4.42.1-cp38-cp38-win_amd64.whl", hash = "sha256:acb47f6f8680de24c1ab65ebde39dd035768e2a9b571a07c7b8da95f6c8815fd"}, {file = "fonttools-4.43.0-cp312-cp312-win_amd64.whl", hash = "sha256:7c76f32051159f8284f1a5f5b605152b5a530736fb8b55b09957db38dcae5348"},
{file = "fonttools-4.42.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5fb289b7a815638a7613d46bcf324c9106804725b2bb8ad913c12b6958ffc4ec"}, {file = "fonttools-4.43.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e3f8acc6ef4a627394021246e099faee4b343afd3ffe2e517d8195b4ebf20289"},
{file = "fonttools-4.42.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:53eb5091ddc8b1199330bb7b4a8a2e7995ad5d43376cadce84523d8223ef3136"}, {file = "fonttools-4.43.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a68b71adc3b3a90346e4ac92f0a69ab9caeba391f3b04ab6f1e98f2c8ebe88e3"},
{file = "fonttools-4.42.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46a0ec8adbc6ff13494eb0c9c2e643b6f009ce7320cf640de106fb614e4d4360"}, {file = "fonttools-4.43.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ace0fd5afb79849f599f76af5c6aa5e865bd042c811e4e047bbaa7752cc26126"},
{file = "fonttools-4.42.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cc7d685b8eeca7ae69dc6416833fbfea61660684b7089bca666067cb2937dcf"}, {file = "fonttools-4.43.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f9660e70a2430780e23830476332bc3391c3c8694769e2c0032a5038702a662"},
{file = "fonttools-4.42.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:be24fcb80493b2c94eae21df70017351851652a37de514de553435b256b2f249"}, {file = "fonttools-4.43.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:48078357984214ccd22d7fe0340cd6ff7286b2f74f173603a1a9a40b5dc25afe"},
{file = "fonttools-4.42.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:515607ec756d7865f23070682622c49d922901943697871fc292277cf1e71967"}, {file = "fonttools-4.43.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d27d960e10cf7617d70cf3104c32a69b008dde56f2d55a9bed4ba6e3df611544"},
{file = "fonttools-4.42.1-cp39-cp39-win32.whl", hash = "sha256:0eb79a2da5eb6457a6f8ab904838454accc7d4cccdaff1fd2bd3a0679ea33d64"}, {file = "fonttools-4.43.0-cp38-cp38-win32.whl", hash = "sha256:a6a2e99bb9ea51e0974bbe71768df42c6dd189308c22f3f00560c3341b345646"},
{file = "fonttools-4.42.1-cp39-cp39-win_amd64.whl", hash = "sha256:7286aed4ea271df9eab8d7a9b29e507094b51397812f7ce051ecd77915a6e26b"}, {file = "fonttools-4.43.0-cp38-cp38-win_amd64.whl", hash = "sha256:030355fbb0cea59cf75d076d04d3852900583d1258574ff2d7d719abf4513836"},
{file = "fonttools-4.42.1-py3-none-any.whl", hash = "sha256:9398f244e28e0596e2ee6024f808b06060109e33ed38dcc9bded452fd9bbb853"}, {file = "fonttools-4.43.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:52e77f23a9c059f8be01a07300ba4c4d23dc271d33eed502aea5a01ab5d2f4c1"},
{file = "fonttools-4.42.1.tar.gz", hash = "sha256:c391cd5af88aacaf41dd7cfb96eeedfad297b5899a39e12f4c2c3706d0a3329d"}, {file = "fonttools-4.43.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6a530fa28c155538d32214eafa0964989098a662bd63e91e790e6a7a4e9c02da"},
{file = "fonttools-4.43.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70f021a6b9eb10dfe7a411b78e63a503a06955dd6d2a4e130906d8760474f77c"},
{file = "fonttools-4.43.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:812142a0e53cc853964d487e6b40963df62f522b1b571e19d1ff8467d7880ceb"},
{file = "fonttools-4.43.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ace51902ab67ef5fe225e8b361039e996db153e467e24a28d35f74849b37b7ce"},
{file = "fonttools-4.43.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8dfd8edfce34ad135bd69de20c77449c06e2c92b38f2a8358d0987737f82b49e"},
{file = "fonttools-4.43.0-cp39-cp39-win32.whl", hash = "sha256:e5d53eddaf436fa131042f44a76ea1ead0a17c354ab9de0d80e818f0cb1629f1"},
{file = "fonttools-4.43.0-cp39-cp39-win_amd64.whl", hash = "sha256:93c5b6d77baf28f306bc13fa987b0b13edca6a39dc2324eaca299a74ccc6316f"},
{file = "fonttools-4.43.0-py3-none-any.whl", hash = "sha256:e4bc589d8da09267c7c4ceaaaa4fc01a7908ac5b43b286ac9279afe76407c384"},
{file = "fonttools-4.43.0.tar.gz", hash = "sha256:b62a53a4ca83c32c6b78cac64464f88d02929779373c716f738af6968c8c821e"},
] ]
[package.extras] [package.extras]
@ -1303,40 +1321,40 @@ files = [
[[package]] [[package]]
name = "ft4222" name = "ft4222"
version = "1.8.1" version = "1.9.0"
description = "Python wrapper around libFT4222." description = "Python wrapper around libFT4222."
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
{file = "ft4222-1.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:32125b9462945db7b8881bba32e73d7202998572b2a8c27d738163ca4a1e5c2a"}, {file = "ft4222-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:f07513c6d0f1f55c198051c8a9f5a58585bfe57d5ea5f9470d9ac149d981e2b4"},
{file = "ft4222-1.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:791cfca70aaf2570892a637d0389fddd88f28d1474cdae810778be45024ea10a"}, {file = "ft4222-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:d019dd0c170de8772bf444a0a06468a5401411aac303400949612a6636cd9533"},
{file = "ft4222-1.8.1-cp310-cp310-win32.whl", hash = "sha256:386b2c98cc95a889809fb509cf0144fd67889ad61d668f55d240300a1e52a9d0"}, {file = "ft4222-1.9.0-cp310-cp310-win32.whl", hash = "sha256:ed7fcc12957bc6041e6064b3cf782181703a8ded5335f85f3392d2a9cd47abaa"},
{file = "ft4222-1.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:e88011aa19afefeb5136bdb5af745a74d2a85981b927ee07b7925187d90e9aa2"}, {file = "ft4222-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:b23c825b1ec494c79d5276c6a34dc978695dcdd0c198dfa6b763f40d9c87a00a"},
{file = "ft4222-1.8.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4cfe1c110e4546384dd9be635c010fa1c6a7f97d2f80b43c7cbda59fcad832cc"}, {file = "ft4222-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:385b39d7b1727800161e86340067d31b58fbe3252e68c0f2aa707d85d2da1d70"},
{file = "ft4222-1.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:99068ada9b2ed785abb15a50ccd78ecc947c0a2b4982e6356c6e910ee2ad9958"}, {file = "ft4222-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8e49945cde97ea5f0b4084c5a5564c5774c3c1ed3e6c31b5324740c21237494d"},
{file = "ft4222-1.8.1-cp311-cp311-win32.whl", hash = "sha256:387b0b7094094a52f069c00fadd58da2666570dc38c2e8b36cf2b4af56a6ab31"}, {file = "ft4222-1.9.0-cp311-cp311-win32.whl", hash = "sha256:7ff367ff0c769f05113a89c35df14461663f40ad6a58b5290a2fddac38d0b2af"},
{file = "ft4222-1.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:4d666d5b3435ece3db782970288fd7b52fb53964ad8cf07434d32c368103ae07"}, {file = "ft4222-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:dbed0608ae6a2cf0f9c9dafc05ca7b657bfdab991472c9b35707762058ad30db"},
{file = "ft4222-1.8.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8a21ef854ada66fbfba587f99c9db601f2643d5647bf7f4539928287cf2c566c"}, {file = "ft4222-1.9.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:06222c41efa7a3ebe615ee2fece4a8a8e363335ac1f0afa5d318084d223dda7c"},
{file = "ft4222-1.8.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e4faf61ef28d7dc48ada862da079ec15470366ece48a1b79b451bb34a4385da9"}, {file = "ft4222-1.9.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:5ec049a5ce706438edfadb03e21f4892464a9ec47269b62eabbfc782c0923884"},
{file = "ft4222-1.8.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:87c080dc966ad666b0eb03fb06f2e0efd7abd67b1be37ce5424cd34881905aee"}, {file = "ft4222-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:d47d1a06899cc5832e509246816c3b20eba549e3d02789e138dd51f7e1a28060"},
{file = "ft4222-1.8.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:488212b83f5eb067b93fa1cefea5d707631ed6d09396af0074e6564733972c7e"}, {file = "ft4222-1.9.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:34d9eca521648135c48058b0c6bfd3de34a0dd05783f387da79201117d8a26f8"},
{file = "ft4222-1.8.1-cp37-cp37m-win32.whl", hash = "sha256:4c3e3aeb02376dae37d22b5a8a2453b94ee656bca0667a62086de62395c2f1af"}, {file = "ft4222-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:0bfabe4e46aaa2e5aa88ef77bb75b755ca2f3633eb9cd34654a8a6b30a151559"},
{file = "ft4222-1.8.1-cp37-cp37m-win_amd64.whl", hash = "sha256:04e7c7d0dc0d555598cc1e608fe1cc60945406e511a7ffe4a8e7059b33a6a683"}, {file = "ft4222-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7da01c5e872fd8b82cbb159697b83f31ae5b2516f90615fc3a66026dd3aed5c0"},
{file = "ft4222-1.8.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:fe076965d9ac110ceccfb4bad4ec73187402f5131e3f8444684755503f90db08"}, {file = "ft4222-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7bb3be2ac0d21e7063aad1c10615bc29369132bb9d5f800fc385ea805ef16583"},
{file = "ft4222-1.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:574bce65a12dc562582c6bd221e4779f9f0ac438bc37e81201e1390022bc4435"}, {file = "ft4222-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:4c2b0c4ba7c621d7a65708fbfa981f7ed34c966e089e7965d6040f318a43221d"},
{file = "ft4222-1.8.1-cp38-cp38-win32.whl", hash = "sha256:d6b78f6e6a6d16769d080373f6ec22cdceb411f23bf4dec366cc809d813e1d8c"}, {file = "ft4222-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0858024c615c495a015fddb81df449f3f7763a6defb44e426afb23ae80faf4d1"},
{file = "ft4222-1.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:7049d5726b0ff02425d7e4e88ebe77ea143cb3d249bbb6c8ff5110f0abb4d533"}, {file = "ft4222-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5375836b967b905146238b2e067936a017a5ec51a8932d950476c1c06b9da87b"},
{file = "ft4222-1.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:2a604b1a79dc203f8d619153255d154da425f811f64a1c322a173f1d3fbde924"}, {file = "ft4222-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:2381aab272200046ee61ec97d2a657d3f03eed2e8270141d5c5617c9ad7cb659"},
{file = "ft4222-1.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:653f3adc6938f0bca26363c513a80c4188c1811cac8e85e94b4b7c87f3801cd6"}, {file = "ft4222-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:b25b30f6b81afab04b763a93b604593d6f1e97b7737c40d41949fa8e61ffda17"},
{file = "ft4222-1.8.1-cp39-cp39-win32.whl", hash = "sha256:7f3c9ea9cc6dded3e8d10de33170236fa32ccf826afc283116eff47565ffe86d"}, {file = "ft4222-1.9.0-cp39-cp39-win32.whl", hash = "sha256:77fe7d5eb9b53f1d05b9a0d6f6ea1b62a55b95330b48aa24c9f6c8157220fc2f"},
{file = "ft4222-1.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:db17d21d0d46e550bf65f50d952a20bf75e6d153de192d4027a70eb347f07026"}, {file = "ft4222-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:cd291d6542a2bcb29ab35eba67291680a666ee88ece66d38ab5922dea7f41259"},
{file = "ft4222-1.8.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:1d995115e8a94a092584ac9ec10d415eb6956fe275d1ef5e549e20dc578caf20"}, {file = "ft4222-1.9.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:80b7a7b2f7937e8442a6d73aa231676bd6b497cd82a1f02b8a5a29dd28deff8b"},
{file = "ft4222-1.8.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ef88304a306f42644a04ca6c1abe4d24b69141659bc59db9f8df6be4b347d149"}, {file = "ft4222-1.9.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:d06d3ca1f5208abafaa7106854c12d142bbde6f1ca5212590b8859bf9908301a"},
{file = "ft4222-1.8.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:549bbe3a18a21f7585877fd3cbb14c46b45eb61b29c0b5039f1fc8655e7fbeca"}, {file = "ft4222-1.9.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:ea756d097863a9afde576ba8a496f702abc1584743c56b17a002d13ac2f0fe99"},
{file = "ft4222-1.8.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:f4ceba4f7b778169c5b14028aeb1f4720295a9754f89222bd5b9a78e4c064b96"}, {file = "ft4222-1.9.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:2d795f77c2481a6565ca4726038db0abd6503f5db3ef2d0f52da74f7e1a12edd"},
{file = "ft4222-1.8.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:0c30500df95075877e8e29a58e0648ceb88571cfb33e244d7a51384e42caccac"}, {file = "ft4222-1.9.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:c41137e64fde5f43263d738c113238196ef16a42e2aa7960d1451e4bed3281f9"},
{file = "ft4222-1.8.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a2e9f22bea3683f171fc0da58ccbdd827a430349d8c26113077d4de79a454a87"}, {file = "ft4222-1.9.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a16ca00027dec92080994031d2a342966e618ea0f4d860c550d6b4b89d534aba"},
{file = "ft4222-1.8.1.tar.gz", hash = "sha256:6532ae1265e4b81416c51def060c2a3bf26494a83b644ec7db5cc273756e03c6"}, {file = "ft4222-1.9.0.tar.gz", hash = "sha256:0d9fe9bc2537b7dd62b06b45e91f362be9f550a7101f71482f954678fe2d1b0f"},
] ]
[[package]] [[package]]
@ -1609,13 +1627,13 @@ zoneinfo = ["backports.zoneinfo (>=0.2.1)", "tzdata (>=2022.1)"]
[[package]] [[package]]
name = "identify" name = "identify"
version = "2.5.29" version = "2.5.30"
description = "File identification library for Python" description = "File identification library for Python"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "identify-2.5.29-py2.py3-none-any.whl", hash = "sha256:24437fbf6f4d3fe6efd0eb9d67e24dd9106db99af5ceb27996a5f7895f24bf1b"}, {file = "identify-2.5.30-py2.py3-none-any.whl", hash = "sha256:afe67f26ae29bab007ec21b03d4114f41316ab9dd15aa8736a167481e108da54"},
{file = "identify-2.5.29.tar.gz", hash = "sha256:d43d52b86b15918c137e3a74fff5224f60385cd0e9c38e99d07c257f02f151a5"}, {file = "identify-2.5.30.tar.gz", hash = "sha256:f302a4256a15c849b91cfcdcec052a8ce914634b2f77ae87dad29cd749f2d88d"},
] ]
[package.extras] [package.extras]
@ -1710,16 +1728,6 @@ files = [
{file = "inputs-0.5.tar.gz", hash = "sha256:a31d5b96a3525f1232f326be9e7ce8ccaf873c6b1fb84d9f3c9bc3d79b23eae4"}, {file = "inputs-0.5.tar.gz", hash = "sha256:a31d5b96a3525f1232f326be9e7ce8ccaf873c6b1fb84d9f3c9bc3d79b23eae4"},
] ]
[[package]]
name = "ioctl-opt"
version = "1.3"
description = "Functions to compute fnctl.ioctl's opt argument"
optional = false
python-versions = "*"
files = [
{file = "ioctl-opt-1.3.tar.gz", hash = "sha256:5ed4f9a80d2e02e152a43d3648d7ed8821a0aac5ea88ecc5fcc14460ff7cf2f9"},
]
[[package]] [[package]]
name = "isodate" name = "isodate"
version = "0.6.1" version = "0.6.1"
@ -2321,8 +2329,8 @@ waymo = ["waymo-open-dataset-tf-2.11.0 (==1.5.0)"]
[package.source] [package.source]
type = "git" type = "git"
url = "https://github.com/metadriverse/metadrive.git" url = "https://github.com/metadriverse/metadrive.git"
reference = "7d6f8ef707bfff67c6b88f3b4a98f8b1d58bf8e6" reference = "72e842cd1d025bf676e4af8797a01e4aa282109f"
resolved_reference = "7d6f8ef707bfff67c6b88f3b4a98f8b1d58bf8e6" resolved_reference = "72e842cd1d025bf676e4af8797a01e4aa282109f"
[[package]] [[package]]
name = "mpld3" name = "mpld3"
@ -2358,13 +2366,13 @@ tests = ["pytest (>=4.6)"]
[[package]] [[package]]
name = "msal" name = "msal"
version = "1.24.0" version = "1.24.1"
description = "The Microsoft Authentication Library (MSAL) for Python library" description = "The Microsoft Authentication Library (MSAL) for Python library"
optional = false optional = false
python-versions = ">=2.7" python-versions = ">=2.7"
files = [ files = [
{file = "msal-1.24.0-py2.py3-none-any.whl", hash = "sha256:a7f2f342b80ba3fe168218003b6798cc81b83c9745284bf63fb8d4ec8e2dbc50"}, {file = "msal-1.24.1-py2.py3-none-any.whl", hash = "sha256:ce4320688f95c301ee74a4d0e9dbcfe029a63663a8cc61756f40d0d0d36574ad"},
{file = "msal-1.24.0.tar.gz", hash = "sha256:7d2ecdad41a5f73bb2b813f3061a4cf47c924621105a8ed137586fcb9d8f827e"}, {file = "msal-1.24.1.tar.gz", hash = "sha256:aa0972884b3c6fdec53d9a0bd15c12e5bd7b71ac1b66d746f54d128709f3f8f8"},
] ]
[package.dependencies] [package.dependencies]
@ -2804,18 +2812,18 @@ sympy = "*"
[[package]] [[package]]
name = "opencv-python" name = "opencv-python"
version = "4.8.0.76" version = "4.8.1.78"
description = "Wrapper package for OpenCV python bindings." description = "Wrapper package for OpenCV python bindings."
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
{file = "opencv-python-4.8.0.76.tar.gz", hash = "sha256:56d84c43ce800938b9b1ec74b33942b2edbcef3f70c2754eb9bfe5dff1ee3ace"}, {file = "opencv-python-4.8.1.78.tar.gz", hash = "sha256:cc7adbbcd1112877a39274106cb2752e04984bc01a031162952e97450d6117f6"},
{file = "opencv_python-4.8.0.76-cp37-abi3-macosx_10_16_x86_64.whl", hash = "sha256:67bce4b9aad307c98a9a07c6afb7de3a4e823c1f4991d6d8e88e229e7dfeee59"}, {file = "opencv_python-4.8.1.78-cp37-abi3-macosx_10_16_x86_64.whl", hash = "sha256:91d5f6f5209dc2635d496f6b8ca6573ecdad051a09e6b5de4c399b8e673c60da"},
{file = "opencv_python-4.8.0.76-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:48eb3121d809a873086d6677565e3ac963e6946110d13cd115533fa70e2aa2eb"}, {file = "opencv_python-4.8.1.78-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:bc31f47e05447da8b3089faa0a07ffe80e114c91ce0b171e6424f9badbd1c5cd"},
{file = "opencv_python-4.8.0.76-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93871871b1c9d6b125cddd45b0638a2fa01ee9fd37f5e428823f750e404f2f15"}, {file = "opencv_python-4.8.1.78-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9814beca408d3a0eca1bae7e3e5be68b07c17ecceb392b94170881216e09b319"},
{file = "opencv_python-4.8.0.76-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9bcb4944211acf13742dbfd9d3a11dc4e36353ffa1746f2c7dcd6a01c32d1376"}, {file = "opencv_python-4.8.1.78-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4c406bdb41eb21ea51b4e90dfbc989c002786c3f601c236a99c59a54670a394"},
{file = "opencv_python-4.8.0.76-cp37-abi3-win32.whl", hash = "sha256:b2349dc9f97ed6c9ba163d0a7a24bcef9695a3e216cd143e92f1b9659c5d9a49"}, {file = "opencv_python-4.8.1.78-cp37-abi3-win32.whl", hash = "sha256:a7aac3900fbacf55b551e7b53626c3dad4c71ce85643645c43e91fcb19045e47"},
{file = "opencv_python-4.8.0.76-cp37-abi3-win_amd64.whl", hash = "sha256:ba32cfa75a806abd68249699d34420737d27b5678553387fc5768747a6492147"}, {file = "opencv_python-4.8.1.78-cp37-abi3-win_amd64.whl", hash = "sha256:b983197f97cfa6fcb74e1da1802c7497a6f94ed561aba6980f1f33123f904956"},
] ]
[package.dependencies] [package.dependencies]
@ -2830,18 +2838,18 @@ numpy = [
[[package]] [[package]]
name = "opencv-python-headless" name = "opencv-python-headless"
version = "4.8.0.76" version = "4.8.1.78"
description = "Wrapper package for OpenCV python bindings." description = "Wrapper package for OpenCV python bindings."
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
{file = "opencv-python-headless-4.8.0.76.tar.gz", hash = "sha256:bc15726187dae26d8a08777faf6bc71d38f20c785c102677f58ba0e935003afb"}, {file = "opencv-python-headless-4.8.1.78.tar.gz", hash = "sha256:bc7197b42352f6f865c302a49140b889ec7cd957dd697e2d7fc016ad0d3f28f1"},
{file = "opencv_python_headless-4.8.0.76-cp37-abi3-macosx_10_16_x86_64.whl", hash = "sha256:f85d2e3b9d952db35d31f9db8882d073c903921b72b8db1cfed8bbc75e8d3e63"}, {file = "opencv_python_headless-4.8.1.78-cp37-abi3-macosx_10_16_x86_64.whl", hash = "sha256:f3a33f644249f9ce1c913eac580e4b3ef4ce7cab0a71900274708959c2feb5e3"},
{file = "opencv_python_headless-4.8.0.76-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:8ee3bf1c9086493c340c6a87899f1c7778d729de92bce8560b8c31ab8a9cdf79"}, {file = "opencv_python_headless-4.8.1.78-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:2c7d45721df9801c4dcd34683a15caa0e30f38b185263fec04a6eb274bc720f0"},
{file = "opencv_python_headless-4.8.0.76-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c675b8dec6298ba6a1eec2ce24077a393b4236a043f68dfacb06bf594354ce06"}, {file = "opencv_python_headless-4.8.1.78-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b6bd6e1132b6f5dcb3a5bfe30fc4d341a7bfb26134da349a06c9255288ded94"},
{file = "opencv_python_headless-4.8.0.76-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:220d2e292fa45ef0582aab730460bbc15cfe61f2089208167a372ccf76f01e21"}, {file = "opencv_python_headless-4.8.1.78-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58e70d2f0915fe23e02c6e405588276c9397844a47d38b9c87fac5f7f9ba2dcc"},
{file = "opencv_python_headless-4.8.0.76-cp37-abi3-win32.whl", hash = "sha256:df0608de207ae9b094ad9eaf1a475cf6e9a069fb12cd289d4a18cefdab2f8aa8"}, {file = "opencv_python_headless-4.8.1.78-cp37-abi3-win32.whl", hash = "sha256:382f8c7a6a14f80091284eecedd52cee4812231ee0eff1118592197b538d9252"},
{file = "opencv_python_headless-4.8.0.76-cp37-abi3-win_amd64.whl", hash = "sha256:9c094faf6ec7bd360244647b26ebdf8f54edec1d9292cb9179fff9badcca7be8"}, {file = "opencv_python_headless-4.8.1.78-cp37-abi3-win_amd64.whl", hash = "sha256:0a0f1e9f836f7d5bad1dd164694944c8761711cbdf4b36ebbd4815a8ef731079"},
] ]
[package.dependencies] [package.dependencies]
@ -2856,13 +2864,13 @@ numpy = [
[[package]] [[package]]
name = "packaging" name = "packaging"
version = "23.1" version = "23.2"
description = "Core utilities for Python packages" description = "Core utilities for Python packages"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
{file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
] ]
[[package]] [[package]]
@ -3149,13 +3157,13 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa
[[package]] [[package]]
name = "platformdirs" name = "platformdirs"
version = "3.10.0" version = "3.11.0"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"},
{file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"},
] ]
[package.extras] [package.extras]
@ -3179,13 +3187,13 @@ testing = ["pytest", "pytest-benchmark"]
[[package]] [[package]]
name = "polyline" name = "polyline"
version = "2.0.0" version = "2.0.1"
description = "A Python implementation of Google's Encoded Polyline Algorithm Format." description = "A Python implementation of Google's Encoded Polyline Algorithm Format."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "polyline-2.0.0-py3-none-any.whl", hash = "sha256:45c9c0e8c0814a17df78390e3196cd47f6bc69697cd8a83f00d527c72f4d2a88"}, {file = "polyline-2.0.1-py3-none-any.whl", hash = "sha256:7b1ff647be393143c1b9268738d9efb98a327dd0b29f9c3b84552dff0e34ea3c"},
{file = "polyline-2.0.0.tar.gz", hash = "sha256:1492b8fcadc2143f8aedc673d3c6d95df45131f1c62eb8d51c8183b24e771486"}, {file = "polyline-2.0.1.tar.gz", hash = "sha256:74cb5cea098dddf09d1a5a1f17af9184d371cbf3e9723de0194e530ec39ca1f6"},
] ]
[package.extras] [package.extras]
@ -3471,8 +3479,6 @@ files = [
{file = "pygame-2.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e24d05184e4195fe5ebcdce8b18ecb086f00182b9ae460a86682d312ce8d31f"}, {file = "pygame-2.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e24d05184e4195fe5ebcdce8b18ecb086f00182b9ae460a86682d312ce8d31f"},
{file = "pygame-2.5.2-cp311-cp311-win32.whl", hash = "sha256:f02c1c7505af18d426d355ac9872bd5c916b27f7b0fe224749930662bea47a50"}, {file = "pygame-2.5.2-cp311-cp311-win32.whl", hash = "sha256:f02c1c7505af18d426d355ac9872bd5c916b27f7b0fe224749930662bea47a50"},
{file = "pygame-2.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:6d58c8cf937815d3b7cdc0fa9590c5129cb2c9658b72d00e8a4568dea2ff1d42"}, {file = "pygame-2.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:6d58c8cf937815d3b7cdc0fa9590c5129cb2c9658b72d00e8a4568dea2ff1d42"},
{file = "pygame-2.5.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1a2a43802bb5e89ce2b3b775744e78db4f9a201bf8d059b946c61722840ceea8"},
{file = "pygame-2.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1c289f2613c44fe70a1e40769de4a49c5ab5a29b9376f1692bb1a15c9c1c9bfa"},
{file = "pygame-2.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:074aa6c6e110c925f7f27f00c7733c6303407edc61d738882985091d1eb2ef17"}, {file = "pygame-2.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:074aa6c6e110c925f7f27f00c7733c6303407edc61d738882985091d1eb2ef17"},
{file = "pygame-2.5.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe0228501ec616779a0b9c4299e837877783e18df294dd690b9ab0eed3d8aaab"}, {file = "pygame-2.5.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe0228501ec616779a0b9c4299e837877783e18df294dd690b9ab0eed3d8aaab"},
{file = "pygame-2.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31648d38ecdc2335ffc0e38fb18a84b3339730521505dac68514f83a1092e3f4"}, {file = "pygame-2.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31648d38ecdc2335ffc0e38fb18a84b3339730521505dac68514f83a1092e3f4"},
@ -3871,6 +3877,20 @@ files = [
colorama = "*" colorama = "*"
pytest = ">=7.0" pytest = ">=7.0"
[[package]]
name = "pytest-random-order"
version = "1.1.0"
description = "Randomise the order in which pytest tests are run with some control over the randomness"
optional = false
python-versions = ">=3.5.0"
files = [
{file = "pytest-random-order-1.1.0.tar.gz", hash = "sha256:dbe6debb9353a7af984cc9eddbeb3577dd4dbbcc1529a79e3d21f68ed9b45605"},
{file = "pytest_random_order-1.1.0-py3-none-any.whl", hash = "sha256:6cb1e59ab0f798bb0c3488c11ae0c70d7d3340306a466d28b28ccd8ef8c20b7e"},
]
[package.dependencies]
pytest = ">=3.0.0"
[[package]] [[package]]
name = "pytest-subtests" name = "pytest-subtests"
version = "0.11.0" version = "0.11.0"
@ -4185,28 +4205,28 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]] [[package]]
name = "ruff" name = "ruff"
version = "0.0.291" version = "0.0.292"
description = "An extremely fast Python linter, written in Rust." description = "An extremely fast Python linter, written in Rust."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "ruff-0.0.291-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:b97d0d7c136a85badbc7fd8397fdbb336e9409b01c07027622f28dcd7db366f2"}, {file = "ruff-0.0.292-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:02f29db018c9d474270c704e6c6b13b18ed0ecac82761e4fcf0faa3728430c96"},
{file = "ruff-0.0.291-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:6ab44ea607967171e18aa5c80335237be12f3a1523375fa0cede83c5cf77feb4"}, {file = "ruff-0.0.292-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:69654e564342f507edfa09ee6897883ca76e331d4bbc3676d8a8403838e9fade"},
{file = "ruff-0.0.291-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a04b384f2d36f00d5fb55313d52a7d66236531195ef08157a09c4728090f2ef0"}, {file = "ruff-0.0.292-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c3c91859a9b845c33778f11902e7b26440d64b9d5110edd4e4fa1726c41e0a4"},
{file = "ruff-0.0.291-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b727c219b43f903875b7503a76c86237a00d1a39579bb3e21ce027eec9534051"}, {file = "ruff-0.0.292-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4476f1243af2d8c29da5f235c13dca52177117935e1f9393f9d90f9833f69e4"},
{file = "ruff-0.0.291-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87671e33175ae949702774071b35ed4937da06f11851af75cd087e1b5a488ac4"}, {file = "ruff-0.0.292-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be8eb50eaf8648070b8e58ece8e69c9322d34afe367eec4210fdee9a555e4ca7"},
{file = "ruff-0.0.291-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b75f5801547f79b7541d72a211949754c21dc0705c70eddf7f21c88a64de8b97"}, {file = "ruff-0.0.292-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9889bac18a0c07018aac75ef6c1e6511d8411724d67cb879103b01758e110a81"},
{file = "ruff-0.0.291-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b09b94efdcd162fe32b472b2dd5bf1c969fcc15b8ff52f478b048f41d4590e09"}, {file = "ruff-0.0.292-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6bdfabd4334684a4418b99b3118793f2c13bb67bf1540a769d7816410402a205"},
{file = "ruff-0.0.291-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d5b56bc3a2f83a7a1d7f4447c54d8d3db52021f726fdd55d549ca87bca5d747"}, {file = "ruff-0.0.292-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7c77c53bfcd75dbcd4d1f42d6cabf2485d2e1ee0678da850f08e1ab13081a8"},
{file = "ruff-0.0.291-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13f0d88e5f367b2dc8c7d90a8afdcfff9dd7d174e324fd3ed8e0b5cb5dc9b7f6"}, {file = "ruff-0.0.292-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e087b24d0d849c5c81516ec740bf4fd48bf363cfb104545464e0fca749b6af9"},
{file = "ruff-0.0.291-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b3eeee1b1a45a247758ecdc3ab26c307336d157aafc61edb98b825cadb153df3"}, {file = "ruff-0.0.292-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f160b5ec26be32362d0774964e218f3fcf0a7da299f7e220ef45ae9e3e67101a"},
{file = "ruff-0.0.291-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6c06006350c3bb689765d71f810128c9cdf4a1121fd01afc655c87bab4fb4f83"}, {file = "ruff-0.0.292-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ac153eee6dd4444501c4bb92bff866491d4bfb01ce26dd2fff7ca472c8df9ad0"},
{file = "ruff-0.0.291-py3-none-musllinux_1_2_i686.whl", hash = "sha256:fd17220611047de247b635596e3174f3d7f2becf63bd56301fc758778df9b629"}, {file = "ruff-0.0.292-py3-none-musllinux_1_2_i686.whl", hash = "sha256:87616771e72820800b8faea82edd858324b29bb99a920d6aa3d3949dd3f88fb0"},
{file = "ruff-0.0.291-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5383ba67ad360caf6060d09012f1fb2ab8bd605ab766d10ca4427a28ab106e0b"}, {file = "ruff-0.0.292-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b76deb3bdbea2ef97db286cf953488745dd6424c122d275f05836c53f62d4016"},
{file = "ruff-0.0.291-py3-none-win32.whl", hash = "sha256:1d5f0616ae4cdc7a938b493b6a1a71c8a47d0300c0d65f6e41c281c2f7490ad3"}, {file = "ruff-0.0.292-py3-none-win32.whl", hash = "sha256:e854b05408f7a8033a027e4b1c7f9889563dd2aca545d13d06711e5c39c3d003"},
{file = "ruff-0.0.291-py3-none-win_amd64.whl", hash = "sha256:8a69bfbde72db8ca1c43ee3570f59daad155196c3fbe357047cd9b77de65f15b"}, {file = "ruff-0.0.292-py3-none-win_amd64.whl", hash = "sha256:f27282bedfd04d4c3492e5c3398360c9d86a295be00eccc63914438b4ac8a83c"},
{file = "ruff-0.0.291-py3-none-win_arm64.whl", hash = "sha256:d867384a4615b7f30b223a849b52104214442b5ba79b473d7edd18da3cde22d6"}, {file = "ruff-0.0.292-py3-none-win_arm64.whl", hash = "sha256:7f67a69c8f12fbc8daf6ae6d36705037bde315abf8b82b6e1f4c9e74eb750f68"},
{file = "ruff-0.0.291.tar.gz", hash = "sha256:c61109661dde9db73469d14a82b42a88c7164f731e6a3b0042e71394c1c7ceed"}, {file = "ruff-0.0.292.tar.gz", hash = "sha256:1093449e37dd1e9b813798f6ad70932b57cf614e5c2b5c51005bf67d55db33ac"},
] ]
[[package]] [[package]]
@ -4288,24 +4308,24 @@ resolved_reference = "f3b0100d3a628e4d18f496815903660a99489bae"
[[package]] [[package]]
name = "seaborn" name = "seaborn"
version = "0.12.2" version = "0.13.0"
description = "Statistical data visualization" description = "Statistical data visualization"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.8"
files = [ files = [
{file = "seaborn-0.12.2-py3-none-any.whl", hash = "sha256:ebf15355a4dba46037dfd65b7350f014ceb1f13c05e814eda2c9f5fd731afc08"}, {file = "seaborn-0.13.0-py3-none-any.whl", hash = "sha256:70d740828c48de0f402bb17234e475eda687e3c65f4383ea25d0cc4728f7772e"},
{file = "seaborn-0.12.2.tar.gz", hash = "sha256:374645f36509d0dcab895cba5b47daf0586f77bfe3b36c97c607db7da5be0139"}, {file = "seaborn-0.13.0.tar.gz", hash = "sha256:0e76abd2ec291c655b516703c6a022f0fd5afed26c8e714e8baef48150f73598"},
] ]
[package.dependencies] [package.dependencies]
matplotlib = ">=3.1,<3.6.1 || >3.6.1" matplotlib = ">=3.3,<3.6.1 || >3.6.1"
numpy = ">=1.17,<1.24.0 || >1.24.0" numpy = ">=1.20,<1.24.0 || >1.24.0"
pandas = ">=0.25" pandas = ">=1.2"
[package.extras] [package.extras]
dev = ["flake8", "flit", "mypy", "pandas-stubs", "pre-commit", "pytest", "pytest-cov", "pytest-xdist"] dev = ["flake8", "flit", "mypy", "pandas-stubs", "pre-commit", "pytest", "pytest-cov", "pytest-xdist"]
docs = ["ipykernel", "nbconvert", "numpydoc", "pydata_sphinx_theme (==0.10.0rc2)", "pyyaml", "sphinx-copybutton", "sphinx-design", "sphinx-issues"] docs = ["ipykernel", "nbconvert", "numpydoc", "pydata_sphinx_theme (==0.10.0rc2)", "pyyaml", "sphinx (<6.0.0)", "sphinx-copybutton", "sphinx-design", "sphinx-issues"]
stats = ["scipy (>=1.3)", "statsmodels (>=0.10)"] stats = ["scipy (>=1.7)", "statsmodels (>=0.12)"]
[[package]] [[package]]
name = "sentry-sdk" name = "sentry-sdk"
@ -4451,23 +4471,24 @@ testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jar
[[package]] [[package]]
name = "setuptools-scm" name = "setuptools-scm"
version = "8.0.3" version = "8.0.4"
description = "the blessed package to manage your versions by scm tags" description = "the blessed package to manage your versions by scm tags"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "setuptools-scm-8.0.3.tar.gz", hash = "sha256:0169fd70197efda2f8c4d0b2a7a3d614431b488116f37b79d031e9e7ec884d8c"}, {file = "setuptools-scm-8.0.4.tar.gz", hash = "sha256:b5f43ff6800669595193fd09891564ee9d1d7dcb196cab4b2506d53a2e1c95c7"},
{file = "setuptools_scm-8.0.3-py3-none-any.whl", hash = "sha256:813822234453438a13c78d05c8af29918fbc06f88efb33d38f065340bbb48c39"}, {file = "setuptools_scm-8.0.4-py3-none-any.whl", hash = "sha256:b47844cd2a84b83b3187a5782c71128c28b4c94cad8bfb871da2784a5cb54c4f"},
] ]
[package.dependencies] [package.dependencies]
packaging = ">=20" packaging = ">=20"
setuptools = "*" setuptools = "*"
typing-extensions = "*"
[package.extras] [package.extras]
docs = ["entangled-cli[rich]", "mkdocs", "mkdocs-entangled-plugin", "mkdocs-material", "mkdocstrings[python]", "pygments"] docs = ["entangled-cli[rich]", "mkdocs", "mkdocs-entangled-plugin", "mkdocs-material", "mkdocstrings[python]", "pygments"]
rich = ["rich"] rich = ["rich"]
test = ["pytest", "rich", "virtualenv (>20)"] test = ["build", "pytest", "rich", "wheel"]
[[package]] [[package]]
name = "shapely" name = "shapely"
@ -4788,19 +4809,6 @@ files = [
{file = "spidev-3.6.tar.gz", hash = "sha256:14dbc37594a4aaef85403ab617985d3c3ef464d62bc9b769ef552db53701115b"}, {file = "spidev-3.6.tar.gz", hash = "sha256:14dbc37594a4aaef85403ab617985d3c3ef464d62bc9b769ef552db53701115b"},
] ]
[[package]]
name = "spidev2"
version = "0.9.0"
description = "Pure-python interface to Linux spidev."
optional = false
python-versions = "*"
files = [
{file = "spidev2-0.9.0.tar.gz", hash = "sha256:152da2911a8660283ceac3a75dd869953379bcbcf079e5436af5aae736876086"},
]
[package.dependencies]
ioctl-opt = "*"
[[package]] [[package]]
name = "sympy" name = "sympy"
version = "1.12" version = "1.12"
@ -4941,17 +4949,17 @@ files = [
[[package]] [[package]]
name = "types-requests" name = "types-requests"
version = "2.31.0.6" version = "2.31.0.7"
description = "Typing stubs for requests" description = "Typing stubs for requests"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "types-requests-2.31.0.6.tar.gz", hash = "sha256:cd74ce3b53c461f1228a9b783929ac73a666658f223e28ed29753771477b3bd0"}, {file = "types-requests-2.31.0.7.tar.gz", hash = "sha256:4d930dcabbc2452e3d70728e581ac4ac8c2d13f62509ad9114673f542af8cb4e"},
{file = "types_requests-2.31.0.6-py3-none-any.whl", hash = "sha256:a2db9cb228a81da8348b49ad6db3f5519452dd20a9c1e1a868c83c5fe88fd1a9"}, {file = "types_requests-2.31.0.7-py3-none-any.whl", hash = "sha256:39844effefca88f4f824dcdc4127b813d3b86a56b2248d3d1afa58832040d979"},
] ]
[package.dependencies] [package.dependencies]
types-urllib3 = "*" urllib3 = ">=2"
[[package]] [[package]]
name = "types-tabulate" name = "types-tabulate"
@ -4964,17 +4972,6 @@ files = [
{file = "types_tabulate-0.9.0.3-py3-none-any.whl", hash = "sha256:462d1b62e01728416e8277614d6a3eb172d53a8efaf04a04a973ff2dd45238f6"}, {file = "types_tabulate-0.9.0.3-py3-none-any.whl", hash = "sha256:462d1b62e01728416e8277614d6a3eb172d53a8efaf04a04a973ff2dd45238f6"},
] ]
[[package]]
name = "types-urllib3"
version = "1.26.25.14"
description = "Typing stubs for urllib3"
optional = false
python-versions = "*"
files = [
{file = "types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f"},
{file = "types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e"},
]
[[package]] [[package]]
name = "typing-extensions" name = "typing-extensions"
version = "4.8.0" version = "4.8.0"
@ -4999,13 +4996,13 @@ files = [
[[package]] [[package]]
name = "urllib3" name = "urllib3"
version = "2.0.5" version = "2.0.6"
description = "HTTP library with thread-safe connection pooling, file post, and more." description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "urllib3-2.0.5-py3-none-any.whl", hash = "sha256:ef16afa8ba34a1f989db38e1dbbe0c302e4289a47856990d0682e374563ce35e"}, {file = "urllib3-2.0.6-py3-none-any.whl", hash = "sha256:7a7c7003b000adf9e7ca2a377c9688bbc54ed41b985789ed576570342a375cd2"},
{file = "urllib3-2.0.5.tar.gz", hash = "sha256:13abf37382ea2ce6fb744d4dad67838eec857c9f4f57009891805e0b5e123594"}, {file = "urllib3-2.0.6.tar.gz", hash = "sha256:b19e1a85d206b56d7df1d5e683df4a7725252a964e3993648dd0fb5a1c157564"},
] ]
[package.extras] [package.extras]
@ -5171,4 +5168,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "~3.11" python-versions = "~3.11"
content-hash = "808489f6658d63643587b06a7881e0f58fc8a97af34c1478a20342e916204a68" content-hash = "173a9329d8f42b01b7d62684fadb257e604fda7e584bfcdd4fcdf71ae6aa99f9"

@ -90,7 +90,6 @@ numpy = "*"
onnx = ">=1.14.0" onnx = ">=1.14.0"
onnxruntime = { version = ">=1.15.1", platform = "linux", markers = "platform_machine == 'aarch64'" } onnxruntime = { version = ">=1.15.1", platform = "linux", markers = "platform_machine == 'aarch64'" }
onnxruntime-gpu = { version = ">=1.15.1", platform = "linux", markers = "platform_machine == 'x86_64'" } onnxruntime-gpu = { version = ">=1.15.1", platform = "linux", markers = "platform_machine == 'x86_64'" }
pillow = "*"
psutil = "*" psutil = "*"
pyaudio = "*" pyaudio = "*"
pycapnp = "*" pycapnp = "*"
@ -109,11 +108,9 @@ setproctitle = "*"
smbus2 = "*" smbus2 = "*"
sounddevice = "*" sounddevice = "*"
spidev = { version = "*", platform = "linux" } spidev = { version = "*", platform = "linux" }
spidev2 = { version = "*", platform = "linux" }
sympy = "*" sympy = "*"
timezonefinder = "*" timezonefinder = "*"
tqdm = "*" tqdm = "*"
urllib3 = "*"
websocket_client = "*" websocket_client = "*"
polyline = "*" polyline = "*"
sconscontrib = {git = "https://github.com/SCons/scons-contrib.git"} sconscontrib = {git = "https://github.com/SCons/scons-contrib.git"}
@ -124,7 +121,6 @@ av = "*"
azure-identity = "*" azure-identity = "*"
azure-storage-blob = "*" azure-storage-blob = "*"
breathe = "*" breathe = "*"
carla = { url = "https://github.com/commaai/carla/releases/download/3.11.4/carla-0.9.14-cp311-cp311-linux_x86_64.whl", platform = "linux", markers = "platform_machine == 'x86_64'" }
coverage = "*" coverage = "*"
dictdiffer = "*" dictdiffer = "*"
ft4222 = "*" ft4222 = "*"
@ -133,7 +129,7 @@ inputs = "*"
lru-dict = "*" lru-dict = "*"
markdown-it-py = "*" markdown-it-py = "*"
matplotlib = "*" matplotlib = "*"
metadrive-simulator = { git = "https://github.com/metadriverse/metadrive.git", rev ="7d6f8ef707bfff67c6b88f3b4a98f8b1d58bf8e6", markers = "platform_machine != 'aarch64'" } # no linux/aarch64 wheels for certain dependencies metadrive-simulator = { git = "https://github.com/metadriverse/metadrive.git", rev ="72e842cd1d025bf676e4af8797a01e4aa282109f", markers = "platform_machine != 'aarch64'" } # no linux/aarch64 wheels for certain dependencies
mpld3 = "*" mpld3 = "*"
mypy = "*" mypy = "*"
myst-parser = "*" myst-parser = "*"
@ -152,6 +148,7 @@ pytest-subtests = "*"
pytest-xdist = "*" pytest-xdist = "*"
pytest-timeout = "*" pytest-timeout = "*"
pytest-timeouts = "*" pytest-timeouts = "*"
pytest-random-order = "*"
ruff = "*" ruff = "*"
scipy = "*" scipy = "*"
sphinx = "*" sphinx = "*"
@ -167,6 +164,11 @@ types-requests = "*"
types-tabulate = "*" types-tabulate = "*"
pyqt5 = { version = "*", markers = "platform_machine == 'x86_64'" } # no aarch64 wheels for macOS/linux pyqt5 = { version = "*", markers = "platform_machine == 'x86_64'" } # no aarch64 wheels for macOS/linux
[tool.poetry.group.carla]
optional = true
[tool.poetry.group.carla.dependencies]
carla = { url = "https://github.com/commaai/carla/releases/download/3.11.4/carla-0.9.14-cp311-cp311-linux_x86_64.whl", platform = "linux", markers = "platform_machine == 'x86_64'" }
[build-system] [build-system]
requires = ["poetry-core"] requires = ["poetry-core"]

@ -71,7 +71,6 @@ selfdrive/__init__.py
selfdrive/sentry.py selfdrive/sentry.py
selfdrive/tombstoned.py selfdrive/tombstoned.py
selfdrive/updated.py selfdrive/updated.py
selfdrive/rtshield.py
selfdrive/statsd.py selfdrive/statsd.py
system/logmessaged.py system/logmessaged.py
@ -201,8 +200,6 @@ selfdrive/controls/lib/longitudinal_mpc_lib/.gitignore
selfdrive/controls/lib/lateral_mpc_lib/* selfdrive/controls/lib/lateral_mpc_lib/*
selfdrive/controls/lib/longitudinal_mpc_lib/* selfdrive/controls/lib/longitudinal_mpc_lib/*
selfdrive/hardware
system/__init__.py system/__init__.py
system/hardware/__init__.py system/hardware/__init__.py

@ -1,59 +0,0 @@
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
void hexdump(uint32_t *d, int l) {
for (int i = 0; i < l; i++) {
if (i%0x10 == 0 && i != 0) printf("\n");
printf("%8x ", d[i]);
}
printf("\n");
}
/* Power cluster primary PLL */
#define C0_PLL_MODE 0x0
#define C0_PLL_L_VAL 0x4
#define C0_PLL_ALPHA 0x8
#define C0_PLL_USER_CTL 0x10
#define C0_PLL_CONFIG_CTL 0x18
#define C0_PLL_CONFIG_CTL_HI 0x1C
#define C0_PLL_STATUS 0x28
#define C0_PLL_TEST_CTL_LO 0x20
#define C0_PLL_TEST_CTL_HI 0x24
/* Power cluster alt PLL */
#define C0_PLLA_MODE 0x100
#define C0_PLLA_L_VAL 0x104
#define C0_PLLA_ALPHA 0x108
#define C0_PLLA_USER_CTL 0x110
#define C0_PLLA_CONFIG_CTL 0x118
#define C0_PLLA_STATUS 0x128
#define C0_PLLA_TEST_CTL_LO 0x120
#define APC_DIAG_OFFSET 0x48
#define CLK_CTL_OFFSET 0x44
#define MUX_OFFSET 0x40
#define MDD_DROOP_CODE 0x7c
#define SSSCTL_OFFSET 0x160
#define PSCTL_OFFSET 0x164
int main() {
int fd = open("/dev/mem", O_RDWR);
volatile uint32_t *mb = (uint32_t *)mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x06400000);
volatile uint32_t *mc = (uint32_t *)mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x06480000);
volatile uint32_t *md = (uint32_t *)mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x09A20000);
while (1) {
printf("PLL MODE:%x L_VAL:%x ALPHA:%x USER_CTL:%x CONFIG_CTL:%x CONFIG_CTL_HI:%x STATUS:%x TEST_CTL_LO:%x TEST_CTL_HI:%x\n",
mb[C0_PLL_MODE/4], mb[C0_PLL_L_VAL/4], mb[C0_PLL_ALPHA/4],
mb[C0_PLL_USER_CTL/4], mb[C0_PLL_CONFIG_CTL/4], mb[C0_PLL_CONFIG_CTL_HI/4],
mb[C0_PLL_STATUS/4], mb[C0_PLL_TEST_CTL_LO/4], mb[C0_PLL_TEST_CTL_HI/4]);
printf(" MUX_OFFSET:%x CLK_CTL_OFFSET:%x APC_DIAG_OFFSET:%x MDD_DROOP_CODE:%x\n",
mb[MUX_OFFSET/4], mb[CLK_CTL_OFFSET/4], mb[APC_DIAG_OFFSET/4], mb[MDD_DROOP_CODE/4]);
printf(" PLLA MODE:%x L_VAL:%x ALPHA:%x USER_CTL:%x CONFIG_CTL:%x STATUS:%x TEST_CTL_LO:%x SSSCTL_OFFSET:%x PSCTL_OFFSET:%x\n",
mb[C0_PLLA_MODE/4], mb[C0_PLLA_L_VAL/4], mb[C0_PLLA_ALPHA/4], mb[C0_PLLA_USER_CTL/4],
mb[C0_PLLA_CONFIG_CTL/4], mb[C0_PLLA_STATUS/4], mb[C0_PLLA_TEST_CTL_LO/4],
mb[SSSCTL_OFFSET/4], mb[PSCTL_OFFSET/4]);
usleep(1000*100);
}
}

@ -40,7 +40,7 @@ from openpilot.system.loggerd.xattr_cache import getxattr, setxattr
from openpilot.selfdrive.statsd import STATS_DIR from openpilot.selfdrive.statsd import STATS_DIR
from openpilot.system.swaglog import cloudlog from openpilot.system.swaglog import cloudlog
from openpilot.system.version import get_commit, get_origin, get_short_branch, get_version from openpilot.system.version import get_commit, get_origin, get_short_branch, get_version
from openpilot.selfdrive.hardware.hw import Paths from openpilot.system.hardware.hw import Paths
# TODO: use socket constant when mypy recognizes this as a valid attribute # TODO: use socket constant when mypy recognizes this as a valid attribute

@ -21,7 +21,7 @@ from openpilot.selfdrive.athena import athenad
from openpilot.selfdrive.athena.athenad import MAX_RETRY_COUNT, dispatcher from openpilot.selfdrive.athena.athenad import MAX_RETRY_COUNT, dispatcher
from openpilot.selfdrive.athena.tests.helpers import MockWebsocket, MockParams, MockApi, EchoSocket, with_http_server from openpilot.selfdrive.athena.tests.helpers import MockWebsocket, MockParams, MockApi, EchoSocket, with_http_server
from cereal import messaging from cereal import messaging
from openpilot.selfdrive.hardware.hw import Paths from openpilot.system.hardware.hw import Paths
class TestAthenadMethods(unittest.TestCase): class TestAthenadMethods(unittest.TestCase):

@ -3,7 +3,6 @@
import os import os
import usb1 import usb1
import time import time
import json
import subprocess import subprocess
from typing import List, NoReturn from typing import List, NoReturn
from functools import cmp_to_key from functools import cmp_to_key
@ -24,51 +23,6 @@ def get_expected_signature(panda: Panda) -> bytes:
cloudlog.exception("Error computing expected signature") cloudlog.exception("Error computing expected signature")
return b"" return b""
def read_panda_logs(panda: Panda) -> None:
"""
Forward panda logs to the cloud
"""
params = Params()
serial = panda.get_usb_serial()
log_state = {}
try:
ls = params.get("PandaLogState")
if ls is not None:
l = json.loads(ls)
for k, v in l.items():
if isinstance(k, str) and isinstance(v, int):
log_state[k] = v
except (TypeError, json.JSONDecodeError):
cloudlog.exception("failed to parse PandaLogState")
try:
if serial in log_state:
logs = panda.get_logs(last_id=log_state[serial])
else:
logs = panda.get_logs(get_all=True)
# truncate logs to 100 entries if needed
MAX_LOGS = 100
if len(logs) > MAX_LOGS:
cloudlog.warning(f"Panda {serial} has {len(logs)} logs, truncating to {MAX_LOGS}")
logs = logs[-MAX_LOGS:]
# update log state
if len(logs) > 0:
log_state[serial] = logs[-1]["id"]
for log in logs:
if log['timestamp'] is not None:
log['timestamp'] = log['timestamp'].isoformat()
cloudlog.event("panda_log", **log, serial=serial)
params.put("PandaLogState", json.dumps(log_state))
except Exception:
cloudlog.exception(f"Error getting logs for panda {serial}")
def flash_panda(panda_serial: str) -> Panda: def flash_panda(panda_serial: str) -> Panda:
try: try:
panda = Panda(panda_serial) panda = Panda(panda_serial)
@ -191,8 +145,6 @@ def main() -> NoReturn:
params.put_bool("PandaHeartbeatLost", True) params.put_bool("PandaHeartbeatLost", True)
cloudlog.event("heartbeat lost", deviceState=health, serial=panda.get_usb_serial()) cloudlog.event("heartbeat lost", deviceState=health, serial=panda.get_usb_serial())
read_panda_logs(panda)
if first_run: if first_run:
if panda.is_internal(): if panda.is_internal():
# update time from RTC # update time from RTC

@ -6,11 +6,9 @@ import unittest
import cereal.messaging as messaging import cereal.messaging as messaging
from cereal import log from cereal import log
from openpilot.common.gpio import gpio_set, gpio_init from openpilot.common.gpio import gpio_set, gpio_init
from openpilot.common.params import Params
from panda import Panda, PandaDFU, PandaProtocolMismatch from panda import Panda, PandaDFU, PandaProtocolMismatch
from openpilot.selfdrive.test.helpers import phone_only
from openpilot.selfdrive.manager.process_config import managed_processes from openpilot.selfdrive.manager.process_config import managed_processes
from openpilot.system.hardware import HARDWARE from openpilot.system.hardware import HARDWARE, PC
from openpilot.system.hardware.tici.pins import GPIO from openpilot.system.hardware.tici.pins import GPIO
HERE = os.path.dirname(os.path.realpath(__file__)) HERE = os.path.dirname(os.path.realpath(__file__))
@ -19,8 +17,11 @@ HERE = os.path.dirname(os.path.realpath(__file__))
class TestPandad(unittest.TestCase): class TestPandad(unittest.TestCase):
def setUp(self): def setUp(self):
self.params = Params() if PC:
self.start_log_state = self.params.get("PandaLogState") raise unittest.SkipTest("needs a panda")
# ensure panda is up
if len(Panda.list()) == 0:
self._run_test(60)
def tearDown(self): def tearDown(self):
managed_processes['pandad'].stop() managed_processes['pandad'].stop()
@ -39,10 +40,6 @@ class TestPandad(unittest.TestCase):
if sm['peripheralState'].pandaType == log.PandaState.PandaType.unknown: if sm['peripheralState'].pandaType == log.PandaState.PandaType.unknown:
raise Exception("boardd failed to start") raise Exception("boardd failed to start")
# simple check that we did something with the panda logs
cur_log_state = self.params.get("PandaLogState")
assert cur_log_state != self.start_log_state
def _go_to_dfu(self): def _go_to_dfu(self):
HARDWARE.recover_internal_panda() HARDWARE.recover_internal_panda()
assert Panda.wait_for_dfu(None, 10) assert Panda.wait_for_dfu(None, 10)
@ -71,19 +68,16 @@ class TestPandad(unittest.TestCase):
self._run_test(45) self._run_test(45)
@phone_only
def test_in_dfu(self): def test_in_dfu(self):
HARDWARE.recover_internal_panda() HARDWARE.recover_internal_panda()
self._run_test(60) self._run_test(60)
@phone_only
def test_in_bootstub(self): def test_in_bootstub(self):
with Panda() as p: with Panda() as p:
p.reset(enter_bootstub=True) p.reset(enter_bootstub=True)
assert p.bootstub assert p.bootstub
self._run_test() self._run_test()
@phone_only
def test_internal_panda_reset(self): def test_internal_panda_reset(self):
gpio_init(GPIO.STM_RST_N, True) gpio_init(GPIO.STM_RST_N, True)
gpio_set(GPIO.STM_RST_N, 1) gpio_set(GPIO.STM_RST_N, 1)
@ -93,28 +87,23 @@ class TestPandad(unittest.TestCase):
assert any(Panda(s).is_internal() for s in Panda.list()) assert any(Panda(s).is_internal() for s in Panda.list())
@phone_only
def test_best_case_startup_time(self): def test_best_case_startup_time(self):
# run once so we're setup # run once so we're setup
self._run_test() self._run_test(60)
# should be fast this time # should be fast this time
self._run_test(8) self._run_test(8)
@phone_only
def test_protocol_version_check(self): def test_protocol_version_check(self):
if HARDWARE.get_device_type() == 'tici': if HARDWARE.get_device_type() == 'tici':
self.skipTest("") raise unittest.SkipTest("SPI test")
# flash old fw # flash old fw
fn = os.path.join(HERE, "bootstub.panda_h7_spiv0.bin") fn = os.path.join(HERE, "bootstub.panda_h7_spiv0.bin")
self._flash_bootstub_and_test(fn, expect_mismatch=True) self._flash_bootstub_and_test(fn, expect_mismatch=True)
@phone_only
def test_release_to_devel_bootstub(self): def test_release_to_devel_bootstub(self):
self._flash_bootstub_and_test(None) self._flash_bootstub_and_test(None)
@phone_only
def test_recover_from_bad_bootstub(self): def test_recover_from_bad_bootstub(self):
self._go_to_dfu() self._go_to_dfu()
with PandaDFU(None) as pd: with PandaDFU(None) as pd:
@ -127,4 +116,4 @@ class TestPandad(unittest.TestCase):
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

@ -1,3 +1,4 @@
from enum import StrEnum
from typing import Dict from typing import Dict
from cereal import car from cereal import car
@ -21,7 +22,7 @@ class CarControllerParams:
pass pass
class CAR: class CAR(StrEnum):
BODY = "COMMA BODY" BODY = "COMMA BODY"

@ -66,9 +66,8 @@ def load_interfaces(brand_names):
def _get_interface_names() -> Dict[str, List[str]]: def _get_interface_names() -> Dict[str, List[str]]:
# returns a dict of brand name and its respective models # returns a dict of brand name and its respective models
brand_names = {} brand_names = {}
for brand_name, model_names in get_interface_attr("CAR").items(): for brand_name, brand_models in get_interface_attr("CAR").items():
model_names = [getattr(model_names, c) for c in model_names.__dict__.keys() if not c.startswith("__")] brand_names[brand_name] = [model.value for model in brand_models]
brand_names[brand_name] = model_names
return brand_names return brand_names

@ -1,5 +1,5 @@
# ruff: noqa: E501 # ruff: noqa: E501
from enum import IntFlag from enum import IntFlag, StrEnum
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Dict, List, Optional, Union from typing import Dict, List, Optional, Union
@ -16,7 +16,7 @@ class ChryslerFlags(IntFlag):
HIGHER_MIN_STEERING_SPEED = 1 HIGHER_MIN_STEERING_SPEED = 1
class CAR: class CAR(StrEnum):
# Chrysler # Chrysler
PACIFICA_2017_HYBRID = "CHRYSLER PACIFICA HYBRID 2017" PACIFICA_2017_HYBRID = "CHRYSLER PACIFICA HYBRID 2017"
PACIFICA_2018_HYBRID = "CHRYSLER PACIFICA HYBRID 2018" PACIFICA_2018_HYBRID = "CHRYSLER PACIFICA HYBRID 2018"

@ -1,6 +1,6 @@
from collections import defaultdict from collections import defaultdict
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum, StrEnum
from typing import Dict, List, Union from typing import Dict, List, Union
from cereal import car from cereal import car
@ -40,7 +40,7 @@ class CarControllerParams:
pass pass
class CAR: class CAR(StrEnum):
BRONCO_SPORT_MK1 = "FORD BRONCO SPORT 1ST GEN" BRONCO_SPORT_MK1 = "FORD BRONCO SPORT 1ST GEN"
ESCAPE_MK4 = "FORD ESCAPE 4TH GEN" ESCAPE_MK4 = "FORD ESCAPE 4TH GEN"
EXPLORER_MK6 = "FORD EXPLORER 6TH GEN" EXPLORER_MK6 = "FORD EXPLORER 6TH GEN"

@ -1,7 +1,7 @@
# ruff: noqa: E501 # ruff: noqa: E501
from collections import defaultdict from collections import defaultdict
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum from enum import Enum, StrEnum
from typing import Dict, List, Union from typing import Dict, List, Union
from cereal import car from cereal import car
@ -61,7 +61,7 @@ class CarControllerParams:
self.BRAKE_LOOKUP_V = [self.MAX_BRAKE, 0.] self.BRAKE_LOOKUP_V = [self.MAX_BRAKE, 0.]
class CAR: class CAR(StrEnum):
HOLDEN_ASTRA = "HOLDEN ASTRA RS-V BK 2017" HOLDEN_ASTRA = "HOLDEN ASTRA RS-V BK 2017"
VOLT = "CHEVROLET VOLT PREMIER 2017" VOLT = "CHEVROLET VOLT PREMIER 2017"
CADILLAC_ATS = "CADILLAC ATS Premium Performance 2018" CADILLAC_ATS = "CADILLAC ATS Premium Performance 2018"

@ -1,5 +1,5 @@
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum, IntFlag from enum import Enum, IntFlag, StrEnum
from typing import Dict, List, Optional, Union from typing import Dict, List, Optional, Union
from cereal import car from cereal import car
@ -72,7 +72,7 @@ VISUAL_HUD = {
} }
class CAR: class CAR(StrEnum):
ACCORD = "HONDA ACCORD 2018" ACCORD = "HONDA ACCORD 2018"
ACCORDH = "HONDA ACCORD HYBRID 2018" ACCORDH = "HONDA ACCORD HYBRID 2018"
CIVIC = "HONDA CIVIC 2016" CIVIC = "HONDA CIVIC 2016"

@ -121,6 +121,11 @@ class CarInterface(CarInterfaceBase):
ret.tireStiffnessFactor = 0.385 ret.tireStiffnessFactor = 0.385
if candidate in (CAR.IONIQ, CAR.IONIQ_EV_LTD, CAR.IONIQ_PHEV_2019): if candidate in (CAR.IONIQ, CAR.IONIQ_EV_LTD, CAR.IONIQ_PHEV_2019):
ret.minSteerSpeed = 32 * CV.MPH_TO_MS ret.minSteerSpeed = 32 * CV.MPH_TO_MS
elif candidate in (CAR.IONIQ_5, CAR.IONIQ_6):
ret.mass = 1948
ret.wheelbase = 2.97
ret.steerRatio = 14.26
ret.tireStiffnessFactor = 0.65
elif candidate == CAR.VELOSTER: elif candidate == CAR.VELOSTER:
ret.mass = 2917. * CV.LB_TO_KG ret.mass = 2917. * CV.LB_TO_KG
ret.wheelbase = 2.80 ret.wheelbase = 2.80
@ -197,11 +202,6 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = 2.9 ret.wheelbase = 2.9
ret.steerRatio = 16. ret.steerRatio = 16.
ret.tireStiffnessFactor = 0.65 ret.tireStiffnessFactor = 0.65
elif candidate in (CAR.IONIQ_5, CAR.IONIQ_6):
ret.mass = 1948
ret.wheelbase = 2.97
ret.steerRatio = 14.26
ret.tireStiffnessFactor = 0.65
elif candidate == CAR.KIA_SPORTAGE_HYBRID_5TH_GEN: elif candidate == CAR.KIA_SPORTAGE_HYBRID_5TH_GEN:
ret.mass = 1767. # SX Prestige trim support only ret.mass = 1767. # SX Prestige trim support only
ret.wheelbase = 2.756 ret.wheelbase = 2.756

@ -1,7 +1,7 @@
# ruff: noqa: E501 # ruff: noqa: E501
import re import re
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum, IntFlag from enum import Enum, IntFlag, StrEnum
from typing import Dict, List, Optional, Set, Tuple, Union from typing import Dict, List, Optional, Set, Tuple, Union
from cereal import car from cereal import car
@ -67,7 +67,7 @@ class HyundaiFlags(IntFlag):
CANFD_HDA2_ALT_STEERING = 512 CANFD_HDA2_ALT_STEERING = 512
class CAR: class CAR(StrEnum):
# Hyundai # Hyundai
AZERA_6TH_GEN = "HYUNDAI AZERA 6TH GEN" AZERA_6TH_GEN = "HYUNDAI AZERA 6TH GEN"
AZERA_HEV_6TH_GEN = "HYUNDAI AZERA HYBRID 6TH GEN" AZERA_HEV_6TH_GEN = "HYUNDAI AZERA HYBRID 6TH GEN"
@ -252,8 +252,8 @@ CAR_INFO: Dict[str, Optional[Union[HyundaiCarInfo, List[HyundaiCarInfo]]]] = {
CAR.KIA_SELTOS: HyundaiCarInfo("Kia Seltos 2021", car_parts=CarParts.common([CarHarness.hyundai_a])), CAR.KIA_SELTOS: HyundaiCarInfo("Kia Seltos 2021", car_parts=CarParts.common([CarHarness.hyundai_a])),
CAR.KIA_SPORTAGE_5TH_GEN: HyundaiCarInfo("Kia Sportage 2023", car_parts=CarParts.common([CarHarness.hyundai_n])), CAR.KIA_SPORTAGE_5TH_GEN: HyundaiCarInfo("Kia Sportage 2023", car_parts=CarParts.common([CarHarness.hyundai_n])),
CAR.KIA_SORENTO: [ CAR.KIA_SORENTO: [
HyundaiCarInfo("Kia Sorento 2018", "Advanced Smart Cruise Control", video_link="https://www.youtube.com/watch?v=Fkh3s6WHJz8", HyundaiCarInfo("Kia Sorento 2018", "Advanced Smart Cruise Control & LKAS", video_link="https://www.youtube.com/watch?v=Fkh3s6WHJz8",
car_parts=CarParts.common([CarHarness.hyundai_c])), car_parts=CarParts.common([CarHarness.hyundai_e])),
HyundaiCarInfo("Kia Sorento 2019", video_link="https://www.youtube.com/watch?v=Fkh3s6WHJz8", car_parts=CarParts.common([CarHarness.hyundai_e])), HyundaiCarInfo("Kia Sorento 2019", video_link="https://www.youtube.com/watch?v=Fkh3s6WHJz8", car_parts=CarParts.common([CarHarness.hyundai_e])),
], ],
CAR.KIA_SORENTO_4TH_GEN: HyundaiCarInfo("Kia Sorento 2021-23", car_parts=CarParts.common([CarHarness.hyundai_k])), CAR.KIA_SORENTO_4TH_GEN: HyundaiCarInfo("Kia Sorento 2021-23", car_parts=CarParts.common([CarHarness.hyundai_k])),
@ -400,8 +400,8 @@ def match_fw_to_car_fuzzy(live_fw_versions) -> Set[str]:
# to distinguish between hybrid and ICE. All EVs so far are either exclusively # to distinguish between hybrid and ICE. All EVs so far are either exclusively
# electric or specify electric in the platform code. # electric or specify electric in the platform code.
# TODO: whitelist platforms that we've seen hybrid and ICE versions of that have these specifiers # TODO: whitelist platforms that we've seen hybrid and ICE versions of that have these specifiers
fuzzy_platform_blacklist = set(CANFD_CAR - EV_CAR) fuzzy_platform_blacklist = {str(car) for car in set(CANFD_CAR - EV_CAR)}
candidates = set() candidates: Set[str] = set()
for candidate, fws in FW_VERSIONS.items(): for candidate, fws in FW_VERSIONS.items():
# Keep track of ECUs which pass all checks (platform codes, within date range) # Keep track of ECUs which pass all checks (platform codes, within date range)

@ -1,4 +1,5 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import StrEnum
from typing import Dict, List, Union from typing import Dict, List, Union
from cereal import car from cereal import car
@ -25,7 +26,7 @@ class CarControllerParams:
pass pass
class CAR: class CAR(StrEnum):
CX5 = "MAZDA CX-5" CX5 = "MAZDA CX-5"
CX9 = "MAZDA CX-9" CX9 = "MAZDA CX-9"
MAZDA3 = "MAZDA 3" MAZDA3 = "MAZDA 3"
@ -46,7 +47,7 @@ CAR_INFO: Dict[str, Union[MazdaCarInfo, List[MazdaCarInfo]]] = {
CAR.MAZDA3: MazdaCarInfo("Mazda 3 2017-18"), CAR.MAZDA3: MazdaCarInfo("Mazda 3 2017-18"),
CAR.MAZDA6: MazdaCarInfo("Mazda 6 2017-20"), CAR.MAZDA6: MazdaCarInfo("Mazda 6 2017-20"),
CAR.CX9_2021: MazdaCarInfo("Mazda CX-9 2021-23", video_link="https://youtu.be/dA3duO4a0O4"), CAR.CX9_2021: MazdaCarInfo("Mazda CX-9 2021-23", video_link="https://youtu.be/dA3duO4a0O4"),
CAR.CX5_2022: MazdaCarInfo("Mazda CX-5 2022-23"), CAR.CX5_2022: MazdaCarInfo("Mazda CX-5 2022-24"),
} }
@ -97,6 +98,7 @@ FW_VERSIONS = {
b'K131-67XK2-F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'K131-67XK2-F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
], ],
(Ecu.abs, 0x760, None): [ (Ecu.abs, 0x760, None): [
b'KGWD-437K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
b'KSD5-437K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'KSD5-437K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
], ],
(Ecu.fwdCamera, 0x706, None): [ (Ecu.fwdCamera, 0x706, None): [
@ -110,6 +112,7 @@ FW_VERSIONS = {
b'SH51-21PS1-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'SH51-21PS1-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
b'PXDL-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'PXDL-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
b'PXFG-21PS1-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'PXFG-21PS1-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
b'PXFG-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
], ],
}, },
CAR.CX5: { CAR.CX5: {

@ -1,9 +1,10 @@
from enum import StrEnum
from typing import Dict, List, Optional, Union from typing import Dict, List, Optional, Union
from openpilot.selfdrive.car.docs_definitions import CarInfo from openpilot.selfdrive.car.docs_definitions import CarInfo
class CAR: class CAR(StrEnum):
MOCK = 'mock' MOCK = 'mock'

@ -1,5 +1,6 @@
# ruff: noqa: E501 # ruff: noqa: E501
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import StrEnum
from typing import Dict, List, Optional, Union from typing import Dict, List, Optional, Union
from cereal import car from cereal import car
@ -21,7 +22,7 @@ class CarControllerParams:
pass pass
class CAR: class CAR(StrEnum):
XTRAIL = "NISSAN X-TRAIL 2017" XTRAIL = "NISSAN X-TRAIL 2017"
LEAF = "NISSAN LEAF 2018" LEAF = "NISSAN LEAF 2018"
# Leaf with ADAS ECU found behind instrument cluster instead of glovebox # Leaf with ADAS ECU found behind instrument cluster instead of glovebox

@ -1,5 +1,5 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum, IntFlag from enum import Enum, IntFlag, StrEnum
from typing import Dict, List, Union from typing import Dict, List, Union
from cereal import car from cereal import car
@ -63,7 +63,7 @@ class CanBus:
camera = 2 camera = 2
class CAR: class CAR(StrEnum):
# Global platform # Global platform
ASCENT = "SUBARU ASCENT LIMITED 2019" ASCENT = "SUBARU ASCENT LIMITED 2019"
ASCENT_2023 = "SUBARU ASCENT 2023" ASCENT_2023 = "SUBARU ASCENT 2023"
@ -114,7 +114,7 @@ CAR_INFO: Dict[str, Union[SubaruCarInfo, List[SubaruCarInfo]]] = {
SubaruCarInfo("Subaru XV 2020-21"), SubaruCarInfo("Subaru XV 2020-21"),
], ],
# TODO: is there an XV and Impreza too? # TODO: is there an XV and Impreza too?
CAR.CROSSTREK_HYBRID: SubaruCarInfo("Subaru Crosstrek Hybrid 2020"), CAR.CROSSTREK_HYBRID: SubaruCarInfo("Subaru Crosstrek Hybrid 2020", car_parts=CarParts.common([CarHarness.subaru_b])),
CAR.FORESTER_HYBRID: SubaruCarInfo("Subaru Forester Hybrid 2020"), CAR.FORESTER_HYBRID: SubaruCarInfo("Subaru Forester Hybrid 2020"),
CAR.FORESTER: SubaruCarInfo("Subaru Forester 2019-21", "All"), CAR.FORESTER: SubaruCarInfo("Subaru Forester 2019-21", "All"),
CAR.FORESTER_PREGLOBAL: SubaruCarInfo("Subaru Forester 2017-18"), CAR.FORESTER_PREGLOBAL: SubaruCarInfo("Subaru Forester 2017-18"),

@ -1,5 +1,6 @@
# ruff: noqa: E501 # ruff: noqa: E501
from collections import namedtuple from collections import namedtuple
from enum import StrEnum
from typing import Dict, List, Union from typing import Dict, List, Union
from cereal import car from cereal import car
@ -12,7 +13,7 @@ Ecu = car.CarParams.Ecu
Button = namedtuple('Button', ['event_type', 'can_addr', 'can_msg', 'values']) Button = namedtuple('Button', ['event_type', 'can_addr', 'can_msg', 'values'])
class CAR: class CAR(StrEnum):
AP1_MODELS = 'TESLA AP1 MODEL S' AP1_MODELS = 'TESLA AP1 MODEL S'
AP2_MODELS = 'TESLA AP2 MODEL S' AP2_MODELS = 'TESLA AP2 MODEL S'

@ -1,7 +1,7 @@
import re import re
from collections import defaultdict from collections import defaultdict
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum, IntFlag from enum import Enum, IntFlag, StrEnum
from typing import Dict, List, Set, Union from typing import Dict, List, Set, Union
from cereal import car from cereal import car
@ -46,7 +46,7 @@ class ToyotaFlags(IntFlag):
DISABLE_RADAR = 4 DISABLE_RADAR = 4
class CAR: class CAR(StrEnum):
# Toyota # Toyota
ALPHARD_TSS2 = "TOYOTA ALPHARD 2020" ALPHARD_TSS2 = "TOYOTA ALPHARD 2020"
ALPHARDH_TSS2 = "TOYOTA ALPHARD HYBRID 2021" ALPHARDH_TSS2 = "TOYOTA ALPHARD HYBRID 2021"
@ -131,7 +131,7 @@ CAR_INFO: Dict[str, Union[ToyotaCarInfo, List[ToyotaCarInfo]]] = {
CAR.CAMRY: ToyotaCarInfo("Toyota Camry 2018-20", video_link="https://www.youtube.com/watch?v=fkcjviZY9CM", footnotes=[Footnote.CAMRY]), CAR.CAMRY: ToyotaCarInfo("Toyota Camry 2018-20", video_link="https://www.youtube.com/watch?v=fkcjviZY9CM", footnotes=[Footnote.CAMRY]),
CAR.CAMRYH: ToyotaCarInfo("Toyota Camry Hybrid 2018-20", video_link="https://www.youtube.com/watch?v=Q2DYY0AWKgk"), CAR.CAMRYH: ToyotaCarInfo("Toyota Camry Hybrid 2018-20", video_link="https://www.youtube.com/watch?v=Q2DYY0AWKgk"),
CAR.CAMRY_TSS2: ToyotaCarInfo("Toyota Camry 2021-23", footnotes=[Footnote.CAMRY]), CAR.CAMRY_TSS2: ToyotaCarInfo("Toyota Camry 2021-23", footnotes=[Footnote.CAMRY]),
CAR.CAMRYH_TSS2: ToyotaCarInfo("Toyota Camry Hybrid 2021-23"), CAR.CAMRYH_TSS2: ToyotaCarInfo("Toyota Camry Hybrid 2021-24"),
CAR.CHR: ToyotaCarInfo("Toyota C-HR 2017-20"), CAR.CHR: ToyotaCarInfo("Toyota C-HR 2017-20"),
CAR.CHR_TSS2: ToyotaCarInfo("Toyota C-HR 2021"), CAR.CHR_TSS2: ToyotaCarInfo("Toyota C-HR 2021"),
CAR.CHRH: ToyotaCarInfo("Toyota C-HR Hybrid 2017-20"), CAR.CHRH: ToyotaCarInfo("Toyota C-HR Hybrid 2017-20"),
@ -361,7 +361,7 @@ FW_QUERY_CONFIG = FwQueryConfig(
[StdQueries.SHORT_TESTER_PRESENT_REQUEST, TOYOTA_VERSION_REQUEST_KWP], [StdQueries.SHORT_TESTER_PRESENT_REQUEST, TOYOTA_VERSION_REQUEST_KWP],
[StdQueries.SHORT_TESTER_PRESENT_RESPONSE, TOYOTA_VERSION_RESPONSE_KWP], [StdQueries.SHORT_TESTER_PRESENT_RESPONSE, TOYOTA_VERSION_RESPONSE_KWP],
whitelist_ecus=[Ecu.fwdCamera, Ecu.fwdRadar, Ecu.dsu, Ecu.abs, Ecu.eps, Ecu.epb, Ecu.telematics, whitelist_ecus=[Ecu.fwdCamera, Ecu.fwdRadar, Ecu.dsu, Ecu.abs, Ecu.eps, Ecu.epb, Ecu.telematics,
Ecu.hybrid, Ecu.srs, Ecu.combinationMeter, Ecu.transmission, Ecu.gateway, Ecu.hvac], Ecu.srs, Ecu.combinationMeter, Ecu.transmission, Ecu.gateway, Ecu.hvac],
bus=0, bus=0,
), ),
Request( Request(
@ -1694,6 +1694,7 @@ FW_VERSIONS = {
(Ecu.engine, 0x700, None): [ (Ecu.engine, 0x700, None): [
b'\x01896634A88100\x00\x00\x00\x00', b'\x01896634A88100\x00\x00\x00\x00',
b'\x01896634AJ2000\x00\x00\x00\x00', b'\x01896634AJ2000\x00\x00\x00\x00',
b'\x01896634A89100\x00\x00\x00\x00',
], ],
(Ecu.fwdRadar, 0x750, 0xf): [ (Ecu.fwdRadar, 0x750, 0xf): [
b'\x018821F0R03100\x00\x00\x00\x00', b'\x018821F0R03100\x00\x00\x00\x00',
@ -1793,6 +1794,7 @@ FW_VERSIONS = {
(Ecu.abs, 0x7b0, None): [ (Ecu.abs, 0x7b0, None): [
b'\x01F15264283200\x00\x00\x00\x00', b'\x01F15264283200\x00\x00\x00\x00',
b'\x01F15264283300\x00\x00\x00\x00', b'\x01F15264283300\x00\x00\x00\x00',
b'\x01F152642F1000\x00\x00\x00\x00',
], ],
(Ecu.eps, 0x7a1, None): [ (Ecu.eps, 0x7a1, None): [
b'\x028965B0R11000\x00\x00\x00\x008965B0R12000\x00\x00\x00\x00', b'\x028965B0R11000\x00\x00\x00\x008965B0R12000\x00\x00\x00\x00',
@ -1803,15 +1805,17 @@ FW_VERSIONS = {
b'\x01896634AF0000\x00\x00\x00\x00', b'\x01896634AF0000\x00\x00\x00\x00',
], ],
(Ecu.hybrid, 0x7d2, None): [ (Ecu.hybrid, 0x7d2, None): [
b'\x02899830R39000\x00\x00\x00\x00899850R20000\x00\x00\x00\x00',
b'\x02899830R41000\x00\x00\x00\x00899850R20000\x00\x00\x00\x00', b'\x02899830R41000\x00\x00\x00\x00899850R20000\x00\x00\x00\x00',
b'\x028998342C0000\x00\x00\x00\x00899854224000\x00\x00\x00\x00', b'\x028998342C0000\x00\x00\x00\x00899854224000\x00\x00\x00\x00',
b'\x02899830R39000\x00\x00\x00\x00899850R20000\x00\x00\x00\x00', b'\x028998342C6000\x00\x00\x00\x00899854224000\x00\x00\x00\x00',
], ],
(Ecu.fwdRadar, 0x750, 0xf): [ (Ecu.fwdRadar, 0x750, 0xf): [
b'\x018821F0R03100\x00\x00\x00\x00', b'\x018821F0R03100\x00\x00\x00\x00',
], ],
(Ecu.fwdCamera, 0x750, 0x6d): [ (Ecu.fwdCamera, 0x750, 0x6d): [
b'\x028646F0R05100\x00\x00\x00\x008646G0R02100\x00\x00\x00\x00', b'\x028646F0R05100\x00\x00\x00\x008646G0R02100\x00\x00\x00\x00',
b'\x028646F0R05200\x00\x00\x00\x008646G0R02200\x00\x00\x00\x00',
], ],
}, },
CAR.SIENNA: { CAR.SIENNA: {

@ -1,6 +1,6 @@
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum, StrEnum
from typing import Dict, List, Union from typing import Dict, List, Union
from cereal import car from cereal import car
@ -114,7 +114,7 @@ class CANBUS:
# FW_VERSIONS for that existing CAR. # FW_VERSIONS for that existing CAR.
# Exception: SEAT Leon and SEAT Ateca share a chassis code # Exception: SEAT Leon and SEAT Ateca share a chassis code
class CAR: class CAR(StrEnum):
ARTEON_MK1 = "VOLKSWAGEN ARTEON 1ST GEN" # Chassis AN, Mk1 VW Arteon and variants ARTEON_MK1 = "VOLKSWAGEN ARTEON 1ST GEN" # Chassis AN, Mk1 VW Arteon and variants
ATLAS_MK1 = "VOLKSWAGEN ATLAS 1ST GEN" # Chassis CA, Mk1 VW Atlas and Atlas Cross Sport ATLAS_MK1 = "VOLKSWAGEN ATLAS 1ST GEN" # Chassis CA, Mk1 VW Atlas and Atlas Cross Sport
CRAFTER_MK2 = "VOLKSWAGEN CRAFTER 2ND GEN" # Chassis SY/SZ, Mk2 VW Crafter, VW Grand California, MAN TGE CRAFTER_MK2 = "VOLKSWAGEN CRAFTER 2ND GEN" # Chassis SY/SZ, Mk2 VW Crafter, VW Grand California, MAN TGE
@ -774,15 +774,18 @@ FW_VERSIONS = {
(Ecu.engine, 0x7e0, None): [ (Ecu.engine, 0x7e0, None): [
b'\xf1\x8704E906027NJ\xf1\x891445', b'\xf1\x8704E906027NJ\xf1\x891445',
b'\xf1\x8704E906027NP\xf1\x891286', b'\xf1\x8704E906027NP\xf1\x891286',
b'\xf1\x8705E906013BD\xf1\x892496',
b'\xf1\x8705E906013E \xf1\x891624', b'\xf1\x8705E906013E \xf1\x891624',
], ],
(Ecu.transmission, 0x7e1, None): [ (Ecu.transmission, 0x7e1, None): [
b'\xf1\x8709G927158EM\xf1\x893812', b'\xf1\x8709G927158EM\xf1\x893812',
b'\xf1\x8709S927158BL\xf1\x893791', b'\xf1\x8709S927158BL\xf1\x893791',
b'\xf1\x8709S927158DN\xf1\x893946',
b'\xf1\x8709S927158FF\xf1\x893876', b'\xf1\x8709S927158FF\xf1\x893876',
], ],
(Ecu.srs, 0x715, None): [ (Ecu.srs, 0x715, None): [
b'\xf1\x875Q0959655CB\xf1\x890421\xf1\x82\x1311111111333500314646021450149333613100', b'\xf1\x875Q0959655CB\xf1\x890421\xf1\x82\x1311111111333500314646021450149333613100',
b'\xf1\x875Q0959655CB\xf1\x890421\xf1\x82\x1312111111333500314646021550159333613100',
b'\xf1\x875Q0959655CE\xf1\x890421\xf1\x82\x1311110011333300314240021350139333613100', b'\xf1\x875Q0959655CE\xf1\x890421\xf1\x82\x1311110011333300314240021350139333613100',
], ],
(Ecu.eps, 0x712, None): [ (Ecu.eps, 0x712, None): [

@ -0,0 +1,105 @@
#!/usr/bin/env python3
import argparse
from openpilot.common.basedir import BASEDIR
from openpilot.tools.lib.logreader import MultiLogIterator
from openpilot.tools.lib.route import Route
from openpilot.selfdrive.car.fw_versions import match_fw_to_car
from openpilot.selfdrive.car.interfaces import get_interface_attr
ALL_FW_VERSIONS = get_interface_attr("FW_VERSIONS")
ALL_CARS = get_interface_attr("CAR")
PLATFORM_TO_PYTHON_CAR_NAME = {brand: {car.value: car.name for car in ALL_CARS[brand]} for brand in ALL_CARS}
BRAND_TO_PLATFORMS = {brand: [car.value for car in ALL_CARS[brand]] for brand in ALL_CARS}
PLATFORM_TO_BRAND = dict(sum([[(platform, brand) for platform in BRAND_TO_PLATFORMS[brand]] for brand in BRAND_TO_PLATFORMS], []))
def add_fw_versions(brand, platform, new_fw_versions):
filename = f"{BASEDIR}/selfdrive/car/{brand}/values.py"
with open(filename, "r") as f:
values_py = f.read()
for key in new_fw_versions.keys():
ecu, addr, subAddr = key
fw_version = new_fw_versions[key]
platform_start = values_py.index(f"CAR.{PLATFORM_TO_PYTHON_CAR_NAME[brand][platform]}: {{")
start = values_py.index(f"(Ecu.{ecu}, {hex(addr)}, {subAddr}): [", platform_start)
try:
end_str = "],\n"
end = values_py.index(end_str, start)
except ValueError:
end_str = "]\n"
end = values_py.index(end_str, start)
values_py = values_py[:end] + f" {fw_version},\n " + values_py[end:]
with open(filename, "w") as f:
f.write(values_py)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Auto fingerprint from a route")
parser.add_argument("route", help="The route name to use")
parser.add_argument("platform", help="The platform, or leave empty to auto-determine using fuzzy", default=None, nargs='?')
args = parser.parse_args()
route = Route(args.route)
lr = MultiLogIterator(route.qlog_paths())
carFw = None
carVin = None
carPlatform = None
for msg in lr:
if msg.which() == "carParams":
carFw = msg.carParams.carFw
carVin = msg.carParams.carVin
carPlatform = msg.carParams.carFingerprint
break
if carFw is None:
raise Exception("No fw versions in the provided route...")
if args.platform is None: # attempt to auto-determine platform with other fuzzy fingerprints
_, possible_platforms = match_fw_to_car(carFw, log=False)
if len(possible_platforms) != 1:
print(f"Unable to auto-determine platform, possible platforms: {possible_platforms}")
if carPlatform != "mock":
print("Using platform from route")
platform = carPlatform
else:
raise Exception("unable to determine platform, try manually specifying the fingerprint.")
else:
platform = list(possible_platforms)[0]
else:
platform = args.platform
print("Attempting to add fw version for: ", platform)
brand = PLATFORM_TO_BRAND[platform]
new_fw_versions = {}
for fw in carFw:
if fw.brand == brand:
addr = fw.address
subAddr = None if fw.subAddress == 0 else fw.subAddress
key = (fw.ecu.raw, addr, subAddr)
if key in ALL_FW_VERSIONS[brand][platform]:
fw_versions = set(ALL_FW_VERSIONS[brand][platform][key])
if fw.fwVersion not in fw_versions:
new_fw_versions[(fw.ecu, addr, subAddr)] = fw.fwVersion
if not new_fw_versions:
print("No new fw versions found...")
add_fw_versions(brand, platform, new_fw_versions)

@ -62,6 +62,10 @@ SUPPORTED_FW_VERSIONS = {
b"TM__ SCC F-CUP 1.00 1.02 99110-S2000\x18\x07\x08\x18W ": ConfigValues( b"TM__ SCC F-CUP 1.00 1.02 99110-S2000\x18\x07\x08\x18W ": ConfigValues(
default_config=b"\x00\x00\x00\x01\x00\x00", default_config=b"\x00\x00\x00\x01\x00\x00",
tracks_enabled=b"\x00\x00\x00\x01\x00\x01"), tracks_enabled=b"\x00\x00\x00\x01\x00\x01"),
# 2021 K5 HEV
b"DLhe SCC FHCUP 1.00 1.02 99110-L7000 \x01 \x102 ": ConfigValues(
default_config=b"\x00\x00\x00\x01\x00\x00",
tracks_enabled=b"\x00\x00\x00\x01\x00\x01"),
} }
if __name__ == "__main__": if __name__ == "__main__":

@ -144,6 +144,7 @@ if __name__ == "__main__":
uds_client.write_data_by_identifier(VOLKSWAGEN_DATA_IDENTIFIER_TYPE.CODING, new_coding) # type: ignore uds_client.write_data_by_identifier(VOLKSWAGEN_DATA_IDENTIFIER_TYPE.CODING, new_coding) # type: ignore
except (NegativeResponseError, MessageTimeoutError): except (NegativeResponseError, MessageTimeoutError):
print("Writing new configuration failed!") print("Writing new configuration failed!")
print("Make sure the comma processes are stopped: tmux kill-session -t comma")
quit() quit()
try: try:

@ -1 +0,0 @@
../system/hardware/

@ -111,7 +111,7 @@ def main():
while not vipc_client_main.connect(False): while not vipc_client_main.connect(False):
time.sleep(0.1) time.sleep(0.1)
while not vipc_client_extra.connect(False): while use_extra_client and not vipc_client_extra.connect(False):
time.sleep(0.1) time.sleep(0.1)
cloudlog.warning(f"connected main cam with buffer size: {vipc_client_main.buffer_len} ({vipc_client_main.width} x {vipc_client_main.height})") cloudlog.warning(f"connected main cam with buffer size: {vipc_client_main.buffer_len} ({vipc_client_main.width} x {vipc_client_main.height})")

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:af5b47a763454cd56a9f16ebe51dbcf54a001898444a9557b39cedb2303d4da3 oid sha256:18e53fa5d0f9a185833d50fa0d777725ca715460062f3a2c050847588525d87c
size 52272357 size 52272467

@ -1,21 +0,0 @@
#!/usr/bin/env python3
import os
import time
from typing import NoReturn
from openpilot.common.realtime import set_core_affinity, set_realtime_priority
# RT shield - ensure CPU 3 always remains available for RT processes
# runs as SCHED_FIFO with minimum priority to ensure kthreads don't
# get scheduled onto CPU 3, but it's always preemptible by realtime
# openpilot processes
def main() -> NoReturn:
set_core_affinity([int(os.getenv("CORE", "3")), ])
set_realtime_priority(1)
while True:
time.sleep(0.000001)
if __name__ == "__main__":
main()

@ -5,6 +5,7 @@ import capnp
import numbers import numbers
import dictdiffer import dictdiffer
from collections import Counter from collections import Counter
from typing import Dict
from openpilot.tools.lib.logreader import LogReader from openpilot.tools.lib.logreader import LogReader
@ -89,7 +90,52 @@ def compare_logs(log1, log2, ignore_fields=None, ignore_msgs=None, tolerance=Non
return diff return diff
def format_diff(results, log_paths, ref_commit):
diff1, diff2 = "", ""
diff2 += f"***** tested against commit {ref_commit} *****\n"
failed = False
for segment, result in list(results.items()):
diff1 += f"***** results for segment {segment} *****\n"
diff2 += f"***** differences for segment {segment} *****\n"
for proc, diff in list(result.items()):
# long diff
diff2 += f"*** process: {proc} ***\n"
diff2 += f"\tref: {log_paths[segment][proc]['ref']}\n"
diff2 += f"\tnew: {log_paths[segment][proc]['new']}\n\n"
# short diff
diff1 += f" {proc}\n"
if isinstance(diff, str):
diff1 += f" ref: {log_paths[segment][proc]['ref']}\n"
diff1 += f" new: {log_paths[segment][proc]['new']}\n\n"
diff1 += f" {diff}\n"
failed = True
elif len(diff):
diff1 += f" ref: {log_paths[segment][proc]['ref']}\n"
diff1 += f" new: {log_paths[segment][proc]['new']}\n\n"
cnt: Dict[str, int] = {}
for d in diff:
diff2 += f"\t{str(d)}\n"
k = str(d[1])
cnt[k] = 1 if k not in cnt else cnt[k] + 1
for k, v in sorted(cnt.items()):
diff1 += f" {k}: {v}\n"
failed = True
return diff1, diff2, failed
if __name__ == "__main__": if __name__ == "__main__":
log1 = list(LogReader(sys.argv[1])) log1 = list(LogReader(sys.argv[1]))
log2 = list(LogReader(sys.argv[2])) log2 = list(LogReader(sys.argv[2]))
print(compare_logs(log1, log2, sys.argv[3:])) ignore_fields = sys.argv[3:] or ["logMonoTime", "controlsState.startMonoTime", "controlsState.cumLagMs"]
results = {"segment": {"proc": compare_logs(log1, log2, ignore_fields)}}
log_paths = {"segment": {"proc": {"ref": sys.argv[1], "new": sys.argv[2]}}}
diff1, diff2, failed = format_diff(results, log_paths, None)
print(diff2)
print(diff1)

@ -2,17 +2,95 @@ from collections import defaultdict
from cereal import messaging from cereal import messaging
from openpilot.selfdrive.test.process_replay.vision_meta import meta_from_encode_index from openpilot.selfdrive.test.process_replay.vision_meta import meta_from_encode_index
from openpilot.selfdrive.car.toyota.values import EPS_SCALE
from openpilot.selfdrive.manager.process_config import managed_processes
from panda import Panda
def migrate_all(lr, old_logtime=False, camera_states=False): def migrate_all(lr, old_logtime=False, manager_states=False, panda_states=False, camera_states=False):
msgs = migrate_sensorEvents(lr, old_logtime) msgs = migrate_sensorEvents(lr, old_logtime)
msgs = migrate_carParams(msgs, old_logtime) msgs = migrate_carParams(msgs, old_logtime)
if manager_states:
msgs = migrate_managerState(msgs)
if panda_states:
msgs = migrate_pandaStates(msgs)
msgs = migrate_peripheralState(msgs)
if camera_states: if camera_states:
msgs = migrate_cameraStates(msgs) msgs = migrate_cameraStates(msgs)
return msgs return msgs
def migrate_managerState(lr):
all_msgs = []
for msg in lr:
if msg.which() != "managerState":
all_msgs.append(msg)
continue
new_msg = msg.as_builder()
new_msg.managerState.processes = [{'name': name, 'running': True} for name in managed_processes]
all_msgs.append(new_msg.as_reader())
return all_msgs
def migrate_pandaStates(lr):
all_msgs = []
# TODO: safety param migration should be handled automatically
safety_param_migration = {
"TOYOTA PRIUS 2017": EPS_SCALE["TOYOTA PRIUS 2017"] | Panda.FLAG_TOYOTA_STOCK_LONGITUDINAL,
"TOYOTA RAV4 2017": EPS_SCALE["TOYOTA RAV4 2017"] | Panda.FLAG_TOYOTA_ALT_BRAKE,
"KIA EV6 2022": Panda.FLAG_HYUNDAI_EV_GAS | Panda.FLAG_HYUNDAI_CANFD_HDA2,
}
# Migrate safety param base on carState
CP = next((m.carParams for m in lr if m.which() == 'carParams'), None)
assert CP is not None, "carParams message not found"
if CP.carFingerprint in safety_param_migration:
safety_param = safety_param_migration[CP.carFingerprint]
elif len(CP.safetyConfigs):
safety_param = CP.safetyConfigs[0].safetyParam
if CP.safetyConfigs[0].safetyParamDEPRECATED != 0:
safety_param = CP.safetyConfigs[0].safetyParamDEPRECATED
else:
safety_param = CP.safetyParamDEPRECATED
for msg in lr:
if msg.which() == 'pandaStateDEPRECATED':
new_msg = messaging.new_message('pandaStates', 1)
new_msg.valid = msg.valid
new_msg.logMonoTime = msg.logMonoTime
new_msg.pandaStates[0] = msg.pandaStateDEPRECATED
new_msg.pandaStates[0].safetyParam = safety_param
all_msgs.append(new_msg.as_reader())
elif msg.which() == 'pandaStates':
new_msg = msg.as_builder()
new_msg.pandaStates[-1].safetyParam = safety_param
all_msgs.append(new_msg.as_reader())
else:
all_msgs.append(msg)
return all_msgs
def migrate_peripheralState(lr):
if any(msg.which() == "peripheralState" for msg in lr):
return lr
all_msg = []
for msg in lr:
all_msg.append(msg)
if msg.which() not in ["pandaStates", "pandaStateDEPRECATED"]:
continue
new_msg = messaging.new_message("peripheralState")
new_msg.logMonoTime = msg.logMonoTime
all_msg.append(new_msg.as_reader())
return all_msg
def migrate_cameraStates(lr): def migrate_cameraStates(lr):
all_msgs = [] all_msgs = []
frame_to_encode_id = defaultdict(dict) frame_to_encode_id = defaultdict(dict)
@ -42,7 +120,11 @@ def migrate_cameraStates(lr):
new_camera_state = getattr(new_msg, new_msg.which()) new_camera_state = getattr(new_msg, new_msg.which())
new_camera_state.frameId = encode_id new_camera_state.frameId = encode_id
new_camera_state.encodeId = encode_id new_camera_state.encodeId = encode_id
new_camera_state.timestampSof = camera_state.timestampSof # timestampSof was added later so it might be missing on some old segments
if camera_state.timestampSof == 0 and camera_state.timestampEof > 25000000:
new_camera_state.timestampSof = camera_state.timestampEof - 18000000
else:
new_camera_state.timestampSof = camera_state.timestampSof
new_camera_state.timestampEof = camera_state.timestampEof new_camera_state.timestampEof = camera_state.timestampEof
new_msg.logMonoTime = msg.logMonoTime new_msg.logMonoTime = msg.logMonoTime
new_msg.valid = msg.valid new_msg.valid = msg.valid

@ -10,8 +10,7 @@ from openpilot.common.params import Params
from openpilot.system.hardware import PC from openpilot.system.hardware import PC
from openpilot.selfdrive.manager.process_config import managed_processes from openpilot.selfdrive.manager.process_config import managed_processes
from openpilot.selfdrive.test.openpilotci import BASE_URL, get_url from openpilot.selfdrive.test.openpilotci import BASE_URL, get_url
from openpilot.selfdrive.test.process_replay.compare_logs import compare_logs from openpilot.selfdrive.test.process_replay.compare_logs import compare_logs, format_diff
from openpilot.selfdrive.test.process_replay.test_processes import format_diff
from openpilot.selfdrive.test.process_replay.process_replay import get_process_config, replay_process from openpilot.selfdrive.test.process_replay.process_replay import get_process_config, replay_process
from openpilot.system.version import get_commit from openpilot.system.version import get_commit
from openpilot.tools.lib.framereader import FrameReader from openpilot.tools.lib.framereader import FrameReader

@ -1 +1 @@
3bb23e270a3a7219cfeedadd8d085c32fc571c0d ed2d58ec217fafb7b6b8f5e27ec622acd9e734f4

@ -204,7 +204,7 @@ class ProcessContainer:
def _setup_vision_ipc(self, all_msgs): def _setup_vision_ipc(self, all_msgs):
assert len(self.cfg.vision_pubs) != 0 assert len(self.cfg.vision_pubs) != 0
device_type = next(msg.initData.deviceType for msg in all_msgs if msg.which() == "initData") device_type = next(str(msg.initData.deviceType) for msg in all_msgs if msg.which() == "initData")
vipc_server = VisionIpcServer("camerad") vipc_server = VisionIpcServer("camerad")
streams_metas = available_streams(all_msgs) streams_metas = available_streams(all_msgs)
@ -214,6 +214,7 @@ class ProcessContainer:
vipc_server.start_listener() vipc_server.start_listener()
self.vipc_server = vipc_server self.vipc_server = vipc_server
self.cfg.vision_pubs = [meta.camera_state for meta in streams_metas if meta.camera_state in self.cfg.vision_pubs]
def _start_process(self): def _start_process(self):
if self.capture is not None: if self.capture is not None:
@ -393,9 +394,8 @@ class ModeldCameraSyncRcvCallback:
self.is_dual_camera = True self.is_dual_camera = True
def __call__(self, msg, cfg, frame): def __call__(self, msg, cfg, frame):
if msg.which() == "initData": self.is_dual_camera = len(cfg.vision_pubs) == 2
self.is_dual_camera = msg.initData.deviceType in ["tici", "tizi"] if msg.which() == "roadCameraState":
elif msg.which() == "roadCameraState":
self.road_present = True self.road_present = True
elif msg.which() == "wideRoadCameraState": elif msg.which() == "wideRoadCameraState":
self.wide_road_present = True self.wide_road_present = True
@ -653,7 +653,10 @@ def replay_process(
else: else:
cfgs = [cfg] cfgs = [cfg]
all_msgs = migrate_all(lr, old_logtime=True, camera_states=any(len(cfg.vision_pubs) != 0 for cfg in cfgs)) all_msgs = migrate_all(lr, old_logtime=True,
manager_states=True,
panda_states=any("pandaStates" in cfg.pubs for cfg in cfgs),
camera_states=any(len(cfg.vision_pubs) != 0 for cfg in cfgs))
process_logs = _replay_multi_process(cfgs, all_msgs, frs, fingerprint, custom_params, captured_output_store, disable_progress) process_logs = _replay_multi_process(cfgs, all_msgs, frs, fingerprint, custom_params, captured_output_store, disable_progress)
if return_all_logs: if return_all_logs:
@ -681,14 +684,13 @@ def _replay_multi_process(
env_config = generate_environ_config(CP=CP) env_config = generate_environ_config(CP=CP)
# validate frs and vision pubs # validate frs and vision pubs
for cfg in cfgs: all_vision_pubs = [pub for cfg in cfgs for pub in cfg.vision_pubs]
if len(cfg.vision_pubs) == 0: if len(all_vision_pubs) != 0:
continue
assert frs is not None, "frs must be provided when replaying process using vision streams" assert frs is not None, "frs must be provided when replaying process using vision streams"
assert all(meta_from_camera_state(st) is not None for st in cfg.vision_pubs),\ assert all(meta_from_camera_state(st) is not None for st in all_vision_pubs), \
f"undefined vision stream spotted, probably misconfigured process: {cfg.vision_pubs}" f"undefined vision stream spotted, probably misconfigured process: (vision pubs: {all_vision_pubs})"
assert all(st in frs for st in cfg.vision_pubs), f"frs for this process must contain following vision streams: {cfg.vision_pubs}" required_vision_pubs = {m.camera_state for m in available_streams(lr)} & set(all_vision_pubs)
assert all(st in frs for st in required_vision_pubs), f"frs for this process must contain following vision streams: {required_vision_pubs}"
all_msgs = sorted(lr, key=lambda msg: msg.logMonoTime) all_msgs = sorted(lr, key=lambda msg: msg.logMonoTime)
log_msgs = [] log_msgs = []

@ -6,8 +6,8 @@ import capnp
from typing import Union, Iterable, Optional, List, Any, Dict, Tuple from typing import Union, Iterable, Optional, List, Any, Dict, Tuple
from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS, FAKEDATA, replay_process, get_process_config, \ from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS, FAKEDATA, ProcessConfig, replay_process, get_process_config, \
check_openpilot_enabled, get_custom_params_from_lr check_openpilot_enabled, get_custom_params_from_lr
from openpilot.selfdrive.test.update_ci_routes import upload_route from openpilot.selfdrive.test.update_ci_routes import upload_route
from openpilot.tools.lib.route import Route from openpilot.tools.lib.route import Route
from openpilot.tools.lib.framereader import FrameReader from openpilot.tools.lib.framereader import FrameReader
@ -17,62 +17,68 @@ from openpilot.tools.lib.helpers import save_log
def regen_segment( def regen_segment(
lr: Union[LogReader, List[capnp._DynamicStructReader]], frs: Optional[Dict[str, Any]] = None, lr: Union[LogReader, List[capnp._DynamicStructReader]], frs: Optional[Dict[str, Any]] = None,
daemons: Union[str, Iterable[str]] = "all", disable_tqdm: bool = False processes: Iterable[ProcessConfig] = CONFIGS, disable_tqdm: bool = False
) -> List[capnp._DynamicStructReader]: ) -> List[capnp._DynamicStructReader]:
if not isinstance(daemons, str) and not hasattr(daemons, "__iter__"):
raise ValueError("whitelist_proc must be a string or iterable")
all_msgs = sorted(lr, key=lambda m: m.logMonoTime) all_msgs = sorted(lr, key=lambda m: m.logMonoTime)
custom_params = get_custom_params_from_lr(all_msgs) custom_params = get_custom_params_from_lr(all_msgs)
if daemons != "all": print("Replayed processes:", [p.proc_name for p in processes])
if isinstance(daemons, str):
raise ValueError(f"Invalid value for daemons: {daemons}")
replayed_processes = []
for d in daemons:
cfg = get_process_config(d)
replayed_processes.append(cfg)
else:
replayed_processes = CONFIGS
print("Replayed processes:", [p.proc_name for p in replayed_processes])
print("\n\n", "*"*30, "\n\n", sep="") print("\n\n", "*"*30, "\n\n", sep="")
output_logs = replay_process(replayed_processes, all_msgs, frs, return_all_logs=True, custom_params=custom_params, disable_progress=disable_tqdm) output_logs = replay_process(processes, all_msgs, frs, return_all_logs=True, custom_params=custom_params, disable_progress=disable_tqdm)
return output_logs return output_logs
def setup_data_readers(route: str, sidx: int, use_route_meta: bool) -> Tuple[LogReader, Dict[str, Any]]: def setup_data_readers(
route: str, sidx: int, use_route_meta: bool, needs_driver_cam: bool = True, needs_road_cam: bool = True
) -> Tuple[LogReader, Dict[str, Any]]:
if use_route_meta: if use_route_meta:
r = Route(route) r = Route(route)
lr = LogReader(r.log_paths()[sidx]) lr = LogReader(r.log_paths()[sidx])
frs = {} frs = {}
if len(r.camera_paths()) > sidx and r.camera_paths()[sidx] is not None: if needs_road_cam and len(r.camera_paths()) > sidx and r.camera_paths()[sidx] is not None:
frs['roadCameraState'] = FrameReader(r.camera_paths()[sidx]) frs['roadCameraState'] = FrameReader(r.camera_paths()[sidx])
if len(r.ecamera_paths()) > sidx and r.ecamera_paths()[sidx] is not None: if needs_road_cam and len(r.ecamera_paths()) > sidx and r.ecamera_paths()[sidx] is not None:
frs['wideCameraState'] = FrameReader(r.ecamera_paths()[sidx]) frs['wideRoadCameraState'] = FrameReader(r.ecamera_paths()[sidx])
if len(r.dcamera_paths()) > sidx and r.dcamera_paths()[sidx] is not None: if needs_driver_cam and len(r.dcamera_paths()) > sidx and r.dcamera_paths()[sidx] is not None:
frs['driverCameraState'] = FrameReader(r.dcamera_paths()[sidx]) frs['driverCameraState'] = FrameReader(r.dcamera_paths()[sidx])
else: else:
lr = LogReader(f"cd:/{route.replace('|', '/')}/{sidx}/rlog.bz2") lr = LogReader(f"cd:/{route.replace('|', '/')}/{sidx}/rlog.bz2")
frs = { frs = {}
'roadCameraState': FrameReader(f"cd:/{route.replace('|', '/')}/{sidx}/fcamera.hevc"), if needs_road_cam:
'driverCameraState': FrameReader(f"cd:/{route.replace('|', '/')}/{sidx}/dcamera.hevc"), frs['roadCameraState'] = FrameReader(f"cd:/{route.replace('|', '/')}/{sidx}/fcamera.hevc")
} if next((True for m in lr if m.which() == "wideRoadCameraState"), False):
if next((True for m in lr if m.which() == "wideRoadCameraState"), False): frs['wideRoadCameraState'] = FrameReader(f"cd:/{route.replace('|', '/')}/{sidx}/ecamera.hevc")
frs['wideRoadCameraState'] = FrameReader(f"cd:/{route.replace('|', '/')}/{sidx}/ecamera.hevc") if needs_driver_cam:
frs['driverCameraState'] = FrameReader(f"cd:/{route.replace('|', '/')}/{sidx}/dcamera.hevc")
return lr, frs return lr, frs
def regen_and_save( def regen_and_save(
route: str, sidx: int, daemons: Union[str, Iterable[str]] = "all", outdir: str = FAKEDATA, route: str, sidx: int, processes: Union[str, Iterable[str]] = "all", outdir: str = FAKEDATA,
upload: bool = False, use_route_meta: bool = False, disable_tqdm: bool = False upload: bool = False, use_route_meta: bool = False, disable_tqdm: bool = False
) -> str: ) -> str:
lr, frs = setup_data_readers(route, sidx, use_route_meta) if not isinstance(processes, str) and not hasattr(processes, "__iter__"):
output_logs = regen_segment(lr, frs, daemons, disable_tqdm=disable_tqdm) raise ValueError("whitelist_proc must be a string or iterable")
if processes != "all":
if isinstance(processes, str):
raise ValueError(f"Invalid value for processes: {processes}")
replayed_processes = []
for d in processes:
cfg = get_process_config(d)
replayed_processes.append(cfg)
else:
replayed_processes = CONFIGS
all_vision_pubs = {pub for cfg in replayed_processes for pub in cfg.vision_pubs}
lr, frs = setup_data_readers(route, sidx, use_route_meta,
needs_driver_cam="driverCameraState" in all_vision_pubs,
needs_road_cam="roadCameraState" in all_vision_pubs or "wideRoadCameraState" in all_vision_pubs)
output_logs = regen_segment(lr, frs, replayed_processes, disable_tqdm=disable_tqdm)
log_dir = os.path.join(outdir, time.strftime("%Y-%m-%d--%H-%M-%S--0", time.gmtime())) log_dir = os.path.join(outdir, time.strftime("%Y-%m-%d--%H-%M-%S--0", time.gmtime()))
rel_log_dir = os.path.relpath(log_dir) rel_log_dir = os.path.relpath(log_dir)
@ -110,5 +116,5 @@ if __name__ == "__main__":
args = parser.parse_args() args = parser.parse_args()
blacklist_set = set(args.blacklist_procs) blacklist_set = set(args.blacklist_procs)
daemons = [p for p in args.whitelist_procs if p not in blacklist_set] processes = [p for p in args.whitelist_procs if p not in blacklist_set]
regen_and_save(args.route, args.seg, daemons=daemons, upload=args.upload, outdir=args.outdir) regen_and_save(args.route, args.seg, processes=processes, upload=args.upload, outdir=args.outdir)

@ -9,7 +9,7 @@ from typing import Any, DefaultDict, Dict
from openpilot.selfdrive.car.car_helpers import interface_names from openpilot.selfdrive.car.car_helpers import interface_names
from openpilot.selfdrive.test.openpilotci import get_url, upload_file from openpilot.selfdrive.test.openpilotci import get_url, upload_file
from openpilot.selfdrive.test.process_replay.compare_logs import compare_logs from openpilot.selfdrive.test.process_replay.compare_logs import compare_logs, format_diff
from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS, PROC_REPLAY_DIR, FAKEDATA, check_openpilot_enabled, replay_process from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS, PROC_REPLAY_DIR, FAKEDATA, check_openpilot_enabled, replay_process
from openpilot.system.version import get_commit from openpilot.system.version import get_commit
from openpilot.tools.lib.filereader import FileReader from openpilot.tools.lib.filereader import FileReader
@ -115,45 +115,6 @@ def test_process(cfg, lr, segment, ref_log_path, new_log_path, ignore_fields=Non
return str(e), log_msgs return str(e), log_msgs
def format_diff(results, log_paths, ref_commit):
diff1, diff2 = "", ""
diff2 += f"***** tested against commit {ref_commit} *****\n"
failed = False
for segment, result in list(results.items()):
diff1 += f"***** results for segment {segment} *****\n"
diff2 += f"***** differences for segment {segment} *****\n"
for proc, diff in list(result.items()):
# long diff
diff2 += f"*** process: {proc} ***\n"
diff2 += f"\tref: {log_paths[segment][proc]['ref']}\n"
diff2 += f"\tnew: {log_paths[segment][proc]['new']}\n\n"
# short diff
diff1 += f" {proc}\n"
if isinstance(diff, str):
diff1 += f" ref: {log_paths[segment][proc]['ref']}\n"
diff1 += f" new: {log_paths[segment][proc]['new']}\n\n"
diff1 += f" {diff}\n"
failed = True
elif len(diff):
diff1 += f" ref: {log_paths[segment][proc]['ref']}\n"
diff1 += f" new: {log_paths[segment][proc]['new']}\n\n"
cnt: Dict[str, int] = {}
for d in diff:
diff2 += f"\t{str(d)}\n"
k = str(d[1])
cnt[k] = 1 if k not in cnt else cnt[k] + 1
for k, v in sorted(cnt.items()):
diff1 += f" {k}: {v}\n"
failed = True
return diff1, diff2, failed
if __name__ == "__main__": if __name__ == "__main__":
all_cars = {car for car, _ in segments} all_cars = {car for car, _ in segments}
all_procs = {cfg.proc_name for cfg in CONFIGS if cfg.proc_name not in EXCLUDED_PROCS} all_procs = {cfg.proc_name for cfg in CONFIGS if cfg.proc_name not in EXCLUDED_PROCS}

@ -4,9 +4,9 @@ from openpilot.common.realtime import DT_MDL, DT_DMON
from openpilot.common.transformations.camera import tici_f_frame_size, tici_d_frame_size, tici_e_frame_size, eon_f_frame_size, eon_d_frame_size from openpilot.common.transformations.camera import tici_f_frame_size, tici_d_frame_size, tici_e_frame_size, eon_f_frame_size, eon_d_frame_size
VideoStreamMeta = namedtuple("VideoStreamMeta", ["camera_state", "encode_index", "stream", "dt", "frame_sizes"]) VideoStreamMeta = namedtuple("VideoStreamMeta", ["camera_state", "encode_index", "stream", "dt", "frame_sizes"])
ROAD_CAMERA_FRAME_SIZES = {"tici": tici_f_frame_size, "tizi": tici_f_frame_size, "eon": eon_f_frame_size} ROAD_CAMERA_FRAME_SIZES = {"tici": tici_f_frame_size, "tizi": tici_f_frame_size, "neo": eon_f_frame_size}
WIDE_ROAD_CAMERA_FRAME_SIZES = {"tici": tici_e_frame_size, "tizi": tici_e_frame_size} WIDE_ROAD_CAMERA_FRAME_SIZES = {"tici": tici_e_frame_size, "tizi": tici_e_frame_size}
DRIVER_FRAME_SIZES = {"tici": tici_d_frame_size, "tizi": tici_d_frame_size, "eon": eon_d_frame_size} DRIVER_FRAME_SIZES = {"tici": tici_d_frame_size, "tizi": tici_d_frame_size, "neo": eon_d_frame_size}
VIPC_STREAM_METADATA = [ VIPC_STREAM_METADATA = [
# metadata: (state_msg_type, encode_msg_type, stream_type, dt, frame_sizes) # metadata: (state_msg_type, encode_msg_type, stream_type, dt, frame_sizes)
("roadCameraState", "roadEncodeIdx", VisionStreamType.VISION_STREAM_ROAD, DT_MDL, ROAD_CAMERA_FRAME_SIZES), ("roadCameraState", "roadEncodeIdx", VisionStreamType.VISION_STREAM_ROAD, DT_MDL, ROAD_CAMERA_FRAME_SIZES),

@ -41,8 +41,6 @@ const char frame_fragment_shader[] =
"out vec4 colorOut;\n" "out vec4 colorOut;\n"
"void main() {\n" "void main() {\n"
" colorOut = texture(uTexture, vTexCoord);\n" " colorOut = texture(uTexture, vTexCoord);\n"
// gamma to improve worst case visibility when dark
" colorOut.rgb = pow(colorOut.rgb, vec3(1.0/1.28));\n"
"}\n"; "}\n";
#else #else
const char frame_fragment_shader[] = const char frame_fragment_shader[] =

@ -26,7 +26,7 @@ class InputDialog : public DialogBase {
public: public:
explicit InputDialog(const QString &title, QWidget *parent, const QString &subtitle = "", bool secret = false); explicit InputDialog(const QString &title, QWidget *parent, const QString &subtitle = "", bool secret = false);
static QString getText(const QString &title, QWidget *parent, const QString &substitle = "", static QString getText(const QString &title, QWidget *parent, const QString &subtitle = "",
bool secret = false, int minLength = -1, const QString &defaultText = ""); bool secret = false, int minLength = -1, const QString &defaultText = "");
QString text(); QString text();
void setMessage(const QString &message, bool clearInputField = true); void setMessage(const QString &message, bool clearInputField = true);

@ -114,6 +114,13 @@ class TestTranslations(unittest.TestCase):
self.assertFalse(line.strip().startswith(LOCATION_TAG), self.assertFalse(line.strip().startswith(LOCATION_TAG),
f"Line contains location tag: {line.strip()}, remove all line numbers.") f"Line contains location tag: {line.strip()}, remove all line numbers.")
def test_entities_error(self):
for name, file in self.translation_files.items():
with self.subTest(name=name, file=file):
cur_translations = self._read_translation_file(TRANSLATIONS_DIR, file)
matches = re.findall(r'@(\w+);', cur_translations)
self.assertEqual(len(matches), 0, f"The string(s) {matches} were found with '@' instead of '&'")
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

File diff suppressed because it is too large Load Diff

@ -1,7 +1,7 @@
import os import os
from pathlib import Path from pathlib import Path
from openpilot.selfdrive.hardware import PC from openpilot.system.hardware import PC
class Paths: class Paths:
@staticmethod @staticmethod

@ -1,105 +0,0 @@
#!/usr/bin/env python3
import os
import time
import numpy as np
from openpilot.system.hardware.tici.hardware import Tici
from openpilot.system.hardware.tici.pins import GPIO
from openpilot.common.gpio import gpio_init, gpio_set, gpio_export
def read_power():
with open("/sys/bus/i2c/devices/0-0040/hwmon/hwmon1/in1_input") as f:
voltage_total = int(f.read()) / 1000.
with open("/sys/bus/i2c/devices/0-0040/hwmon/hwmon1/curr1_input") as f:
current_total = int(f.read())
with open("/sys/class/power_supply/bms/voltage_now") as f:
voltage = int(f.read()) / 1e6 # volts
with open("/sys/class/power_supply/bms/current_now") as f:
current = int(f.read()) / 1e3 # ma
power_som = voltage*current
power_total = voltage_total*current_total
return power_total, power_som
def read_power_avg():
pwrs = []
for _ in range(100):
pwrs.append(read_power())
time.sleep(0.01)
power_total, power_som = np.mean([x[0] for x in pwrs]), np.mean([x[1] for x in pwrs])
return "total %7.2f mW SOM %7.2f mW" % (power_total, power_som)
if __name__ == "__main__":
gpio_export(GPIO.CAM0_AVDD_EN)
gpio_export(GPIO.CAM0_RSTN)
gpio_export(GPIO.CAM1_RSTN)
gpio_export(GPIO.CAM2_RSTN)
print("hello")
os.system('kill $(pgrep -f "manager.py")')
os.system('kill $(pgrep -f "python -m selfdrive.athena.manage_athenad")')
os.system('kill $(pgrep -f "selfdrive.athena.athenad")')
# stopping weston turns off lcd3v3
os.system("sudo service weston stop")
os.system("sudo service ModemManager stop")
print("services stopped")
t = Tici()
t.initialize_hardware()
t.set_power_save(True)
t.set_screen_brightness(0)
gpio_init(GPIO.STM_RST_N, True)
gpio_init(GPIO.HUB_RST_N, True)
gpio_init(GPIO.GNSS_PWR_EN, True)
gpio_init(GPIO.LTE_RST_N, True)
gpio_init(GPIO.LTE_PWRKEY, True)
gpio_init(GPIO.CAM0_AVDD_EN, True)
gpio_init(GPIO.CAM0_RSTN, True)
gpio_init(GPIO.CAM1_RSTN, True)
gpio_init(GPIO.CAM2_RSTN, True)
os.system("sudo su -c 'echo 0 > /sys/kernel/debug/regulator/camera_rear_ldo/enable'") # cam 1v2 off
gpio_set(GPIO.CAM0_AVDD_EN, False) # cam 2v8 off
gpio_set(GPIO.LTE_RST_N, True) # quectel off
gpio_set(GPIO.GNSS_PWR_EN, False) # gps off
gpio_set(GPIO.STM_RST_N, True) # panda off
gpio_set(GPIO.HUB_RST_N, False) # hub off
# cameras in reset
gpio_set(GPIO.CAM0_RSTN, False)
gpio_set(GPIO.CAM1_RSTN, False)
gpio_set(GPIO.CAM2_RSTN, False)
time.sleep(8)
print("baseline: ", read_power_avg())
gpio_set(GPIO.CAM0_AVDD_EN, True)
time.sleep(2)
print("cam avdd: ", read_power_avg())
os.system("sudo su -c 'echo 1 > /sys/kernel/debug/regulator/camera_rear_ldo/enable'")
time.sleep(2)
print("cam dvdd: ", read_power_avg())
gpio_set(GPIO.CAM0_RSTN, True)
gpio_set(GPIO.CAM1_RSTN, True)
gpio_set(GPIO.CAM2_RSTN, True)
time.sleep(2)
print("cams up: ", read_power_avg())
gpio_set(GPIO.HUB_RST_N, True)
time.sleep(2)
print("usb hub: ", read_power_avg())
gpio_set(GPIO.STM_RST_N, False)
time.sleep(5)
print("panda: ", read_power_avg())
gpio_set(GPIO.GNSS_PWR_EN, True)
time.sleep(5)
print("gps: ", read_power_avg())
gpio_set(GPIO.LTE_RST_N, False)
time.sleep(1)
gpio_set(GPIO.LTE_PWRKEY, True)
time.sleep(1)
gpio_set(GPIO.LTE_PWRKEY, False)
time.sleep(5)
print("quectel: ", read_power_avg())

@ -1,7 +1,7 @@
import os import os
from pathlib import Path from pathlib import Path
from openpilot.system.hardware import PC from openpilot.system.hardware import PC
from openpilot.selfdrive.hardware.hw import Paths from openpilot.system.hardware.hw import Paths
CAMERA_FPS = 20 CAMERA_FPS = 20

@ -16,7 +16,7 @@ from openpilot.common.timeout import Timeout
from openpilot.system.hardware import TICI from openpilot.system.hardware import TICI
from openpilot.selfdrive.manager.process_config import managed_processes from openpilot.selfdrive.manager.process_config import managed_processes
from openpilot.tools.lib.logreader import LogReader from openpilot.tools.lib.logreader import LogReader
from openpilot.selfdrive.hardware.hw import Paths from openpilot.system.hardware.hw import Paths
SEGMENT_LENGTH = 2 SEGMENT_LENGTH = 2
FULL_SIZE = 2507572 FULL_SIZE = 2507572

@ -164,12 +164,12 @@ def initialize_pigeon(pigeon: TTYPigeon) -> bool:
pigeon.send_with_ack(b"\xB5\x62\x06\x08\x06\x00\x64\x00\x01\x00\x00\x00\x79\x10") pigeon.send_with_ack(b"\xB5\x62\x06\x08\x06\x00\x64\x00\x01\x00\x00\x00\x79\x10")
# UBX-CFG-NAV5 (0x06 0x24) # UBX-CFG-NAV5 (0x06 0x24)
pigeon.send_with_ack(b"\xB5\x62\x06\x24\x24\x00\x05\x00\x04\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5A\x63") # noqa: E501 pigeon.send_with_ack(b"\xB5\x62\x06\x24\x24\x00\x05\x00\x04\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5A\x63")
# UBX-CFG-ODO (0x06 0x1E) # UBX-CFG-ODO (0x06 0x1E)
pigeon.send_with_ack(b"\xB5\x62\x06\x1E\x14\x00\x00\x00\x00\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3C\x37") pigeon.send_with_ack(b"\xB5\x62\x06\x1E\x14\x00\x00\x00\x00\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3C\x37")
pigeon.send_with_ack(b"\xB5\x62\x06\x39\x08\x00\xFF\xAD\x62\xAD\x1E\x63\x00\x00\x83\x0C") pigeon.send_with_ack(b"\xB5\x62\x06\x39\x08\x00\xFF\xAD\x62\xAD\x1E\x63\x00\x00\x83\x0C")
pigeon.send_with_ack(b"\xB5\x62\x06\x23\x28\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x56\x24") # noqa: E501 pigeon.send_with_ack(b"\xB5\x62\x06\x23\x28\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x56\x24")
# UBX-CFG-NAV5 (0x06 0x24) # UBX-CFG-NAV5 (0x06 0x24)
pigeon.send_with_ack(b"\xB5\x62\x06\x24\x00\x00\x2A\x84") pigeon.send_with_ack(b"\xB5\x62\x06\x24\x00\x00\x2A\x84")

@ -1,134 +1,134 @@
/* /*
* This file is part of qpOASES. * This file is part of qpOASES.
* *
* qpOASES -- An Implementation of the Online Active Set Strategy. * qpOASES -- An Implementation of the Online Active Set Strategy.
* Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka,
* Christian Kirches et al. All rights reserved. * Christian Kirches et al. All rights reserved.
* *
* qpOASES is free software; you can redistribute it and/or * qpOASES is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* qpOASES is distributed in the hope that it will be useful, * qpOASES is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with qpOASES; if not, write to the Free Software * License along with qpOASES; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
*/ */
/** /**
* \file include/qpOASES_e/Constants.h * \file include/qpOASES_e/Constants.h
* \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches
* \version 3.1embedded * \version 3.1embedded
* \date 2007-2015 * \date 2007-2015
* *
* Definition of all global constants. * Definition of all global constants.
*/ */
#ifndef QPOASES_CONSTANTS_H #ifndef QPOASES_CONSTANTS_H
#define QPOASES_CONSTANTS_H #define QPOASES_CONSTANTS_H
#include <qpOASES_e/Types.h> #include <qpOASES_e/Types.h>
#ifdef __CODE_GENERATION__ #ifdef __CODE_GENERATION__
#define CONVERTTOSTRINGAUX(x) #x #define CONVERTTOSTRINGAUX(x) #x
#define CONVERTTOSTRING(x) CONVERTTOSTRINGAUX(x) #define CONVERTTOSTRING(x) CONVERTTOSTRINGAUX(x)
#ifndef QPOASES_CUSTOM_INTERFACE #ifndef QPOASES_CUSTOM_INTERFACE
#include "acado_qpoases3_interface.h" #include "acado_qpoases3_interface.h"
#else #else
#include CONVERTTOSTRING(QPOASES_CUSTOM_INTERFACE) #include CONVERTTOSTRING(QPOASES_CUSTOM_INTERFACE)
#endif #endif
#endif #endif
BEGIN_NAMESPACE_QPOASES BEGIN_NAMESPACE_QPOASES
#ifndef __EXTERNAL_DIMENSIONS__ #ifndef __EXTERNAL_DIMENSIONS__
/*#define QPOASES_NVMAX 50 /*#define QPOASES_NVMAX 50
#define QPOASES_NCMAX 100*/ #define QPOASES_NCMAX 100*/
#define QPOASES_NVMAX 287 #define QPOASES_NVMAX 287
#define QPOASES_NCMAX 709 #define QPOASES_NCMAX 709
#endif /* __EXTERNAL_DIMENSIONS__ */ #endif /* __EXTERNAL_DIMENSIONS__ */
/** Maximum number of variables within a QP formulation. /** Maximum number of variables within a QP formulation.
* Note: this value has to be positive! */ * Note: this value has to be positive! */
#define NVMAX QPOASES_NVMAX #define NVMAX QPOASES_NVMAX
/** Maximum number of constraints within a QP formulation. /** Maximum number of constraints within a QP formulation.
* Note: this value has to be positive! */ * Note: this value has to be positive! */
#define NCMAX QPOASES_NCMAX #define NCMAX QPOASES_NCMAX
#if ( QPOASES_NVMAX > QPOASES_NCMAX ) #if ( QPOASES_NVMAX > QPOASES_NCMAX )
#define NVCMAX QPOASES_NVMAX #define NVCMAX QPOASES_NVMAX
#else #else
#define NVCMAX QPOASES_NCMAX #define NVCMAX QPOASES_NCMAX
#endif #endif
#if ( QPOASES_NVMAX > QPOASES_NCMAX ) #if ( QPOASES_NVMAX > QPOASES_NCMAX )
#define NVCMIN QPOASES_NCMAX #define NVCMIN QPOASES_NCMAX
#else #else
#define NVCMIN QPOASES_NVMAX #define NVCMIN QPOASES_NVMAX
#endif #endif
/** Maximum number of QPs in a sequence solved by means of the OQP interface. /** Maximum number of QPs in a sequence solved by means of the OQP interface.
* Note: this value has to be positive! */ * Note: this value has to be positive! */
#define NQPMAX 1000 #define NQPMAX 1000
/** Numerical value of machine precision (min eps, s.t. 1+eps > 1). /** Numerical value of machine precision (min eps, s.t. 1+eps > 1).
* Note: this value has to be positive! */ * Note: this value has to be positive! */
#ifndef __CODE_GENERATION__ #ifndef __CODE_GENERATION__
#ifdef __USE_SINGLE_PRECISION__ #ifdef __USE_SINGLE_PRECISION__
static const real_t QPOASES_EPS = 1.193e-07; static const real_t QPOASES_EPS = 1.193e-07;
#else #else
static const real_t QPOASES_EPS = 2.221e-16; static const real_t QPOASES_EPS = 2.221e-16;
#endif /* __USE_SINGLE_PRECISION__ */ #endif /* __USE_SINGLE_PRECISION__ */
#endif /* __CODE_GENERATION__ */ #endif /* __CODE_GENERATION__ */
/** Numerical value of zero (for situations in which it would be /** Numerical value of zero (for situations in which it would be
* unreasonable to compare with 0.0). * unreasonable to compare with 0.0).
* Note: this value has to be positive! */ * Note: this value has to be positive! */
static const real_t QPOASES_ZERO = 1.0e-25; static const real_t QPOASES_ZERO = 1.0e-25;
/** Numerical value of infinity (e.g. for non-existing bounds). /** Numerical value of infinity (e.g. for non-existing bounds).
* Note: this value has to be positive! */ * Note: this value has to be positive! */
static const real_t QPOASES_INFTY = 1.0e20; static const real_t QPOASES_INFTY = 1.0e20;
/** Tolerance to used for isEqual, isZero etc. /** Tolerance to used for isEqual, isZero etc.
* Note: this value has to be positive! */ * Note: this value has to be positive! */
static const real_t QPOASES_TOL = 1.0e-25; static const real_t QPOASES_TOL = 1.0e-25;
/** Maximum number of characters within a string. /** Maximum number of characters within a string.
* Note: this value should be at least 41! */ * Note: this value should be at least 41! */
#define QPOASES_MAX_STRING_LENGTH 160 #define QPOASES_MAX_STRING_LENGTH 160
END_NAMESPACE_QPOASES END_NAMESPACE_QPOASES
#endif /* QPOASES_CONSTANTS_H */ #endif /* QPOASES_CONSTANTS_H */
/* /*
* end of file * end of file
*/ */

@ -1,62 +1,62 @@
/* /*
* This file is part of qpOASES. * This file is part of qpOASES.
* *
* qpOASES -- An Implementation of the Online Active Set Strategy. * qpOASES -- An Implementation of the Online Active Set Strategy.
* Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka,
* Christian Kirches et al. All rights reserved. * Christian Kirches et al. All rights reserved.
* *
* qpOASES is free software; you can redistribute it and/or * qpOASES is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* qpOASES is distributed in the hope that it will be useful, * qpOASES is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with qpOASES; if not, write to the Free Software * License along with qpOASES; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
*/ */
/** /**
* \file include/qpOASES_e/ConstraintProduct.h * \file include/qpOASES_e/ConstraintProduct.h
* \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches (thanks to D. Kwame Minde Kufoalor) * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches (thanks to D. Kwame Minde Kufoalor)
* \version 3.1embedded * \version 3.1embedded
* \date 2009-2015 * \date 2009-2015
* *
* Declaration of the ConstraintProduct interface which allows to specify a * Declaration of the ConstraintProduct interface which allows to specify a
* user-defined function for evaluating the constraint product at the * user-defined function for evaluating the constraint product at the
* current iterate to speed-up QP solution in case of a specially structured * current iterate to speed-up QP solution in case of a specially structured
* constraint matrix. * constraint matrix.
*/ */
#ifndef QPOASES_CONSTRAINT_PRODUCT_H #ifndef QPOASES_CONSTRAINT_PRODUCT_H
#define QPOASES_CONSTRAINT_PRODUCT_H #define QPOASES_CONSTRAINT_PRODUCT_H
BEGIN_NAMESPACE_QPOASES BEGIN_NAMESPACE_QPOASES
/** /**
* \brief Interface for specifying user-defined evaluations of constraint products. * \brief Interface for specifying user-defined evaluations of constraint products.
* *
* An interface which allows to specify a user-defined function for evaluating the * An interface which allows to specify a user-defined function for evaluating the
* constraint product at the current iterate to speed-up QP solution in case * constraint product at the current iterate to speed-up QP solution in case
* of a specially structured constraint matrix. * of a specially structured constraint matrix.
* *
* \author Hans Joachim Ferreau (thanks to Kwame Minde Kufoalor) * \author Hans Joachim Ferreau (thanks to Kwame Minde Kufoalor)
* \version 3.1embedded * \version 3.1embedded
* \date 2009-2015 * \date 2009-2015
*/ */
typedef int(*ConstraintProduct)( int, const real_t* const, real_t* const ); typedef int(*ConstraintProduct)( int, const real_t* const, real_t* const );
END_NAMESPACE_QPOASES END_NAMESPACE_QPOASES
#endif /* QPOASES_CONSTRAINT_PRODUCT_H */ #endif /* QPOASES_CONSTRAINT_PRODUCT_H */

@ -1,221 +1,221 @@
/* /*
* This file is part of qpOASES. * This file is part of qpOASES.
* *
* qpOASES -- An Implementation of the Online Active Set Strategy. * qpOASES -- An Implementation of the Online Active Set Strategy.
* Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka,
* Christian Kirches et al. All rights reserved. * Christian Kirches et al. All rights reserved.
* *
* qpOASES is free software; you can redistribute it and/or * qpOASES is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* qpOASES is distributed in the hope that it will be useful, * qpOASES is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with qpOASES; if not, write to the Free Software * License along with qpOASES; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
*/ */
/** /**
* \file include/qpOASES_e/Indexlist.h * \file include/qpOASES_e/Indexlist.h
* \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches
* \version 3.1embedded * \version 3.1embedded
* \date 2007-2015 * \date 2007-2015
* *
* Declaration of the Indexlist class designed to manage index lists of * Declaration of the Indexlist class designed to manage index lists of
* constraints and bounds within a SubjectTo object. * constraints and bounds within a SubjectTo object.
*/ */
#ifndef QPOASES_INDEXLIST_H #ifndef QPOASES_INDEXLIST_H
#define QPOASES_INDEXLIST_H #define QPOASES_INDEXLIST_H
#include <qpOASES_e/Utils.h> #include <qpOASES_e/Utils.h>
BEGIN_NAMESPACE_QPOASES BEGIN_NAMESPACE_QPOASES
/** /**
* \brief Stores and manages index lists. * \brief Stores and manages index lists.
* *
* This class manages index lists of active/inactive bounds/constraints. * This class manages index lists of active/inactive bounds/constraints.
* *
* \author Hans Joachim Ferreau * \author Hans Joachim Ferreau
* \version 3.1embedded * \version 3.1embedded
* \date 2007-2015 * \date 2007-2015
*/ */
typedef struct typedef struct
{ {
int *number; /**< Array to store numbers of constraints or bounds. */ int *number; /**< Array to store numbers of constraints or bounds. */
int *iSort; /**< Index list to sort vector \a number */ int *iSort; /**< Index list to sort vector \a number */
int length; /**< Length of index list. */ int length; /**< Length of index list. */
int first; /**< Physical index of first element. */ int first; /**< Physical index of first element. */
int last; /**< Physical index of last element. */ int last; /**< Physical index of last element. */
int lastusedindex; /**< Physical index of last entry in index list. */ int lastusedindex; /**< Physical index of last entry in index list. */
int physicallength; /**< Physical length of index list. */ int physicallength; /**< Physical length of index list. */
} Indexlist; } Indexlist;
int Indexlist_calculateMemorySize( int n); int Indexlist_calculateMemorySize( int n);
char *Indexlist_assignMemory(int n, Indexlist **mem, void *raw_memory); char *Indexlist_assignMemory(int n, Indexlist **mem, void *raw_memory);
Indexlist *Indexlist_createMemory( int n ); Indexlist *Indexlist_createMemory( int n );
/** Constructor which takes the desired physical length of the index list. */ /** Constructor which takes the desired physical length of the index list. */
void IndexlistCON( Indexlist* _THIS, void IndexlistCON( Indexlist* _THIS,
int n /**< Physical length of index list. */ int n /**< Physical length of index list. */
); );
/** Copies all members from given rhs object. /** Copies all members from given rhs object.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
void IndexlistCPY( Indexlist* FROM, void IndexlistCPY( Indexlist* FROM,
Indexlist* TO Indexlist* TO
); );
/** Initialises index list of desired physical length. /** Initialises index list of desired physical length.
* \return SUCCESSFUL_RETURN \n * \return SUCCESSFUL_RETURN \n
RET_INVALID_ARGUMENTS */ RET_INVALID_ARGUMENTS */
returnValue Indexlist_init( Indexlist* _THIS, returnValue Indexlist_init( Indexlist* _THIS,
int n /**< Physical length of index list. */ int n /**< Physical length of index list. */
); );
/** Creates an array of all numbers within the index set in correct order. /** Creates an array of all numbers within the index set in correct order.
* \return SUCCESSFUL_RETURN \n * \return SUCCESSFUL_RETURN \n
RET_INDEXLIST_CORRUPTED */ RET_INDEXLIST_CORRUPTED */
returnValue Indexlist_getNumberArray( Indexlist* _THIS, returnValue Indexlist_getNumberArray( Indexlist* _THIS,
int** const numberarray /**< Output: Array of numbers (NULL on error). */ int** const numberarray /**< Output: Array of numbers (NULL on error). */
); );
/** Creates an array of all numbers within the index set in correct order. /** Creates an array of all numbers within the index set in correct order.
* \return SUCCESSFUL_RETURN \n * \return SUCCESSFUL_RETURN \n
RET_INDEXLIST_CORRUPTED */ RET_INDEXLIST_CORRUPTED */
returnValue Indexlist_getISortArray( Indexlist* _THIS, returnValue Indexlist_getISortArray( Indexlist* _THIS,
int** const iSortArray /**< Output: iSort Array. */ int** const iSortArray /**< Output: iSort Array. */
); );
/** Determines the index within the index list at which a given number is stored. /** Determines the index within the index list at which a given number is stored.
* \return >= 0: Index of given number. \n * \return >= 0: Index of given number. \n
-1: Number not found. */ -1: Number not found. */
int Indexlist_getIndex( Indexlist* _THIS, int Indexlist_getIndex( Indexlist* _THIS,
int givennumber /**< Number whose index shall be determined. */ int givennumber /**< Number whose index shall be determined. */
); );
/** Returns the number stored at a given physical index. /** Returns the number stored at a given physical index.
* \return >= 0: Number stored at given physical index. \n * \return >= 0: Number stored at given physical index. \n
-RET_INDEXLIST_OUTOFBOUNDS */ -RET_INDEXLIST_OUTOFBOUNDS */
static inline int Indexlist_getNumber( Indexlist* _THIS, static inline int Indexlist_getNumber( Indexlist* _THIS,
int physicalindex /**< Physical index of the number to be returned. */ int physicalindex /**< Physical index of the number to be returned. */
); );
/** Returns the current length of the index list. /** Returns the current length of the index list.
* \return Current length of the index list. */ * \return Current length of the index list. */
static inline int Indexlist_getLength( Indexlist* _THIS static inline int Indexlist_getLength( Indexlist* _THIS
); );
/** Returns last number within the index list. /** Returns last number within the index list.
* \return Last number within the index list. */ * \return Last number within the index list. */
static inline int Indexlist_getLastNumber( Indexlist* _THIS static inline int Indexlist_getLastNumber( Indexlist* _THIS
); );
/** Adds number to index list. /** Adds number to index list.
* \return SUCCESSFUL_RETURN \n * \return SUCCESSFUL_RETURN \n
RET_INDEXLIST_MUST_BE_REORDERD \n RET_INDEXLIST_MUST_BE_REORDERD \n
RET_INDEXLIST_EXCEEDS_MAX_LENGTH */ RET_INDEXLIST_EXCEEDS_MAX_LENGTH */
returnValue Indexlist_addNumber( Indexlist* _THIS, returnValue Indexlist_addNumber( Indexlist* _THIS,
int addnumber /**< Number to be added. */ int addnumber /**< Number to be added. */
); );
/** Removes number from index list. /** Removes number from index list.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
returnValue Indexlist_removeNumber( Indexlist* _THIS, returnValue Indexlist_removeNumber( Indexlist* _THIS,
int removenumber /**< Number to be removed. */ int removenumber /**< Number to be removed. */
); );
/** Swaps two numbers within index list. /** Swaps two numbers within index list.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
returnValue Indexlist_swapNumbers( Indexlist* _THIS, returnValue Indexlist_swapNumbers( Indexlist* _THIS,
int number1, /**< First number for swapping. */ int number1, /**< First number for swapping. */
int number2 /**< Second number for swapping. */ int number2 /**< Second number for swapping. */
); );
/** Determines if a given number is contained in the index set. /** Determines if a given number is contained in the index set.
* \return BT_TRUE iff number is contain in the index set */ * \return BT_TRUE iff number is contain in the index set */
static inline BooleanType Indexlist_isMember( Indexlist* _THIS, static inline BooleanType Indexlist_isMember( Indexlist* _THIS,
int _number /**< Number to be tested for membership. */ int _number /**< Number to be tested for membership. */
); );
/** Find first index j between -1 and length in sorted list of indices /** Find first index j between -1 and length in sorted list of indices
* iSort such that numbers[iSort[j]] <= i < numbers[iSort[j+1]]. Uses * iSort such that numbers[iSort[j]] <= i < numbers[iSort[j+1]]. Uses
* bisection. * bisection.
* \return j. */ * \return j. */
int Indexlist_findInsert( Indexlist* _THIS, int Indexlist_findInsert( Indexlist* _THIS,
int i int i
); );
/* /*
* g e t N u m b e r * g e t N u m b e r
*/ */
static inline int Indexlist_getNumber( Indexlist* _THIS, int physicalindex ) static inline int Indexlist_getNumber( Indexlist* _THIS, int physicalindex )
{ {
/* consistency check */ /* consistency check */
if ( ( physicalindex < 0 ) || ( physicalindex > _THIS->length ) ) if ( ( physicalindex < 0 ) || ( physicalindex > _THIS->length ) )
return -RET_INDEXLIST_OUTOFBOUNDS; return -RET_INDEXLIST_OUTOFBOUNDS;
return _THIS->number[physicalindex]; return _THIS->number[physicalindex];
} }
/* /*
* g e t L e n g t h * g e t L e n g t h
*/ */
static inline int Indexlist_getLength( Indexlist* _THIS ) static inline int Indexlist_getLength( Indexlist* _THIS )
{ {
return _THIS->length; return _THIS->length;
} }
/* /*
* g e t L a s t N u m b e r * g e t L a s t N u m b e r
*/ */
static inline int Indexlist_getLastNumber( Indexlist* _THIS ) static inline int Indexlist_getLastNumber( Indexlist* _THIS )
{ {
return _THIS->number[_THIS->length-1]; return _THIS->number[_THIS->length-1];
} }
/* /*
* g e t L a s t N u m b e r * g e t L a s t N u m b e r
*/ */
static inline BooleanType Indexlist_isMember( Indexlist* _THIS, int _number ) static inline BooleanType Indexlist_isMember( Indexlist* _THIS, int _number )
{ {
if ( Indexlist_getIndex( _THIS,_number ) >= 0 ) if ( Indexlist_getIndex( _THIS,_number ) >= 0 )
return BT_TRUE; return BT_TRUE;
else else
return BT_FALSE; return BT_FALSE;
} }
END_NAMESPACE_QPOASES END_NAMESPACE_QPOASES
#endif /* QPOASES_INDEXLIST_H */ #endif /* QPOASES_INDEXLIST_H */
/* /*
* end of file * end of file
*/ */

@ -1,287 +1,287 @@
/* /*
* This file is part of qpOASES. * This file is part of qpOASES.
* *
* qpOASES -- An Implementation of the Online Active Set Strategy. * qpOASES -- An Implementation of the Online Active Set Strategy.
* Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka,
* Christian Kirches et al. All rights reserved. * Christian Kirches et al. All rights reserved.
* *
* qpOASES is free software; you can redistribute it and/or * qpOASES is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* qpOASES is distributed in the hope that it will be useful, * qpOASES is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with qpOASES; if not, write to the Free Software * License along with qpOASES; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
*/ */
/** /**
* \file include/qpOASES_e/Matrices.h * \file include/qpOASES_e/Matrices.h
* \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches
* \version 3.1embedded * \version 3.1embedded
* \date 2009-2015 * \date 2009-2015
* *
* Various matrix classes: Abstract base matrix class, dense and sparse matrices, * Various matrix classes: Abstract base matrix class, dense and sparse matrices,
* including symmetry exploiting specializations. * including symmetry exploiting specializations.
*/ */
#ifndef QPOASES_MATRICES_H #ifndef QPOASES_MATRICES_H
#define QPOASES_MATRICES_H #define QPOASES_MATRICES_H
#ifdef __USE_SINGLE_PRECISION__ #ifdef __USE_SINGLE_PRECISION__
// single precision // single precision
#define GEMM sgemm_ #define GEMM sgemm_
#define GEMV sgemv_ #define GEMV sgemv_
// #define SYR ssyr_ // #define SYR ssyr_
// #define SYR2 ssyr2_ // #define SYR2 ssyr2_
#define POTRF spotrf_ #define POTRF spotrf_
#else #else
// double precision // double precision
#define GEMM dgemm_ #define GEMM dgemm_
#define GEMV dgemv_ #define GEMV dgemv_
// #define SYR dsyr_ // #define SYR dsyr_
// #define SYR2 dsyr2_ // #define SYR2 dsyr2_
#define POTRF dpotrf_ #define POTRF dpotrf_
#endif /* __USE_SINGLE_PRECISION__ */ #endif /* __USE_SINGLE_PRECISION__ */
#ifdef EXTERNAL_BLAS #ifdef EXTERNAL_BLAS
// double precision // double precision
void dgemm_(char *ta, char *tb, int *m, int *n, int *k, double *alpha, double *A, int *lda, double *B, int ldb, double *beta, double *C, int *ldc); void dgemm_(char *ta, char *tb, int *m, int *n, int *k, double *alpha, double *A, int *lda, double *B, int ldb, double *beta, double *C, int *ldc);
void dgemv_(char *ta, int *m, int *n, double *alpha, double *A, int *lda, double *x, int *incx, double *beta, double *y, int *incy); void dgemv_(char *ta, int *m, int *n, double *alpha, double *A, int *lda, double *x, int *incx, double *beta, double *y, int *incy);
void dpotrf_(char *uplo, int *m, double *A, int *lda, int *info); void dpotrf_(char *uplo, int *m, double *A, int *lda, int *info);
// single precision // single precision
void sgemm_(char *ta, char *tb, int *m, int *n, int *k, float *alpha, float *A, int *lda, float *B, int ldb, float *beta, float *C, int *ldc); void sgemm_(char *ta, char *tb, int *m, int *n, int *k, float *alpha, float *A, int *lda, float *B, int ldb, float *beta, float *C, int *ldc);
void sgemv_(char *ta, int *m, int *n, float *alpha, float *A, int *lda, float *x, int *incx, float *beta, float *y, int *incy); void sgemv_(char *ta, int *m, int *n, float *alpha, float *A, int *lda, float *x, int *incx, float *beta, float *y, int *incy);
void spotrf_(char *uplo, int *m, float *A, int *lda, int *info); void spotrf_(char *uplo, int *m, float *A, int *lda, int *info);
#else #else
/** Performs one of the matrix-matrix operation in double precision. */ /** Performs one of the matrix-matrix operation in double precision. */
void dgemm_ ( const char*, const char*, const unsigned long*, const unsigned long*, const unsigned long*, void dgemm_ ( const char*, const char*, const unsigned long*, const unsigned long*, const unsigned long*,
const double*, const double*, const unsigned long*, const double*, const unsigned long*, const double*, const double*, const unsigned long*, const double*, const unsigned long*,
const double*, double*, const unsigned long* ); const double*, double*, const unsigned long* );
/** Performs one of the matrix-matrix operation in single precision. */ /** Performs one of the matrix-matrix operation in single precision. */
void sgemm_ ( const char*, const char*, const unsigned long*, const unsigned long*, const unsigned long*, void sgemm_ ( const char*, const char*, const unsigned long*, const unsigned long*, const unsigned long*,
const float*, const float*, const unsigned long*, const float*, const unsigned long*, const float*, const float*, const unsigned long*, const float*, const unsigned long*,
const float*, float*, const unsigned long* ); const float*, float*, const unsigned long* );
/** Calculates the Cholesky factorization of a real symmetric positive definite matrix in double precision. */ /** Calculates the Cholesky factorization of a real symmetric positive definite matrix in double precision. */
void dpotrf_ ( const char *, const unsigned long *, double *, const unsigned long *, long * ); void dpotrf_ ( const char *, const unsigned long *, double *, const unsigned long *, long * );
/** Calculates the Cholesky factorization of a real symmetric positive definite matrix in single precision. */ /** Calculates the Cholesky factorization of a real symmetric positive definite matrix in single precision. */
void spotrf_ ( const char *, const unsigned long *, float *, const unsigned long *, long * ); void spotrf_ ( const char *, const unsigned long *, float *, const unsigned long *, long * );
#endif #endif
/** Performs a symmetric rank 1 operation in double precision. */ /** Performs a symmetric rank 1 operation in double precision. */
// void dsyr_ ( const char *, const unsigned long *, const double *, const double *, // void dsyr_ ( const char *, const unsigned long *, const double *, const double *,
// const unsigned long *, double *, const unsigned long *); // const unsigned long *, double *, const unsigned long *);
/** Performs a symmetric rank 1 operation in single precision. */ /** Performs a symmetric rank 1 operation in single precision. */
// void ssyr_ ( const char *, const unsigned long *, const float *, const float *, // void ssyr_ ( const char *, const unsigned long *, const float *, const float *,
// const unsigned long *, float *, const unsigned long *); // const unsigned long *, float *, const unsigned long *);
/** Performs a symmetric rank 2 operation in double precision. */ /** Performs a symmetric rank 2 operation in double precision. */
// void dsyr2_ ( const char *, const unsigned long *, const double *, const double *, // void dsyr2_ ( const char *, const unsigned long *, const double *, const double *,
// const unsigned long *, const double *, const unsigned long *, double *, const unsigned long *); // const unsigned long *, const double *, const unsigned long *, double *, const unsigned long *);
/** Performs a symmetric rank 2 operation in single precision. */ /** Performs a symmetric rank 2 operation in single precision. */
// void ssyr2_ ( const char *, const unsigned long *, const float *, const float *, // void ssyr2_ ( const char *, const unsigned long *, const float *, const float *,
// const unsigned long *, const float *, const unsigned long *, float *, const unsigned long *); // const unsigned long *, const float *, const unsigned long *, float *, const unsigned long *);
#include <qpOASES_e/Indexlist.h> #include <qpOASES_e/Indexlist.h>
BEGIN_NAMESPACE_QPOASES BEGIN_NAMESPACE_QPOASES
/** /**
* \brief Interfaces matrix-vector operations tailored to general dense matrices. * \brief Interfaces matrix-vector operations tailored to general dense matrices.
* *
* Dense matrix class (row major format). * Dense matrix class (row major format).
* *
* \author Andreas Potschka, Christian Kirches, Hans Joachim Ferreau * \author Andreas Potschka, Christian Kirches, Hans Joachim Ferreau
* \version 3.1embedded * \version 3.1embedded
* \date 2011-2015 * \date 2011-2015
*/ */
typedef struct typedef struct
{ {
real_t *val; /**< Vector of entries. */ real_t *val; /**< Vector of entries. */
int nRows; /**< Number of rows. */ int nRows; /**< Number of rows. */
int nCols; /**< Number of columns. */ int nCols; /**< Number of columns. */
int leaDim; /**< Leading dimension. */ int leaDim; /**< Leading dimension. */
} DenseMatrix; } DenseMatrix;
int DenseMatrix_calculateMemorySize( int m, int n ); int DenseMatrix_calculateMemorySize( int m, int n );
char *DenseMatrix_assignMemory( int m, int n, DenseMatrix **mem, void *raw_memory ); char *DenseMatrix_assignMemory( int m, int n, DenseMatrix **mem, void *raw_memory );
DenseMatrix *DenseMatrix_createMemory( int m, int n ); DenseMatrix *DenseMatrix_createMemory( int m, int n );
/** Constructor from vector of values. /** Constructor from vector of values.
* Caution: Data pointer must be valid throughout lifetime * Caution: Data pointer must be valid throughout lifetime
*/ */
void DenseMatrixCON( DenseMatrix* _THIS, void DenseMatrixCON( DenseMatrix* _THIS,
int m, /**< Number of rows. */ int m, /**< Number of rows. */
int n, /**< Number of columns. */ int n, /**< Number of columns. */
int lD, /**< Leading dimension. */ int lD, /**< Leading dimension. */
real_t *v /**< Values. */ real_t *v /**< Values. */
); );
void DenseMatrixCPY( DenseMatrix* FROM, void DenseMatrixCPY( DenseMatrix* FROM,
DenseMatrix* TO DenseMatrix* TO
); );
/** Frees all internal memory. */ /** Frees all internal memory. */
void DenseMatrix_free( DenseMatrix* _THIS ); void DenseMatrix_free( DenseMatrix* _THIS );
/** Constructor from vector of values. /** Constructor from vector of values.
* Caution: Data pointer must be valid throughout lifetime * Caution: Data pointer must be valid throughout lifetime
*/ */
returnValue DenseMatrix_init( DenseMatrix* _THIS, returnValue DenseMatrix_init( DenseMatrix* _THIS,
int m, /**< Number of rows. */ int m, /**< Number of rows. */
int n, /**< Number of columns. */ int n, /**< Number of columns. */
int lD, /**< Leading dimension. */ int lD, /**< Leading dimension. */
real_t *v /**< Values. */ real_t *v /**< Values. */
); );
/** Returns i-th diagonal entry. /** Returns i-th diagonal entry.
* \return i-th diagonal entry */ * \return i-th diagonal entry */
real_t DenseMatrix_diag( DenseMatrix* _THIS, real_t DenseMatrix_diag( DenseMatrix* _THIS,
int i /**< Index. */ int i /**< Index. */
); );
/** Checks whether matrix is square and diagonal. /** Checks whether matrix is square and diagonal.
* \return BT_TRUE iff matrix is square and diagonal; \n * \return BT_TRUE iff matrix is square and diagonal; \n
* BT_FALSE otherwise. */ * BT_FALSE otherwise. */
BooleanType DenseMatrix_isDiag( DenseMatrix* _THIS ); BooleanType DenseMatrix_isDiag( DenseMatrix* _THIS );
/** Get the N-norm of the matrix /** Get the N-norm of the matrix
* \return N-norm of the matrix * \return N-norm of the matrix
*/ */
real_t DenseMatrix_getNorm( DenseMatrix* _THIS, real_t DenseMatrix_getNorm( DenseMatrix* _THIS,
int type /**< Norm type, 1: one-norm, 2: Euclidean norm. */ int type /**< Norm type, 1: one-norm, 2: Euclidean norm. */
); );
/** Get the N-norm of a row /** Get the N-norm of a row
* \return N-norm of row \a rNum * \return N-norm of row \a rNum
*/ */
real_t DenseMatrix_getRowNorm( DenseMatrix* _THIS, real_t DenseMatrix_getRowNorm( DenseMatrix* _THIS,
int rNum, /**< Row number. */ int rNum, /**< Row number. */
int type /**< Norm type, 1: one-norm, 2: Euclidean norm. */ int type /**< Norm type, 1: one-norm, 2: Euclidean norm. */
); );
/** Retrieve indexed entries of matrix row multiplied by alpha. /** Retrieve indexed entries of matrix row multiplied by alpha.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
returnValue DenseMatrix_getRow( DenseMatrix* _THIS, returnValue DenseMatrix_getRow( DenseMatrix* _THIS,
int rNum, /**< Row number. */ int rNum, /**< Row number. */
const Indexlist* const icols, /**< Index list specifying columns. */ const Indexlist* const icols, /**< Index list specifying columns. */
real_t alpha, /**< Scalar factor. */ real_t alpha, /**< Scalar factor. */
real_t *row /**< Output row vector. */ real_t *row /**< Output row vector. */
); );
/** Retrieve indexed entries of matrix column multiplied by alpha. /** Retrieve indexed entries of matrix column multiplied by alpha.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
returnValue DenseMatrix_getCol( DenseMatrix* _THIS, returnValue DenseMatrix_getCol( DenseMatrix* _THIS,
int cNum, /**< Column number. */ int cNum, /**< Column number. */
const Indexlist* const irows, /**< Index list specifying rows. */ const Indexlist* const irows, /**< Index list specifying rows. */
real_t alpha, /**< Scalar factor. */ real_t alpha, /**< Scalar factor. */
real_t *col /**< Output column vector. */ real_t *col /**< Output column vector. */
); );
/** Evaluate Y=alpha*A*X + beta*Y. /** Evaluate Y=alpha*A*X + beta*Y.
* \return SUCCESSFUL_RETURN. */ * \return SUCCESSFUL_RETURN. */
returnValue DenseMatrix_times( DenseMatrix* _THIS, returnValue DenseMatrix_times( DenseMatrix* _THIS,
int xN, /**< Number of vectors to multiply. */ int xN, /**< Number of vectors to multiply. */
real_t alpha, /**< Scalar factor for matrix vector product. */ real_t alpha, /**< Scalar factor for matrix vector product. */
const real_t *x, /**< Input vector to be multiplied. */ const real_t *x, /**< Input vector to be multiplied. */
int xLD, /**< Leading dimension of input x. */ int xLD, /**< Leading dimension of input x. */
real_t beta, /**< Scalar factor for y. */ real_t beta, /**< Scalar factor for y. */
real_t *y, /**< Output vector of results. */ real_t *y, /**< Output vector of results. */
int yLD /**< Leading dimension of output y. */ int yLD /**< Leading dimension of output y. */
); );
/** Evaluate Y=alpha*A'*X + beta*Y. /** Evaluate Y=alpha*A'*X + beta*Y.
* \return SUCCESSFUL_RETURN. */ * \return SUCCESSFUL_RETURN. */
returnValue DenseMatrix_transTimes( DenseMatrix* _THIS, returnValue DenseMatrix_transTimes( DenseMatrix* _THIS,
int xN, /**< Number of vectors to multiply. */ int xN, /**< Number of vectors to multiply. */
real_t alpha, /**< Scalar factor for matrix vector product. */ real_t alpha, /**< Scalar factor for matrix vector product. */
const real_t *x, /**< Input vector to be multiplied. */ const real_t *x, /**< Input vector to be multiplied. */
int xLD, /**< Leading dimension of input x. */ int xLD, /**< Leading dimension of input x. */
real_t beta, /**< Scalar factor for y. */ real_t beta, /**< Scalar factor for y. */
real_t *y, /**< Output vector of results. */ real_t *y, /**< Output vector of results. */
int yLD /**< Leading dimension of output y. */ int yLD /**< Leading dimension of output y. */
); );
/** Evaluate matrix vector product with submatrix given by Indexlist. /** Evaluate matrix vector product with submatrix given by Indexlist.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
returnValue DenseMatrix_subTimes( DenseMatrix* _THIS, returnValue DenseMatrix_subTimes( DenseMatrix* _THIS,
const Indexlist* const irows, /**< Index list specifying rows. */ const Indexlist* const irows, /**< Index list specifying rows. */
const Indexlist* const icols, /**< Index list specifying columns. */ const Indexlist* const icols, /**< Index list specifying columns. */
int xN, /**< Number of vectors to multiply. */ int xN, /**< Number of vectors to multiply. */
real_t alpha, /**< Scalar factor for matrix vector product. */ real_t alpha, /**< Scalar factor for matrix vector product. */
const real_t *x, /**< Input vector to be multiplied. */ const real_t *x, /**< Input vector to be multiplied. */
int xLD, /**< Leading dimension of input x. */ int xLD, /**< Leading dimension of input x. */
real_t beta, /**< Scalar factor for y. */ real_t beta, /**< Scalar factor for y. */
real_t *y, /**< Output vector of results. */ real_t *y, /**< Output vector of results. */
int yLD, /**< Leading dimension of output y. */ int yLD, /**< Leading dimension of output y. */
BooleanType yCompr /**< Compressed storage for y. */ BooleanType yCompr /**< Compressed storage for y. */
); );
/** Evaluate matrix transpose vector product. /** Evaluate matrix transpose vector product.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
returnValue DenseMatrix_subTransTimes( DenseMatrix* _THIS, returnValue DenseMatrix_subTransTimes( DenseMatrix* _THIS,
const Indexlist* const irows, /**< Index list specifying rows. */ const Indexlist* const irows, /**< Index list specifying rows. */
const Indexlist* const icols, /**< Index list specifying columns. */ const Indexlist* const icols, /**< Index list specifying columns. */
int xN, /**< Number of vectors to multiply. */ int xN, /**< Number of vectors to multiply. */
real_t alpha, /**< Scalar factor for matrix vector product. */ real_t alpha, /**< Scalar factor for matrix vector product. */
const real_t *x, /**< Input vector to be multiplied. */ const real_t *x, /**< Input vector to be multiplied. */
int xLD, /**< Leading dimension of input x. */ int xLD, /**< Leading dimension of input x. */
real_t beta, /**< Scalar factor for y. */ real_t beta, /**< Scalar factor for y. */
real_t *y, /**< Output vector of results. */ real_t *y, /**< Output vector of results. */
int yLD /**< Leading dimension of output y. */ int yLD /**< Leading dimension of output y. */
); );
/** Adds given offset to diagonal of matrix. /** Adds given offset to diagonal of matrix.
* \return SUCCESSFUL_RETURN \n * \return SUCCESSFUL_RETURN \n
RET_NO_DIAGONAL_AVAILABLE */ RET_NO_DIAGONAL_AVAILABLE */
returnValue DenseMatrix_addToDiag( DenseMatrix* _THIS, returnValue DenseMatrix_addToDiag( DenseMatrix* _THIS,
real_t alpha /**< Diagonal offset. */ real_t alpha /**< Diagonal offset. */
); );
/** Prints matrix to screen. /** Prints matrix to screen.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
returnValue DenseMatrix_print( DenseMatrix* _THIS returnValue DenseMatrix_print( DenseMatrix* _THIS
); );
static inline real_t* DenseMatrix_getVal( DenseMatrix* _THIS ) { return _THIS->val; } static inline real_t* DenseMatrix_getVal( DenseMatrix* _THIS ) { return _THIS->val; }
/** Compute bilinear form y = x'*H*x using submatrix given by index list. /** Compute bilinear form y = x'*H*x using submatrix given by index list.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
returnValue DenseMatrix_bilinear( DenseMatrix* _THIS, returnValue DenseMatrix_bilinear( DenseMatrix* _THIS,
const Indexlist* const icols, /**< Index list specifying columns of x. */ const Indexlist* const icols, /**< Index list specifying columns of x. */
int xN, /**< Number of vectors to multiply. */ int xN, /**< Number of vectors to multiply. */
const real_t *x, /**< Input vector to be multiplied (uncompressed). */ const real_t *x, /**< Input vector to be multiplied (uncompressed). */
int xLD, /**< Leading dimension of input x. */ int xLD, /**< Leading dimension of input x. */
real_t *y, /**< Output vector of results (compressed). */ real_t *y, /**< Output vector of results (compressed). */
int yLD /**< Leading dimension of output y. */ int yLD /**< Leading dimension of output y. */
); );
END_NAMESPACE_QPOASES END_NAMESPACE_QPOASES
#endif /* QPOASES_MATRICES_H */ #endif /* QPOASES_MATRICES_H */

@ -1,153 +1,153 @@
/* /*
* This file is part of qpOASES. * This file is part of qpOASES.
* *
* qpOASES -- An Implementation of the Online Active Set Strategy. * qpOASES -- An Implementation of the Online Active Set Strategy.
* Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka,
* Christian Kirches et al. All rights reserved. * Christian Kirches et al. All rights reserved.
* *
* qpOASES is free software; you can redistribute it and/or * qpOASES is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* qpOASES is distributed in the hope that it will be useful, * qpOASES is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with qpOASES; if not, write to the Free Software * License along with qpOASES; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
*/ */
/** /**
* \file include/qpOASES_e/Options.h * \file include/qpOASES_e/Options.h
* \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches
* \version 3.1embedded * \version 3.1embedded
* \date 2007-2015 * \date 2007-2015
* *
* Declaration of the Options class designed to manage user-specified * Declaration of the Options class designed to manage user-specified
* options for solving a QProblem. * options for solving a QProblem.
*/ */
#ifndef QPOASES_OPTIONS_H #ifndef QPOASES_OPTIONS_H
#define QPOASES_OPTIONS_H #define QPOASES_OPTIONS_H
#include <qpOASES_e/Utils.h> #include <qpOASES_e/Utils.h>
BEGIN_NAMESPACE_QPOASES BEGIN_NAMESPACE_QPOASES
/** /**
* \brief Manages all user-specified options for solving QPs. * \brief Manages all user-specified options for solving QPs.
* *
* This class manages all user-specified options used for solving * This class manages all user-specified options used for solving
* quadratic programs. * quadratic programs.
* *
* \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches
* \version 3.1embedded * \version 3.1embedded
* \date 2007-2015 * \date 2007-2015
*/ */
typedef struct typedef struct
{ {
PrintLevel printLevel; /**< Print level. */ PrintLevel printLevel; /**< Print level. */
BooleanType enableRamping; /**< Specifies whether ramping shall be enabled or not. */ BooleanType enableRamping; /**< Specifies whether ramping shall be enabled or not. */
BooleanType enableFarBounds; /**< Specifies whether far bounds shall be used or not. */ BooleanType enableFarBounds; /**< Specifies whether far bounds shall be used or not. */
BooleanType enableFlippingBounds; /**< Specifies whether flipping bounds shall be used or not. */ BooleanType enableFlippingBounds; /**< Specifies whether flipping bounds shall be used or not. */
BooleanType enableRegularisation; /**< Specifies whether Hessian matrix shall be regularised in case semi-definiteness is detected. */ BooleanType enableRegularisation; /**< Specifies whether Hessian matrix shall be regularised in case semi-definiteness is detected. */
BooleanType enableFullLITests; /**< Specifies whether condition-hardened LI test shall be used or not. */ BooleanType enableFullLITests; /**< Specifies whether condition-hardened LI test shall be used or not. */
BooleanType enableNZCTests; /**< Specifies whether nonzero curvature tests shall be used. */ BooleanType enableNZCTests; /**< Specifies whether nonzero curvature tests shall be used. */
int enableDriftCorrection; /**< Specifies the frequency of drift corrections (0 = off). */ int enableDriftCorrection; /**< Specifies the frequency of drift corrections (0 = off). */
int enableCholeskyRefactorisation; /**< Specifies the frequency of full refactorisation of proj. Hessian (otherwise updates). */ int enableCholeskyRefactorisation; /**< Specifies the frequency of full refactorisation of proj. Hessian (otherwise updates). */
BooleanType enableEqualities; /**< Specifies whether equalities shall be always treated as active constraints. */ BooleanType enableEqualities; /**< Specifies whether equalities shall be always treated as active constraints. */
real_t terminationTolerance; /**< Termination tolerance. */ real_t terminationTolerance; /**< Termination tolerance. */
real_t boundTolerance; /**< Lower/upper (constraints') bound tolerance (an inequality constraint whose lower and upper bounds differ by less is regarded to be an equality constraint). */ real_t boundTolerance; /**< Lower/upper (constraints') bound tolerance (an inequality constraint whose lower and upper bounds differ by less is regarded to be an equality constraint). */
real_t boundRelaxation; /**< Offset for relaxing (constraints') bounds at beginning of an initial homotopy. It is also as initial value for far bounds. */ real_t boundRelaxation; /**< Offset for relaxing (constraints') bounds at beginning of an initial homotopy. It is also as initial value for far bounds. */
real_t epsNum; /**< Numerator tolerance for ratio tests. */ real_t epsNum; /**< Numerator tolerance for ratio tests. */
real_t epsDen; /**< Denominator tolerance for ratio tests. */ real_t epsDen; /**< Denominator tolerance for ratio tests. */
real_t maxPrimalJump; /**< Maximum allowed jump in primal variables in nonzero curvature tests. */ real_t maxPrimalJump; /**< Maximum allowed jump in primal variables in nonzero curvature tests. */
real_t maxDualJump; /**< Maximum allowed jump in dual variables in linear independence tests. */ real_t maxDualJump; /**< Maximum allowed jump in dual variables in linear independence tests. */
real_t initialRamping; /**< Start value for Ramping Strategy. */ real_t initialRamping; /**< Start value for Ramping Strategy. */
real_t finalRamping; /**< Final value for Ramping Strategy. */ real_t finalRamping; /**< Final value for Ramping Strategy. */
real_t initialFarBounds; /**< Initial size of Far Bounds. */ real_t initialFarBounds; /**< Initial size of Far Bounds. */
real_t growFarBounds; /**< Factor to grow Far Bounds. */ real_t growFarBounds; /**< Factor to grow Far Bounds. */
SubjectToStatus initialStatusBounds; /**< Initial status of bounds at first iteration. */ SubjectToStatus initialStatusBounds; /**< Initial status of bounds at first iteration. */
real_t epsFlipping; /**< Tolerance of squared Cholesky diagonal factor which triggers flipping bound. */ real_t epsFlipping; /**< Tolerance of squared Cholesky diagonal factor which triggers flipping bound. */
int numRegularisationSteps; /**< Maximum number of successive regularisation steps. */ int numRegularisationSteps; /**< Maximum number of successive regularisation steps. */
real_t epsRegularisation; /**< Scaling factor of identity matrix used for Hessian regularisation. */ real_t epsRegularisation; /**< Scaling factor of identity matrix used for Hessian regularisation. */
int numRefinementSteps; /**< Maximum number of iterative refinement steps. */ int numRefinementSteps; /**< Maximum number of iterative refinement steps. */
real_t epsIterRef; /**< Early termination tolerance for iterative refinement. */ real_t epsIterRef; /**< Early termination tolerance for iterative refinement. */
real_t epsLITests; /**< Tolerance for linear independence tests. */ real_t epsLITests; /**< Tolerance for linear independence tests. */
real_t epsNZCTests; /**< Tolerance for nonzero curvature tests. */ real_t epsNZCTests; /**< Tolerance for nonzero curvature tests. */
BooleanType enableDropInfeasibles; /**< ... */ BooleanType enableDropInfeasibles; /**< ... */
int dropBoundPriority; /**< ... */ int dropBoundPriority; /**< ... */
int dropEqConPriority; /**< ... */ int dropEqConPriority; /**< ... */
int dropIneqConPriority; /**< ... */ int dropIneqConPriority; /**< ... */
} Options; } Options;
void OptionsCON( Options* _THIS void OptionsCON( Options* _THIS
); );
/** Copies all members from given rhs object. /** Copies all members from given rhs object.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
void OptionsCPY( Options* FROM, void OptionsCPY( Options* FROM,
Options* TO Options* TO
); );
/** Sets all options to default values. /** Sets all options to default values.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
returnValue Options_setToDefault( Options* _THIS returnValue Options_setToDefault( Options* _THIS
); );
/** Sets all options to values resulting in maximum reliabilty. /** Sets all options to values resulting in maximum reliabilty.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
returnValue Options_setToReliable( Options* _THIS returnValue Options_setToReliable( Options* _THIS
); );
/** Sets all options to values resulting in minimum solution time. /** Sets all options to values resulting in minimum solution time.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
returnValue Options_setToMPC( Options* _THIS returnValue Options_setToMPC( Options* _THIS
); );
/** Same as setToMPC( ), for ensuring backwards compatibility. /** Same as setToMPC( ), for ensuring backwards compatibility.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
returnValue Options_setToFast( Options* _THIS returnValue Options_setToFast( Options* _THIS
); );
/** Ensures that all options have consistent values by automatically /** Ensures that all options have consistent values by automatically
* adjusting inconsistent ones. * adjusting inconsistent ones.
* Note: This routine cannot (and does not try to) ensure that values * Note: This routine cannot (and does not try to) ensure that values
* are set to reasonable values that make the QP solution work! * are set to reasonable values that make the QP solution work!
* \return SUCCESSFUL_RETURN \n * \return SUCCESSFUL_RETURN \n
* RET_OPTIONS_ADJUSTED */ * RET_OPTIONS_ADJUSTED */
returnValue Options_ensureConsistency( Options* _THIS returnValue Options_ensureConsistency( Options* _THIS
); );
/** Prints values of all options. /** Prints values of all options.
* \return SUCCESSFUL_RETURN */ * \return SUCCESSFUL_RETURN */
returnValue Options_print( Options* _THIS returnValue Options_print( Options* _THIS
); );
END_NAMESPACE_QPOASES END_NAMESPACE_QPOASES
#endif /* QPOASES_OPTIONS_H */ #endif /* QPOASES_OPTIONS_H */
/* /*
* end of file * end of file
*/ */

File diff suppressed because it is too large Load Diff

@ -1,310 +1,310 @@
/* /*
* This file is part of qpOASES. * This file is part of qpOASES.
* *
* qpOASES -- An Implementation of the Online Active Set Strategy. * qpOASES -- An Implementation of the Online Active Set Strategy.
* Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka,
* Christian Kirches et al. All rights reserved. * Christian Kirches et al. All rights reserved.
* *
* qpOASES is free software; you can redistribute it and/or * qpOASES is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* qpOASES is distributed in the hope that it will be useful, * qpOASES is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with qpOASES; if not, write to the Free Software * License along with qpOASES; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
*/ */
/** /**
* \file include/qpOASES_e/Types.h * \file include/qpOASES_e/Types.h
* \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches
* \version 3.1embedded * \version 3.1embedded
* \date 2007-2015 * \date 2007-2015
* *
* Declaration of all non-built-in types (except for classes). * Declaration of all non-built-in types (except for classes).
*/ */
#ifndef QPOASES_TYPES_H #ifndef QPOASES_TYPES_H
#define QPOASES_TYPES_H #define QPOASES_TYPES_H
#ifdef USE_ACADOS_TYPES #ifdef USE_ACADOS_TYPES
#include "acados/utils/types.h" #include "acados/utils/types.h"
#endif #endif
/* If your compiler does not support the snprintf() function, /* If your compiler does not support the snprintf() function,
* uncomment the following line and try to compile again. */ * uncomment the following line and try to compile again. */
/* #define __NO_SNPRINTF__ */ /* #define __NO_SNPRINTF__ */
/* Uncomment the following line for setting the __DSPACE__ flag. */ /* Uncomment the following line for setting the __DSPACE__ flag. */
/* #define __DSPACE__ */ /* #define __DSPACE__ */
/* Uncomment the following line for setting the __XPCTARGET__ flag. */ /* Uncomment the following line for setting the __XPCTARGET__ flag. */
/* #define __XPCTARGET__ */ /* #define __XPCTARGET__ */
/* Uncomment the following line for setting the __NO_FMATH__ flag. */ /* Uncomment the following line for setting the __NO_FMATH__ flag. */
/* #define __NO_FMATH__ */ /* #define __NO_FMATH__ */
/* Uncomment the following line to enable debug information. */ /* Uncomment the following line to enable debug information. */
/* #define __DEBUG__ */ /* #define __DEBUG__ */
/* Uncomment the following line to enable suppress any kind of console output. */ /* Uncomment the following line to enable suppress any kind of console output. */
/* #define __SUPPRESSANYOUTPUT__ */ /* #define __SUPPRESSANYOUTPUT__ */
/** Forces to always include all implicitly fixed bounds and all equality constraints /** Forces to always include all implicitly fixed bounds and all equality constraints
* into the initial working set when setting up an auxiliary QP. */ * into the initial working set when setting up an auxiliary QP. */
#define __ALWAYS_INITIALISE_WITH_ALL_EQUALITIES__ #define __ALWAYS_INITIALISE_WITH_ALL_EQUALITIES__
/* Uncomment the following line to activate the use of an alternative Givens /* Uncomment the following line to activate the use of an alternative Givens
* plane rotation requiring only three multiplications. */ * plane rotation requiring only three multiplications. */
/* #define __USE_THREE_MULTS_GIVENS__ */ /* #define __USE_THREE_MULTS_GIVENS__ */
/* Uncomment the following line to activate the use of single precision arithmetic. */ /* Uncomment the following line to activate the use of single precision arithmetic. */
/* #define __USE_SINGLE_PRECISION__ */ /* #define __USE_SINGLE_PRECISION__ */
/* The inline keyword is skipped by default as it is not part of the C90 standard. /* The inline keyword is skipped by default as it is not part of the C90 standard.
* However, by uncommenting the following line, use of the inline keyword can be enforced. */ * However, by uncommenting the following line, use of the inline keyword can be enforced. */
/* #define __USE_INLINE__ */ /* #define __USE_INLINE__ */
/* Work-around for Borland BCC 5.5 compiler. */ /* Work-around for Borland BCC 5.5 compiler. */
#ifdef __BORLANDC__ #ifdef __BORLANDC__
#if __BORLANDC__ < 0x0561 #if __BORLANDC__ < 0x0561
#define __STDC__ 1 #define __STDC__ 1
#endif #endif
#endif #endif
/* Work-around for Microsoft compilers. */ /* Work-around for Microsoft compilers. */
#ifdef _MSC_VER #ifdef _MSC_VER
#define __NO_SNPRINTF__ #define __NO_SNPRINTF__
#pragma warning( disable : 4061 4100 4250 4514 4996 ) #pragma warning( disable : 4061 4100 4250 4514 4996 )
#endif #endif
/* Apply pre-processor settings when using qpOASES within auto-generated code. */ /* Apply pre-processor settings when using qpOASES within auto-generated code. */
#ifdef __CODE_GENERATION__ #ifdef __CODE_GENERATION__
#define __NO_COPYRIGHT__ #define __NO_COPYRIGHT__
#define __EXTERNAL_DIMENSIONS__ #define __EXTERNAL_DIMENSIONS__
#endif /* __CODE_GENERATION__ */ #endif /* __CODE_GENERATION__ */
/* Avoid using static variables declaration within functions. */ /* Avoid using static variables declaration within functions. */
#ifdef __NO_STATIC__ #ifdef __NO_STATIC__
#define myStatic #define myStatic
#else #else
#define myStatic static #define myStatic static
#endif /* __NO_STATIC__ */ #endif /* __NO_STATIC__ */
/* Skip inline keyword if not specified otherwise. */ /* Skip inline keyword if not specified otherwise. */
#ifndef __USE_INLINE__ #ifndef __USE_INLINE__
#define inline #define inline
#endif #endif
/* Avoid any printing on embedded platforms. */ /* Avoid any printing on embedded platforms. */
#if defined(__DSPACE__) || defined(__XPCTARGET__) #if defined(__DSPACE__) || defined(__XPCTARGET__)
#define __SUPPRESSANYOUTPUT__ #define __SUPPRESSANYOUTPUT__
#define __NO_SNPRINTF__ #define __NO_SNPRINTF__
#endif #endif
#ifdef __NO_SNPRINTF__ #ifdef __NO_SNPRINTF__
#if (!defined(_MSC_VER)) || defined(__DSPACE__) || defined(__XPCTARGET__) #if (!defined(_MSC_VER)) || defined(__DSPACE__) || defined(__XPCTARGET__)
/* If snprintf is not available, provide an empty implementation... */ /* If snprintf is not available, provide an empty implementation... */
int snprintf( char* s, size_t n, const char* format, ... ); int snprintf( char* s, size_t n, const char* format, ... );
#else #else
/* ... or substitute snprintf by _snprintf for Microsoft compilers. */ /* ... or substitute snprintf by _snprintf for Microsoft compilers. */
#define snprintf _snprintf #define snprintf _snprintf
#endif #endif
#endif /* __NO_SNPRINTF__ */ #endif /* __NO_SNPRINTF__ */
/** Macro for switching on/off the beginning of the qpOASES namespace definition. */ /** Macro for switching on/off the beginning of the qpOASES namespace definition. */
#define BEGIN_NAMESPACE_QPOASES #define BEGIN_NAMESPACE_QPOASES
/** Macro for switching on/off the end of the qpOASES namespace definition. */ /** Macro for switching on/off the end of the qpOASES namespace definition. */
#define END_NAMESPACE_QPOASES #define END_NAMESPACE_QPOASES
/** Macro for switching on/off the use of the qpOASES namespace. */ /** Macro for switching on/off the use of the qpOASES namespace. */
#define USING_NAMESPACE_QPOASES #define USING_NAMESPACE_QPOASES
/** Macro for switching on/off references to the qpOASES namespace. */ /** Macro for switching on/off references to the qpOASES namespace. */
#define REFER_NAMESPACE_QPOASES /*::*/ #define REFER_NAMESPACE_QPOASES /*::*/
/** Macro for accessing the Cholesky factor R. */ /** Macro for accessing the Cholesky factor R. */
#define RR( I,J ) _THIS->R[(I)+nV*(J)] #define RR( I,J ) _THIS->R[(I)+nV*(J)]
/** Macro for accessing the orthonormal matrix Q of the QT factorisation. */ /** Macro for accessing the orthonormal matrix Q of the QT factorisation. */
#define QQ( I,J ) _THIS->Q[(I)+nV*(J)] #define QQ( I,J ) _THIS->Q[(I)+nV*(J)]
/** Macro for accessing the triangular matrix T of the QT factorisation. */ /** Macro for accessing the triangular matrix T of the QT factorisation. */
#define TT( I,J ) _THIS->T[(I)*nVC_min+(J)] #define TT( I,J ) _THIS->T[(I)*nVC_min+(J)]
BEGIN_NAMESPACE_QPOASES BEGIN_NAMESPACE_QPOASES
/** Defines real_t for facilitating switching between double and float. */ /** Defines real_t for facilitating switching between double and float. */
#ifndef USE_ACADOS_TYPES #ifndef USE_ACADOS_TYPES
#ifndef __CODE_GENERATION__ #ifndef __CODE_GENERATION__
#ifdef __USE_SINGLE_PRECISION__ #ifdef __USE_SINGLE_PRECISION__
typedef float real_t; typedef float real_t;
#else #else
typedef double real_t; typedef double real_t;
#endif /* __USE_SINGLE_PRECISION__ */ #endif /* __USE_SINGLE_PRECISION__ */
#endif /* __CODE_GENERATION__ */ #endif /* __CODE_GENERATION__ */
#endif /* USE_ACADOS_TYPES */ #endif /* USE_ACADOS_TYPES */
/** Summarises all possible logical values. */ /** Summarises all possible logical values. */
typedef enum typedef enum
{ {
BT_FALSE = 0, /**< Logical value for "false". */ BT_FALSE = 0, /**< Logical value for "false". */
BT_TRUE /**< Logical value for "true". */ BT_TRUE /**< Logical value for "true". */
} BooleanType; } BooleanType;
/** Summarises all possible print levels. Print levels are used to describe /** Summarises all possible print levels. Print levels are used to describe
* the desired amount of output during runtime of qpOASES. */ * the desired amount of output during runtime of qpOASES. */
typedef enum typedef enum
{ {
PL_DEBUG_ITER = -2, /**< Full tabular debugging output. */ PL_DEBUG_ITER = -2, /**< Full tabular debugging output. */
PL_TABULAR, /**< Tabular output. */ PL_TABULAR, /**< Tabular output. */
PL_NONE, /**< No output. */ PL_NONE, /**< No output. */
PL_LOW, /**< Print error messages only. */ PL_LOW, /**< Print error messages only. */
PL_MEDIUM, /**< Print error and warning messages as well as concise info messages. */ PL_MEDIUM, /**< Print error and warning messages as well as concise info messages. */
PL_HIGH /**< Print all messages with full details. */ PL_HIGH /**< Print all messages with full details. */
} PrintLevel; } PrintLevel;
/** Defines visibility status of a message. */ /** Defines visibility status of a message. */
typedef enum typedef enum
{ {
VS_HIDDEN, /**< Message not visible. */ VS_HIDDEN, /**< Message not visible. */
VS_VISIBLE /**< Message visible. */ VS_VISIBLE /**< Message visible. */
} VisibilityStatus; } VisibilityStatus;
/** Summarises all possible states of the (S)QProblem(B) object during the /** Summarises all possible states of the (S)QProblem(B) object during the
solution process of a QP sequence. */ solution process of a QP sequence. */
typedef enum typedef enum
{ {
QPS_NOTINITIALISED, /**< QProblem object is freshly instantiated or reset. */ QPS_NOTINITIALISED, /**< QProblem object is freshly instantiated or reset. */
QPS_PREPARINGAUXILIARYQP, /**< An auxiliary problem is currently setup, either at the very beginning QPS_PREPARINGAUXILIARYQP, /**< An auxiliary problem is currently setup, either at the very beginning
* via an initial homotopy or after changing the QP matrices. */ * via an initial homotopy or after changing the QP matrices. */
QPS_AUXILIARYQPSOLVED, /**< An auxilary problem was solved, either at the very beginning QPS_AUXILIARYQPSOLVED, /**< An auxilary problem was solved, either at the very beginning
* via an initial homotopy or after changing the QP matrices. */ * via an initial homotopy or after changing the QP matrices. */
QPS_PERFORMINGHOMOTOPY, /**< A homotopy according to the main idea of the online active QPS_PERFORMINGHOMOTOPY, /**< A homotopy according to the main idea of the online active
* set strategy is performed. */ * set strategy is performed. */
QPS_HOMOTOPYQPSOLVED, /**< An intermediate QP along the homotopy path was solved. */ QPS_HOMOTOPYQPSOLVED, /**< An intermediate QP along the homotopy path was solved. */
QPS_SOLVED /**< The solution of the actual QP was found. */ QPS_SOLVED /**< The solution of the actual QP was found. */
} QProblemStatus; } QProblemStatus;
/** Summarises all possible types of the QP's Hessian matrix. */ /** Summarises all possible types of the QP's Hessian matrix. */
typedef enum typedef enum
{ {
HST_ZERO, /**< Hessian is zero matrix (i.e. LP formulation). */ HST_ZERO, /**< Hessian is zero matrix (i.e. LP formulation). */
HST_IDENTITY, /**< Hessian is identity matrix. */ HST_IDENTITY, /**< Hessian is identity matrix. */
HST_POSDEF, /**< Hessian is (strictly) positive definite. */ HST_POSDEF, /**< Hessian is (strictly) positive definite. */
HST_POSDEF_NULLSPACE, /**< Hessian is positive definite on null space of active bounds/constraints. */ HST_POSDEF_NULLSPACE, /**< Hessian is positive definite on null space of active bounds/constraints. */
HST_SEMIDEF, /**< Hessian is positive semi-definite. */ HST_SEMIDEF, /**< Hessian is positive semi-definite. */
HST_INDEF, /**< Hessian is indefinite. */ HST_INDEF, /**< Hessian is indefinite. */
HST_UNKNOWN /**< Hessian type is unknown. */ HST_UNKNOWN /**< Hessian type is unknown. */
} HessianType; } HessianType;
/** Summarises all possible types of bounds and constraints. */ /** Summarises all possible types of bounds and constraints. */
typedef enum typedef enum
{ {
ST_UNBOUNDED, /**< Bound/constraint is unbounded. */ ST_UNBOUNDED, /**< Bound/constraint is unbounded. */
ST_BOUNDED, /**< Bound/constraint is bounded but not fixed. */ ST_BOUNDED, /**< Bound/constraint is bounded but not fixed. */
ST_EQUALITY, /**< Bound/constraint is fixed (implicit equality bound/constraint). */ ST_EQUALITY, /**< Bound/constraint is fixed (implicit equality bound/constraint). */
ST_DISABLED, /**< Bound/constraint is disabled (i.e. ignored when solving QP). */ ST_DISABLED, /**< Bound/constraint is disabled (i.e. ignored when solving QP). */
ST_UNKNOWN /**< Type of bound/constraint unknown. */ ST_UNKNOWN /**< Type of bound/constraint unknown. */
} SubjectToType; } SubjectToType;
/** Summarises all possible states of bounds and constraints. */ /** Summarises all possible states of bounds and constraints. */
typedef enum typedef enum
{ {
ST_LOWER = -1, /**< Bound/constraint is at its lower bound. */ ST_LOWER = -1, /**< Bound/constraint is at its lower bound. */
ST_INACTIVE, /**< Bound/constraint is inactive. */ ST_INACTIVE, /**< Bound/constraint is inactive. */
ST_UPPER, /**< Bound/constraint is at its upper bound. */ ST_UPPER, /**< Bound/constraint is at its upper bound. */
ST_INFEASIBLE_LOWER, /**< (to be documented) */ ST_INFEASIBLE_LOWER, /**< (to be documented) */
ST_INFEASIBLE_UPPER, /**< (to be documented) */ ST_INFEASIBLE_UPPER, /**< (to be documented) */
ST_UNDEFINED /**< Status of bound/constraint undefined. */ ST_UNDEFINED /**< Status of bound/constraint undefined. */
} SubjectToStatus; } SubjectToStatus;
/** /**
* \brief Stores internal information for tabular (debugging) output. * \brief Stores internal information for tabular (debugging) output.
* *
* Struct storing internal information for tabular (debugging) output * Struct storing internal information for tabular (debugging) output
* when using the (S)QProblem(B) objects. * when using the (S)QProblem(B) objects.
* *
* \author Hans Joachim Ferreau * \author Hans Joachim Ferreau
* \version 3.1embedded * \version 3.1embedded
* \date 2013-2015 * \date 2013-2015
*/ */
typedef struct typedef struct
{ {
int idxAddB; /**< Index of bound that has been added to working set. */ int idxAddB; /**< Index of bound that has been added to working set. */
int idxRemB; /**< Index of bound that has been removed from working set. */ int idxRemB; /**< Index of bound that has been removed from working set. */
int idxAddC; /**< Index of constraint that has been added to working set. */ int idxAddC; /**< Index of constraint that has been added to working set. */
int idxRemC; /**< Index of constraint that has been removed from working set. */ int idxRemC; /**< Index of constraint that has been removed from working set. */
int excAddB; /**< Flag indicating whether a bound has been added to working set to keep a regular projected Hessian. */ int excAddB; /**< Flag indicating whether a bound has been added to working set to keep a regular projected Hessian. */
int excRemB; /**< Flag indicating whether a bound has been removed from working set to keep a regular projected Hessian. */ int excRemB; /**< Flag indicating whether a bound has been removed from working set to keep a regular projected Hessian. */
int excAddC; /**< Flag indicating whether a constraint has been added to working set to keep a regular projected Hessian. */ int excAddC; /**< Flag indicating whether a constraint has been added to working set to keep a regular projected Hessian. */
int excRemC; /**< Flag indicating whether a constraint has been removed from working set to keep a regular projected Hessian. */ int excRemC; /**< Flag indicating whether a constraint has been removed from working set to keep a regular projected Hessian. */
} TabularOutput; } TabularOutput;
/** /**
* \brief Struct containing the variable header for mat file. * \brief Struct containing the variable header for mat file.
* *
* Struct storing the header of a variable to be stored in * Struct storing the header of a variable to be stored in
* Matlab's binary format (using the outdated Level 4 variant * Matlab's binary format (using the outdated Level 4 variant
* for simplictiy). * for simplictiy).
* *
* Note, this code snippet has been inspired from the document * Note, this code snippet has been inspired from the document
* "Matlab(R) MAT-file Format, R2013b" by MathWorks * "Matlab(R) MAT-file Format, R2013b" by MathWorks
* *
* \author Hans Joachim Ferreau * \author Hans Joachim Ferreau
* \version 3.1embedded * \version 3.1embedded
* \date 2013-2015 * \date 2013-2015
*/ */
typedef struct typedef struct
{ {
long numericFormat; /**< Flag indicating numerical format. */ long numericFormat; /**< Flag indicating numerical format. */
long nRows; /**< Number of rows. */ long nRows; /**< Number of rows. */
long nCols; /**< Number of rows. */ long nCols; /**< Number of rows. */
long imaginaryPart; /**< (to be documented) */ long imaginaryPart; /**< (to be documented) */
long nCharName; /**< Number of character in name. */ long nCharName; /**< Number of character in name. */
} MatMatrixHeader; } MatMatrixHeader;
END_NAMESPACE_QPOASES END_NAMESPACE_QPOASES
#endif /* QPOASES_TYPES_H */ #endif /* QPOASES_TYPES_H */
/* /*
* end of file * end of file
*/ */

@ -1,79 +1,79 @@
/* /*
* This file is part of qpOASES. * This file is part of qpOASES.
* *
* qpOASES -- An Implementation of the Online Active Set Strategy. * qpOASES -- An Implementation of the Online Active Set Strategy.
* Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka,
* Christian Kirches et al. All rights reserved. * Christian Kirches et al. All rights reserved.
* *
* qpOASES is free software; you can redistribute it and/or * qpOASES is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* qpOASES is distributed in the hope that it will be useful, * qpOASES is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details. * See the GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with qpOASES; if not, write to the Free Software * License along with qpOASES; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
*/ */
/** /**
* \file include/qpOASES_e/UnitTesting.h * \file include/qpOASES_e/UnitTesting.h
* \author Hans Joachim Ferreau * \author Hans Joachim Ferreau
* \version 3.1embedded * \version 3.1embedded
* \date 2014-2015 * \date 2014-2015
* *
* Definition of auxiliary functions/macros for unit testing. * Definition of auxiliary functions/macros for unit testing.
*/ */
#ifndef QPOASES_UNIT_TESTING_H #ifndef QPOASES_UNIT_TESTING_H
#define QPOASES_UNIT_TESTING_H #define QPOASES_UNIT_TESTING_H
#ifndef TEST_TOL_FACTOR #ifndef TEST_TOL_FACTOR
#define TEST_TOL_FACTOR 1 #define TEST_TOL_FACTOR 1
#endif #endif
/** Return value for tests that passed. */ /** Return value for tests that passed. */
#define TEST_PASSED 0 #define TEST_PASSED 0
/** Return value for tests that failed. */ /** Return value for tests that failed. */
#define TEST_FAILED 1 #define TEST_FAILED 1
/** Return value for tests that could not run due to missing external data. */ /** Return value for tests that could not run due to missing external data. */
#define TEST_DATA_NOT_FOUND 99 #define TEST_DATA_NOT_FOUND 99
/** Macro verifying that two numerical values are equal in order to pass unit test. */ /** Macro verifying that two numerical values are equal in order to pass unit test. */
#define QPOASES_TEST_FOR_EQUAL( x,y ) if ( REFER_NAMESPACE_QPOASES isEqual( (x),(y) ) == BT_FALSE ) { return TEST_FAILED; } #define QPOASES_TEST_FOR_EQUAL( x,y ) if ( REFER_NAMESPACE_QPOASES isEqual( (x),(y) ) == BT_FALSE ) { return TEST_FAILED; }
/** Macro verifying that two numerical values are close to each other in order to pass unit test. */ /** Macro verifying that two numerical values are close to each other in order to pass unit test. */
#define QPOASES_TEST_FOR_NEAR( x,y ) if ( REFER_NAMESPACE_QPOASES getAbs((x)-(y)) / REFER_NAMESPACE_QPOASES getMax( 1.0,REFER_NAMESPACE_QPOASES getAbs(x) ) >= 1e-10 ) { return TEST_FAILED; } #define QPOASES_TEST_FOR_NEAR( x,y ) if ( REFER_NAMESPACE_QPOASES getAbs((x)-(y)) / REFER_NAMESPACE_QPOASES getMax( 1.0,REFER_NAMESPACE_QPOASES getAbs(x) ) >= 1e-10 ) { return TEST_FAILED; }
/** Macro verifying that first quantity is lower or equal than second one in order to pass unit test. */ /** Macro verifying that first quantity is lower or equal than second one in order to pass unit test. */
#define QPOASES_TEST_FOR_TOL( x,tol ) if ( (x) > (tol)*(TEST_TOL_FACTOR) ) { return TEST_FAILED; } #define QPOASES_TEST_FOR_TOL( x,tol ) if ( (x) > (tol)*(TEST_TOL_FACTOR) ) { return TEST_FAILED; }
/** Macro verifying that a logical expression holds in order to pass unit test. */ /** Macro verifying that a logical expression holds in order to pass unit test. */
#define QPOASES_TEST_FOR_TRUE( x ) if ( (x) == 0 ) { return TEST_FAILED; } #define QPOASES_TEST_FOR_TRUE( x ) if ( (x) == 0 ) { return TEST_FAILED; }
BEGIN_NAMESPACE_QPOASES BEGIN_NAMESPACE_QPOASES
END_NAMESPACE_QPOASES END_NAMESPACE_QPOASES
#endif /* QPOASES_UNIT_TESTING_H */ #endif /* QPOASES_UNIT_TESTING_H */
/* /*
* end of file * end of file
*/ */

@ -1,62 +1,62 @@
/* /*
* Created by Justin R. Wilson on 2/19/2017. * Created by Justin R. Wilson on 2/19/2017.
* Copyright 2017 Justin R. Wilson. All rights reserved. * Copyright 2017 Justin R. Wilson. All rights reserved.
* *
* Distributed under the Boost Software License, Version 1.0. (See accompanying * Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#ifndef TWOBLUECUBES_CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED #ifndef TWOBLUECUBES_CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED #define TWOBLUECUBES_CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
// Don't #include any Catch headers here - we can assume they are already // Don't #include any Catch headers here - we can assume they are already
// included before this header. // included before this header.
// This is not good practice in general but is necessary in this case so this // This is not good practice in general but is necessary in this case so this
// file can be distributed as a single header that works with the main // file can be distributed as a single header that works with the main
// Catch single header. // Catch single header.
namespace Catch { namespace Catch {
struct AutomakeReporter : StreamingReporterBase<AutomakeReporter> { struct AutomakeReporter : StreamingReporterBase<AutomakeReporter> {
AutomakeReporter( ReporterConfig const& _config ) AutomakeReporter( ReporterConfig const& _config )
: StreamingReporterBase( _config ) : StreamingReporterBase( _config )
{} {}
~AutomakeReporter() override; ~AutomakeReporter() override;
static std::string getDescription() { static std::string getDescription() {
return "Reports test results in the format of Automake .trs files"; return "Reports test results in the format of Automake .trs files";
} }
void assertionStarting( AssertionInfo const& ) override {} void assertionStarting( AssertionInfo const& ) override {}
bool assertionEnded( AssertionStats const& /*_assertionStats*/ ) override { return true; } bool assertionEnded( AssertionStats const& /*_assertionStats*/ ) override { return true; }
void testCaseEnded( TestCaseStats const& _testCaseStats ) override { void testCaseEnded( TestCaseStats const& _testCaseStats ) override {
// Possible values to emit are PASS, XFAIL, SKIP, FAIL, XPASS and ERROR. // Possible values to emit are PASS, XFAIL, SKIP, FAIL, XPASS and ERROR.
stream << ":test-result: "; stream << ":test-result: ";
if (_testCaseStats.totals.assertions.allPassed()) { if (_testCaseStats.totals.assertions.allPassed()) {
stream << "PASS"; stream << "PASS";
} else if (_testCaseStats.totals.assertions.allOk()) { } else if (_testCaseStats.totals.assertions.allOk()) {
stream << "XFAIL"; stream << "XFAIL";
} else { } else {
stream << "FAIL"; stream << "FAIL";
} }
stream << ' ' << _testCaseStats.testInfo.name << '\n'; stream << ' ' << _testCaseStats.testInfo.name << '\n';
StreamingReporterBase::testCaseEnded( _testCaseStats ); StreamingReporterBase::testCaseEnded( _testCaseStats );
} }
void skipTest( TestCaseInfo const& testInfo ) override { void skipTest( TestCaseInfo const& testInfo ) override {
stream << ":test-result: SKIP " << testInfo.name << '\n'; stream << ":test-result: SKIP " << testInfo.name << '\n';
} }
}; };
#ifdef CATCH_IMPL #ifdef CATCH_IMPL
AutomakeReporter::~AutomakeReporter() {} AutomakeReporter::~AutomakeReporter() {}
#endif #endif
CATCH_REGISTER_REPORTER( "automake", AutomakeReporter) CATCH_REGISTER_REPORTER( "automake", AutomakeReporter)
} // end namespace Catch } // end namespace Catch
#endif // TWOBLUECUBES_CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED

@ -1,181 +1,181 @@
/* /*
* Created by Daniel Garcia on 2018-12-04. * Created by Daniel Garcia on 2018-12-04.
* Copyright Social Point SL. All rights reserved. * Copyright Social Point SL. All rights reserved.
* *
* Distributed under the Boost Software License, Version 1.0. (See accompanying * Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#ifndef CATCH_REPORTER_SONARQUBE_HPP_INCLUDED #ifndef CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
#define CATCH_REPORTER_SONARQUBE_HPP_INCLUDED #define CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
// Don't #include any Catch headers here - we can assume they are already // Don't #include any Catch headers here - we can assume they are already
// included before this header. // included before this header.
// This is not good practice in general but is necessary in this case so this // This is not good practice in general but is necessary in this case so this
// file can be distributed as a single header that works with the main // file can be distributed as a single header that works with the main
// Catch single header. // Catch single header.
#include <map> #include <map>
namespace Catch { namespace Catch {
struct SonarQubeReporter : CumulativeReporterBase<SonarQubeReporter> { struct SonarQubeReporter : CumulativeReporterBase<SonarQubeReporter> {
SonarQubeReporter(ReporterConfig const& config) SonarQubeReporter(ReporterConfig const& config)
: CumulativeReporterBase(config) : CumulativeReporterBase(config)
, xml(config.stream()) { , xml(config.stream()) {
m_reporterPrefs.shouldRedirectStdOut = true; m_reporterPrefs.shouldRedirectStdOut = true;
m_reporterPrefs.shouldReportAllAssertions = true; m_reporterPrefs.shouldReportAllAssertions = true;
} }
~SonarQubeReporter() override; ~SonarQubeReporter() override;
static std::string getDescription() { static std::string getDescription() {
return "Reports test results in the Generic Test Data SonarQube XML format"; return "Reports test results in the Generic Test Data SonarQube XML format";
} }
static std::set<Verbosity> getSupportedVerbosities() { static std::set<Verbosity> getSupportedVerbosities() {
return { Verbosity::Normal }; return { Verbosity::Normal };
} }
void noMatchingTestCases(std::string const& /*spec*/) override {} void noMatchingTestCases(std::string const& /*spec*/) override {}
void testRunStarting(TestRunInfo const& testRunInfo) override { void testRunStarting(TestRunInfo const& testRunInfo) override {
CumulativeReporterBase::testRunStarting(testRunInfo); CumulativeReporterBase::testRunStarting(testRunInfo);
xml.startElement("testExecutions"); xml.startElement("testExecutions");
xml.writeAttribute("version", "1"); xml.writeAttribute("version", "1");
} }
void testGroupEnded(TestGroupStats const& testGroupStats) override { void testGroupEnded(TestGroupStats const& testGroupStats) override {
CumulativeReporterBase::testGroupEnded(testGroupStats); CumulativeReporterBase::testGroupEnded(testGroupStats);
writeGroup(*m_testGroups.back()); writeGroup(*m_testGroups.back());
} }
void testRunEndedCumulative() override { void testRunEndedCumulative() override {
xml.endElement(); xml.endElement();
} }
void writeGroup(TestGroupNode const& groupNode) { void writeGroup(TestGroupNode const& groupNode) {
std::map<std::string, TestGroupNode::ChildNodes> testsPerFile; std::map<std::string, TestGroupNode::ChildNodes> testsPerFile;
for(auto const& child : groupNode.children) for(auto const& child : groupNode.children)
testsPerFile[child->value.testInfo.lineInfo.file].push_back(child); testsPerFile[child->value.testInfo.lineInfo.file].push_back(child);
for(auto const& kv : testsPerFile) for(auto const& kv : testsPerFile)
writeTestFile(kv.first.c_str(), kv.second); writeTestFile(kv.first.c_str(), kv.second);
} }
void writeTestFile(const char* filename, TestGroupNode::ChildNodes const& testCaseNodes) { void writeTestFile(const char* filename, TestGroupNode::ChildNodes const& testCaseNodes) {
XmlWriter::ScopedElement e = xml.scopedElement("file"); XmlWriter::ScopedElement e = xml.scopedElement("file");
xml.writeAttribute("path", filename); xml.writeAttribute("path", filename);
for(auto const& child : testCaseNodes) for(auto const& child : testCaseNodes)
writeTestCase(*child); writeTestCase(*child);
} }
void writeTestCase(TestCaseNode const& testCaseNode) { void writeTestCase(TestCaseNode const& testCaseNode) {
// All test cases have exactly one section - which represents the // All test cases have exactly one section - which represents the
// test case itself. That section may have 0-n nested sections // test case itself. That section may have 0-n nested sections
assert(testCaseNode.children.size() == 1); assert(testCaseNode.children.size() == 1);
SectionNode const& rootSection = *testCaseNode.children.front(); SectionNode const& rootSection = *testCaseNode.children.front();
writeSection("", rootSection, testCaseNode.value.testInfo.okToFail()); writeSection("", rootSection, testCaseNode.value.testInfo.okToFail());
} }
void writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail) { void writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail) {
std::string name = trim(sectionNode.stats.sectionInfo.name); std::string name = trim(sectionNode.stats.sectionInfo.name);
if(!rootName.empty()) if(!rootName.empty())
name = rootName + '/' + name; name = rootName + '/' + name;
if(!sectionNode.assertions.empty() || !sectionNode.stdOut.empty() || !sectionNode.stdErr.empty()) { if(!sectionNode.assertions.empty() || !sectionNode.stdOut.empty() || !sectionNode.stdErr.empty()) {
XmlWriter::ScopedElement e = xml.scopedElement("testCase"); XmlWriter::ScopedElement e = xml.scopedElement("testCase");
xml.writeAttribute("name", name); xml.writeAttribute("name", name);
xml.writeAttribute("duration", static_cast<long>(sectionNode.stats.durationInSeconds * 1000)); xml.writeAttribute("duration", static_cast<long>(sectionNode.stats.durationInSeconds * 1000));
writeAssertions(sectionNode, okToFail); writeAssertions(sectionNode, okToFail);
} }
for(auto const& childNode : sectionNode.childSections) for(auto const& childNode : sectionNode.childSections)
writeSection(name, *childNode, okToFail); writeSection(name, *childNode, okToFail);
} }
void writeAssertions(SectionNode const& sectionNode, bool okToFail) { void writeAssertions(SectionNode const& sectionNode, bool okToFail) {
for(auto const& assertion : sectionNode.assertions) for(auto const& assertion : sectionNode.assertions)
writeAssertion( assertion, okToFail); writeAssertion( assertion, okToFail);
} }
void writeAssertion(AssertionStats const& stats, bool okToFail) { void writeAssertion(AssertionStats const& stats, bool okToFail) {
AssertionResult const& result = stats.assertionResult; AssertionResult const& result = stats.assertionResult;
if(!result.isOk()) { if(!result.isOk()) {
std::string elementName; std::string elementName;
if(okToFail) { if(okToFail) {
elementName = "skipped"; elementName = "skipped";
} }
else { else {
switch(result.getResultType()) { switch(result.getResultType()) {
case ResultWas::ThrewException: case ResultWas::ThrewException:
case ResultWas::FatalErrorCondition: case ResultWas::FatalErrorCondition:
elementName = "error"; elementName = "error";
break; break;
case ResultWas::ExplicitFailure: case ResultWas::ExplicitFailure:
elementName = "failure"; elementName = "failure";
break; break;
case ResultWas::ExpressionFailed: case ResultWas::ExpressionFailed:
elementName = "failure"; elementName = "failure";
break; break;
case ResultWas::DidntThrowException: case ResultWas::DidntThrowException:
elementName = "failure"; elementName = "failure";
break; break;
// We should never see these here: // We should never see these here:
case ResultWas::Info: case ResultWas::Info:
case ResultWas::Warning: case ResultWas::Warning:
case ResultWas::Ok: case ResultWas::Ok:
case ResultWas::Unknown: case ResultWas::Unknown:
case ResultWas::FailureBit: case ResultWas::FailureBit:
case ResultWas::Exception: case ResultWas::Exception:
elementName = "internalError"; elementName = "internalError";
break; break;
} }
} }
XmlWriter::ScopedElement e = xml.scopedElement(elementName); XmlWriter::ScopedElement e = xml.scopedElement(elementName);
ReusableStringStream messageRss; ReusableStringStream messageRss;
messageRss << result.getTestMacroName() << "(" << result.getExpression() << ")"; messageRss << result.getTestMacroName() << "(" << result.getExpression() << ")";
xml.writeAttribute("message", messageRss.str()); xml.writeAttribute("message", messageRss.str());
ReusableStringStream textRss; ReusableStringStream textRss;
if (stats.totals.assertions.total() > 0) { if (stats.totals.assertions.total() > 0) {
textRss << "FAILED:\n"; textRss << "FAILED:\n";
if (result.hasExpression()) { if (result.hasExpression()) {
textRss << "\t" << result.getExpressionInMacro() << "\n"; textRss << "\t" << result.getExpressionInMacro() << "\n";
} }
if (result.hasExpandedExpression()) { if (result.hasExpandedExpression()) {
textRss << "with expansion:\n\t" << result.getExpandedExpression() << "\n"; textRss << "with expansion:\n\t" << result.getExpandedExpression() << "\n";
} }
} }
if(!result.getMessage().empty()) if(!result.getMessage().empty())
textRss << result.getMessage() << "\n"; textRss << result.getMessage() << "\n";
for(auto const& msg : stats.infoMessages) for(auto const& msg : stats.infoMessages)
if(msg.type == ResultWas::Info) if(msg.type == ResultWas::Info)
textRss << msg.message << "\n"; textRss << msg.message << "\n";
textRss << "at " << result.getSourceInfo(); textRss << "at " << result.getSourceInfo();
xml.writeText(textRss.str(), XmlFormatting::Newline); xml.writeText(textRss.str(), XmlFormatting::Newline);
} }
} }
private: private:
XmlWriter xml; XmlWriter xml;
}; };
#ifdef CATCH_IMPL #ifdef CATCH_IMPL
SonarQubeReporter::~SonarQubeReporter() {} SonarQubeReporter::~SonarQubeReporter() {}
#endif #endif
CATCH_REGISTER_REPORTER( "sonarqube", SonarQubeReporter ) CATCH_REGISTER_REPORTER( "sonarqube", SonarQubeReporter )
} // end namespace Catch } // end namespace Catch
#endif // CATCH_REPORTER_SONARQUBE_HPP_INCLUDED #endif // CATCH_REPORTER_SONARQUBE_HPP_INCLUDED

@ -1,254 +1,254 @@
/* /*
* Created by Colton Wolkins on 2015-08-15. * Created by Colton Wolkins on 2015-08-15.
* Copyright 2015 Martin Moene. All rights reserved. * Copyright 2015 Martin Moene. All rights reserved.
* *
* Distributed under the Boost Software License, Version 1.0. (See accompanying * Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#ifndef TWOBLUECUBES_CATCH_REPORTER_TAP_HPP_INCLUDED #ifndef TWOBLUECUBES_CATCH_REPORTER_TAP_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_REPORTER_TAP_HPP_INCLUDED #define TWOBLUECUBES_CATCH_REPORTER_TAP_HPP_INCLUDED
// Don't #include any Catch headers here - we can assume they are already // Don't #include any Catch headers here - we can assume they are already
// included before this header. // included before this header.
// This is not good practice in general but is necessary in this case so this // This is not good practice in general but is necessary in this case so this
// file can be distributed as a single header that works with the main // file can be distributed as a single header that works with the main
// Catch single header. // Catch single header.
#include <algorithm> #include <algorithm>
namespace Catch { namespace Catch {
struct TAPReporter : StreamingReporterBase<TAPReporter> { struct TAPReporter : StreamingReporterBase<TAPReporter> {
using StreamingReporterBase::StreamingReporterBase; using StreamingReporterBase::StreamingReporterBase;
TAPReporter( ReporterConfig const& config ): TAPReporter( ReporterConfig const& config ):
StreamingReporterBase( config ) { StreamingReporterBase( config ) {
m_reporterPrefs.shouldReportAllAssertions = true; m_reporterPrefs.shouldReportAllAssertions = true;
} }
~TAPReporter() override; ~TAPReporter() override;
static std::string getDescription() { static std::string getDescription() {
return "Reports test results in TAP format, suitable for test harnesses"; return "Reports test results in TAP format, suitable for test harnesses";
} }
void noMatchingTestCases( std::string const& spec ) override { void noMatchingTestCases( std::string const& spec ) override {
stream << "# No test cases matched '" << spec << "'" << std::endl; stream << "# No test cases matched '" << spec << "'" << std::endl;
} }
void assertionStarting( AssertionInfo const& ) override {} void assertionStarting( AssertionInfo const& ) override {}
bool assertionEnded( AssertionStats const& _assertionStats ) override { bool assertionEnded( AssertionStats const& _assertionStats ) override {
++counter; ++counter;
stream << "# " << currentTestCaseInfo->name << std::endl; stream << "# " << currentTestCaseInfo->name << std::endl;
AssertionPrinter printer( stream, _assertionStats, counter ); AssertionPrinter printer( stream, _assertionStats, counter );
printer.print(); printer.print();
stream << std::endl; stream << std::endl;
return true; return true;
} }
void testRunEnded( TestRunStats const& _testRunStats ) override { void testRunEnded( TestRunStats const& _testRunStats ) override {
printTotals( _testRunStats.totals ); printTotals( _testRunStats.totals );
stream << "\n" << std::endl; stream << "\n" << std::endl;
StreamingReporterBase::testRunEnded( _testRunStats ); StreamingReporterBase::testRunEnded( _testRunStats );
} }
private: private:
std::size_t counter = 0; std::size_t counter = 0;
class AssertionPrinter { class AssertionPrinter {
public: public:
AssertionPrinter& operator= ( AssertionPrinter const& ) = delete; AssertionPrinter& operator= ( AssertionPrinter const& ) = delete;
AssertionPrinter( AssertionPrinter const& ) = delete; AssertionPrinter( AssertionPrinter const& ) = delete;
AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, std::size_t _counter ) AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, std::size_t _counter )
: stream( _stream ) : stream( _stream )
, result( _stats.assertionResult ) , result( _stats.assertionResult )
, messages( _stats.infoMessages ) , messages( _stats.infoMessages )
, itMessage( _stats.infoMessages.begin() ) , itMessage( _stats.infoMessages.begin() )
, printInfoMessages( true ) , printInfoMessages( true )
, counter(_counter) , counter(_counter)
{} {}
void print() { void print() {
itMessage = messages.begin(); itMessage = messages.begin();
switch( result.getResultType() ) { switch( result.getResultType() ) {
case ResultWas::Ok: case ResultWas::Ok:
printResultType( passedString() ); printResultType( passedString() );
printOriginalExpression(); printOriginalExpression();
printReconstructedExpression(); printReconstructedExpression();
if ( ! result.hasExpression() ) if ( ! result.hasExpression() )
printRemainingMessages( Colour::None ); printRemainingMessages( Colour::None );
else else
printRemainingMessages(); printRemainingMessages();
break; break;
case ResultWas::ExpressionFailed: case ResultWas::ExpressionFailed:
if (result.isOk()) { if (result.isOk()) {
printResultType(passedString()); printResultType(passedString());
} else { } else {
printResultType(failedString()); printResultType(failedString());
} }
printOriginalExpression(); printOriginalExpression();
printReconstructedExpression(); printReconstructedExpression();
if (result.isOk()) { if (result.isOk()) {
printIssue(" # TODO"); printIssue(" # TODO");
} }
printRemainingMessages(); printRemainingMessages();
break; break;
case ResultWas::ThrewException: case ResultWas::ThrewException:
printResultType( failedString() ); printResultType( failedString() );
printIssue( "unexpected exception with message:" ); printIssue( "unexpected exception with message:" );
printMessage(); printMessage();
printExpressionWas(); printExpressionWas();
printRemainingMessages(); printRemainingMessages();
break; break;
case ResultWas::FatalErrorCondition: case ResultWas::FatalErrorCondition:
printResultType( failedString() ); printResultType( failedString() );
printIssue( "fatal error condition with message:" ); printIssue( "fatal error condition with message:" );
printMessage(); printMessage();
printExpressionWas(); printExpressionWas();
printRemainingMessages(); printRemainingMessages();
break; break;
case ResultWas::DidntThrowException: case ResultWas::DidntThrowException:
printResultType( failedString() ); printResultType( failedString() );
printIssue( "expected exception, got none" ); printIssue( "expected exception, got none" );
printExpressionWas(); printExpressionWas();
printRemainingMessages(); printRemainingMessages();
break; break;
case ResultWas::Info: case ResultWas::Info:
printResultType( "info" ); printResultType( "info" );
printMessage(); printMessage();
printRemainingMessages(); printRemainingMessages();
break; break;
case ResultWas::Warning: case ResultWas::Warning:
printResultType( "warning" ); printResultType( "warning" );
printMessage(); printMessage();
printRemainingMessages(); printRemainingMessages();
break; break;
case ResultWas::ExplicitFailure: case ResultWas::ExplicitFailure:
printResultType( failedString() ); printResultType( failedString() );
printIssue( "explicitly" ); printIssue( "explicitly" );
printRemainingMessages( Colour::None ); printRemainingMessages( Colour::None );
break; break;
// These cases are here to prevent compiler warnings // These cases are here to prevent compiler warnings
case ResultWas::Unknown: case ResultWas::Unknown:
case ResultWas::FailureBit: case ResultWas::FailureBit:
case ResultWas::Exception: case ResultWas::Exception:
printResultType( "** internal error **" ); printResultType( "** internal error **" );
break; break;
} }
} }
private: private:
static Colour::Code dimColour() { return Colour::FileName; } static Colour::Code dimColour() { return Colour::FileName; }
static const char* failedString() { return "not ok"; } static const char* failedString() { return "not ok"; }
static const char* passedString() { return "ok"; } static const char* passedString() { return "ok"; }
void printSourceInfo() const { void printSourceInfo() const {
Colour colourGuard( dimColour() ); Colour colourGuard( dimColour() );
stream << result.getSourceInfo() << ":"; stream << result.getSourceInfo() << ":";
} }
void printResultType( std::string const& passOrFail ) const { void printResultType( std::string const& passOrFail ) const {
if( !passOrFail.empty() ) { if( !passOrFail.empty() ) {
stream << passOrFail << ' ' << counter << " -"; stream << passOrFail << ' ' << counter << " -";
} }
} }
void printIssue( std::string const& issue ) const { void printIssue( std::string const& issue ) const {
stream << " " << issue; stream << " " << issue;
} }
void printExpressionWas() { void printExpressionWas() {
if( result.hasExpression() ) { if( result.hasExpression() ) {
stream << ";"; stream << ";";
{ {
Colour colour( dimColour() ); Colour colour( dimColour() );
stream << " expression was:"; stream << " expression was:";
} }
printOriginalExpression(); printOriginalExpression();
} }
} }
void printOriginalExpression() const { void printOriginalExpression() const {
if( result.hasExpression() ) { if( result.hasExpression() ) {
stream << " " << result.getExpression(); stream << " " << result.getExpression();
} }
} }
void printReconstructedExpression() const { void printReconstructedExpression() const {
if( result.hasExpandedExpression() ) { if( result.hasExpandedExpression() ) {
{ {
Colour colour( dimColour() ); Colour colour( dimColour() );
stream << " for: "; stream << " for: ";
} }
std::string expr = result.getExpandedExpression(); std::string expr = result.getExpandedExpression();
std::replace( expr.begin(), expr.end(), '\n', ' '); std::replace( expr.begin(), expr.end(), '\n', ' ');
stream << expr; stream << expr;
} }
} }
void printMessage() { void printMessage() {
if ( itMessage != messages.end() ) { if ( itMessage != messages.end() ) {
stream << " '" << itMessage->message << "'"; stream << " '" << itMessage->message << "'";
++itMessage; ++itMessage;
} }
} }
void printRemainingMessages( Colour::Code colour = dimColour() ) { void printRemainingMessages( Colour::Code colour = dimColour() ) {
if (itMessage == messages.end()) { if (itMessage == messages.end()) {
return; return;
} }
const auto itEnd = messages.cend(); const auto itEnd = messages.cend();
const auto N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) ); const auto N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
{ {
Colour colourGuard( colour ); Colour colourGuard( colour );
stream << " with " << pluralise( N, "message" ) << ":"; stream << " with " << pluralise( N, "message" ) << ":";
} }
while( itMessage != itEnd ) { while( itMessage != itEnd ) {
// If this assertion is a warning ignore any INFO messages // If this assertion is a warning ignore any INFO messages
if( printInfoMessages || itMessage->type != ResultWas::Info ) { if( printInfoMessages || itMessage->type != ResultWas::Info ) {
stream << " '" << itMessage->message << "'"; stream << " '" << itMessage->message << "'";
if ( ++itMessage != itEnd ) { if ( ++itMessage != itEnd ) {
Colour colourGuard( dimColour() ); Colour colourGuard( dimColour() );
stream << " and"; stream << " and";
} }
continue; continue;
} }
++itMessage; ++itMessage;
} }
} }
private: private:
std::ostream& stream; std::ostream& stream;
AssertionResult const& result; AssertionResult const& result;
std::vector<MessageInfo> messages; std::vector<MessageInfo> messages;
std::vector<MessageInfo>::const_iterator itMessage; std::vector<MessageInfo>::const_iterator itMessage;
bool printInfoMessages; bool printInfoMessages;
std::size_t counter; std::size_t counter;
}; };
void printTotals( const Totals& totals ) const { void printTotals( const Totals& totals ) const {
stream << "1.." << totals.assertions.total(); stream << "1.." << totals.assertions.total();
if( totals.testCases.total() == 0 ) { if( totals.testCases.total() == 0 ) {
stream << " # Skipped: No tests ran."; stream << " # Skipped: No tests ran.";
} }
} }
}; };
#ifdef CATCH_IMPL #ifdef CATCH_IMPL
TAPReporter::~TAPReporter() {} TAPReporter::~TAPReporter() {}
#endif #endif
CATCH_REGISTER_REPORTER( "tap", TAPReporter ) CATCH_REGISTER_REPORTER( "tap", TAPReporter )
} // end namespace Catch } // end namespace Catch
#endif // TWOBLUECUBES_CATCH_REPORTER_TAP_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_REPORTER_TAP_HPP_INCLUDED

@ -1,219 +1,219 @@
/* /*
* Created by Phil Nash on 19th December 2014 * Created by Phil Nash on 19th December 2014
* Copyright 2014 Two Blue Cubes Ltd. All rights reserved. * Copyright 2014 Two Blue Cubes Ltd. All rights reserved.
* *
* Distributed under the Boost Software License, Version 1.0. (See accompanying * Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/ */
#ifndef TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED #ifndef TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED #define TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
// Don't #include any Catch headers here - we can assume they are already // Don't #include any Catch headers here - we can assume they are already
// included before this header. // included before this header.
// This is not good practice in general but is necessary in this case so this // This is not good practice in general but is necessary in this case so this
// file can be distributed as a single header that works with the main // file can be distributed as a single header that works with the main
// Catch single header. // Catch single header.
#include <cstring> #include <cstring>
#ifdef __clang__ #ifdef __clang__
# pragma clang diagnostic push # pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded" # pragma clang diagnostic ignored "-Wpadded"
#endif #endif
namespace Catch { namespace Catch {
struct TeamCityReporter : StreamingReporterBase<TeamCityReporter> { struct TeamCityReporter : StreamingReporterBase<TeamCityReporter> {
TeamCityReporter( ReporterConfig const& _config ) TeamCityReporter( ReporterConfig const& _config )
: StreamingReporterBase( _config ) : StreamingReporterBase( _config )
{ {
m_reporterPrefs.shouldRedirectStdOut = true; m_reporterPrefs.shouldRedirectStdOut = true;
} }
static std::string escape( std::string const& str ) { static std::string escape( std::string const& str ) {
std::string escaped = str; std::string escaped = str;
replaceInPlace( escaped, "|", "||" ); replaceInPlace( escaped, "|", "||" );
replaceInPlace( escaped, "'", "|'" ); replaceInPlace( escaped, "'", "|'" );
replaceInPlace( escaped, "\n", "|n" ); replaceInPlace( escaped, "\n", "|n" );
replaceInPlace( escaped, "\r", "|r" ); replaceInPlace( escaped, "\r", "|r" );
replaceInPlace( escaped, "[", "|[" ); replaceInPlace( escaped, "[", "|[" );
replaceInPlace( escaped, "]", "|]" ); replaceInPlace( escaped, "]", "|]" );
return escaped; return escaped;
} }
~TeamCityReporter() override; ~TeamCityReporter() override;
static std::string getDescription() { static std::string getDescription() {
return "Reports test results as TeamCity service messages"; return "Reports test results as TeamCity service messages";
} }
void skipTest( TestCaseInfo const& /* testInfo */ ) override { void skipTest( TestCaseInfo const& /* testInfo */ ) override {
} }
void noMatchingTestCases( std::string const& /* spec */ ) override {} void noMatchingTestCases( std::string const& /* spec */ ) override {}
void testGroupStarting( GroupInfo const& groupInfo ) override { void testGroupStarting( GroupInfo const& groupInfo ) override {
StreamingReporterBase::testGroupStarting( groupInfo ); StreamingReporterBase::testGroupStarting( groupInfo );
stream << "##teamcity[testSuiteStarted name='" stream << "##teamcity[testSuiteStarted name='"
<< escape( groupInfo.name ) << "']\n"; << escape( groupInfo.name ) << "']\n";
} }
void testGroupEnded( TestGroupStats const& testGroupStats ) override { void testGroupEnded( TestGroupStats const& testGroupStats ) override {
StreamingReporterBase::testGroupEnded( testGroupStats ); StreamingReporterBase::testGroupEnded( testGroupStats );
stream << "##teamcity[testSuiteFinished name='" stream << "##teamcity[testSuiteFinished name='"
<< escape( testGroupStats.groupInfo.name ) << "']\n"; << escape( testGroupStats.groupInfo.name ) << "']\n";
} }
void assertionStarting( AssertionInfo const& ) override {} void assertionStarting( AssertionInfo const& ) override {}
bool assertionEnded( AssertionStats const& assertionStats ) override { bool assertionEnded( AssertionStats const& assertionStats ) override {
AssertionResult const& result = assertionStats.assertionResult; AssertionResult const& result = assertionStats.assertionResult;
if( !result.isOk() ) { if( !result.isOk() ) {
ReusableStringStream msg; ReusableStringStream msg;
if( !m_headerPrintedForThisSection ) if( !m_headerPrintedForThisSection )
printSectionHeader( msg.get() ); printSectionHeader( msg.get() );
m_headerPrintedForThisSection = true; m_headerPrintedForThisSection = true;
msg << result.getSourceInfo() << "\n"; msg << result.getSourceInfo() << "\n";
switch( result.getResultType() ) { switch( result.getResultType() ) {
case ResultWas::ExpressionFailed: case ResultWas::ExpressionFailed:
msg << "expression failed"; msg << "expression failed";
break; break;
case ResultWas::ThrewException: case ResultWas::ThrewException:
msg << "unexpected exception"; msg << "unexpected exception";
break; break;
case ResultWas::FatalErrorCondition: case ResultWas::FatalErrorCondition:
msg << "fatal error condition"; msg << "fatal error condition";
break; break;
case ResultWas::DidntThrowException: case ResultWas::DidntThrowException:
msg << "no exception was thrown where one was expected"; msg << "no exception was thrown where one was expected";
break; break;
case ResultWas::ExplicitFailure: case ResultWas::ExplicitFailure:
msg << "explicit failure"; msg << "explicit failure";
break; break;
// We shouldn't get here because of the isOk() test // We shouldn't get here because of the isOk() test
case ResultWas::Ok: case ResultWas::Ok:
case ResultWas::Info: case ResultWas::Info:
case ResultWas::Warning: case ResultWas::Warning:
CATCH_ERROR( "Internal error in TeamCity reporter" ); CATCH_ERROR( "Internal error in TeamCity reporter" );
// These cases are here to prevent compiler warnings // These cases are here to prevent compiler warnings
case ResultWas::Unknown: case ResultWas::Unknown:
case ResultWas::FailureBit: case ResultWas::FailureBit:
case ResultWas::Exception: case ResultWas::Exception:
CATCH_ERROR( "Not implemented" ); CATCH_ERROR( "Not implemented" );
} }
if( assertionStats.infoMessages.size() == 1 ) if( assertionStats.infoMessages.size() == 1 )
msg << " with message:"; msg << " with message:";
if( assertionStats.infoMessages.size() > 1 ) if( assertionStats.infoMessages.size() > 1 )
msg << " with messages:"; msg << " with messages:";
for( auto const& messageInfo : assertionStats.infoMessages ) for( auto const& messageInfo : assertionStats.infoMessages )
msg << "\n \"" << messageInfo.message << "\""; msg << "\n \"" << messageInfo.message << "\"";
if( result.hasExpression() ) { if( result.hasExpression() ) {
msg << msg <<
"\n " << result.getExpressionInMacro() << "\n" "\n " << result.getExpressionInMacro() << "\n"
"with expansion:\n" << "with expansion:\n" <<
" " << result.getExpandedExpression() << "\n"; " " << result.getExpandedExpression() << "\n";
} }
if( currentTestCaseInfo->okToFail() ) { if( currentTestCaseInfo->okToFail() ) {
msg << "- failure ignore as test marked as 'ok to fail'\n"; msg << "- failure ignore as test marked as 'ok to fail'\n";
stream << "##teamcity[testIgnored" stream << "##teamcity[testIgnored"
<< " name='" << escape( currentTestCaseInfo->name )<< "'" << " name='" << escape( currentTestCaseInfo->name )<< "'"
<< " message='" << escape( msg.str() ) << "'" << " message='" << escape( msg.str() ) << "'"
<< "]\n"; << "]\n";
} }
else { else {
stream << "##teamcity[testFailed" stream << "##teamcity[testFailed"
<< " name='" << escape( currentTestCaseInfo->name )<< "'" << " name='" << escape( currentTestCaseInfo->name )<< "'"
<< " message='" << escape( msg.str() ) << "'" << " message='" << escape( msg.str() ) << "'"
<< "]\n"; << "]\n";
} }
} }
stream.flush(); stream.flush();
return true; return true;
} }
void sectionStarting( SectionInfo const& sectionInfo ) override { void sectionStarting( SectionInfo const& sectionInfo ) override {
m_headerPrintedForThisSection = false; m_headerPrintedForThisSection = false;
StreamingReporterBase::sectionStarting( sectionInfo ); StreamingReporterBase::sectionStarting( sectionInfo );
} }
void testCaseStarting( TestCaseInfo const& testInfo ) override { void testCaseStarting( TestCaseInfo const& testInfo ) override {
m_testTimer.start(); m_testTimer.start();
StreamingReporterBase::testCaseStarting( testInfo ); StreamingReporterBase::testCaseStarting( testInfo );
stream << "##teamcity[testStarted name='" stream << "##teamcity[testStarted name='"
<< escape( testInfo.name ) << "']\n"; << escape( testInfo.name ) << "']\n";
stream.flush(); stream.flush();
} }
void testCaseEnded( TestCaseStats const& testCaseStats ) override { void testCaseEnded( TestCaseStats const& testCaseStats ) override {
StreamingReporterBase::testCaseEnded( testCaseStats ); StreamingReporterBase::testCaseEnded( testCaseStats );
if( !testCaseStats.stdOut.empty() ) if( !testCaseStats.stdOut.empty() )
stream << "##teamcity[testStdOut name='" stream << "##teamcity[testStdOut name='"
<< escape( testCaseStats.testInfo.name ) << escape( testCaseStats.testInfo.name )
<< "' out='" << escape( testCaseStats.stdOut ) << "']\n"; << "' out='" << escape( testCaseStats.stdOut ) << "']\n";
if( !testCaseStats.stdErr.empty() ) if( !testCaseStats.stdErr.empty() )
stream << "##teamcity[testStdErr name='" stream << "##teamcity[testStdErr name='"
<< escape( testCaseStats.testInfo.name ) << escape( testCaseStats.testInfo.name )
<< "' out='" << escape( testCaseStats.stdErr ) << "']\n"; << "' out='" << escape( testCaseStats.stdErr ) << "']\n";
stream << "##teamcity[testFinished name='" stream << "##teamcity[testFinished name='"
<< escape( testCaseStats.testInfo.name ) << "' duration='" << escape( testCaseStats.testInfo.name ) << "' duration='"
<< m_testTimer.getElapsedMilliseconds() << "']\n"; << m_testTimer.getElapsedMilliseconds() << "']\n";
stream.flush(); stream.flush();
} }
private: private:
void printSectionHeader( std::ostream& os ) { void printSectionHeader( std::ostream& os ) {
assert( !m_sectionStack.empty() ); assert( !m_sectionStack.empty() );
if( m_sectionStack.size() > 1 ) { if( m_sectionStack.size() > 1 ) {
os << getLineOfChars<'-'>() << "\n"; os << getLineOfChars<'-'>() << "\n";
std::vector<SectionInfo>::const_iterator std::vector<SectionInfo>::const_iterator
it = m_sectionStack.begin()+1, // Skip first section (test case) it = m_sectionStack.begin()+1, // Skip first section (test case)
itEnd = m_sectionStack.end(); itEnd = m_sectionStack.end();
for( ; it != itEnd; ++it ) for( ; it != itEnd; ++it )
printHeaderString( os, it->name ); printHeaderString( os, it->name );
os << getLineOfChars<'-'>() << "\n"; os << getLineOfChars<'-'>() << "\n";
} }
SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
os << lineInfo << "\n"; os << lineInfo << "\n";
os << getLineOfChars<'.'>() << "\n\n"; os << getLineOfChars<'.'>() << "\n\n";
} }
// if string has a : in first line will set indent to follow it on // if string has a : in first line will set indent to follow it on
// subsequent lines // subsequent lines
static void printHeaderString( std::ostream& os, std::string const& _string, std::size_t indent = 0 ) { static void printHeaderString( std::ostream& os, std::string const& _string, std::size_t indent = 0 ) {
std::size_t i = _string.find( ": " ); std::size_t i = _string.find( ": " );
if( i != std::string::npos ) if( i != std::string::npos )
i+=2; i+=2;
else else
i = 0; i = 0;
os << Column( _string ) os << Column( _string )
.indent( indent+i) .indent( indent+i)
.initialIndent( indent ) << "\n"; .initialIndent( indent ) << "\n";
} }
private: private:
bool m_headerPrintedForThisSection = false; bool m_headerPrintedForThisSection = false;
Timer m_testTimer; Timer m_testTimer;
}; };
#ifdef CATCH_IMPL #ifdef CATCH_IMPL
TeamCityReporter::~TeamCityReporter() {} TeamCityReporter::~TeamCityReporter() {}
#endif #endif
CATCH_REGISTER_REPORTER( "teamcity", TeamCityReporter ) CATCH_REGISTER_REPORTER( "teamcity", TeamCityReporter )
} // end namespace Catch } // end namespace Catch
#ifdef __clang__ #ifdef __clang__
# pragma clang diagnostic pop # pragma clang diagnostic pop
#endif #endif
#endif // TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED

@ -1,127 +1,127 @@
//============================================================================= //=============================================================================
// //
// Copyright (c) 2021-2022 Qualcomm Technologies, Inc. // Copyright (c) 2021-2022 Qualcomm Technologies, Inc.
// All Rights Reserved. // All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc. // Confidential and Proprietary - Qualcomm Technologies, Inc.
// //
//============================================================================= //=============================================================================
#ifndef DL_SYSTEM_IOBUFFER_DATATYPE_MAP_HPP #ifndef DL_SYSTEM_IOBUFFER_DATATYPE_MAP_HPP
#define DL_SYSTEM_IOBUFFER_DATATYPE_MAP_HPP #define DL_SYSTEM_IOBUFFER_DATATYPE_MAP_HPP
#include <cstddef> #include <cstddef>
#include <memory> #include <memory>
#include "DlSystem/DlEnums.hpp" #include "DlSystem/DlEnums.hpp"
namespace DlSystem namespace DlSystem
{ {
// Forward declaration of IOBufferDataTypeMapImpl implementation. // Forward declaration of IOBufferDataTypeMapImpl implementation.
class IOBufferDataTypeMapImpl; class IOBufferDataTypeMapImpl;
} }
namespace zdl namespace zdl
{ {
namespace DlSystem namespace DlSystem
{ {
/** @addtogroup c_plus_plus_apis C++ /** @addtogroup c_plus_plus_apis C++
@{ */ @{ */
/** /**
* @brief . * @brief .
* *
* The IoBufferDataTypeMap class definition * The IoBufferDataTypeMap class definition
*/ */
class ZDL_EXPORT IOBufferDataTypeMap final class ZDL_EXPORT IOBufferDataTypeMap final
{ {
public: public:
/** /**
* @brief . * @brief .
* *
* Creates a new Buffer Data type map * Creates a new Buffer Data type map
* *
*/ */
IOBufferDataTypeMap(); IOBufferDataTypeMap();
/** /**
* @brief Adds a name and the corresponding buffer data type * @brief Adds a name and the corresponding buffer data type
* to the map * to the map
* *
* @param[name] name The name of the buffer * @param[name] name The name of the buffer
* @param[bufferDataType] buffer Data Type of the buffer * @param[bufferDataType] buffer Data Type of the buffer
* *
* @note If a buffer with the same name already exists, no new * @note If a buffer with the same name already exists, no new
* buffer is added. * buffer is added.
*/ */
void add(const char* name, zdl::DlSystem::IOBufferDataType_t bufferDataType); void add(const char* name, zdl::DlSystem::IOBufferDataType_t bufferDataType);
/** /**
* @brief Removes a buffer name from the map * @brief Removes a buffer name from the map
* *
* @param[name] name The name of the buffer * @param[name] name The name of the buffer
* *
*/ */
void remove(const char* name); void remove(const char* name);
/** /**
* @brief Returns the type of the named buffer * @brief Returns the type of the named buffer
* *
* @param[name] name The name of the buffer * @param[name] name The name of the buffer
* *
* @return The type of the buffer, or UNSPECIFIED if the buffer does not exist * @return The type of the buffer, or UNSPECIFIED if the buffer does not exist
* *
*/ */
zdl::DlSystem::IOBufferDataType_t getBufferDataType(const char* name); zdl::DlSystem::IOBufferDataType_t getBufferDataType(const char* name);
/** /**
* @brief Returns the type of the first buffer * @brief Returns the type of the first buffer
* *
* @return The type of the first buffer, or UNSPECIFIED if the map is empty. * @return The type of the first buffer, or UNSPECIFIED if the map is empty.
* *
*/ */
zdl::DlSystem::IOBufferDataType_t getBufferDataType(); zdl::DlSystem::IOBufferDataType_t getBufferDataType();
/** /**
* @brief Returns the size of the buffer type map. * @brief Returns the size of the buffer type map.
* *
* @return The size of the map * @return The size of the map
* *
*/ */
size_t size(); size_t size();
/** /**
* @brief Checks the existence of the named buffer in the map * @brief Checks the existence of the named buffer in the map
* *
* @return True if the named buffer exists, false otherwise. * @return True if the named buffer exists, false otherwise.
* *
*/ */
bool find(const char* name); bool find(const char* name);
/** /**
* @brief Resets the map * @brief Resets the map
* *
*/ */
void clear(); void clear();
/** /**
* @brief Checks whether the map is empty * @brief Checks whether the map is empty
* *
* @return True if the map is empty, false otherwise. * @return True if the map is empty, false otherwise.
* *
*/ */
bool empty(); bool empty();
/** /**
* @brief Destroys the map * @brief Destroys the map
* *
*/ */
~IOBufferDataTypeMap(); ~IOBufferDataTypeMap();
private: private:
std::shared_ptr<::DlSystem::IOBufferDataTypeMapImpl> m_IOBufferDataTypeMapImpl; std::shared_ptr<::DlSystem::IOBufferDataTypeMapImpl> m_IOBufferDataTypeMapImpl;
}; };
} }
} }
#endif #endif

@ -169,7 +169,7 @@ void ChartView::msgUpdated(MessageId id) {
} }
void ChartView::manageSignals() { void ChartView::manageSignals() {
SignalSelector dlg(tr("Mange Chart"), this); SignalSelector dlg(tr("Manage Chart"), this);
for (auto &s : sigs) { for (auto &s : sigs) {
dlg.addSelected(s.msg_id, s.sig); dlg.addSelected(s.msg_id, s.sig);
} }

@ -395,7 +395,7 @@ QWidget *SignalItemDelegate::createEditor(QWidget *parent, const QStyleOptionVie
else e->setValidator(double_validator); else e->setValidator(double_validator);
if (item->type == SignalModel::Item::Name) { if (item->type == SignalModel::Item::Name) {
QCompleter *completer = new QCompleter(dbc()->signalNames()); QCompleter *completer = new QCompleter(dbc()->signalNames(), e);
completer->setCaseSensitivity(Qt::CaseInsensitive); completer->setCaseSensitivity(Qt::CaseInsensitive);
completer->setFilterMode(Qt::MatchContains); completer->setFilterMode(Qt::MatchContains);
e->setCompleter(completer); e->setCompleter(completer);

@ -19,7 +19,11 @@ ENCODE_SOCKETS = {
VisionStreamType.VISION_STREAM_DRIVER: "driverEncodeData", VisionStreamType.VISION_STREAM_DRIVER: "driverEncodeData",
} }
def decoder(addr, vipc_server, vst, nvidia, debug=False): def decoder(addr, vst, nvidia, debug=False):
vipc_server = VisionIpcServer("camerad")
vipc_server.create_buffers(vst, 4, False, W, H)
vipc_server.start_listener()
sock_name = ENCODE_SOCKETS[vst] sock_name = ENCODE_SOCKETS[vst]
if debug: if debug:
print("start decoder for %s" % sock_name) print("start decoder for %s" % sock_name)
@ -101,14 +105,9 @@ def decoder(addr, vipc_server, vst, nvidia, debug=False):
class CompressedVipc: class CompressedVipc:
def __init__(self, addr, vision_streams, nvidia=False, debug=False): def __init__(self, addr, vision_streams, nvidia=False, debug=False):
self.vipc_server = VisionIpcServer("camerad")
for vst in vision_streams:
self.vipc_server.create_buffers(vst, 4, False, W, H)
self.vipc_server.start_listener()
self.procs = [] self.procs = []
for vst in vision_streams: for vst in vision_streams:
p = multiprocessing.Process(target=decoder, args=(addr, self.vipc_server, vst, nvidia, debug)) p = multiprocessing.Process(target=decoder, args=(addr, vst, nvidia, debug))
p.start() p.start()
self.procs.append(p) self.procs.append(p)

@ -1,6 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import unittest import unittest
from pathlib import Path
from parameterized import parameterized
from unittest import mock
from openpilot.system.hardware.hw import Paths
from openpilot.tools.lib.url_file import URLFile from openpilot.tools.lib.url_file import URLFile
@ -59,6 +65,34 @@ class TestFileDownload(unittest.TestCase):
self.compare_loads(large_file_url, length - 100, 100) self.compare_loads(large_file_url, length - 100, 100)
self.compare_loads(large_file_url) self.compare_loads(large_file_url)
@parameterized.expand([(True, ), (False, )])
def test_recover_from_missing_file(self, cache_enabled):
os.environ["FILEREADER_CACHE"] = "1" if cache_enabled else "0"
file_url = "http://localhost:5001/test.png"
file_exists = False
def get_length_online_mock(self):
if file_exists:
return 4
return -1
patch_length = mock.patch.object(URLFile, "get_length_online", get_length_online_mock)
patch_length.start()
try:
length = URLFile(file_url).get_length()
self.assertEqual(length, -1)
file_exists = True
length = URLFile(file_url).get_length()
self.assertEqual(length, 4)
finally:
tempfile_length = Path(Paths.download_cache_root()) / "ba2119904385654cb0105a2da174875f8e7648db175f202ecae6d6428b0e838f_length"
if tempfile_length.exists():
tempfile_length.unlink()
patch_length.stop()
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

@ -73,7 +73,7 @@ class URLFile:
return self._length return self._length
self._length = self.get_length_online() self._length = self.get_length_online()
if not self._force_download: if not self._force_download and self._length != -1:
with atomic_write_in_dir(file_length_path, mode="w") as file_length: with atomic_write_in_dir(file_length_path, mode="w") as file_length:
file_length.write(str(self._length)) file_length.write(str(self._length))
return self._length return self._length

@ -433,7 +433,7 @@ void Replay::stream() {
long etime = (cur_mono_time_ - evt_start_ts) / speed_; long etime = (cur_mono_time_ - evt_start_ts) / speed_;
long rtime = nanos_since_boot() - loop_start_ts; long rtime = nanos_since_boot() - loop_start_ts;
long behind_ns = etime - rtime; long behind_ns = etime - rtime;
// if behind_ns is greater than 1 second, it means that an invalid segemnt is skipped by seeking/replaying // if behind_ns is greater than 1 second, it means that an invalid segment is skipped by seeking/replaying
if (behind_ns >= 1 * 1e9 || speed_ != prev_replay_speed) { if (behind_ns >= 1 * 1e9 || speed_ != prev_replay_speed) {
// reset event start times // reset event start times
evt_start_ts = cur_mono_time_; evt_start_ts = cur_mono_time_;

@ -2,10 +2,16 @@
import sys import sys
if len(sys.argv) < 4: if len(sys.argv) < 4:
print(f"{sys.argv[0]} <route> <segment> <frame number>") print(f"{sys.argv[0]} <route> <segment> <frame number> [front|wide|driver]")
print('example: ./fetch_image_from_route.py "02c45f73a2e5c6e9|2020-06-01--18-03-08" 3 500') print('example: ./fetch_image_from_route.py "02c45f73a2e5c6e9|2020-06-01--18-03-08" 3 500 driver')
exit(0) exit(0)
cameras = {
"front": "cameras",
"wide": "ecameras",
"driver": "dcameras"
}
import requests import requests
from PIL import Image from PIL import Image
from openpilot.tools.lib.auth_config import get_token from openpilot.tools.lib.auth_config import get_token
@ -16,22 +22,22 @@ jwt = get_token()
route = sys.argv[1] route = sys.argv[1]
segment = int(sys.argv[2]) segment = int(sys.argv[2])
frame = int(sys.argv[3]) frame = int(sys.argv[3])
camera = cameras[sys.argv[4]] if len(sys.argv) > 4 and sys.argv[4] in cameras else "cameras"
url = 'https://api.commadotai.com/v1/route/'+sys.argv[1]+"/files" url = f'https://api.commadotai.com/v1/route/{route}/files'
r = requests.get(url, headers={"Authorization": "JWT "+jwt}, timeout=10) r = requests.get(url, headers={"Authorization": f"JWT {jwt}"}, timeout=10)
assert r.status_code == 200 assert r.status_code == 200
print("got api response") print("got api response")
cameras = r.json()['cameras'] segments = r.json()[camera]
if segment >= len(cameras): if segment >= len(segments):
raise Exception("segment %d not found, got %d segments" % (segment, len(cameras))) raise Exception("segment %d not found, got %d segments" % (segment, len(segments)))
fr = FrameReader(cameras[segment]) fr = FrameReader(segments[segment])
if frame >= fr.frame_count: if frame >= fr.frame_count:
raise Exception("frame %d not found, got %d frames" % (frame, fr.frame_count)) raise Exception("frame %d not found, got %d frames" % (frame, fr.frame_count))
im = Image.fromarray(fr.get(frame, count=1, pix_fmt="rgb24")[0]) im = Image.fromarray(fr.get(frame, count=1, pix_fmt="rgb24")[0])
fn = "uxxx_"+route.replace("|", "_")+"_%d_%d.png" % (segment, frame) fn = f"uxxx_{route.replace('|', '_')}_{segment}_{frame}.png"
im.save(fn) im.save(fn)
print(f"saved {fn}") print(f"saved {fn}")

@ -1,58 +1,82 @@
openpilot in simulator openpilot in simulator
===================== =====================
openpilot implements a [bridge](bridge.py) that allows it to run in the [CARLA simulator](https://carla.org/). openpilot implements a [bridge](run_bridge.py) that allows it to run in the [MetaDrive simulator](https://github.com/metadriverse/metadrive) or [CARLA simulator](https://carla.org/).
## System Requirements ## Launching openpilot
First, start openpilot.
``` bash
# Run locally
./tools/sim/launch_openpilot.sh
```
## Bridge usage
```
$ ./run_bridge.py -h
usage: run_bridge.py [-h] [--joystick] [--high_quality] [--dual_camera] [--simulator SIMULATOR] [--town TOWN] [--spawn_point NUM_SELECTED_SPAWN_POINT] [--host HOST] [--port PORT]
Bridge between the simulator and openpilot.
options:
-h, --help show this help message and exit
--joystick
--high_quality
--dual_camera
--simulator SIMULATOR
--town TOWN
--spawn_point NUM_SELECTED_SPAWN_POINT
--host HOST
--port PORT
```
#### Bridge Controls:
- To engage openpilot press 2, then press 1 to increase the speed and 2 to decrease.
- To disengage, press "S" (simulates a user brake)
#### All inputs:
```
| key | functionality |
|------|-----------------------|
| 1 | Cruise Resume / Accel |
| 2 | Cruise Set / Decel |
| 3 | Cruise Cancel |
| r | Reset Simulation |
| i | Toggle Ignition |
| q | Exit all |
| wasd | Control manually |
```
## MetaDrive
### Launching Metadrive
Start bridge processes located in tools/sim:
``` bash
./run_bridge.py --simulator metadrive
```
## Carla
CARLA is also partially supported, though the performance is not great. It needs to be manually installed with:
```bash
poetry install --with=carla
```
openpilot doesn't have any extreme hardware requirements, however CARLA requires an NVIDIA graphics card and is very resource-intensive and may not run smoothly on your system. openpilot doesn't have any extreme hardware requirements, however CARLA requires an NVIDIA graphics card and is very resource-intensive and may not run smoothly on your system.
For this case, we have the simulator in low quality by default. For this case, we have the simulator in low quality by default.
You can also check out the [CARLA python documentation](https://carla.readthedocs.io/en/latest/python_api/) to find more parameters to tune that might increase performance on your system. You can also check out the [CARLA python documentation](https://carla.readthedocs.io/en/latest/python_api/) to find more parameters to tune that might increase performance on your system.
## Running the simulator ### Launching Carla
Start Carla simulator, openpilot and bridge processes located in tools/sim: Start Carla simulator and bridge processes located in tools/sim:
``` bash ``` bash
# Terminal 1 # Terminal 1
./start_carla.sh ./start_carla.sh
# Terminal 2 - Run openpilot and bridge in one Docker: # Terminal 2
./start_openpilot_docker.sh ./run_bridge.py --simulator carla
# Running the latest local code execute
# Terminal 2:
./launch_openpilot.sh
# Terminal 3
./bridge.py
```
### Bridge usage
_Same commands hold for start_openpilot_docker_
``` ```
$ ./bridge.py -h
Usage: bridge.py [options]
Bridge between CARLA and openpilot.
Options:
-h, --help show this help message and exit
--joystick Use joystick input to control the car
--high_quality Set simulator to higher quality (requires good GPU)
--town TOWN Select map to drive in
--spawn_point NUM Number of the spawn point to start in
--host HOST Host address of Carla client (127.0.0.1 as default)
--port PORT Port of Carla client (2000 as default)
```
To engage openpilot press 1 a few times while focused on bridge.py to increase the cruise speed.
All inputs:
| key | functionality |
|:----:|:-----------------:|
| 1 | Cruise up 1 mph |
| 2 | Cruise down 1 mph |
| 3 | Cruise cancel |
| q | Exit all |
| wasd | Control manually |
## Further Reading ## Further Reading

@ -1,5 +1,3 @@
import carla
from openpilot.tools.sim.bridge.common import SimulatorBridge from openpilot.tools.sim.bridge.common import SimulatorBridge
from openpilot.tools.sim.bridge.carla.carla_world import CarlaWorld from openpilot.tools.sim.bridge.carla.carla_world import CarlaWorld
@ -15,6 +13,8 @@ class CarlaBridge(SimulatorBridge):
self.num_selected_spawn_point = arguments.num_selected_spawn_point self.num_selected_spawn_point = arguments.num_selected_spawn_point
def spawn_world(self): def spawn_world(self):
import carla
client = carla.Client(self.host, self.port) client = carla.Client(self.host, self.port)
client.set_timeout(5) client.set_timeout(5)

@ -1,4 +1,3 @@
import carla
import numpy as np import numpy as np
from openpilot.common.params import Params from openpilot.common.params import Params
@ -10,6 +9,8 @@ from openpilot.tools.sim.lib.camerad import W, H
class CarlaWorld(World): class CarlaWorld(World):
def __init__(self, client, high_quality, dual_camera, num_selected_spawn_point, town): def __init__(self, client, high_quality, dual_camera, num_selected_spawn_point, town):
super().__init__(dual_camera) super().__init__(dual_camera)
import carla
low_quality_layers = carla.MapLayer(carla.MapLayer.Ground | carla.MapLayer.Walls | carla.MapLayer.Decals) low_quality_layers = carla.MapLayer(carla.MapLayer.Ground | carla.MapLayer.Walls | carla.MapLayer.Decals)
layers = carla.MapLayer.All if high_quality else low_quality_layers layers = carla.MapLayer.All if high_quality else low_quality_layers
@ -139,5 +140,6 @@ class CarlaWorld(World):
self.world.tick() self.world.tick()
def reset(self): def reset(self):
import carla
self.vehicle.set_transform(self.spawn_point) self.vehicle.set_transform(self.spawn_point)
self.vehicle.set_target_velocity(carla.Vector3D()) self.vehicle.set_target_velocity(carla.Vector3D())

@ -68,7 +68,7 @@ class SimulatorBridge(ABC):
self.world.close() self.world.close()
def run(self, queue, retries=-1): def run(self, queue, retries=-1):
bridge_p = Process(target=self.bridge_keep_alive, args=(queue, retries), daemon=True) bridge_p = Process(name="bridge", target=self.bridge_keep_alive, args=(queue, retries))
bridge_p.start() bridge_p.start()
return bridge_p return bridge_p
@ -96,6 +96,10 @@ Ignition: {self.simulator_state.ignition} Engaged: {self.simulator_state.is_enga
100, self._exit_event)) 100, self._exit_event))
self.simulated_car_thread.start() self.simulated_car_thread.start()
self.simulated_camera_thread = threading.Thread(target=rk_loop, args=(functools.partial(self.simulated_sensors.send_camera_images, self.world),
20, self._exit_event))
self.simulated_camera_thread.start()
# Simulation tends to be slow in the initial steps. This prevents lagging later # Simulation tends to be slow in the initial steps. This prevents lagging later
for _ in range(20): for _ in range(20):
self.world.tick() self.world.tick()
@ -105,6 +109,8 @@ Ignition: {self.simulator_state.ignition} Engaged: {self.simulator_state.is_enga
throttle_op = steer_op = brake_op = 0.0 throttle_op = steer_op = brake_op = 0.0
self.simulator_state.cruise_button = 0 self.simulator_state.cruise_button = 0
self.simulator_state.left_blinker = False
self.simulator_state.right_blinker = False
throttle_manual = steer_manual = brake_manual = 0. throttle_manual = steer_manual = brake_manual = 0.
@ -127,6 +133,11 @@ Ignition: {self.simulator_state.ignition} Engaged: {self.simulator_state.is_enga
self.simulator_state.cruise_button = CruiseButtons.CANCEL self.simulator_state.cruise_button = CruiseButtons.CANCEL
elif m[1] == "main": elif m[1] == "main":
self.simulator_state.cruise_button = CruiseButtons.MAIN self.simulator_state.cruise_button = CruiseButtons.MAIN
elif m[0] == "blinker":
if m[1] == "left":
self.simulator_state.left_blinker = True
elif m[1] == "right":
self.simulator_state.right_blinker = True
elif m[0] == "ignition": elif m[0] == "ignition":
self.simulator_state.ignition = not self.simulator_state.ignition self.simulator_state.ignition = not self.simulator_state.ignition
elif m[0] == "reset": elif m[0] == "reset":
@ -136,6 +147,7 @@ Ignition: {self.simulator_state.ignition} Engaged: {self.simulator_state.is_enga
self.simulator_state.user_brake = brake_manual self.simulator_state.user_brake = brake_manual
self.simulator_state.user_gas = throttle_manual self.simulator_state.user_gas = throttle_manual
self.simulator_state.user_torque = steer_manual * 10000
steer_manual = steer_manual * -40 steer_manual = steer_manual * -40
@ -143,7 +155,8 @@ Ignition: {self.simulator_state.ignition} Engaged: {self.simulator_state.is_enga
self.simulated_sensors.update(self.simulator_state, self.world) self.simulated_sensors.update(self.simulator_state, self.world)
self.simulated_car.sm.update(0) self.simulated_car.sm.update(0)
self.simulator_state.is_engaged = self.simulated_car.sm['controlsState'].active controlsState = self.simulated_car.sm['controlsState']
self.simulator_state.is_engaged = controlsState.active
if self.simulator_state.is_engaged: if self.simulator_state.is_engaged:
throttle_op = clip(self.simulated_car.sm['carControl'].actuators.accel / 1.6, 0.0, 1.0) throttle_op = clip(self.simulated_car.sm['carControl'].actuators.accel / 1.6, 0.0, 1.0)
@ -151,7 +164,7 @@ Ignition: {self.simulator_state.ignition} Engaged: {self.simulator_state.is_enga
steer_op = self.simulated_car.sm['carControl'].actuators.steeringAngleDeg steer_op = self.simulated_car.sm['carControl'].actuators.steeringAngleDeg
self.past_startup_engaged = True self.past_startup_engaged = True
elif not self.past_startup_engaged: elif not self.past_startup_engaged and controlsState.engageable:
self.simulator_state.cruise_button = CruiseButtons.DECEL_SET # force engagement on startup self.simulator_state.cruise_button = CruiseButtons.DECEL_SET # force engagement on startup
throttle_out = throttle_op if self.simulator_state.is_engaged else throttle_manual throttle_out = throttle_op if self.simulator_state.is_engaged else throttle_manual

@ -1,39 +1,50 @@
import numpy as np
from metadrive.component.sensors.rgb_camera import RGBCamera from metadrive.component.sensors.rgb_camera import RGBCamera
from metadrive.component.sensors.base_camera import _cuda_enable from metadrive.component.sensors.base_camera import _cuda_enable
from metadrive.component.map.pg_map import MapGenerateMethod from metadrive.component.map.pg_map import MapGenerateMethod
from metadrive.engine.core.engine_core import EngineCore from panda3d.core import Vec3, Texture, GraphicsOutput
from metadrive.engine.core.image_buffer import ImageBuffer
from metadrive.envs.metadrive_env import MetaDriveEnv
from metadrive.obs.image_obs import ImageObservation
from panda3d.core import Vec3
from openpilot.tools.sim.bridge.common import SimulatorBridge from openpilot.tools.sim.bridge.common import SimulatorBridge
from openpilot.tools.sim.bridge.metadrive.metadrive_world import MetaDriveWorld from openpilot.tools.sim.bridge.metadrive.metadrive_world import MetaDriveWorld
from openpilot.tools.sim.lib.camerad import W, H from openpilot.tools.sim.lib.camerad import W, H
def apply_metadrive_patches(): C3_POSITION = Vec3(0, 0, 1)
# By default, metadrive won't try to use cuda images unless it's used as a sensor for vehicles, so patch that in
def add_image_sensor_patched(self, name: str, cls, args):
if self.global_config["image_on_cuda"]:# and name == self.global_config["vehicle_config"]["image_source"]:
sensor = cls(*args, self, cuda=True)
else:
sensor = cls(*args, self, cuda=False)
assert isinstance(sensor, ImageBuffer), "This API is for adding image sensor"
self.sensors[name] = sensor
EngineCore.add_image_sensor = add_image_sensor_patched class CopyRamRGBCamera(RGBCamera):
"""Camera which copies its content into RAM during the render process, for faster image grabbing."""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.cpu_texture = Texture()
self.buffer.addRenderTexture(self.cpu_texture, GraphicsOutput.RTMCopyRam)
# we aren't going to use the built-in observation stack, so disable it to save time def get_rgb_array_cpu(self):
def observe_patched(self, vehicle): origin_img = self.cpu_texture
return self.state img = np.frombuffer(origin_img.getRamImage().getData(), dtype=np.uint8)
img = img.reshape((origin_img.getYSize(), origin_img.getXSize(), -1))
img = img[:,:,:3] # RGBA to RGB
# img = np.swapaxes(img, 1, 0)
img = img[::-1] # Flip on vertical axis
return img
ImageObservation.observe = observe_patched
def arrive_destination_patch(self, vehicle): class RGBCameraWide(CopyRamRGBCamera):
return False def __init__(self, *args, **kwargs):
super(RGBCameraWide, self).__init__(*args, **kwargs)
cam = self.get_cam()
cam.setPos(C3_POSITION)
lens = self.get_lens()
lens.setFov(160)
MetaDriveEnv._is_arrive_destination = arrive_destination_patch class RGBCameraRoad(CopyRamRGBCamera):
def __init__(self, *args, **kwargs):
super(RGBCameraRoad, self).__init__(*args, **kwargs)
cam = self.get_cam()
cam.setPos(C3_POSITION)
lens = self.get_lens()
lens.setFov(40)
def straight_block(length): def straight_block(length):
@ -55,7 +66,7 @@ def curve_block(length, angle=45, direction=0):
class MetaDriveBridge(SimulatorBridge): class MetaDriveBridge(SimulatorBridge):
TICKS_PER_FRAME = 2 TICKS_PER_FRAME = 5
def __init__(self, args): def __init__(self, args):
self.should_render = False self.should_render = False
@ -63,30 +74,6 @@ class MetaDriveBridge(SimulatorBridge):
super(MetaDriveBridge, self).__init__(args) super(MetaDriveBridge, self).__init__(args)
def spawn_world(self): def spawn_world(self):
print("----------------------------------------------------------")
print("---- Spawning Metadrive world, this might take awhile ----")
print("----------------------------------------------------------")
apply_metadrive_patches()
C3_POSITION = Vec3(0, 0, 1)
class RGBCameraWide(RGBCamera):
def __init__(self, *args, **kwargs):
super(RGBCameraWide, self).__init__(*args, **kwargs)
cam = self.get_cam()
cam.setPos(C3_POSITION)
lens = self.get_lens()
lens.setFov(160)
class RGBCameraRoad(RGBCamera):
def __init__(self, *args, **kwargs):
super(RGBCameraRoad, self).__init__(*args, **kwargs)
cam = self.get_cam()
cam.setPos(C3_POSITION)
lens = self.get_lens()
lens.setFov(40)
sensors = { sensors = {
"rgb_road": (RGBCameraRoad, W, H, ) "rgb_road": (RGBCameraRoad, W, H, )
} }
@ -94,39 +81,39 @@ class MetaDriveBridge(SimulatorBridge):
if self.dual_camera: if self.dual_camera:
sensors["rgb_wide"] = (RGBCameraWide, W, H) sensors["rgb_wide"] = (RGBCameraWide, W, H)
env = MetaDriveEnv( config = dict(
dict( use_render=self.should_render,
use_render=self.should_render, vehicle_config=dict(
vehicle_config=dict( enable_reverse=False,
enable_reverse=False, image_source="rgb_road",
image_source="rgb_road", spawn_longitude=15
spawn_longitude=15 ),
), sensors=sensors,
sensors=sensors, image_on_cuda=_cuda_enable,
image_on_cuda=_cuda_enable, image_observation=True,
image_observation=True, interface_panel=[],
interface_panel=[], out_of_route_done=False,
out_of_route_done=False, on_continuous_line_done=False,
on_continuous_line_done=False, crash_vehicle_done=False,
crash_vehicle_done=False, crash_object_done=False,
crash_object_done=False, traffic_density=0.0, # traffic is incredibly expensive
map_config=dict( map_config=dict(
type=MapGenerateMethod.PG_MAP_FILE, type=MapGenerateMethod.PG_MAP_FILE,
config=[ config=[
None, None,
straight_block(120), straight_block(120),
curve_block(120, 90), curve_block(240, 90),
straight_block(120), straight_block(120),
curve_block(120, 90), curve_block(240, 90),
straight_block(120), straight_block(120),
curve_block(120, 90), curve_block(240, 90),
straight_block(120), straight_block(120),
curve_block(120, 90), curve_block(240, 90),
] ]
) ),
) decision_repeat=1,
) physics_world_step_size=self.TICKS_PER_FRAME/100,
preload_models=False
env.reset() )
return MetaDriveWorld(env) return MetaDriveWorld(config)

@ -0,0 +1,99 @@
import math
import numpy as np
from collections import namedtuple
from multiprocessing.connection import Connection
from metadrive.engine.core.engine_core import EngineCore
from metadrive.engine.core.image_buffer import ImageBuffer
from metadrive.envs.metadrive_env import MetaDriveEnv
from metadrive.obs.image_obs import ImageObservation
from openpilot.common.realtime import Ratekeeper
from openpilot.tools.sim.lib.common import vec3
from openpilot.tools.sim.lib.camerad import W, H
metadrive_state = namedtuple("metadrive_state", ["velocity", "position", "bearing", "steering_angle"])
def apply_metadrive_patches():
# By default, metadrive won't try to use cuda images unless it's used as a sensor for vehicles, so patch that in
def add_image_sensor_patched(self, name: str, cls, args):
if self.global_config["image_on_cuda"]:# and name == self.global_config["vehicle_config"]["image_source"]:
sensor = cls(*args, self, cuda=True)
else:
sensor = cls(*args, self, cuda=False)
assert isinstance(sensor, ImageBuffer), "This API is for adding image sensor"
self.sensors[name] = sensor
EngineCore.add_image_sensor = add_image_sensor_patched
# we aren't going to use the built-in observation stack, so disable it to save time
def observe_patched(self, vehicle):
return self.state
ImageObservation.observe = observe_patched
def arrive_destination_patch(self, vehicle):
return False
MetaDriveEnv._is_arrive_destination = arrive_destination_patch
def metadrive_process(dual_camera: bool, config: dict, camera_array, controls_recv: Connection, state_send: Connection, exit_event):
apply_metadrive_patches()
road_image = np.frombuffer(camera_array.get_obj(), dtype=np.uint8).reshape((H, W, 3))
env = MetaDriveEnv(config)
def reset():
env.reset()
env.vehicle.config["max_speed_km_h"] = 1000
reset()
def get_cam_as_rgb(cam):
cam = env.engine.sensors[cam]
img = cam.perceive(env.vehicle, clip=False)
if type(img) != np.ndarray:
img = img.get() # convert cupy array to numpy
return img
rk = Ratekeeper(100, None)
steer_ratio = 15
vc = [0,0]
while not exit_event.is_set():
state = metadrive_state(
velocity=vec3(x=float(env.vehicle.velocity[0]), y=float(env.vehicle.velocity[1]), z=0),
position=env.vehicle.position,
bearing=float(math.degrees(env.vehicle.heading_theta)),
steering_angle=env.vehicle.steering * env.vehicle.MAX_STEERING
)
state_send.send(state)
if controls_recv.poll(0):
while controls_recv.poll(0):
steer_angle, gas, should_reset = controls_recv.recv()
steer_metadrive = steer_angle * 1 / (env.vehicle.MAX_STEERING * steer_ratio)
steer_metadrive = np.clip(steer_metadrive, -1, 1)
vc = [steer_metadrive, gas]
if should_reset:
reset()
if rk.frame % 5 == 0:
obs, _, terminated, _, info = env.step(vc)
if terminated:
reset()
#if dual_camera:
# wide_road_image = get_cam_as_rgb("rgb_wide")
road_image[...] = get_cam_as_rgb("rgb_road")
rk.keep_time()

@ -1,65 +1,75 @@
import math import ctypes
import functools
import multiprocessing
import numpy as np import numpy as np
import time import time
from openpilot.tools.sim.lib.common import SimulatorState, World, vec3 from multiprocessing import Pipe, Array
from openpilot.tools.sim.bridge.metadrive.metadrive_process import metadrive_process, metadrive_state
from openpilot.tools.sim.lib.common import SimulatorState, World
from openpilot.tools.sim.lib.camerad import W, H
class MetaDriveWorld(World): class MetaDriveWorld(World):
def __init__(self, env, dual_camera = False): def __init__(self, config, dual_camera = False):
super().__init__(dual_camera) super().__init__(dual_camera)
self.env = env self.camera_array = Array(ctypes.c_uint8, W*H*3)
self.dual_camera = dual_camera self.road_image = np.frombuffer(self.camera_array.get_obj(), dtype=np.uint8).reshape((H, W, 3))
self.steer_ratio = 15 self.controls_send, self.controls_recv = Pipe()
self.state_send, self.state_recv = Pipe()
self.vc = [0.0,0.0] self.exit_event = multiprocessing.Event()
self.reset_time = 0 self.metadrive_process = multiprocessing.Process(name="metadrive process", target=
functools.partial(metadrive_process, dual_camera, config,
self.camera_array, self.controls_recv, self.state_send, self.exit_event))
self.metadrive_process.start()
def get_cam_as_rgb(self, cam): print("----------------------------------------------------------")
cam = self.env.engine.sensors[cam] print("---- Spawning Metadrive world, this might take awhile ----")
img = cam.perceive(self.env.vehicle, clip=False) print("----------------------------------------------------------")
if type(img) != np.ndarray:
img = img.get() # convert cupy array to numpy
return img
def apply_controls(self, steer_angle, throttle_out, brake_out): self.state_recv.recv() # wait for a state message to ensure metadrive is launched
steer_metadrive = steer_angle * 1 / (self.env.vehicle.MAX_STEERING * self.steer_ratio)
steer_metadrive = np.clip(steer_metadrive, -1, 1)
if (time.monotonic() - self.reset_time) > 5: self.steer_ratio = 15
self.vc[0] = steer_metadrive self.vc = [0.0,0.0]
self.reset_time = 0
self.should_reset = False
def apply_controls(self, steer_angle, throttle_out, brake_out):
if (time.monotonic() - self.reset_time) > 2:
self.vc[0] = steer_angle
if throttle_out: if throttle_out:
self.vc[1] = throttle_out/10 self.vc[1] = throttle_out
else: else:
self.vc[1] = -brake_out self.vc[1] = -brake_out
else: else:
self.vc[0] = 0 self.vc[0] = 0
self.vc[1] = 0 self.vc[1] = 0
self.controls_send.send([*self.vc, self.should_reset])
self.should_reset = False
def read_sensors(self, state: SimulatorState): def read_sensors(self, state: SimulatorState):
state.velocity = vec3(x=float(self.env.vehicle.velocity[0]), y=float(self.env.vehicle.velocity[1]), z=0) while self.state_recv.poll(0):
state.gps.from_xy(self.env.vehicle.position) md_state: metadrive_state = self.state_recv.recv()
state.bearing = float(math.degrees(self.env.vehicle.heading_theta)) state.velocity = md_state.velocity
state.steering_angle = self.env.vehicle.steering * self.env.vehicle.MAX_STEERING state.bearing = md_state.bearing
state.valid = True state.steering_angle = md_state.steering_angle
state.gps.from_xy(md_state.position)
state.valid = True
def read_cameras(self): def read_cameras(self):
if self.dual_camera: pass
self.wide_road_image = self.get_cam_as_rgb("rgb_wide")
self.road_image = self.get_cam_as_rgb("rgb_road")
def tick(self): def tick(self):
obs, _, terminated, _, info = self.env.step(self.vc) pass
if terminated:
self.reset()
def reset(self): def reset(self):
self.env.reset() self.should_reset = True
self.reset_time = time.monotonic()
def close(self): def close(self):
pass self.exit_event.set()
self.metadrive_process.join()

@ -49,9 +49,13 @@ class SimulatorState:
self.user_gas: float = 0 self.user_gas: float = 0
self.user_brake: float = 0 self.user_brake: float = 0
self.user_torque: float = 0
self.cruise_button = 0 self.cruise_button = 0
self.left_blinker = False
self.right_blinker = False
@property @property
def speed(self): def speed(self):
return math.sqrt(self.velocity.x ** 2 + self.velocity.y ** 2 + self.velocity.z ** 2) return math.sqrt(self.velocity.x ** 2 + self.velocity.y ** 2 + self.velocity.z ** 2)

@ -19,15 +19,15 @@ STDIN_FD = sys.stdin.fileno()
KEYBOARD_HELP = """ KEYBOARD_HELP = """
| key | functionality | | key | functionality |
----------------------------- |------|-----------------------|
| 1 | Cruise Resume | | 1 | Cruise Resume / Accel |
| 2 | Cruise Set | | 2 | Cruise Set / Decel |
| 3 | Cruise Cancel | | 3 | Cruise Cancel |
| r | Reset Simulation | | r | Reset Simulation |
| i | Toggle Ignition | | i | Toggle Ignition |
| q | Exit all | | q | Exit all |
| wasd | Control manually | | wasd | Control manually |
""" """
@ -67,6 +67,10 @@ def keyboard_poll_thread(q: 'Queue[str]'):
q.put("brake_%f" % 1.0) q.put("brake_%f" % 1.0)
elif c == 'd': elif c == 'd':
q.put("steer_%f" % -0.15) q.put("steer_%f" % -0.15)
elif c == 'z':
q.put("blinker_left")
elif c == 'x':
q.put("blinker_right")
elif c == 'i': elif c == 'i':
q.put("ignition") q.put("ignition")
elif c == 'r': elif c == 'r':

@ -59,7 +59,7 @@ class SimulatedCar:
msg.append(self.packer.make_can_msg("GEARBOX", 0, {"GEAR": 4, "GEAR_SHIFTER": 8})) msg.append(self.packer.make_can_msg("GEARBOX", 0, {"GEAR": 4, "GEAR_SHIFTER": 8}))
msg.append(self.packer.make_can_msg("GAS_PEDAL_2", 0, {})) msg.append(self.packer.make_can_msg("GAS_PEDAL_2", 0, {}))
msg.append(self.packer.make_can_msg("SEATBELT_STATUS", 0, {"SEATBELT_DRIVER_LATCHED": 1})) msg.append(self.packer.make_can_msg("SEATBELT_STATUS", 0, {"SEATBELT_DRIVER_LATCHED": 1}))
msg.append(self.packer.make_can_msg("STEER_STATUS", 0, {})) msg.append(self.packer.make_can_msg("STEER_STATUS", 0, {"STEER_TORQUE_SENSOR": simulator_state.user_torque}))
msg.append(self.packer.make_can_msg("STEERING_SENSORS", 0, {"STEER_ANGLE": simulator_state.steering_angle})) msg.append(self.packer.make_can_msg("STEERING_SENSORS", 0, {"STEER_ANGLE": simulator_state.steering_angle}))
msg.append(self.packer.make_can_msg("VSA_STATUS", 0, {})) msg.append(self.packer.make_can_msg("VSA_STATUS", 0, {}))
msg.append(self.packer.make_can_msg("STANDSTILL", 0, {"WHEELS_MOVING": 1 if simulator_state.speed >= 1.0 else 0})) msg.append(self.packer.make_can_msg("STANDSTILL", 0, {"WHEELS_MOVING": 1 if simulator_state.speed >= 1.0 else 0}))
@ -68,7 +68,12 @@ class SimulatedCar:
msg.append(self.packer.make_can_msg("DOORS_STATUS", 0, {})) msg.append(self.packer.make_can_msg("DOORS_STATUS", 0, {}))
msg.append(self.packer.make_can_msg("CRUISE_PARAMS", 0, {})) msg.append(self.packer.make_can_msg("CRUISE_PARAMS", 0, {}))
msg.append(self.packer.make_can_msg("CRUISE", 0, {})) msg.append(self.packer.make_can_msg("CRUISE", 0, {}))
msg.append(self.packer.make_can_msg("SCM_FEEDBACK", 0, {"MAIN_ON": 1})) msg.append(self.packer.make_can_msg("SCM_FEEDBACK", 0,
{
"MAIN_ON": 1,
"LEFT_BLINKER": simulator_state.left_blinker,
"RIGHT_BLINKER": simulator_state.right_blinker
}))
msg.append(self.packer.make_can_msg("POWERTRAIN_DATA", 0, msg.append(self.packer.make_can_msg("POWERTRAIN_DATA", 0,
{ {
"ACC_STATUS": int(simulator_state.is_engaged), "ACC_STATUS": int(simulator_state.is_engaged),

@ -122,6 +122,4 @@ class SimulatedSensors:
if (now - self.last_perp_update) > 0.25: if (now - self.last_perp_update) > 0.25:
self.send_peripheral_state() self.send_peripheral_state()
self.last_perp_update = now self.last_perp_update = now
self.send_camera_images(world)

@ -11,11 +11,11 @@ from openpilot.tools.sim.bridge.metadrive.metadrive_bridge import MetaDriveBridg
def parse_args(add_args=None): def parse_args(add_args=None):
parser = argparse.ArgumentParser(description='Bridge between CARLA and openpilot.') parser = argparse.ArgumentParser(description='Bridge between the simulator and openpilot.')
parser.add_argument('--joystick', action='store_true') parser.add_argument('--joystick', action='store_true')
parser.add_argument('--high_quality', action='store_true') parser.add_argument('--high_quality', action='store_true')
parser.add_argument('--dual_camera', action='store_true') parser.add_argument('--dual_camera', action='store_true')
parser.add_argument('--simulator', dest='simulator', type=str, default='carla') parser.add_argument('--simulator', dest='simulator', type=str, default='metadrive')
# Carla specific # Carla specific
parser.add_argument('--town', type=str, default='Town04_Opt') parser.add_argument('--town', type=str, default='Town04_Opt')

@ -2,5 +2,5 @@
tmux new -d -s carla-sim tmux new -d -s carla-sim
tmux send-keys "./launch_openpilot.sh" ENTER tmux send-keys "./launch_openpilot.sh" ENTER
tmux neww tmux neww
tmux send-keys "./bridge.py $*" ENTER tmux send-keys "./run_bridge.py $*" ENTER
tmux a -t carla-sim tmux a -t carla-sim

Loading…
Cancel
Save