Compare commits

..

1 Commits

Author SHA1 Message Date
github-actions[bot] ba6db36314 sunnypilot v2026.07.24-4586
version: sunnypilot v2026.003.000 (dev)
date: 2026-07-24T16:32:00
master commit: a0cc313fdc
2026-07-24 16:32:00 +00:00
318 changed files with 13388 additions and 10540 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ export VECLIB_MAXIMUM_THREADS=1
export QCOM_PRIORITY=12
if [ -z "$AGNOS_VERSION" ]; then
export AGNOS_VERSION="18.4"
export AGNOS_VERSION="18.5"
fi
export STAGING_ROOT="/data/safe_staging"
-17
View File
@@ -1,20 +1,3 @@
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
# On any failure, run the fallback launcher
trap 'exec ./launch_chffrplus.sh' ERR
C3_LAUNCH_SH="./openpilot/sunnypilot/system/hardware/c3/launch_chffrplus.sh"
MODEL="$(tr -d '\0' < "/sys/firmware/devicetree/base/model")"
export MODEL
if [ "$MODEL" = "comma tici" ]; then
# Force a failure if the launcher doesn't exist
[ -x "$C3_LAUNCH_SH" ] || false
# If it exists, run it
exec "$C3_LAUNCH_SH"
fi
exec ./launch_chffrplus.sh
Binary file not shown.
+11 -31
View File
@@ -1,6 +1,6 @@
<!--- AUTOGENERATED FROM selfdrive/car/CARS_template.md, DO NOT EDIT. --->
# Support Information for 421 Known Cars
# Support Information for 401 Known Cars
|Make|Model|Package|Support Level|
|---|---|---|:---:|
@@ -34,21 +34,11 @@
|Audi|Q5 2017-24|All|[Not compatible](#flexray)|
|Audi|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)|
|Audi|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)|
|Cadillac|CT6 Non-ACC 2017-18|No Adaptive Cruise Control (Non-ACC)|[Dashcam mode](#dashcam)|
|Cadillac|XT5 Non-ACC 2018|No Adaptive Cruise Control (Non-ACC)|[Dashcam mode](#dashcam)|
|Chevrolet|Bolt EUV 2022-23|Premier or Premier Redline Trim, without Super Cruise Package|[Upstream](#upstream)|
|Chevrolet|Bolt EUV LT Non-ACC 2022-23|No Adaptive Cruise Control (Non-ACC)|[Community](community)|
|Chevrolet|Bolt EV 2022-23|2LT Trim with Adaptive Cruise Control Package|[Upstream](#upstream)|
|Chevrolet|Bolt EV LT Non-ACC 2022-23|No Adaptive Cruise Control (Non-ACC)|[Community](community)|
|Chevrolet|Bolt EV Non-ACC 2017|No Adaptive Cruise Control (Non-ACC)|[Community](community)|
|Chevrolet|Bolt EV Non-ACC 2018-21|No Adaptive Cruise Control (Non-ACC)|[Community](community)|
|Chevrolet|Equinox 2019-22|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|Chevrolet|Equinox Non-ACC 2019-22|No Adaptive Cruise Control (Non-ACC)|[Community](community)|
|Chevrolet|Malibu Non-ACC 2016-23|No Adaptive Cruise Control (Non-ACC)|[Community](community)|
|Chevrolet|Silverado 1500 2020-21|Safety Package II|[Upstream](#upstream)|
|Chevrolet|Suburban Non-ACC 2016-20|No Adaptive Cruise Control (Non-ACC)|[Dashcam mode](#dashcam)|
|Chevrolet|Trailblazer 2021-22|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|Chevrolet|Trailblazer Non-ACC 2021-22|No Adaptive Cruise Control (Non-ACC)|[Dashcam mode](#dashcam)|
|Chrysler|Pacifica 2017-18|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|Chrysler|Pacifica 2019-20|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|Chrysler|Pacifica 2021-23|All|[Upstream](#upstream)|
@@ -86,7 +76,6 @@
|Genesis|G70 2018|All|[Upstream](#upstream)|
|Genesis|G70 2019-21|All|[Upstream](#upstream)|
|Genesis|G70 2022-23|All|[Upstream](#upstream)|
|Genesis|G70 Non-SCC 2021|No Smart Cruise Control (Non-SCC)|[Dashcam mode](#dashcam)|
|Genesis|G80 2017|All|[Upstream](#upstream)|
|Genesis|G80 2018-19|All|[Upstream](#upstream)|
|Genesis|G80 (2.5T Advanced Trim, with HDA II) 2024|Highway Driving Assist II|[Upstream](#upstream)|
@@ -116,7 +105,6 @@
|Honda|Civic Hatchback Hybrid 2025-26|All|[Upstream](#upstream)|
|Honda|Civic Hatchback Hybrid (Europe only) 2023|All|[Upstream](#upstream)|
|Honda|Civic Hybrid 2025-26|All|[Upstream](#upstream)|
|Honda|Clarity 2018-21|All|[Community](community)|
|Honda|Clarity 2018-21|All|[Community](#community)|
|Honda|CR-V 2015-16|Touring Trim|[Upstream](#upstream)|
|Honda|CR-V 2017-22|Honda Sensing|[Upstream](#upstream)|
@@ -140,19 +128,18 @@
|Honda|Pilot 2016-22|Honda Sensing|[Upstream](#upstream)|
|Honda|Pilot 2023-25|All|[Upstream](#upstream)|
|Honda|Pilot 2026|All|[Community](#community)|
|Honda|Prologue 2024-25|All|[Not compatible](#can-bus-security)|
|Honda|Prologue 2024-26|All|[Not compatible](#can-bus-security)|
|Honda|Ridgeline 2017-25|Honda Sensing|[Upstream](#upstream)|
|Honda|Ridgeline 2026|All|[Community](#community)|
|Hyundai|Azera 2022|All|[Upstream](#upstream)|
|Hyundai|Azera Hybrid 2019|All|[Upstream](#upstream)|
|Hyundai|Azera Hybrid 2020|All|[Upstream](#upstream)|
|Hyundai|Bayon Non-SCC 2021|No Smart Cruise Control (Non-SCC)|[Dashcam mode](#dashcam)|
|Hyundai|Custin 2023|All|[Upstream](#upstream)|
|Hyundai|Elantra 2017-18|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Elantra 2019|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Elantra 2021-23|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Elantra GT 2017-20|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Elantra Non-SCC 2022|No Smart Cruise Control (Non-SCC)|[Community](community)|
|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|i30 2017-19|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Ioniq 5 (Southeast Asia and Europe only) 2022-24|All|[Upstream](#upstream)|
@@ -167,13 +154,11 @@
|Hyundai|Ioniq Plug-in Hybrid 2019|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Ioniq Plug-in Hybrid 2020-22|All|[Upstream](#upstream)|
|Hyundai|Kona 2020|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Kona 2022-23|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Kona 2022-23|Smart Cruise Control (SCC)|[Dashcam mode](#dashcam)|
|Hyundai|Kona Electric 2018-21|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Kona Electric 2022-23|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Kona Electric (with HDA II, Korea only) 2023|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Kona Electric Non-SCC 2019|No Smart Cruise Control (Non-SCC)|[Community](community)|
|Hyundai|Kona Hybrid 2020|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Kona Non-SCC 2019|No Smart Cruise Control (Non-SCC)|[Community](community)|
|Hyundai|Nexo 2021|All|[Upstream](#upstream)|
|Hyundai|Palisade 2020-22|All|[Upstream](#upstream)|
|Hyundai|Palisade 2023-24|Highway Driving Assist II|[Community](#community)|
@@ -199,14 +184,11 @@
|Kia|Carnival 2022-24|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Carnival (China only) 2023|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Ceed 2019-21|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Ceed Plug-in Hybrid Non-SCC 2022|No Smart Cruise Control (Non-SCC)|[Community](community)|
|Kia|EV6 (Southeast Asia only) 2022-24|All|[Upstream](#upstream)|
|Kia|EV6 (with HDA II) 2022-24|Highway Driving Assist II|[Upstream](#upstream)|
|Kia|EV6 (without HDA II) 2022-24|Highway Driving Assist|[Upstream](#upstream)|
|Kia|Forte 2019-21|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Forte 2022-23|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Forte Non-SCC 2019|No Smart Cruise Control (Non-SCC)|[Community](community)|
|Kia|Forte Non-SCC 2021|No Smart Cruise Control (Non-SCC)|[Dashcam mode](#dashcam)|
|Kia|K5 2021-24|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|K5 Hybrid 2020-22|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|K7 2017|Smart Cruise Control (SCC)|[Upstream](#upstream)|
@@ -230,7 +212,6 @@
|Kia|Optima Hybrid 2017|Advanced Smart Cruise Control|[Dashcam mode](#dashcam)|
|Kia|Optima Hybrid 2019|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Seltos 2021|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Seltos Non-SCC 2023-24|No Smart Cruise Control (Non-SCC)|[Dashcam mode](#dashcam)|
|Kia|Sorento 2018|Advanced Smart Cruise Control & LKAS|[Upstream](#upstream)|
|Kia|Sorento 2019|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Sorento 2021-23|Smart Cruise Control (SCC)|[Upstream](#upstream)|
@@ -278,14 +259,13 @@
|Mazda|CX-9 2021-23|All|[Upstream](#upstream)|
|Nissan|Altima 2019-24|ProPILOT Assist|[Upstream](#upstream)|
|Nissan|Leaf 2018-23|ProPILOT Assist|[Upstream](#upstream)|
|Nissan|Leaf IC 2018-23|ProPILOT Assist|[Upstream](#upstream)|
|Nissan|Rogue 2018-20|ProPILOT Assist|[Upstream](#upstream)|
|Nissan|X-Trail 2017|ProPILOT Assist|[Upstream](#upstream)|
|Peugeot|208 2019-25|Adaptive Cruise Control (ACC) & Lane Assist|[Dashcam mode](#dashcam)|
|Porsche|Macan 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|[Dashcam mode](#dashcam)|
|Ram|1500 2019-24|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|Ram|2500 2020-24|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|Ram|3500 2019-22|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|Ram|2500 2020-24|Adaptive Cruise Control (ACC)|[Dashcam mode](#dashcam)|
|Ram|3500 2019-22|Adaptive Cruise Control (ACC)|[Dashcam mode](#dashcam)|
|Rivian|R1S 2022-24|All|[Upstream](#upstream)|
|Rivian|R1T 2022-24|All|[Upstream](#upstream)|
|SEAT|Alhambra 2018-20|Adaptive Cruise Control (ACC) & Lane Assist|[Dashcam mode](#dashcam)|
@@ -296,16 +276,16 @@
|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance|[Upstream](#upstream)|
|Subaru|Crosstrek 2020-23|EyeSight Driver Assistance|[Upstream](#upstream)|
|Subaru|Crosstrek Hybrid 2020|EyeSight Driver Assistance|[Dashcam mode](#dashcam)|
|Subaru|Forester 2017-18|EyeSight Driver Assistance|[Upstream](#upstream)|
|Subaru|Forester 2017-18|EyeSight Driver Assistance|[Dashcam mode](#dashcam)|
|Subaru|Forester 2019-21|All|[Upstream](#upstream)|
|Subaru|Forester 2022-24|All|[Dashcam mode](#dashcam)|
|Subaru|Forester Hybrid 2020|EyeSight Driver Assistance|[Dashcam mode](#dashcam)|
|Subaru|Impreza 2017-19|EyeSight Driver Assistance|[Upstream](#upstream)|
|Subaru|Impreza 2020-22|EyeSight Driver Assistance|[Upstream](#upstream)|
|Subaru|Legacy 2015-18|EyeSight Driver Assistance|[Upstream](#upstream)|
|Subaru|Legacy 2015-18|EyeSight Driver Assistance|[Dashcam mode](#dashcam)|
|Subaru|Legacy 2020-22|All|[Upstream](#upstream)|
|Subaru|Outback 2015-17|EyeSight Driver Assistance|[Upstream](#upstream)|
|Subaru|Outback 2018-19|EyeSight Driver Assistance|[Upstream](#upstream)|
|Subaru|Outback 2015-17|EyeSight Driver Assistance|[Dashcam mode](#dashcam)|
|Subaru|Outback 2018-19|EyeSight Driver Assistance|[Dashcam mode](#dashcam)|
|Subaru|Outback 2020-22|All|[Upstream](#upstream)|
|Subaru|Outback 2023|All|[Dashcam mode](#dashcam)|
|Subaru|Solterra 2023-25|All|[Not compatible](#can-bus-security)|
@@ -322,7 +302,7 @@
|Škoda|Superb 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)|
|Tesla|Model 3 (with HW3) 2019-23|All|[Upstream](#upstream)|
|Tesla|Model 3 (with HW4) 2024-25|All|[Upstream](#upstream)|
|Tesla|Model X (with HW4) 2024|All|[Community](community)|
|Tesla|Model X (with HW4) 2024|All|[Dashcam mode](#dashcam)|
|Tesla|Model Y (with HW3) 2020-23|All|[Upstream](#upstream)|
|Tesla|Model Y (with HW4) 2024-25|All|[Upstream](#upstream)|
|Toyota|Alphard 2019-20|All|[Upstream](#upstream)|
+90 -69
View File
@@ -244,7 +244,9 @@ struct CarState {
standstill @4 :Bool;
nonAdaptive @5 :Bool;
speedOffsetDEPRECATED @3 :Float32;
deprecated :group {
speedOffset @3 :Float32;
}
}
enum GearShifter {
@@ -281,17 +283,18 @@ struct CarState {
}
}
# deprecated
errorsDEPRECATED @0 :List(OnroadEventDEPRECATED.EventName);
gasDEPRECATED @3 :Float32;
brakeDEPRECATED @5 :Float32;
brakeLightsDEPRECATED @19 :Bool;
steeringRateLimitedDEPRECATED @29 :Bool;
canMonoTimesDEPRECATED @12: List(UInt64);
canRcvTimeoutDEPRECATED @49 :Bool;
eventsDEPRECATED @13 :List(OnroadEventDEPRECATED);
clutchPressedDEPRECATED @28 :Bool;
engineRpmDEPRECATED @46 :Float32;
deprecated :group {
errors @0 :List(OnroadEventDEPRECATED.EventName);
gas @3 :Float32;
brake @5 :Float32;
brakeLights @19 :Bool;
steeringRateLimited @29 :Bool;
canMonoTimes @12: List(UInt64);
canRcvTimeout @49 :Bool;
events @13 :List(OnroadEventDEPRECATED);
clutchPressed @28 :Bool;
engineRpm @46 :Float32;
}
}
# ******* radar state @ 20hz *******
@@ -386,8 +389,11 @@ struct CarControl {
cancel @0: Bool;
resume @1: Bool;
override @4: Bool;
speedOverrideDEPRECATED @2: Float32;
accelOverrideDEPRECATED @3: Float32;
deprecated :group {
speedOverride @2: Float32;
accelOverride @3: Float32;
}
}
struct HUDControl {
@@ -434,13 +440,15 @@ struct CarControl {
}
}
gasDEPRECATED @1 :Float32;
brakeDEPRECATED @2 :Float32;
steeringTorqueDEPRECATED @3 :Float32;
activeDEPRECATED @7 :Bool;
rollDEPRECATED @8 :Float32;
pitchDEPRECATED @9 :Float32;
actuatorsOutputDEPRECATED @10 :Actuators;
deprecated :group {
gas @1 :Float32;
brake @2 :Float32;
steeringTorque @3 :Float32;
active @7 :Bool;
roll @8 :Float32;
pitch @9 :Float32;
actuatorsOutput @10 :Actuators;
}
}
struct CarOutput {
@@ -491,22 +499,16 @@ struct CarParams {
lateralParams @48 :LateralParams;
lateralTuning :union {
pid @26 :LateralPIDTuning;
indiDEPRECATED @27 :LateralINDITuning;
lqrDEPRECATED @40 :LateralLQRTuning;
indiDEPRECATED @27 :LateralINDITuningDEPRECATED;
lqrDEPRECATED @40 :LateralLQRTuningDEPRECATED;
torque @67 :LateralTorqueTuning;
}
steerLimitAlert @28 :Bool;
steerLimitTimer @47 :Float32; # time before steerLimitAlert is issued
vEgoStopping @29 :Float32; # Speed at which the car goes into stopping state
vEgoStarting @59 :Float32; # Speed at which the car goes into starting state
steerControlType @34 :SteerControlType;
radarUnavailable @35 :Bool; # True when radar objects aren't visible on CAN or aren't parsed out
stopAccel @60 :Float32; # Required acceleration to keep vehicle stationary
stoppingDecelRate @52 :Float32; # m/s^2/s while trying to stop
startAccel @32 :Float32; # Required acceleration to get car moving
startingState @70 :Bool; # Does this car make use of special starting state
steerActuatorDelay @36 :Float32; # Steering wheel actuator delay in seconds
longitudinalActuatorDelay @58 :Float32; # Gas/Brake actuator delay in seconds
@@ -529,8 +531,11 @@ struct CarParams {
struct SafetyConfig {
safetyModel @0 :SafetyModel;
safetyParam @3 :UInt16;
safetyParamDEPRECATED @1 :Int16;
safetyParam2DEPRECATED @2 :UInt32;
deprecated :group {
safetyParam @1 :Int16;
safetyParam2 @2 :UInt32;
}
}
struct LateralParams {
@@ -551,11 +556,14 @@ struct CarParams {
steeringAngleDeadzoneDeg @5 :Float32;
latAccelFactor @6 :Float32;
latAccelOffset @7 :Float32;
useSteeringAngleDEPRECATED @0 :Bool;
kpDEPRECATED @1 :Float32;
kiDEPRECATED @2 :Float32;
kfDEPRECATED @4 :Float32;
kdDEPRECATED @8 : Float32;
deprecated :group {
useSteeringAngle @0 :Bool;
kp @1 :Float32;
ki @2 :Float32;
kf @4 :Float32;
kd @8 : Float32;
}
}
struct LongitudinalPIDTuning {
@@ -563,12 +571,15 @@ struct CarParams {
kpV @1 :List(Float32);
kiBP @2 :List(Float32);
kiV @3 :List(Float32);
kfDEPRECATED @6 :Float32;
deadzoneBPDEPRECATED @4 :List(Float32);
deadzoneVDEPRECATED @5 :List(Float32);
deprecated :group {
kf @6 :Float32;
deadzoneBP @4 :List(Float32);
deadzoneV @5 :List(Float32);
}
}
struct LateralINDITuning {
struct LateralINDITuningDEPRECATED {
outerLoopGainBP @4 :List(Float32);
outerLoopGainV @5 :List(Float32);
innerLoopGainBP @6 :List(Float32);
@@ -578,13 +589,15 @@ struct CarParams {
actuatorEffectivenessBP @10 :List(Float32);
actuatorEffectivenessV @11 :List(Float32);
outerLoopGainDEPRECATED @0 :Float32;
innerLoopGainDEPRECATED @1 :Float32;
timeConstantDEPRECATED @2 :Float32;
actuatorEffectivenessDEPRECATED @3 :Float32;
deprecated :group {
outerLoopGain @0 :Float32;
innerLoopGain @1 :Float32;
timeConstant @2 :Float32;
actuatorEffectiveness @3 :Float32;
}
}
struct LateralLQRTuning {
struct LateralLQRTuningDEPRECATED {
scale @0 :Float32;
ki @1 :Float32;
dcGain @2 :Float32;
@@ -707,28 +720,36 @@ struct CarParams {
gateway @1; # Integration at vehicle's CAN gateway
}
enableGasInterceptorDEPRECATED @2 :Bool;
enableCameraDEPRECATED @4 :Bool;
enableApgsDEPRECATED @6 :Bool;
steerRateCostDEPRECATED @33 :Float32;
isPandaBlackDEPRECATED @39 :Bool;
hasStockCameraDEPRECATED @57 :Bool;
safetyParamDEPRECATED @10 :Int16;
safetyModelDEPRECATED @9 :SafetyModel;
safetyModelPassiveDEPRECATED @42 :SafetyModel = silent;
minSpeedCanDEPRECATED @51 :Float32;
communityFeatureDEPRECATED @46: Bool;
startingAccelRateDEPRECATED @53 :Float32;
steerMaxBPDEPRECATED @11 :List(Float32);
steerMaxVDEPRECATED @12 :List(Float32);
gasMaxBPDEPRECATED @13 :List(Float32);
gasMaxVDEPRECATED @14 :List(Float32);
brakeMaxBPDEPRECATED @15 :List(Float32);
brakeMaxVDEPRECATED @16 :List(Float32);
directAccelControlDEPRECATED @30 :Bool;
maxSteeringAngleDegDEPRECATED @54 :Float32;
longitudinalActuatorDelayLowerBoundDEPRECATED @61 :Float32;
stoppingControlDEPRECATED @31 :Bool; # Does the car allow full control even at lows speeds when stopping
radarTimeStepDEPRECATED @45: Float32 = 0.05; # time delta between radar updates, 20Hz is very standard
enableDsuDEPRECATED @5 :Bool; # driving support unit
deprecated :group {
enableGasInterceptor @2 :Bool;
enableCamera @4 :Bool;
enableApgs @6 :Bool;
steerLimitAlert @28 :Bool;
steerRateCost @33 :Float32;
isPandaBlack @39 :Bool;
hasStockCamera @57 :Bool;
safetyParam @10 :Int16;
safetyModel @9 :SafetyModel;
safetyModelPassive @42 :SafetyModel = silent;
minSpeedCan @51 :Float32;
communityFeature @46: Bool;
startingAccelRate @53 :Float32;
steerMaxBP @11 :List(Float32);
steerMaxV @12 :List(Float32);
gasMaxBP @13 :List(Float32);
gasMaxV @14 :List(Float32);
brakeMaxBP @15 :List(Float32);
brakeMaxV @16 :List(Float32);
directAccelControl @30 :Bool;
maxSteeringAngleDeg @54 :Float32;
longitudinalActuatorDelayLowerBound @61 :Float32;
stoppingControl @31 :Bool; # Does the car allow full control even at lows speeds when stopping
radarTimeStep @45: Float32 = 0.05; # time delta between radar updates, 20Hz is very standard
enableDsu @5 :Bool; # driving support unit
vEgoStarting @59 :Float32; # Speed at which the car goes into starting state
startAccel @32 :Float32; # Required acceleration to get car moving
startingState @70 :Bool; # Does this car make use of special starting state
vEgoStopping @29 :Float32; # Speed at which the car goes into stopping state
stoppingDecelRate @52 :Float32; # m/s^2/s while trying to stop
}
}
+2 -1
View File
@@ -52,7 +52,8 @@ class CAR(Platforms):
CommunityCarDocs("Honda Accord Hybrid 2017"),
CommunityCarDocs("Honda Clarity 2018-21"),
CommunityCarDocs("Honda Pilot 2026"),
GMSecurityCarDocs("Honda Prologue 2024-25"),
GMSecurityCarDocs("Honda Prologue 2024-26"),
CommunityCarDocs("Honda Ridgeline 2026"),
],
)
@@ -97,7 +97,6 @@ class RadarInterface(RadarInterfaceBase):
self.clusters: list[Cluster] = []
self.updated_messages = set()
self.track_id = 0
self.radar = DBC[CP.carFingerprint].get(Bus.radar)
self.scan_index_invalid_cnt = 0
self.radar_unavailable_cnt = 0
-3
View File
@@ -124,9 +124,6 @@ class CarInterface(CarInterfaceBase, CarInterfaceExt):
# Tuning for experimental long
ret.longitudinalTuning.kiV = [2.0, 1.5]
ret.stoppingDecelRate = 2.0 # reach brake quickly after enabling
ret.vEgoStopping = 0.25
ret.vEgoStarting = 0.25
if alpha_long:
ret.pcmCruise = False
+2 -2
View File
@@ -198,13 +198,13 @@ class CarState(CarStateBase, CarStateExt):
self.brake_switch_prev = brake_switch
ret.brakePressed = (cp.vl["POWERTRAIN_DATA"]["BRAKE_PRESSED"] != 0) or self.brake_switch_active
ret.brakeDEPRECATED = cp.vl["VSA_STATUS"]["USER_BRAKE"]
ret.deprecated.brake = cp.vl["VSA_STATUS"]["USER_BRAKE"]
ret.cruiseState.enabled = cp.vl["POWERTRAIN_DATA"]["ACC_STATUS"] != 0
ret.cruiseState.available = bool(cp.vl[self.car_state_scm_msg]["MAIN_ON"])
# Gets rid of Pedal Grinding noise when brake is pressed at slow speeds for some models
if self.CP.carFingerprint in (CAR.HONDA_PILOT, CAR.HONDA_RIDGELINE):
if ret.brakeDEPRECATED > 0.1:
if ret.deprecated.brake > 0.1:
ret.brakePressed = True
if self.CP.carFingerprint in HONDA_BOSCH:
@@ -14,7 +14,6 @@ def _create_nidec_can_parser(car_fingerprint):
class RadarInterface(RadarInterfaceBase):
def __init__(self, CP, CP_SP):
super().__init__(CP, CP_SP)
self.track_id = 0
self.radar_fault = False
self.radar_wrong_config = False
self.radar_off_can = CP.radarUnavailable
@@ -133,9 +133,6 @@ class CarInterface(CarInterfaceBase):
ret.radarUnavailable = RADAR_START_ADDR not in fingerprint[1] or Bus.radar not in DBC[ret.carFingerprint]
ret.openpilotLongitudinalControl = alpha_long and ret.alphaLongitudinalAvailable
ret.pcmCruise = not ret.openpilotLongitudinalControl
ret.startingState = True
ret.vEgoStarting = 0.1
ret.startAccel = 1.0
ret.longitudinalActuatorDelay = 0.5
if ret.openpilotLongitudinalControl:
@@ -27,7 +27,6 @@ class RadarInterface(RadarInterfaceBase, RadarInterfaceExt):
RadarInterfaceExt.__init__(self, CP, CP_SP)
self.updated_messages = set()
self.trigger_msg = RADAR_START_ADDR + RADAR_MSG_COUNT - 1
self.track_id = 0
self.radar_off_can = CP.radarUnavailable
self.rcp = get_radar_can_parser(CP)
+1 -3
View File
@@ -86,6 +86,7 @@ class RadarInterfaceBase(ABC):
self.CP_SP = CP_SP
self.rcp = None
self.pts: dict[int, structs.RadarData.RadarPoint] = {}
self.track_id: int = 0
self.frame = 0
def update(self, can_packets: list[tuple[int, list[CanData]]]) -> structs.RadarDataT | None:
@@ -245,9 +246,6 @@ class CarInterfaceBase(ABC, CarInterfaceBaseSP):
ret.steerRatioRear = 0. # no rear steering, at least on the listed cars aboveA
ret.openpilotLongitudinalControl = False
ret.stopAccel = -2.0
ret.stoppingDecelRate = 0.8 # brake_travel/s while trying to stop
ret.vEgoStopping = 0.5
ret.vEgoStarting = 0.5
ret.longitudinalTuning.kpBP = [0.]
ret.longitudinalTuning.kpV = [0.]
ret.longitudinalTuning.kiBP = [0.]
@@ -36,7 +36,6 @@ class CarInterface(CarInterfaceBase):
ret.safetyConfigs[0].safetyParam |= RivianSafetyFlags.LONG_CONTROL.value
ret.longitudinalActuatorDelay = 0.35
ret.vEgoStopping = 0.25
ret.stopAccel = 0
return ret
@@ -19,7 +19,6 @@ class RadarInterface(RadarInterfaceBase):
super().__init__(CP, CP_SP)
self.updated_messages = set()
self.trigger_msg = RADAR_START_ADDR + RADAR_MSG_COUNT - 1
self.track_id = 0
self.radar_off_can = CP.radarUnavailable
self.rcp = get_radar_can_parser(CP)
@@ -41,10 +41,6 @@ class CarInterface(CarInterfaceBase):
ret.openpilotLongitudinalControl = True
ret.safetyConfigs[0].safetyParam |= TeslaSafetyFlags.LONG_CONTROL.value
ret.vEgoStopping = 0.1
ret.vEgoStarting = 0.1
ret.stoppingDecelRate = 0.3
fsd_14 = any(fw.ecu == Ecu.eps and fw.fwVersion in FSD_14_FW.get(candidate, []) for fw in car_fw)
if fsd_14:
ret.flags |= TeslaFlags.FSD_14.value
@@ -26,7 +26,6 @@ class RadarInterface(RadarInterfaceBase):
super().__init__(CP, CP_SP)
self.updated_messages = set()
self.trigger_msg = RADAR_START_ADDR + RADAR_MSG_COUNT - 1
self.track_id = 0
self.radar_off_can = CP.radarUnavailable
self.rcp = get_radar_can_parser(CP)
@@ -119,10 +119,6 @@ class CarInterface(CarInterfaceBase):
if candidate in TSS2_CAR:
ret.flags |= ToyotaFlags.RAISED_ACCEL_LIMIT.value
ret.vEgoStopping = 0.25
ret.vEgoStarting = 0.25
ret.stoppingDecelRate = 0.3 # reach stopping target smoothly
# Hybrids have much quicker longitudinal actuator response
if ret.flags & ToyotaFlags.HYBRID.value:
ret.longitudinalActuatorDelay = 0.05
@@ -26,7 +26,6 @@ def _create_radar_can_parser(car_fingerprint):
class RadarInterface(RadarInterfaceBase):
def __init__(self, CP, CP_SP):
super().__init__(CP, CP_SP)
self.track_id = 0
if CP.carFingerprint in TSS2_CAR:
self.RADAR_A_MSGS = list(range(0x180, 0x190))
@@ -138,7 +138,8 @@ class CarController(CarControllerBase):
stopping = actuators.longControlState == LongCtrlState.stopping
if self.CP.flags & VolkswagenFlags.MEB:
starting = actuators.longControlState == LongCtrlState.starting and CS.out.vEgo <= self.CP.vEgoStarting
# only send ACC_HMS_RELEASE when in cruise standstill and want to resume
starting = actuators.longControlState == LongCtrlState.pid and CS.esp_hold_confirmation
accel = float(np.clip(actuators.accel, self.CCP.ACCEL_MIN, self.CCP.ACCEL_MAX) if CC.enabled else 0)
long_override = CC.cruiseControl.override or CS.out.gasPressed
@@ -148,11 +149,10 @@ class CarController(CarControllerBase):
self.long_disabled_counter = min(self.long_disabled_counter + 1, 5) if not CC.enabled else 0
long_disabling = not CC.enabled and self.long_disabled_counter < 5
acc_control = mebcan.acc_control_value(CS.out.cruiseState.available, CS.out.accFaulted, CC.enabled, long_override)
acc_hold_type = mebcan.acc_hold_type(CS.out.cruiseState.available, CS.out.accFaulted, CC.enabled, starting, stopping,
CS.esp_hold_confirmation, long_override, long_override_begin, long_disabling)
can_sends.extend(mebcan.create_acc_accel_control(self.packer_pt, self.CAN.pt, CS.acc_type, CC.enabled,
4.0, 4.0, 0., 0.,
acc_control = mebcan.get_acc_control(CS.out, CC, long_override)
acc_hold_type = mebcan.get_acc_hold_type(CS.out, CC, starting, stopping,
CS.esp_hold_confirmation, long_override, long_override_begin, long_disabling)
can_sends.extend(mebcan.create_acc_accel_control(self.packer_pt, self.CAN.pt, self.CCP, CS.acc_type, CC.enabled,
accel, acc_control, acc_hold_type, stopping, starting, CS.esp_hold_confirmation,
CS.out.vEgoRaw * CV.MS_TO_KPH, long_override, CS.travel_assist_available))
self.accel_last = accel
@@ -160,7 +160,7 @@ class CarController(CarControllerBase):
else:
acc_control = self.CCS.acc_control_value(CS.out.cruiseState.available, CS.out.accFaulted, CC.longActive)
accel = float(np.clip(actuators.accel, self.CCP.ACCEL_MIN, self.CCP.ACCEL_MAX) if CC.longActive else 0)
starting = actuators.longControlState == LongCtrlState.pid and (CS.esp_hold_confirmation or CS.out.vEgo < self.CP.vEgoStopping)
starting = actuators.longControlState == LongCtrlState.pid and (CS.esp_hold_confirmation or CS.out.vEgo < 0.25)
can_sends.extend(self.CCS.create_acc_accel_control(self.packer_pt, self.CAN.pt, CS.acc_type, CC.longActive, accel,
acc_control, stopping, starting, CS.esp_hold_confirmation))
@@ -189,8 +189,7 @@ class CarController(CarControllerBase):
lead_distance = 0
if hud_control.leadVisible and self.frame * DT_CTRL > 1.0:
lead_distance = 8
acc_hud_status = mebcan.acc_hud_status_value(CS.out.cruiseState.available, CS.out.accFaulted, CC.enabled,
CC.cruiseControl.override or CS.out.gasPressed)
acc_hud_status = mebcan.get_acc_hud_status(CS.out, CC, CC.cruiseControl.override or CS.out.gasPressed)
can_sends.append(mebcan.create_acc_hud_control(self.packer_pt, self.CAN.pt, acc_hud_status, hud_control.setSpeed * CV.MS_TO_KPH,
hud_control.leadVisible, hud_control.leadDistanceBars + 1, show_distance_bars,
CS.esp_hold_confirmation, lead_distance, 0, fcw_alert))
@@ -298,7 +298,8 @@ class CarState(CarStateBase):
ret.cruiseState.speed = 0
else:
ret.cruiseState.nonAdaptive = bool(pt_cp.vl["Motor_51"]["TSK_Limiter_ausgewaehlt"])
accFaulted = pt_cp.vl["Motor_51"]["TSK_Status"] in (6, 7)
accFaulted = (pt_cp.vl["Motor_51"]["TSK_Status"] in (6, 7) or
ext_cp.vl["ACC_19"]["ACC_Status_ACC"] == 6) # reversible fault in ACC system
ret.accFaulted = self.update_acc_fault(accFaulted, parking_brake=ret.parkingBrake, drive_mode=drive_mode,
brake_pressed=ret.brakePressed)
@@ -1,12 +1,14 @@
from opendbc.car import get_safety_config, structs
from opendbc.car import Bus, get_safety_config, structs
from opendbc.car.interfaces import CarInterfaceBase
from opendbc.car.volkswagen.carcontroller import CarController
from opendbc.car.volkswagen.carstate import CarState
from opendbc.car.volkswagen.values import CanBus, CAR, NetworkLocation, TransmissionType, VolkswagenFlags, VolkswagenSafetyFlags
from opendbc.car.volkswagen.radar_interface import RadarInterface
from opendbc.car.volkswagen.values import CanBus, CAR, DBC, NetworkLocation, TransmissionType, VolkswagenFlags, VolkswagenSafetyFlags
class CarInterface(CarInterfaceBase):
CarState = CarState
CarController = CarController
RadarInterface = RadarInterface
DRIVABLE_GEARS = (structs.CarState.GearShifter.eco, structs.CarState.GearShifter.sport,
structs.CarState.GearShifter.manumatic)
@@ -14,7 +16,7 @@ class CarInterface(CarInterfaceBase):
@staticmethod
def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
ret.brand = "volkswagen"
ret.radarUnavailable = True
ret.radarUnavailable = Bus.radar not in DBC[candidate]
if ret.flags & VolkswagenFlags.PQ:
# Set global PQ35/PQ46/NMS parameters
@@ -61,6 +63,7 @@ class CarInterface(CarInterfaceBase):
ret.networkLocation = NetworkLocation.gateway
else:
ret.networkLocation = NetworkLocation.fwdCamera
ret.radarUnavailable = True
ret.enableBsm = 0x24C in fingerprint[0] # MEB_Side_Assist_01
@@ -130,13 +133,7 @@ class CarInterface(CarInterfaceBase):
ret.steerActuatorDelay = 0.07
ret.pcmCruise = not ret.openpilotLongitudinalControl
if ret.flags & VolkswagenFlags.MEB:
ret.startingState = True
ret.startAccel = 0.8
else:
ret.stopAccel = -0.55
ret.vEgoStarting = 0.1
ret.vEgoStopping = 0.5
ret.stopAccel = -0.55
ret.autoResumeSng = ret.minEnableSpeed == -1
CAN = CanBus(fingerprint=fingerprint)
+47 -54
View File
@@ -69,9 +69,6 @@ def create_acc_buttons_control(packer, bus, gra_stock_values, cancel=False, resu
return packer.make_can_msg("GRA_ACC_01", bus, values)
ACCEL_INACTIVE = 3.01
ACCEL_OVERRIDE = 0.00
ACC_CTRL_ERROR = 6
ACC_CTRL_OVERRIDE = 4
ACC_CTRL_ACTIVE = 3
@@ -90,50 +87,48 @@ ACC_HUD_ENABLED = 2
ACC_HUD_DISABLED = 0
def acc_control_value(main_switch_on, acc_faulted, long_active, override):
if acc_faulted:
acc_control = ACC_CTRL_ERROR # error state
elif long_active:
if override:
acc_control = ACC_CTRL_OVERRIDE # overriding
def get_acc_control(CS, CC, long_override):
if CS.accFaulted:
acc_control = ACC_CTRL_ERROR # error state
elif CC.enabled:
if long_override:
acc_control = ACC_CTRL_OVERRIDE # overriding
else:
acc_control = ACC_CTRL_ACTIVE # active long control state
elif main_switch_on:
acc_control = ACC_CTRL_ENABLED # long control ready
acc_control = ACC_CTRL_ACTIVE # active long control state
elif CS.cruiseState.available:
acc_control = ACC_CTRL_ENABLED # long control ready
else:
acc_control = ACC_CTRL_DISABLED # long control deactivated state
acc_control = ACC_CTRL_DISABLED # long control deactivated state
return acc_control
def acc_hold_type(main_switch_on, acc_faulted, long_active, starting, stopping, esp_hold, override, override_begin, long_disabling):
def get_acc_hold_type(CS, CC, starting, stopping, esp_hold, long_override, long_override_begin, long_disabling):
# warning: car is reacting to hold mechanic even with long control off
if acc_faulted:
acc_hold_type = ACC_HMS_NO_REQUEST # no hold request
elif not long_active:
if CS.accFaulted:
acc_hold_type = ACC_HMS_NO_REQUEST # no hold request
elif not CC.enabled:
if long_disabling:
acc_hold_type = ACC_HMS_RAMP_RELEASE # ramp release of requests right after disabling long control (prevents car error with EPB at low speed)
acc_hold_type = ACC_HMS_RAMP_RELEASE # ramp release of requests right after disabling long control (prevents car error with EPB at low speed)
else:
acc_hold_type = ACC_HMS_NO_REQUEST # no hold request
elif override:
if override_begin:
acc_hold_type = ACC_HMS_RAMP_RELEASE # ramp release of requests at the beginning of override (prevents car error with EPB at low speed)
acc_hold_type = ACC_HMS_NO_REQUEST # no hold request
elif long_override:
if long_override_begin:
acc_hold_type = ACC_HMS_RAMP_RELEASE # ramp release of requests at the beginning of override (prevents car error with EPB at low speed)
else:
acc_hold_type = ACC_HMS_NO_REQUEST # overriding / no request
acc_hold_type = ACC_HMS_NO_REQUEST # overriding / no request
elif starting:
acc_hold_type = ACC_HMS_RELEASE # release request and startup
elif stopping or esp_hold:
acc_hold_type = ACC_HMS_HOLD # hold or hold request
acc_hold_type = ACC_HMS_RELEASE # release request and startup
elif stopping:
acc_hold_type = ACC_HMS_HOLD # hold while stopping/stopped
else:
acc_hold_type = ACC_HMS_NO_REQUEST # no hold request
acc_hold_type = ACC_HMS_NO_REQUEST # no hold request
return acc_hold_type
def create_acc_accel_control(packer, bus, acc_type, acc_enabled, upper_jerk, lower_jerk, upper_control_limit, lower_control_limit,
accel, acc_control, acc_hold_type, stopping, starting, esp_hold, speed, override, travel_assist_available):
def create_acc_accel_control(packer, bus, CCP, acc_type, acc_enabled, accel, acc_control, acc_hold_type,
stopping, starting, esp_hold, speed, long_override, travel_assist_available):
# active longitudinal control disables one pedal driving (regen mode) while using overriding mechanism
# error mitigation when stopping or stopped: (newer gen cars can be very sensitive)
# - send 0 m stopping distance for cars in kind of parameterized stopping mode (stopping accel -0.2 seen for those cars)
@@ -146,30 +141,30 @@ def create_acc_accel_control(packer, bus, acc_type, acc_enabled, upper_jerk, low
# ACC_Anhalteweg: when stopping: MEB: values <> 0 the car can execute a hard brake probably if target is too close, MQBEvo: value 0 results in hard brake
terminal_rollout = 0
full_stop = stopping and esp_hold
full_stop = stopping and esp_hold
full_stop_no_start = esp_hold and not starting
actually_stopping = stopping and not esp_hold
actually_stopping = stopping and not esp_hold
if acc_enabled:
if override: # the car expects a non inactive accel while overriding
acceleration = ACCEL_OVERRIDE # original ACC still sends active accel in this case (seamless experience)
if long_override: # the car expects a non-inactive accel while overriding
acceleration = CCP.ACCEL_OVERRIDE # original ACC still sends active accel in this case (seamless experience)
elif full_stop:
acceleration = ACCEL_INACTIVE # inactive accel, newer gen >2024 error of not neutral value
acceleration = CCP.ACCEL_INACTIVE # inactive accel, newer gen >2024 error of not neutral value
else:
acceleration = accel
else:
acceleration = ACCEL_INACTIVE # inactive accel
acceleration = CCP.ACCEL_INACTIVE # inactive accel
values = {
"ACC_Typ": acc_type,
"ACC_Status_ACC": acc_control,
"ACC_StartStopp_Info": acc_enabled,
"ACC_Sollbeschleunigung_02": acceleration,
"ACC_zul_Regelabw_unten": lower_control_limit if acc_control in (ACC_CTRL_ACTIVE, ACC_CTRL_OVERRIDE) and not full_stop_no_start else 0,
"ACC_zul_Regelabw_oben": upper_control_limit if acc_control in (ACC_CTRL_ACTIVE, ACC_CTRL_OVERRIDE) and not full_stop_no_start else 0,
"ACC_neg_Sollbeschl_Grad_02": lower_jerk if acc_control in (ACC_CTRL_ACTIVE, ACC_CTRL_OVERRIDE) and not full_stop_no_start else 0,
"ACC_pos_Sollbeschl_Grad_02": upper_jerk if acc_control in (ACC_CTRL_ACTIVE, ACC_CTRL_OVERRIDE) and not full_stop_no_start else 0,
"ACC_Anfahren": starting,
"ACC_zul_Regelabw_unten": 0,
"ACC_zul_Regelabw_oben": 0,
"ACC_neg_Sollbeschl_Grad_02": CCP.JERK_LIMIT if acc_control in (ACC_CTRL_ACTIVE, ACC_CTRL_OVERRIDE) and not full_stop_no_start else 0,
"ACC_pos_Sollbeschl_Grad_02": CCP.JERK_LIMIT if acc_control in (ACC_CTRL_ACTIVE, ACC_CTRL_OVERRIDE) and not full_stop_no_start else 0,
"ACC_Anfahren": 0, # always zero, stock uses ACC_Anforderung_HMS
"ACC_Anhalten": 1 if actually_stopping else 0,
"ACC_Anhalteweg": terminal_rollout if actually_stopping else 20.46,
"ACC_Anforderung_HMS": acc_hold_type,
@@ -195,19 +190,18 @@ def create_acc_accel_control(packer, bus, acc_type, acc_enabled, upper_jerk, low
return commands
def acc_hud_status_value(main_switch_on, acc_faulted, long_active, override):
if acc_faulted:
acc_hud_control = ACC_HUD_ERROR # error state
elif long_active:
if override:
acc_hud_control = ACC_HUD_OVERRIDE # overriding
def get_acc_hud_status(CS, CC, long_override):
if CS.accFaulted:
acc_hud_control = ACC_HUD_ERROR # error state
elif CC.enabled:
if long_override:
acc_hud_control = ACC_HUD_OVERRIDE # overriding
else:
acc_hud_control = ACC_HUD_ACTIVE # active
elif main_switch_on:
acc_hud_control = ACC_HUD_ENABLED # inactive
acc_hud_control = ACC_HUD_ACTIVE # active
elif CS.cruiseState.available:
acc_hud_control = ACC_HUD_ENABLED # inactive
else:
acc_hud_control = ACC_HUD_DISABLED # deactivated
acc_hud_control = ACC_HUD_DISABLED # deactivated
return acc_hud_control
@@ -223,7 +217,6 @@ def get_desired_gap(distance_bars, desired_gap, current_gap_signal):
def create_acc_hud_control(packer, bus, acc_control, set_speed, lead_visible, distance_bars, show_distance_bars, esp_hold, distance, desired_gap, fcw_alert):
values = {
"ACC_Status_ACC": acc_control,
"ACC_Tempolimit": 0,
@@ -0,0 +1,85 @@
from opendbc.can import CANParser
from opendbc.car import Bus, structs
from opendbc.car.interfaces import RadarInterfaceBase
from opendbc.car.volkswagen.values import DBC, VolkswagenFlags, CanBus
NO_OBJECT_ID = 0
LANE_TYPES = ("Same_Lane", "Left_Lane", "Right_Lane")
SIGNAL_SETS = tuple(
(
f"{prefix}_ObjectID",
f"{prefix}_Long_Distance",
f"{prefix}_Lat_Distance",
f"{prefix}_Rel_Velo",
)
for lane in LANE_TYPES
for idx in (1, 2)
for prefix in (f"{lane}_0{idx}",)
)
class RadarInterface(RadarInterfaceBase):
def __init__(self, CP, CP_SP):
super().__init__(CP, CP_SP)
# With the MEB gateway harness, we do not have access to the raw points from the radar.
# However, the camera publishes decent, albeit filtered, tracks. Two for each lane; left, center, and right.
self.rcp: CANParser | None = None
if CP.flags & VolkswagenFlags.MEB and not self.CP.radarUnavailable:
self.rcp = CANParser(DBC[CP.carFingerprint][Bus.radar], [("MEB_Distance_01", 25)], CanBus(CP).cam)
def update(self, can_strings):
if self.rcp is None:
return super().update(None)
self.rcp.update(can_strings)
if len(self.rcp.vl_all["MEB_Distance_01"]["Distance_Status"]) == 0:
return None
return self._update()
def _update(self):
ret = structs.RadarData()
if not self.rcp.can_valid:
ret.errors.canError = True
return ret
msg = self.rcp.vl["MEB_Distance_01"]
# Can be 3 when radar sensor is obstructed
if msg["Distance_Status"] != 0:
ret.errors.radarUnavailableTemporary = True
seen_ids = set()
for obj_id_sig, long_sig, lat_sig, vel_sig in SIGNAL_SETS:
obj_id = int(msg[obj_id_sig])
if obj_id == NO_OBJECT_ID:
continue
# We shouldn't see duplicate track ids
if obj_id in seen_ids:
ret.errors.radarFault = True
return ret
seen_ids.add(obj_id)
if obj_id not in self.pts:
pt = structs.RadarData.RadarPoint()
pt.trackId = self.track_id
self.track_id += 1
self.pts[obj_id] = pt
else:
pt = self.pts[obj_id]
pt.dRel = msg[long_sig]
pt.yRel = msg[lat_sig]
pt.vRel = msg[vel_sig]
inactive_ids = self.pts.keys() - seen_ids
for obj_id in inactive_ids:
self.pts.pop(obj_id, None)
ret.points = list(self.pts.values())
return ret
@@ -113,6 +113,11 @@ class CarControllerParams:
self.CURVATURE_MAX = 0.195 # Max curvature for steering command, m^-1
self.CURVATURE_LIMITS = CurvatureSteeringLimits(self.CURVATURE_MAX)
# Longitudinal constants
self.ACCEL_INACTIVE = 3.01 # m/s^2
self.ACCEL_OVERRIDE = 0.00 # m/s^2
self.JERK_LIMIT = 4.0 # m/s^3
self.shifter_values = can_define.dv["Getriebe_11"]["GE_Fahrstufe"]
self.hca_status_values = can_define.dv["QFK_01"]["LatCon_HCA_Status"]
@@ -334,24 +334,24 @@ BO_ 591 MEB_Distance_01: 64 XXX
SG_ Right_Lane_02_ObjectID : 46|6@1+ (1,0) [0|63] "Unit_ObjectID" XXX
SG_ Unknown_02 : 52|2@1+ (1,0) [0|3] "" XXX
SG_ Unknown_03 : 54|10@1+ (1,0) [0|3] "" XXX
SG_ Same_Lane_01_Long_Distance : 64|12@1+ (0.07,-6) [0|300] "Unit_Meter" XXX
SG_ Same_Lane_01_Long_Distance : 64|12@1+ (0.0625,-3.75) [0|300] "Unit_Meter" XXX
SG_ Same_Lane_01_Lat_Distance : 76|10@1+ (0.065,-33.28) [-50|50] "Unit_Meter" XXX
SG_ Same_Lane_01_Rel_Velo : 86|10@1+ (0.28,-143.36) [-150|150] "Unit_MeterPerSecond" XXX
SG_ Left_Lane_01_Long_Distance : 96|12@1+ (0.07,-6) [0|300] "Unit_Meter" XXX
SG_ Same_Lane_01_Rel_Velo : 86|10@1+ (0.25,-128) [-150|150] "Unit_MeterPerSecond" XXX
SG_ Left_Lane_01_Long_Distance : 96|12@1+ (0.0625,-3.75) [0|300] "Unit_Meter" XXX
SG_ Left_Lane_01_Lat_Distance : 108|10@1+ (0.065,-33.28) [-50|50] "Unit_Meter" XXX
SG_ Left_Lane_01_Rel_Velo : 118|10@1+ (0.28,-143.36) [-150|150] "Unit_MeterPerSecond" XXX
SG_ Right_Lane_01_Long_Distance : 128|12@1+ (0.07,-6) [0|300] "Unit_Meter" XXX
SG_ Left_Lane_01_Rel_Velo : 118|10@1+ (0.25,-128) [-150|150] "Unit_MeterPerSecond" XXX
SG_ Right_Lane_01_Long_Distance : 128|12@1+ (0.0625,-3.75) [0|300] "Unit_Meter" XXX
SG_ Right_Lane_01_Lat_Distance : 140|10@1+ (0.065,-33.28) [-50|50] "Unit_Meter" XXX
SG_ Right_Lane_01_Rel_Velo : 150|10@1+ (0.28,-143.36) [-150|150] "Unit_MeterPerSecond" XXX
SG_ Same_Lane_02_Long_Distance : 160|12@1+ (0.07,-6) [0|300] "Unit_Meter" XXX
SG_ Right_Lane_01_Rel_Velo : 150|10@1+ (0.25,-128) [-150|150] "Unit_MeterPerSecond" XXX
SG_ Same_Lane_02_Long_Distance : 160|12@1+ (0.0625,-3.75) [0|300] "Unit_Meter" XXX
SG_ Same_Lane_02_Lat_Distance : 172|10@1+ (0.065,-33.28) [-50|50] "Unit_Meter" XXX
SG_ Same_Lane_02_Rel_Velo : 182|10@1+ (0.28,-143.36) [-150|150] "Unit_MeterPerSecond" XXX
SG_ Left_Lane_02_Long_Distance : 192|12@1+ (0.07,-6) [0|300] "Unit_Meter" XXX
SG_ Same_Lane_02_Rel_Velo : 182|10@1+ (0.25,-128) [-150|150] "Unit_MeterPerSecond" XXX
SG_ Left_Lane_02_Long_Distance : 192|12@1+ (0.0625,-3.75) [0|300] "Unit_Meter" XXX
SG_ Left_Lane_02_Lat_Distance : 204|10@1+ (0.065,-33.28) [-50|50] "Unit_Meter" XXX
SG_ Left_Lane_02_Rel_Velo : 214|10@1+ (0.28,-143.36) [-150|150] "Unit_MeterPerSecond" XXX
SG_ Right_Lane_02_Long_Distance : 224|12@1+ (0.07,-6) [0|300] "Unit_Meter" XXX
SG_ Left_Lane_02_Rel_Velo : 214|10@1+ (0.25,-128) [-150|150] "Unit_MeterPerSecond" XXX
SG_ Right_Lane_02_Long_Distance : 224|12@1+ (0.0625,-3.75) [0|300] "Unit_Meter" XXX
SG_ Right_Lane_02_Lat_Distance : 236|10@1+ (0.065,-33.28) [-50|50] "Unit_Meter" XXX
SG_ Right_Lane_02_Rel_Velo : 246|10@1+ (0.28,-143.36) [-150|150] "Unit_MeterPerSecond" XXX
SG_ Right_Lane_02_Rel_Velo : 246|10@1+ (0.25,-128) [-150|150] "Unit_MeterPerSecond" XXX
SG_ Unknown_04 : 256|8@1+ (1,-128) [0|31] "" XXX
SG_ Unknown_05 : 264|6@1+ (1,-15) [0|31] "" XXX
SG_ Unknown_06 : 270|6@1+ (1,0) [0|127] "" XXX
@@ -39,11 +39,11 @@ This standard provides the foundation for the safety limits enforced by this tun
**Configuration (`config.py`)**
* The `CarTuningConfig` dataclass holds tuning parameters like stopping/starting speeds, lookahead jerk profiles, actuator delay, and base jerk limits.
* The `CarTuningConfig` dataclass holds tuning parameters like lookahead jerk profiles, actuator delay, and base jerk limits.
* `TUNING_CONFIGS` provides default configurations based on car type (CANFD, EV, HYBRID, DEFAULT).
* `CAR_SPECIFIC_CONFIGS` allows overriding defaults for specific car models (e.g., `KIA_NIRO_EV`, `HYUNDAI_IONIQ`).
* `CAR_SPECIFIC_CONFIGS` allows overriding defaults for specific car models (e.g., `KIA_NIRO_EV`).
* The `get_car_config` helper function selects the appropriate configuration based on the car fingerprint and flags.
* `get_longitudinal_tune` applies relevant config values (like stopping/starting speeds, delay) to the main `CarParams` (CP).
* `get_longitudinal_tune` applies the actuator delay config value to the main `CarParams` (CP).
**Summary**
@@ -12,9 +12,6 @@ from opendbc.car.hyundai.values import CAR
@dataclass
class CarTuningConfig:
v_ego_stopping: float = 0.25
v_ego_starting: float = 0.10
stopping_decel_rate: float = 0.40
lookahead_jerk_bp: list[float] = field(default_factory=lambda: [2., 5., 20.])
lookahead_jerk_upper_v: list[float] = field(default_factory=lambda: [0.3, 0.45, 0.6])
lookahead_jerk_lower_v: list[float] = field(default_factory=lambda: [0.3, 0.45, 0.6])
@@ -24,32 +21,18 @@ class CarTuningConfig:
# Default configurations for different car types
TUNING_CONFIGS = {
"CANFD": CarTuningConfig(
v_ego_stopping=0.30,
),
"EV": CarTuningConfig(
stopping_decel_rate=0.45,
v_ego_stopping=0.35,
),
"HYBRID": CarTuningConfig(
v_ego_starting=0.15,
stopping_decel_rate=0.45,
v_ego_stopping=0.4,
),
"DEFAULT": CarTuningConfig(
v_ego_stopping=0.3,
)
"CANFD": CarTuningConfig(),
"EV": CarTuningConfig(),
"HYBRID": CarTuningConfig(),
"DEFAULT": CarTuningConfig(),
}
# Car-specific configs
CAR_SPECIFIC_CONFIGS = {
CAR.KIA_NIRO_EV: CarTuningConfig(
v_ego_stopping=0.1,
stopping_decel_rate=0.3,
jerk_limits=3.3,
),
CAR.KIA_NIRO_PHEV_2022: CarTuningConfig(
stopping_decel_rate=0.8,
jerk_limits=5.0,
),
}
@@ -5,7 +5,6 @@ This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
from opendbc.car import structs, DT_CTRL, rate_limit
from opendbc.car.hyundai.values import HyundaiFlags
from opendbc.sunnypilot.car.hyundai.longitudinal.config import CarTuningConfig, TUNING_CONFIGS, CAR_SPECIFIC_CONFIGS
JERK_THRESHOLD = 0.1
@@ -23,24 +22,13 @@ def get_car_config(CP: structs.CarParams) -> CarTuningConfig:
car_config = CAR_SPECIFIC_CONFIGS.get(CP.carFingerprint)
# If car is not in specific configs, determine from flags
if car_config is None:
if CP.flags & HyundaiFlags.CANFD:
car_config = TUNING_CONFIGS["CANFD"]
elif CP.flags & HyundaiFlags.EV:
car_config = TUNING_CONFIGS["EV"]
elif CP.flags & HyundaiFlags.HYBRID:
car_config = TUNING_CONFIGS["HYBRID"]
else:
car_config = TUNING_CONFIGS["DEFAULT"]
car_config = TUNING_CONFIGS["DEFAULT"]
return car_config
def get_longitudinal_tune(CP: structs.CarParams) -> None:
config = get_car_config(CP)
CP.vEgoStopping = config.v_ego_stopping
CP.vEgoStarting = config.v_ego_starting
CP.stoppingDecelRate = config.stopping_decel_rate
CP.startingState = False
CP.longitudinalActuatorDelay = config.longitudinal_actuator_delay
+80 -80
View File
@@ -97,11 +97,11 @@ wheels = [
[[package]]
name = "codespell"
version = "2.4.2"
version = "2.4.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/2d/9d/1d0903dff693160f893ca6abcabad545088e7a2ee0a6deae7c24e958be69/codespell-2.4.2.tar.gz", hash = "sha256:3c33be9ae34543807f088aeb4832dfad8cb2dae38da61cac0a7045dd376cfdf3", size = 352058, upload-time = "2026-03-05T18:10:42.936Z" }
sdist = { url = "https://files.pythonhosted.org/packages/80/19/45e941380f69c042b43423513d201e6592346f992394347f5e7174c31407/codespell-2.4.3.tar.gz", hash = "sha256:cbe085e331227b37bb86ef8bddd08dc768c704ee9a07ca869852c093fa2793e2", size = 352773, upload-time = "2026-07-15T11:51:54.159Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/42/a1/52fa05533e95fe45bcc09bcf8a503874b1c08f221a4e35608017e0938f55/codespell-2.4.2-py3-none-any.whl", hash = "sha256:97e0c1060cf46bd1d5db89a936c98db8c2b804e1fdd4b5c645e82a1ec6b1f886", size = 353715, upload-time = "2026-03-05T18:10:41.398Z" },
{ url = "https://files.pythonhosted.org/packages/8b/bf/bdb951d34eb169140b546f44be9ec4525d1acefb9eb5572071f5492b19fc/codespell-2.4.3-py3-none-any.whl", hash = "sha256:af2505b335e8573dbd2d384d1c4ef498f4006f4ba2d6fceca01e55b91f52628a", size = 340736, upload-time = "2026-07-15T11:51:52.925Z" },
]
[[package]]
@@ -115,14 +115,14 @@ wheels = [
[[package]]
name = "colorlog"
version = "6.10.1"
version = "6.11.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a2/61/f083b5ac52e505dfc1c624eafbf8c7589a0d7f32daa398d2e7590efa5fda/colorlog-6.10.1.tar.gz", hash = "sha256:eb4ae5cb65fe7fec7773c2306061a8e63e02efc2c72eba9d27b0fa23c94f1321", size = 17162, upload-time = "2025-10-16T16:14:11.978Z" }
sdist = { url = "https://files.pythonhosted.org/packages/0a/bf/cb30a51af3aa8ce63735f77e23dcd4fc0720fe0339bcb04f77345659c277/colorlog-6.11.0.tar.gz", hash = "sha256:9d90fb53fa906c8970c18fbe46506bae1fb5f86b513b8f867db37e4ace9be7ae", size = 17734, upload-time = "2026-07-17T12:16:46.59Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl", hash = "sha256:2d7e8348291948af66122cff006c9f8da6255d224e7cf8e37d8de2df3bad8c9c", size = 11743, upload-time = "2025-10-16T16:14:10.512Z" },
{ url = "https://files.pythonhosted.org/packages/ec/a1/6b71004ab0fea510230be9ce05a4059029ac847c009fcc80b1b73d6fa5ab/colorlog-6.11.0-py3-none-any.whl", hash = "sha256:f1e27d75aa2cb138f3f640c0e305b65b680ccbef6ecc034eba7e03494ffcd2a1", size = 12016, upload-time = "2026-07-17T12:16:45.3Z" },
]
[[package]]
@@ -141,41 +141,41 @@ requires-dist = [{ name = "requests" }]
[[package]]
name = "coverage"
version = "7.15.1"
version = "7.15.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/4a/83/6051c2a2feab48ae5bd27c84ef047191d2d4a3172f689e38eaa48ed17db1/coverage-7.15.1.tar.gz", hash = "sha256:165e9949eaf222ef1f018635d0d7f368a23bfe0212af558534c40d8c04686d67", size = 927640, upload-time = "2026-07-12T20:58:19.908Z" }
sdist = { url = "https://files.pythonhosted.org/packages/76/d0/55fe630f4cf94e3fcba868240fad8c8cdd1f764e2a932f8926347e6ec4cd/coverage-7.15.2.tar.gz", hash = "sha256:3df60dc267f0a2ca23cb7a9ab1109c62b9335ffbf519fcfe167157c28c09b81d", size = 927741, upload-time = "2026-07-15T18:56:19.558Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/67/ee/5095e07a0986930174fc153fd0bb115f7f2724f5344cc672e016d4f23a4e/coverage-7.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6506330b4a8dcf53b95bd84d8d0e817107cdb3fc1438e835029cdf0bc6612eb0", size = 221320, upload-time = "2026-07-12T20:56:16.036Z" },
{ url = "https://files.pythonhosted.org/packages/43/7a/7e2598ce98433a214020a61c0755d5961f9f26df0c630dc73e06b86d3416/coverage-7.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8a51a8ec382c39d939cba0ab07ae949077ae4e842343bd4eed22d432358cea9", size = 221823, upload-time = "2026-07-12T20:56:17.54Z" },
{ url = "https://files.pythonhosted.org/packages/8b/4f/67dac6a69139b490a239d91b6d5ef127982ffb89159769241656ab879ee5/coverage-7.15.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:18ea20e3922d7f8ca9e0ef1084408d08c4ad62d5e531cb9c1f6896a99297ebea", size = 252242, upload-time = "2026-07-12T20:56:18.868Z" },
{ url = "https://files.pythonhosted.org/packages/05/37/5e439725a96de592309725550c8df639c359c209dcb4b152ed46032d4c0d/coverage-7.15.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:aab9902a64b8390e3b56e539fddae1d79a267807fe5cb0c18d7d2f544ce867e2", size = 254153, upload-time = "2026-07-12T20:56:20.118Z" },
{ url = "https://files.pythonhosted.org/packages/0f/1c/671ba9e15f9651a99962fb588a1fe4fb267cae4bb85f9bb4ac4413c6f7ef/coverage-7.15.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cc316264317b07a9e90d7f2b4188a15e36e9b54e651081b791b0515fa612a29", size = 256261, upload-time = "2026-07-12T20:56:21.682Z" },
{ url = "https://files.pythonhosted.org/packages/d6/3c/88305322b4d015b4536b7174b8f9b87f850f01af9d89008cdbf984b65ff2/coverage-7.15.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d4e47e7eea81a8ccf060a07627654151d929da62c7b715738387c200905cec89", size = 258222, upload-time = "2026-07-12T20:56:22.962Z" },
{ url = "https://files.pythonhosted.org/packages/8d/20/d02e42333a57f266ded61ed4fb3821da1f2dc143734aaa3dcc9c117204c5/coverage-7.15.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c6829d9a3b55ad2b73ef5fda8302e5be03683789e88b1a079dcf4a773229c21d", size = 252368, upload-time = "2026-07-12T20:56:24.475Z" },
{ url = "https://files.pythonhosted.org/packages/f3/d0/94ebc010926a191d83e83b1f1236f8bd0d14d0eb98b5c324aa4be2589a8e/coverage-7.15.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:764e045811f9c8cda436641f3f088283351d331a519b5807f19041cd0a68da1c", size = 253953, upload-time = "2026-07-12T20:56:26.036Z" },
{ url = "https://files.pythonhosted.org/packages/2e/a6/2c8553191da0c2da2c43ff294fb9bab57a5b0fae03560304a82a8b5addc3/coverage-7.15.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:09b3b088aa24489c4082bcc35fcc8224281ab94a653dfb6d3f0c8165b0d628ab", size = 252016, upload-time = "2026-07-12T20:56:27.374Z" },
{ url = "https://files.pythonhosted.org/packages/17/99/20f47986d8360fa1a31d9858dd2ba0be009d44ecfa8d02120b1eb93c028b/coverage-7.15.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7911b02f57053adf8164ae63edb1c26574d24dfccabadc5268cf69310a69a358", size = 255783, upload-time = "2026-07-12T20:56:28.921Z" },
{ url = "https://files.pythonhosted.org/packages/17/36/fb61983b5259f78fa5e62ee74e91fe4de4c556fcbc9a3b9c9021c2f8b57b/coverage-7.15.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:664e279ed40599b8ed16f4db18d92a7e212c73129672bec8f5d96d4da48d2404", size = 251735, upload-time = "2026-07-12T20:56:30.465Z" },
{ url = "https://files.pythonhosted.org/packages/6c/2e/d109d8d2d6c726ba2e78125297073918a2a91464f0ea777e5398fa3cf75c/coverage-7.15.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:34fe7cf79d5f1f87f2e8ce7dc1c32950841f50e10d0120f263856acfad66de34", size = 252645, upload-time = "2026-07-12T20:56:32.076Z" },
{ url = "https://files.pythonhosted.org/packages/bc/a0/5b3219cbb46135e14673427f2bf5890c4da4e6f655243692f3448aa3f42c/coverage-7.15.1-cp311-cp311-win32.whl", hash = "sha256:5e2d2536d2f57a354aa382ed303ac0e2e5c9522a508c05b998d26181b94163a7", size = 223414, upload-time = "2026-07-12T20:56:33.432Z" },
{ url = "https://files.pythonhosted.org/packages/5b/80/24e13ade0b6df8090e2492f9c55044bf1423f7ef28c76fc1af8c827a61cb/coverage-7.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:c337da8fca7ea93ab43f3868cfcde6cf6dad32c3906b273cfbad5d7390bc423b", size = 223888, upload-time = "2026-07-12T20:56:34.784Z" },
{ url = "https://files.pythonhosted.org/packages/2d/9e/34659930ae380491af48e2f5f5f9a2e99cd9fb7de3d30f27be5ac5425137/coverage-7.15.1-cp311-cp311-win_arm64.whl", hash = "sha256:db3403fdb7a94d5eb73e099befad8104d2a7d110a0f0d99df0de61c5d1fa756c", size = 223435, upload-time = "2026-07-12T20:56:36.302Z" },
{ url = "https://files.pythonhosted.org/packages/d9/76/32c1826309beaf4604c54accef108fdd611e5e5e93f2f5192f050cd5f6bd/coverage-7.15.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d9476292594309db922cc841dd13b303b3c388f4c25d279884f7e2341c681f80", size = 221497, upload-time = "2026-07-12T20:56:37.628Z" },
{ url = "https://files.pythonhosted.org/packages/db/5c/b88ce0d68fa550c7f3b58617fbf363bce64df5bf8295a01b627e4696e022/coverage-7.15.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0c579056b0de461b3a62318b63d0b6ce90aed7f8158d3f00da094df82f29d189", size = 221854, upload-time = "2026-07-12T20:56:39.033Z" },
{ url = "https://files.pythonhosted.org/packages/0e/fe/8509fd2a66fc4e0a829f76a0f0b1dc3cc163368352435b5f243168658077/coverage-7.15.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:23214bdbe226f2b0e9c66a7d6a1d59d4a88045dcf86e702cf0fe0d0935e3d615", size = 253359, upload-time = "2026-07-12T20:56:40.423Z" },
{ url = "https://files.pythonhosted.org/packages/e5/81/c7009ed7ea9765adb2b9d095054d748266fae5f07ac6c5f925f33715fcde/coverage-7.15.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:df164be93b46b4825cc39339440a05edc54c4d1d865ba4a60fd43d151a2a1cd3", size = 256096, upload-time = "2026-07-12T20:56:42.115Z" },
{ url = "https://files.pythonhosted.org/packages/21/52/dc8ee03968a5ba86e2da5aa48ddc9e3747bd65d63825fdce2d96acb9c5ff/coverage-7.15.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a524fca1a6f08927d9dc2d4c873cfb7bd7202c247f08b14bdc02424071b8b304", size = 257211, upload-time = "2026-07-12T20:56:43.513Z" },
{ url = "https://files.pythonhosted.org/packages/b8/27/95d7623908da8937deb53d48efcdbf423907a47540e63c62fa21372c652b/coverage-7.15.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d70f3542cd38de85a9e257dcb1ac4c1ab4b6d7d2c2a645809207556628755d1c", size = 259473, upload-time = "2026-07-12T20:56:44.974Z" },
{ url = "https://files.pythonhosted.org/packages/f1/3b/730d761928de97d585465680b568ae69622fb40716babadeabffe75cb51b/coverage-7.15.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d78aa537237212c4313aabe5e964b66acc86350ed19ebc56a3e202df33b6077b", size = 253759, upload-time = "2026-07-12T20:56:46.615Z" },
{ url = "https://files.pythonhosted.org/packages/f1/fc/6b9277acff1f9484b6c12857af5774689d1a6a95e13265f7405329d2f5da/coverage-7.15.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a318112bb4f79d9d04766196d5a3388caa825908a6a9b052aa87de3d9aea7c61", size = 255131, upload-time = "2026-07-12T20:56:48.073Z" },
{ url = "https://files.pythonhosted.org/packages/3d/f2/c704f86129594ba34e25a64695d2068c71d51c2b98907184d716c94f4aec/coverage-7.15.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e55d24cada901963eed5bc89fa562aa033f0d84b9d3de4ecf363737c13aed11e", size = 253275, upload-time = "2026-07-12T20:56:49.538Z" },
{ url = "https://files.pythonhosted.org/packages/f6/29/80fee8af47de4a6dce71ccf2938491f444687a756af258a56d8469b8f1b0/coverage-7.15.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3c78f0cea7275342cf2adc2ad5fdd0aafa106ad91e66d573568f2fcf62c41df5", size = 257345, upload-time = "2026-07-12T20:56:51.038Z" },
{ url = "https://files.pythonhosted.org/packages/20/21/a1e7d7ed1b48a8adf8fd5154d9e83fcc5ad8e6ff20ae00e44865057dce8d/coverage-7.15.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:86bd37eabe39977216f630a7fc1b698e7f5e81a191c7186013245c6c3d313f9d", size = 252844, upload-time = "2026-07-12T20:56:52.535Z" },
{ url = "https://files.pythonhosted.org/packages/a7/8c/a4bc26e6ee207d412f3678f04d74be1550e83140563ca0e4997510579712/coverage-7.15.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c6db15c217693bdc3ca0b84de1ba9afafe1c14c26a8a29d77f4ed0de2b6132e2", size = 254716, upload-time = "2026-07-12T20:56:53.968Z" },
{ url = "https://files.pythonhosted.org/packages/11/9d/8ad0266ecfada6353cf6627a1a02294cf55a907521b6ee0bd7b770cfd659/coverage-7.15.1-cp312-cp312-win32.whl", hash = "sha256:359f3fbe09a51500c51966596ee4ee4070b356552c70b3b2420eb200d68e0f76", size = 223554, upload-time = "2026-07-12T20:56:55.583Z" },
{ url = "https://files.pythonhosted.org/packages/81/6d/24224929e06c6e05a93f738bc5f9e8e6ab658f8f1d9b823e7b85430e28b8/coverage-7.15.1-cp312-cp312-win_amd64.whl", hash = "sha256:fa75dc099c126e941a9c0baa8ebd2cbc78bd778687534fe410baf754f6d9e374", size = 224087, upload-time = "2026-07-12T20:56:57.041Z" },
{ url = "https://files.pythonhosted.org/packages/35/23/f81441dd01de88e53c97842e706907b307d9078918c3f4998b11e9ac7250/coverage-7.15.1-cp312-cp312-win_arm64.whl", hash = "sha256:26f89cf6d0634375f454fa71057945ad18edb0f1607a90fecf22c57dc3dc289a", size = 223472, upload-time = "2026-07-12T20:56:58.594Z" },
{ url = "https://files.pythonhosted.org/packages/34/98/07a67cf1a26e795d617ed5c540c042b0ac87b72f810c30c07f076cf334f3/coverage-7.15.1-py3-none-any.whl", hash = "sha256:717d01e6e00bed56ad13306f19e0dd2f4f645ee8159d2c72c72301d6cfc7090c", size = 213284, upload-time = "2026-07-12T20:58:18.079Z" },
{ url = "https://files.pythonhosted.org/packages/7d/3a/54536704f507d4573bf9161c4d0dd3dd59b6d85e48c664e901b6844d8e33/coverage-7.15.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f1ec6f304b156669cfde653b4e9a953f5de87e247ea02ac599bce0ab2744036", size = 221414, upload-time = "2026-07-15T18:53:51.941Z" },
{ url = "https://files.pythonhosted.org/packages/b6/d9/8ba925d29743e3577b21e4d8c11a702b76bc93c41e7fdfd1177af63d4b8d/coverage-7.15.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4d3361879d736f469f45723c11ea1a5bbdaf1f6928f0e632c940378b5aa9b660", size = 221913, upload-time = "2026-07-15T18:53:53.682Z" },
{ url = "https://files.pythonhosted.org/packages/09/54/a855f3aa0187f2b431ade4e4791b77b56282cfb5d201c83ec26a31b5b36a/coverage-7.15.2-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c6a98d698f9e2c8008d0370ec7fc452ebfcc530002ae2d0061170d768b992589", size = 252332, upload-time = "2026-07-15T18:53:55.467Z" },
{ url = "https://files.pythonhosted.org/packages/8e/d3/13ac97b4370640ba3452fc8559b06cc2f479ce3ba4a0b632a73e44c38a7d/coverage-7.15.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d50dd325e18ec25bfcc10cd7f99b04df1ab9ec76b0918c260e60817ad0643dee", size = 254243, upload-time = "2026-07-15T18:53:57.055Z" },
{ url = "https://files.pythonhosted.org/packages/88/83/5eca144942d8d0659d3f55176517f4a59cdc65eefd17146a0770935a3ebd/coverage-7.15.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:67d7602480a47bdf5b675635403625553ebaa70d5a62a657c035149fd401cea0", size = 256352, upload-time = "2026-07-15T18:53:58.83Z" },
{ url = "https://files.pythonhosted.org/packages/4e/ba/d3db2e01a50fc88cdb4c0f19542bcf6f61489e34dc9aa3538413e2459a38/coverage-7.15.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cee0f89f4767a6057c8fbf168f8135f18be651300496086bd873e3189fed0487", size = 258313, upload-time = "2026-07-15T18:54:00.497Z" },
{ url = "https://files.pythonhosted.org/packages/78/b3/aba83416e9177df28e5186d856c19158c59fc0e7e814aaa61a4a2354ad1b/coverage-7.15.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a29ec5305a7335aacee2d799e3422e91e1c8a12474986e2b3b07e315c91be82f", size = 252449, upload-time = "2026-07-15T18:54:02.456Z" },
{ url = "https://files.pythonhosted.org/packages/6a/a5/4b00ecac0194431ab451b0f6710f8e2517d04cef60f821b14dec4637d575/coverage-7.15.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:48ccc6395958eda89093ecdc35644c86f23a8b23a7f4d44958812b721aad67c1", size = 254043, upload-time = "2026-07-15T18:54:04.072Z" },
{ url = "https://files.pythonhosted.org/packages/75/b6/cfa209b4313ee7f1b34da47efcd789ea51c024ad35af390e00f5a3c10a2e/coverage-7.15.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:81f382c5a94b434ec1f6da607edb904c76d7212e618cd4d1bc9f97bed4120ef5", size = 252107, upload-time = "2026-07-15T18:54:06.745Z" },
{ url = "https://files.pythonhosted.org/packages/36/67/e8cac5a6954038c98d7fe7eb9802afe7ab3ecb637bb7cc00e69b4148b56d/coverage-7.15.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bbc808daf4f5cd567af8075ecc72d21c6dfef9a254709a621a84c217c935ebc0", size = 255873, upload-time = "2026-07-15T18:54:08.48Z" },
{ url = "https://files.pythonhosted.org/packages/2c/92/395cca9f330a86c3fe3471d73e2c102116c4c58fdc619dbbc125c6e93a54/coverage-7.15.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:a4c46b247b5d4b78f613bd89fea926d32b25c6cc61a50bd1e99ba310348f3dad", size = 251826, upload-time = "2026-07-15T18:54:10.083Z" },
{ url = "https://files.pythonhosted.org/packages/51/60/3e91b20295439652424f426b7086ec5bf4fbe3f604c73eda22b986c4fd6b/coverage-7.15.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:094dd37f3ef7b2da8b068b583d1f4c40f91c65197e16c52a71962d5d537fc5db", size = 252735, upload-time = "2026-07-15T18:54:11.878Z" },
{ url = "https://files.pythonhosted.org/packages/a5/eb/8c07839005e5e3c6b3877d3a6e2a80ce766589f31dd2b6882b78d59a7b8c/coverage-7.15.2-cp311-cp311-win32.whl", hash = "sha256:a63b9e190711134d581c4d703df5df09851b1acf99792c7aacbbe9f41f0283c9", size = 223500, upload-time = "2026-07-15T18:54:13.525Z" },
{ url = "https://files.pythonhosted.org/packages/2e/98/59d83c257cd59f0fbaf9d9ddb26b744a576760dfd1ae16e516408894a02b/coverage-7.15.2-cp311-cp311-win_amd64.whl", hash = "sha256:8bb9f4b4279187560796a4cdaca3b0a93dd97e48ee667df005f4ed9a97403688", size = 223973, upload-time = "2026-07-15T18:54:15.163Z" },
{ url = "https://files.pythonhosted.org/packages/ea/09/2d285c8bef5c4f695d120c1c96dc11715638aa8e134069f210bb6a62a9fe/coverage-7.15.2-cp311-cp311-win_arm64.whl", hash = "sha256:8c726b232659cbd2ae57ade46509eb068c9bd7a06df9fcbff6fe484870006934", size = 223519, upload-time = "2026-07-15T18:54:16.803Z" },
{ url = "https://files.pythonhosted.org/packages/6a/50/eb5bf42e531611a9f8d272556b1ed4de503f84a91413584094487cf69f8f/coverage-7.15.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1adac78e5abc7c5438f7a209c9ca69d06542f0bf481d728b6989ea80b813fdf9", size = 221587, upload-time = "2026-07-15T18:54:18.439Z" },
{ url = "https://files.pythonhosted.org/packages/06/d1/da99af464c335d4e023a6efcd7ec30f63b88a43c93745154ab74ffb31cea/coverage-7.15.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b868acc62aa5de3be7a9d05c2333bf8359ca987e43f9cb30ff8fbda6a024ab73", size = 221943, upload-time = "2026-07-15T18:54:20.062Z" },
{ url = "https://files.pythonhosted.org/packages/5b/8a/13c42723d61ca447eafa18732e8141dd6a63f2732e1c7e1502c182dd88d7/coverage-7.15.2-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6f6966fc30e6f06ca8f98fb0ce51eda6b111b3ee8d066a8b1ec9e77fa06ab55d", size = 253450, upload-time = "2026-07-15T18:54:21.765Z" },
{ url = "https://files.pythonhosted.org/packages/d7/29/99021303f98fbdcb63504b4d07bea4cc025b9b2dd907c4f07c85d50a0dab/coverage-7.15.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:68af907f595ab01a78f794932ff3bdf929c316d3000810d38dbc247129e26f8b", size = 256187, upload-time = "2026-07-15T18:54:23.4Z" },
{ url = "https://files.pythonhosted.org/packages/f9/a8/fd503715ed6ca9c5d742923aa5209257340b367a867b2ced0c7d4ba8a0b9/coverage-7.15.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:afa29e2eff3d5729267e2cb2fd4ce9d61c952932fb2694e34ccb5d9540c6a296", size = 257301, upload-time = "2026-07-15T18:54:25.183Z" },
{ url = "https://files.pythonhosted.org/packages/da/40/3f4b8fb409810036ebc2857d36adc0498c6e957b5df0290c5036b2e143f1/coverage-7.15.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bbf44513ceb1589e31948e20eafbde9deaface90e1a1afa5f5f77b4423d17ce6", size = 259562, upload-time = "2026-07-15T18:54:27.204Z" },
{ url = "https://files.pythonhosted.org/packages/0b/8a/9bdffbef47db77cce3d6b02a28f7e919b19f0106c4b080c2c2246040f885/coverage-7.15.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9deddf09eecb717b7f980414b43d90a5b22ff3967d2949ab29cb0aa83d9e9098", size = 253841, upload-time = "2026-07-15T18:54:29.134Z" },
{ url = "https://files.pythonhosted.org/packages/1b/1e/9031efde019d31a06646261fce6dfc5c3c74e951e27a71e5c9a424563178/coverage-7.15.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ae901f7e55ba405c84ee1cab3d3e962e4e871e4a2bcb9c90911adbd69b42ac5a", size = 255221, upload-time = "2026-07-15T18:54:31.142Z" },
{ url = "https://files.pythonhosted.org/packages/56/db/787acde872389fc84a9ef9d8cd1ccc658e391ab4cb5b28092a714426a394/coverage-7.15.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a0f47002c6eeb7c280228467a4cb0cc15ca2103a8421b986b2d3ec04a0f9bd8b", size = 253366, upload-time = "2026-07-15T18:54:32.886Z" },
{ url = "https://files.pythonhosted.org/packages/2f/9b/6f57bc4b93c842eef1695f8cdaf2318e35e7ba54f5ba80d84be213ab7858/coverage-7.15.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1cd7a5beb7af3e864a13b1f0fb26efd3695da43ef0daf71e586adfffaf34d5b2", size = 257434, upload-time = "2026-07-15T18:54:34.7Z" },
{ url = "https://files.pythonhosted.org/packages/88/26/b3186a21b2acc83e451118978905c81c7072c3333707804db09a78c096a2/coverage-7.15.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:97a5c5457a9fb1d6c4e06cfb5dc835871fbfb6a6a51addc9e925bdeff5ef7440", size = 252935, upload-time = "2026-07-15T18:54:36.548Z" },
{ url = "https://files.pythonhosted.org/packages/20/c2/c9f3376b2e717ea69ed7a6e9a5fcab968fb0b290db6cf4bd9a1fc7541b75/coverage-7.15.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0901cfe6c13bcd2302da4f83e884555d2a22bda6e4c476f09ef204ba20ca536e", size = 254807, upload-time = "2026-07-15T18:54:38.296Z" },
{ url = "https://files.pythonhosted.org/packages/f0/e1/dfc15401f4a8aaeb486e1ba3e9e3c40522a6e38bd0ecf0b3f29cb8082957/coverage-7.15.2-cp312-cp312-win32.whl", hash = "sha256:b171bdd71cb7ff792bf32e376173b0ace7e7963e7e57c58dfc42063a6a7174cd", size = 223641, upload-time = "2026-07-15T18:54:40.103Z" },
{ url = "https://files.pythonhosted.org/packages/91/40/81b6d809d320cd366ec5bdf8176575e897dcb8efe7fb4b489ef9e93e4d13/coverage-7.15.2-cp312-cp312-win_amd64.whl", hash = "sha256:582edc45c2040543fef83341be23c43024a3ab3ae0c2d8bc498a06282905ad40", size = 224172, upload-time = "2026-07-15T18:54:41.882Z" },
{ url = "https://files.pythonhosted.org/packages/ef/28/9f14ec438149f7de557f45518f09b4a7917b795cc37083aa7db482693f8c/coverage-7.15.2-cp312-cp312-win_arm64.whl", hash = "sha256:a638db90c61cd219aeee65e83a24fdaa57269a741ae0cf773309208ac862cee3", size = 223556, upload-time = "2026-07-15T18:54:43.674Z" },
{ url = "https://files.pythonhosted.org/packages/ec/82/32e3bd191d498e64f6f911ad55d14006a0861e54869d2d32452326399e65/coverage-7.15.2-py3-none-any.whl", hash = "sha256:eb6bcae8d1a9d305351ecb108232441d11c5cfe9de840a04388ba5d2db8d735c", size = 213375, upload-time = "2026-07-15T18:56:17.305Z" },
]
[[package]]
@@ -565,27 +565,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.15.21"
version = "0.15.22"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
sdist = { url = "https://files.pythonhosted.org/packages/3a/06/ae069393fc66e8ff33036d4b368003833bf6e88ccf182e17e7a2f1c754fd/ruff-0.15.22.tar.gz", hash = "sha256:3f15175b1fb580126f58285a5dae6b2ea89000136d980c64499211f116b54809", size = 4785063, upload-time = "2026-07-16T15:14:13.244Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
{ url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
{ url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
{ url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
{ url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
{ url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
{ url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
{ url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
{ url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
{ url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
{ url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
{ url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
{ url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
{ url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
{ url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
{ url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
{ url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
{ url = "https://files.pythonhosted.org/packages/23/18/ee54b7ae1e121be7a28ea6da4b67564ebb0530e183a54415ab7e3bcd2c4e/ruff-0.15.22-py3-none-linux_armv6l.whl", hash = "sha256:44423e73493737f5e7c5b41d475483898ff37afcdae38bc3da5085e29af1c2d8", size = 10781258, upload-time = "2026-07-16T15:13:19.452Z" },
{ url = "https://files.pythonhosted.org/packages/2f/d2/2520cb14761ddbeaf57642a76942fc36adcbdbe53b4532241995f6fc485c/ruff-0.15.22-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b82c6482946e9eda7ff2e091d25b8bad3f718684e1916d41bd56873cee05b697", size = 10999477, upload-time = "2026-07-16T15:13:23.318Z" },
{ url = "https://files.pythonhosted.org/packages/c9/10/74e53572aa758dfaa678c2a2646b5c5515d884b7ca56be4d2ce03ca4b560/ruff-0.15.22-py3-none-macosx_11_0_arm64.whl", hash = "sha256:11c1c715af53a09f714e011106bffc419751ec8232fcb5da42173284ea3fec6f", size = 10466716, upload-time = "2026-07-16T15:13:26.162Z" },
{ url = "https://files.pythonhosted.org/packages/1e/cc/44eaaf0844e028182f2d0a8f2190d0f359159aed0a9e5ab861d892f1ae2a/ruff-0.15.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:742a29cf29bddb7c8327895d6a10e0e6c5b38a96dd407af9b5d0857f809c0576", size = 10892644, upload-time = "2026-07-16T15:13:29.229Z" },
{ url = "https://files.pythonhosted.org/packages/9f/21/8edf559014d2b0f82beea19cfb713993ad802ccda16868769979c6090a84/ruff-0.15.22-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72af58b951b0ae395935ae79763dc349bc0eb706319d28f7a33ad2cfb3cfc178", size = 10576719, upload-time = "2026-07-16T15:13:32.35Z" },
{ url = "https://files.pythonhosted.org/packages/bf/1e/3a13abd392a3b50b62e5938a831f9ab6e588358cacad5c18545b716d2182/ruff-0.15.22-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d425005c1835eb24e2ee4161cb90e8db263415f4a71c8c72c33abaa6c0c224", size = 11376494, upload-time = "2026-07-16T15:13:35.958Z" },
{ url = "https://files.pythonhosted.org/packages/bf/3e/422d3d95bcf04dd78e1aeac22184d4f9a8fb2c01865d39d44618484a0317/ruff-0.15.22-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8b9b3f8779a4f08c969defc3c8c35abffaa757e601ed5ae66d6d1db6519969a", size = 12208370, upload-time = "2026-07-16T15:13:39.185Z" },
{ url = "https://files.pythonhosted.org/packages/1e/91/5d065a0e0a02bf4813f5119ad278462eed081d2b832eb7c021ade0ec9e65/ruff-0.15.22-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e0dd1b2e4d3d585f897a0d137cbf4eaf6223bef4e8ce34d6bb12556c5f9249e", size = 11581098, upload-time = "2026-07-16T15:13:42.132Z" },
{ url = "https://files.pythonhosted.org/packages/f6/f9/a0d4871d12fae702eb1f41b686caf05f1f8b124dc6db6f784f53d74918fa/ruff-0.15.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:365523eb91d9224e1bcb03b022fbf0facb8f9e23792a2c53d9d4b3924bdbdebb", size = 11399422, upload-time = "2026-07-16T15:13:45.2Z" },
{ url = "https://files.pythonhosted.org/packages/18/80/c843a5176cddbceb0b7e8dd41cf9993490796c1c469348d384f5a5c13c56/ruff-0.15.22-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:fabfd168afdf29fee5be98b831efa9683c94d7c5a3b58b9ce5a2e38444589a74", size = 11381683, upload-time = "2026-07-16T15:13:48.46Z" },
{ url = "https://files.pythonhosted.org/packages/d4/00/8485de0ae92239438a36cfc51350db9b9e85c9ebdfaea91b18e422706662/ruff-0.15.22-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:225dbf095a87f1d9f90f5fd7924d2613ee452a75a4308c63a8f50f761787aa7c", size = 10850295, upload-time = "2026-07-16T15:13:51.655Z" },
{ url = "https://files.pythonhosted.org/packages/fa/91/24977ec2ec72eaf15e4394ace2959fdff2dd1e14f03e005e838023407169/ruff-0.15.22-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1877d63b9d24ed278744f1523fd11b85540566d54641f97c566d7d9dc5ca5296", size = 10579640, upload-time = "2026-07-16T15:13:54.79Z" },
{ url = "https://files.pythonhosted.org/packages/9c/47/9b51216951974df1f263ac19da550d34252e0ed7218c25f10c5ef9ed7517/ruff-0.15.22-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a1606c510bd7215680d32efab38965f7cdec3ef69f5170a3f4791404ffdd5262", size = 11105077, upload-time = "2026-07-16T15:13:57.915Z" },
{ url = "https://files.pythonhosted.org/packages/c2/47/20e9d4a3b8016778acea5fc32bb50d35d207500a17ddb529ffa6996feef8/ruff-0.15.22-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:630479b18625f5ffc373f77603a22a9f8ac0acd7ff0501178b5db28ec71e9c64", size = 11490980, upload-time = "2026-07-16T15:14:01.032Z" },
{ url = "https://files.pythonhosted.org/packages/4d/76/3f72d8fc38c1cb77b38c56a70da9d0c17700cc1cc50f9649c9d3c8f5ba71/ruff-0.15.22-py3-none-win32.whl", hash = "sha256:e5ba0e4a13fd14abbed2a77b517a3911290c6c6c59ef67784328d1668fab76cf", size = 10789165, upload-time = "2026-07-16T15:14:04.16Z" },
{ url = "https://files.pythonhosted.org/packages/cb/46/4965251734c2b6fcdca1b1b187d20bcac3af0ee5b083b89c910bb961ce3a/ruff-0.15.22-py3-none-win_amd64.whl", hash = "sha256:9be63ba1eb936acd2d1342fb8337c356353706fce233b2a15a09a97037e6acde", size = 11938297, upload-time = "2026-07-16T15:14:07.316Z" },
{ url = "https://files.pythonhosted.org/packages/57/c9/e69b1ff4c8b69093ef08b8919ab767af0569666865b39c30a8795d88d3c6/ruff-0.15.22-py3-none-win_arm64.whl", hash = "sha256:e1168075b72158510839f250027659cdd78476f40507dd517892304c41318661", size = 11298172, upload-time = "2026-07-16T15:14:10.51Z" },
]
[[package]]
@@ -599,14 +599,14 @@ wheels = [
[[package]]
name = "tqdm"
version = "4.68.4"
version = "4.69.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ae/5f/57ff8b434839e70dab45601284ea413e947a63799891b7553e5960a793a8/tqdm-4.68.4.tar.gz", hash = "sha256:19829c9673638f2a0b8617da4cdcb927e831cd88bcfcb6e78d42a4d1af131520", size = 792418, upload-time = "2026-07-07T09:58:18.369Z" }
sdist = { url = "https://files.pythonhosted.org/packages/8c/69/40407dfc835517f058b603dbf37a6df094d8582b015a51eddc988febbcb7/tqdm-4.69.0.tar.gz", hash = "sha256:700c5e85dcd5f009dd6222588a29180a193a748247a5d855b4d67db93d79a53b", size = 792569, upload-time = "2026-07-17T18:09:06.2Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/22/2a/5e5e750890ada51017d18d0d4c30da696e5b5bd3180947729927628fc3cb/tqdm-4.68.4-py3-none-any.whl", hash = "sha256:5168118b2368f48c561afda8020fd79195b1bdb0bdf8086b88442c267a315dc2", size = 676612, upload-time = "2026-07-07T09:58:16.256Z" },
{ url = "https://files.pythonhosted.org/packages/fe/21/99a0cdaf54eb35e77623c41b5a2c9472ee4404bba687052791fe2aba6773/tqdm-4.69.0-py3-none-any.whl", hash = "sha256:9979978912be667a6ef21fd5d8abf54e324e63d82f7f43c360792ebc2bc4e622", size = 676680, upload-time = "2026-07-17T18:09:04.172Z" },
]
[[package]]
@@ -651,27 +651,27 @@ wheels = [
[[package]]
name = "ty"
version = "0.0.59"
version = "0.0.61"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/95/b0/84ae7b3bf6e3e9f57eb9635eeff5a80b36e57aa089f40be0fb5c384fa176/ty-0.0.59.tar.gz", hash = "sha256:53e53ffeed78ad59cd237fa8ea1316d2b94e13efdea9a945698acab549e005aa", size = 6145435, upload-time = "2026-07-12T20:22:02.781Z" }
sdist = { url = "https://files.pythonhosted.org/packages/92/63/6944925d0fe9a4bb9cc744e6c045a42bbd2ee4654c103190674577a36c3f/ty-0.0.61.tar.gz", hash = "sha256:acbf0d914cc7e2e57ccc440036af36114819e2a604a5ffb554e72e4ca7dd65a2", size = 6234957, upload-time = "2026-07-18T01:39:54.696Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/57/e8/650b42fbef4d48e6ca682b0b6e9b68fa8fcf55cbb0a6892ab89990018b6f/ty-0.0.59-py3-none-linux_armv6l.whl", hash = "sha256:f8fb08a767ef8f11ea3c537b9d77860726cc2bc39e6f77ad13c02d5b289f20a7", size = 11700328, upload-time = "2026-07-12T20:21:26.046Z" },
{ url = "https://files.pythonhosted.org/packages/22/ac/0ca3a89d5f59ae5f308e5e83428cac5f9143200767743e052fba90b4b81e/ty-0.0.59-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:c7f4d5630836c8a0ba13dd4ac7bdae080a7d6ebe965b817ff642dc961bcf2a53", size = 11494310, upload-time = "2026-07-12T20:21:28.491Z" },
{ url = "https://files.pythonhosted.org/packages/f3/f8/5076de6001cefbccd8e6dc8472262697e43308ff66b0e87c72abba136357/ty-0.0.59-py3-none-macosx_11_0_arm64.whl", hash = "sha256:872f6fb02c6db5553c4d5fb283b3d50f0985fb9a29a910e4fda4793a775c1926", size = 11026797, upload-time = "2026-07-12T20:21:30.879Z" },
{ url = "https://files.pythonhosted.org/packages/2e/0f/fca28481b6a138e2b798ad9fdc98a095475f9104948ba242fce4b477782b/ty-0.0.59-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2af8eefbfe806337770eec12c0c819c5f1b8f5b85f8369cb1cc9fa25234a2208", size = 11475304, upload-time = "2026-07-12T20:21:33.041Z" },
{ url = "https://files.pythonhosted.org/packages/08/4b/1fed8b81b389ef4bbc0400f19e05fc16496b162577779dc0e5fc65ac216c/ty-0.0.59-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0acf8b76a1c9a7ddef460b42475f6c76193164426ab080783af1c3175b4b999b", size = 11533131, upload-time = "2026-07-12T20:21:35.189Z" },
{ url = "https://files.pythonhosted.org/packages/5f/fc/04eec35e05a10e0fea1c6503a290ccc3935efda9c845aff64e83282c1af7/ty-0.0.59-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:043c2e00eb1d7475f928af7dedd71f69b64e69bfca55e36f4c968479e1373fc4", size = 12205932, upload-time = "2026-07-12T20:21:37.324Z" },
{ url = "https://files.pythonhosted.org/packages/a9/dd/a61de859659fa11b55917ad38340a8f2c61f5ae17d1874929f29084c6990/ty-0.0.59-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f0d688d857441df57f48fca66c029d85cf737c510e7be1d01144cdad1e58d968", size = 12758406, upload-time = "2026-07-12T20:21:39.525Z" },
{ url = "https://files.pythonhosted.org/packages/c6/e8/fa66f05997eab8ca75fc4f17320140e25467849e0cc75597f898cc22099c/ty-0.0.59-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a96c9f88394a3b42c737e2125b2330543f0d90a43b49761f377d96f8c3ee0d62", size = 12288176, upload-time = "2026-07-12T20:21:41.784Z" },
{ url = "https://files.pythonhosted.org/packages/15/68/0fca59963bd5123f42d5f7da50667e7a52e8e9615e3a16d8c2c0d3b2d143/ty-0.0.59-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f08dbcb268edcafcb152e59475b5b495ce28d0b340a395c09943557678f4d5a6", size = 12028471, upload-time = "2026-07-12T20:21:43.82Z" },
{ url = "https://files.pythonhosted.org/packages/e1/5b/cd7dabbbab392578f11179919da5c25d8c3322e5388a688f539ea0539603/ty-0.0.59-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:8812764b9a40fdc98df1272826e73a298ef56b06681135e643bcf90aad1896f7", size = 12297646, upload-time = "2026-07-12T20:21:45.76Z" },
{ url = "https://files.pythonhosted.org/packages/1d/37/2e9c94f0b383d8cbe1a35517ab470b7810bc9d7501603ab532bcd5be5e90/ty-0.0.59-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:fd53b8581641d8dad7bfac6d5ea589e91a883d6837e0b9a286fdae30722b7c69", size = 11432519, upload-time = "2026-07-12T20:21:47.694Z" },
{ url = "https://files.pythonhosted.org/packages/9d/0a/af93e9785200f11ac416cc20235fc2464c9bd978e791190684ea0e458795/ty-0.0.59-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:86da5872124a41877d95058bc17d33ddcff034b587eb5f1e2917ab88ba227dac", size = 11554993, upload-time = "2026-07-12T20:21:49.671Z" },
{ url = "https://files.pythonhosted.org/packages/4b/dd/651bf87e20d00376c81b19124756491cffaf20eb8bec05a8794e5a8cf641/ty-0.0.59-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6a233eef5f2fd4d894881e4a0aec83c9f172bfae1d787d6596ee1939fcc7723e", size = 11818230, upload-time = "2026-07-12T20:21:51.659Z" },
{ url = "https://files.pythonhosted.org/packages/16/50/c947c4155fea751d135b19affdf734bbce72a94e446b866cf0c62f8bed69/ty-0.0.59-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7ff678c18b5f1e3128b75a35e50dee7908dea55155baa31cd790619d5014cbf5", size = 12135194, upload-time = "2026-07-12T20:21:53.796Z" },
{ url = "https://files.pythonhosted.org/packages/b1/13/e5feb138888de1e95037c843571bbbd4ac21bf0a190507468098599a321f/ty-0.0.59-py3-none-win32.whl", hash = "sha256:cf8abb4b8095c5fe39102b8127f5886db308c8d4600909ddbc905512ce9c8163", size = 11179249, upload-time = "2026-07-12T20:21:55.752Z" },
{ url = "https://files.pythonhosted.org/packages/76/dd/52914dcbeeba92c207de40ef7109a58dcb5527aeb21c8f8feb7402aa9e29/ty-0.0.59-py3-none-win_amd64.whl", hash = "sha256:1dde20a82243d24407869e5a608c2f15efddd5cefc662aef461a5af84bfb3f8b", size = 12251079, upload-time = "2026-07-12T20:21:58.1Z" },
{ url = "https://files.pythonhosted.org/packages/d4/8f/ac36fde77e223297454c1e0aeb8888c169eaacf3163bb609e3af942c88cb/ty-0.0.59-py3-none-win_arm64.whl", hash = "sha256:987043ee9e021f49493d9135891ac69c1affeee0d4ad4480c5fa4d9c975fc91b", size = 11650921, upload-time = "2026-07-12T20:22:00.348Z" },
{ url = "https://files.pythonhosted.org/packages/dc/cf/044f31523e2768e3e64b0ca2ec32f70b3a731d4a2caa6ea110baf26e251c/ty-0.0.61-py3-none-linux_armv6l.whl", hash = "sha256:148779b8675eac93f40ec58bd70037fe67537117f20a23272264f8f136d41336", size = 11891448, upload-time = "2026-07-18T01:39:18.449Z" },
{ url = "https://files.pythonhosted.org/packages/d2/55/558cfe76b65d91d1854bbfac336020bd42fd887caa632d845d13c0c539eb/ty-0.0.61-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:08217382b3385808ee7288501ea3214b32631b08d1fd091ece6799b0c95264c5", size = 11602442, upload-time = "2026-07-18T01:39:20.914Z" },
{ url = "https://files.pythonhosted.org/packages/27/be/78c0ae6634cd606a68e5b46b338db427a48a1800c96a749b2d2f7a702e03/ty-0.0.61-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6d99c729011b47dec20e78a32ac9c8f6defd4cf62f7bb851bbccf70dde6cee50", size = 11125286, upload-time = "2026-07-18T01:39:22.893Z" },
{ url = "https://files.pythonhosted.org/packages/a4/18/a40793962f1b6337938ddb0bca7496b54e70879e23b4d2cc8dfd7e5d1af3/ty-0.0.61-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cda607978ae271b77e51c947663218bce635c3507e256865444b10c37cdb60d", size = 11663403, upload-time = "2026-07-18T01:39:25.017Z" },
{ url = "https://files.pythonhosted.org/packages/98/c1/7879244da5b30407dc368946d36be5024380073408b079f144ffe034030e/ty-0.0.61-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0d78f160a0f9434d570cdcdbc4dafba1f6aac3c47a32f9f63995b3cb55ffe4b6", size = 11715250, upload-time = "2026-07-18T01:39:27.045Z" },
{ url = "https://files.pythonhosted.org/packages/35/c4/8a4637cd58abd37f315dd515e24c582986cb1bfdf2edc4786882f5a4f69a/ty-0.0.61-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09aeab4800b36e93e4ce918699004da642d74988cac920b7592a6a2b9be6611c", size = 12393876, upload-time = "2026-07-18T01:39:29.197Z" },
{ url = "https://files.pythonhosted.org/packages/27/4b/27e7c640b1272743503229aa17ae2167a538040c4716a2fa1777c2b34fea/ty-0.0.61-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dccc8136df44142a109953a168be17b4915c99876b047d0b6672c31dae939bdf", size = 12958187, upload-time = "2026-07-18T01:39:31.308Z" },
{ url = "https://files.pythonhosted.org/packages/3a/f5/70eaaefb6081fb0a8115cff66fbfaa20dafac8c646df2477adad95a59de2/ty-0.0.61-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:220760c2d13a887d027ee1093172c24ac35b6e634805329c93a30908ae4d3f5c", size = 12560101, upload-time = "2026-07-18T01:39:33.35Z" },
{ url = "https://files.pythonhosted.org/packages/e3/5a/17bae3b6429b5c479dc6c1e344d34e1f79efbc27531f15f3ee5b5da63745/ty-0.0.61-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:effefbb89da7128d18059529d1c2ea390fe7f1f3882690d257ca2143d49a0c34", size = 12225389, upload-time = "2026-07-18T01:39:35.436Z" },
{ url = "https://files.pythonhosted.org/packages/d2/0e/2ac380ba20d6395542c8df1d6fa4f00e2aead784c2e6aaefa1e02ed0610c/ty-0.0.61-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:ba8b28a5ef811d5bb6461e37d76110c06fd20487474865c323d3d18b08b972b2", size = 12548403, upload-time = "2026-07-18T01:39:37.556Z" },
{ url = "https://files.pythonhosted.org/packages/b0/e5/7da4b73e825e1a9808c26d68b0156e9a37aede1846191210dfffb8c64042/ty-0.0.61-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:88ecd6d9b05e8174b1860dac9bd3e188d6cef5702b0d3239fd9f94f6ac73a29d", size = 11621813, upload-time = "2026-07-18T01:39:39.919Z" },
{ url = "https://files.pythonhosted.org/packages/9b/3c/5b58015e998cd0d89b17a463b6321421457d86d987574e8dac65ddfceba3/ty-0.0.61-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fb0cdfe4c48542ffb9a1139825dfa3d4aae49e96e966682ef7da762ab97831ff", size = 11734101, upload-time = "2026-07-18T01:39:42.097Z" },
{ url = "https://files.pythonhosted.org/packages/a6/21/294f4cc819b7b12ed659fd860e5cdfbd592d4c768c8f23596685dbc43e6b/ty-0.0.61-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dff03873c0c3d0b44738f8b6d403b0756a31cf54c65136397df7624c6159b1f0", size = 11988401, upload-time = "2026-07-18T01:39:44.183Z" },
{ url = "https://files.pythonhosted.org/packages/2e/26/0f96f79fdac118521a9771e9eef3f9b3f447d647b2c77953e80a1715c7e8/ty-0.0.61-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a9210e80e3d41c1dfc751e9e8e0980272f475031fafd0fb0f48aee233c78da03", size = 12330624, upload-time = "2026-07-18T01:39:46.662Z" },
{ url = "https://files.pythonhosted.org/packages/e3/08/1e62d1bca5c0cebdc7a34db1f4b61557aab85961cedd56953dd2c32d3e66/ty-0.0.61-py3-none-win32.whl", hash = "sha256:e3e1fe06f49a5492a922a5df2739834aa5ee978c7dd10414119dc8755cc40c9c", size = 11313991, upload-time = "2026-07-18T01:39:48.761Z" },
{ url = "https://files.pythonhosted.org/packages/26/f1/d8e33b3aeb36b73d81ae34d10e46ec4abf506d68f4e0a1491a76a593dd42/ty-0.0.61-py3-none-win_amd64.whl", hash = "sha256:25f2291169e0298fcdbba1b1fea64f8207a6c1908dddef32346fd5e3e6ac9221", size = 12311717, upload-time = "2026-07-18T01:39:50.881Z" },
{ url = "https://files.pythonhosted.org/packages/e1/14/7caec26d93a943c0e7d15eb7374644508d08cbd387d112b722b12d14e044/ty-0.0.61-py3-none-win_arm64.whl", hash = "sha256:3e496f7698bc4b5bbb1eb66d8b5799ba87596d88d36604ca359083893fa2fc49", size = 11693485, upload-time = "2026-07-18T01:39:52.73Z" },
]
[[package]]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+115 -94
View File
@@ -8366,7 +8366,7 @@ const ::capnp::_::RawSchema s_b52430dc48f4a83b = {
7, 14, i_b52430dc48f4a83b, nullptr, nullptr, { &s_b52430dc48f4a83b, nullptr, nullptr, 0, 0, nullptr }, false
};
#endif // !CAPNP_LITE
static const ::capnp::_::AlignedData<67> b_e9e600c8b9e6b62d = {
static const ::capnp::_::AlignedData<72> b_e9e600c8b9e6b62d = {
{ 0, 0, 0, 0, 5, 0, 6, 0,
45, 182, 230, 185, 200, 0, 230, 233,
25, 0, 0, 0, 2, 0, 0, 0,
@@ -8376,7 +8376,7 @@ static const ::capnp::_::AlignedData<67> b_e9e600c8b9e6b62d = {
21, 0, 0, 0, 50, 1, 0, 0,
37, 0, 0, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
33, 0, 0, 0, 247, 0, 0, 0,
33, 0, 0, 0, 15, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
108, 111, 103, 46, 99, 97, 112, 110,
@@ -8385,36 +8385,39 @@ static const ::capnp::_::AlignedData<67> b_e9e600c8b9e6b62d = {
46, 65, 117, 100, 105, 98, 108, 101,
65, 108, 101, 114, 116, 0, 0, 0,
0, 0, 0, 0, 1, 0, 1, 0,
40, 0, 0, 0, 1, 0, 2, 0,
44, 0, 0, 0, 1, 0, 2, 0,
0, 0, 0, 0, 0, 0, 0, 0,
113, 0, 0, 0, 42, 0, 0, 0,
125, 0, 0, 0, 42, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
105, 0, 0, 0, 58, 0, 0, 0,
117, 0, 0, 0, 58, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
2, 0, 0, 0, 0, 0, 0, 0,
97, 0, 0, 0, 82, 0, 0, 0,
109, 0, 0, 0, 82, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
3, 0, 0, 0, 0, 0, 0, 0,
93, 0, 0, 0, 58, 0, 0, 0,
105, 0, 0, 0, 58, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
4, 0, 0, 0, 0, 0, 0, 0,
85, 0, 0, 0, 98, 0, 0, 0,
97, 0, 0, 0, 98, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
5, 0, 0, 0, 0, 0, 0, 0,
81, 0, 0, 0, 138, 0, 0, 0,
93, 0, 0, 0, 138, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
6, 0, 0, 0, 0, 0, 0, 0,
81, 0, 0, 0, 58, 0, 0, 0,
93, 0, 0, 0, 58, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
7, 0, 0, 0, 0, 0, 0, 0,
73, 0, 0, 0, 106, 0, 0, 0,
85, 0, 0, 0, 106, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
8, 0, 0, 0, 0, 0, 0, 0,
69, 0, 0, 0, 138, 0, 0, 0,
81, 0, 0, 0, 138, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
9, 0, 0, 0, 0, 0, 0, 0,
69, 0, 0, 0, 74, 0, 0, 0,
81, 0, 0, 0, 74, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
10, 0, 0, 0, 0, 0, 0, 0,
77, 0, 0, 0, 74, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
110, 111, 110, 101, 0, 0, 0, 0,
101, 110, 103, 97, 103, 101, 0, 0,
@@ -8433,14 +8436,16 @@ static const ::capnp::_::AlignedData<67> b_e9e600c8b9e6b62d = {
115, 116, 114, 97, 99, 116, 101, 100,
0, 0, 0, 0, 0, 0, 0, 0,
112, 114, 101, 65, 108, 101, 114, 116,
0, 0, 0, 0, 0, 0, 0, 0,
99, 111, 109, 112, 108, 101, 116, 101,
0, 0, 0, 0, 0, 0, 0, 0, }
};
::capnp::word const* const bp_e9e600c8b9e6b62d = b_e9e600c8b9e6b62d.words;
#if !CAPNP_LITE
static const uint16_t m_e9e600c8b9e6b62d[] = {2, 1, 0, 9, 6, 8, 7, 3, 5, 4};
static const uint16_t m_e9e600c8b9e6b62d[] = {10, 2, 1, 0, 9, 6, 8, 7, 3, 5, 4};
const ::capnp::_::RawSchema s_e9e600c8b9e6b62d = {
0xe9e600c8b9e6b62d, b_e9e600c8b9e6b62d.words, 67, nullptr, m_e9e600c8b9e6b62d,
0, 10, nullptr, nullptr, nullptr, { &s_e9e600c8b9e6b62d, nullptr, nullptr, 0, 0, nullptr }, false
0xe9e600c8b9e6b62d, b_e9e600c8b9e6b62d.words, 72, nullptr, m_e9e600c8b9e6b62d,
0, 11, nullptr, nullptr, nullptr, { &s_e9e600c8b9e6b62d, nullptr, nullptr, 0, 0, nullptr }, false
};
#endif // !CAPNP_LITE
CAPNP_DEFINE_ENUM(AudibleAlert_e9e600c8b9e6b62d, e9e600c8b9e6b62d);
@@ -25624,7 +25629,7 @@ const ::capnp::_::RawSchema s_8aad6ef40447efb7 = {
2, 5, i_8aad6ef40447efb7, nullptr, nullptr, { &s_8aad6ef40447efb7, nullptr, nullptr, 0, 0, nullptr }, false
};
#endif // !CAPNP_LITE
static const ::capnp::_::AlignedData<261> b_a0df507d7df1052d = {
static const ::capnp::_::AlignedData<277> b_a0df507d7df1052d = {
{ 0, 0, 0, 0, 5, 0, 6, 0,
45, 5, 241, 125, 125, 80, 223, 160,
10, 0, 0, 0, 1, 0, 2, 0,
@@ -25634,7 +25639,7 @@ static const ::capnp::_::AlignedData<261> b_a0df507d7df1052d = {
21, 0, 0, 0, 2, 1, 0, 0,
33, 0, 0, 0, 87, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
125, 0, 0, 0, 23, 3, 0, 0,
125, 0, 0, 0, 79, 3, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
108, 111, 103, 46, 99, 97, 112, 110,
@@ -25666,105 +25671,112 @@ static const ::capnp::_::AlignedData<261> b_a0df507d7df1052d = {
67, 97, 108, 105, 98, 114, 97, 116,
105, 111, 110, 83, 116, 97, 116, 101,
0, 0, 0, 0, 0, 0, 0, 0,
56, 0, 0, 0, 3, 0, 4, 0,
60, 0, 0, 0, 3, 0, 4, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
121, 1, 0, 0, 66, 0, 0, 0,
149, 1, 0, 0, 66, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
116, 1, 0, 0, 3, 0, 1, 0,
128, 1, 0, 0, 2, 0, 1, 0,
13, 0, 0, 0, 0, 0, 0, 0,
144, 1, 0, 0, 3, 0, 1, 0,
156, 1, 0, 0, 2, 0, 1, 0,
14, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
204, 238, 2, 226, 42, 156, 210, 177,
125, 1, 0, 0, 90, 0, 0, 0,
153, 1, 0, 0, 90, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
5, 0, 0, 0, 1, 0, 0, 0,
6, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 3, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
105, 1, 0, 0, 74, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
104, 1, 0, 0, 3, 0, 1, 0,
116, 1, 0, 0, 2, 0, 1, 0,
6, 0, 0, 0, 2, 0, 0, 0,
0, 0, 1, 0, 4, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
113, 1, 0, 0, 130, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
112, 1, 0, 0, 3, 0, 1, 0,
124, 1, 0, 0, 2, 0, 1, 0,
7, 0, 0, 0, 2, 0, 0, 0,
0, 0, 1, 0, 5, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
121, 1, 0, 0, 90, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
120, 1, 0, 0, 3, 0, 1, 0,
132, 1, 0, 0, 2, 0, 1, 0,
8, 0, 0, 0, 3, 0, 0, 0,
0, 0, 1, 0, 6, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
129, 1, 0, 0, 106, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
128, 1, 0, 0, 3, 0, 1, 0,
140, 1, 0, 0, 2, 0, 1, 0,
9, 0, 0, 0, 3, 0, 0, 0,
0, 0, 1, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
137, 1, 0, 0, 50, 0, 0, 0,
133, 1, 0, 0, 74, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
132, 1, 0, 0, 3, 0, 1, 0,
144, 1, 0, 0, 2, 0, 1, 0,
10, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 8, 0, 0, 0,
7, 0, 0, 0, 2, 0, 0, 0,
0, 0, 1, 0, 4, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
141, 1, 0, 0, 122, 0, 0, 0,
141, 1, 0, 0, 130, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
140, 1, 0, 0, 3, 0, 1, 0,
152, 1, 0, 0, 2, 0, 1, 0,
11, 0, 0, 0, 1, 0, 0, 0,
8, 0, 0, 0, 2, 0, 0, 0,
0, 0, 1, 0, 5, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
149, 1, 0, 0, 90, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
148, 1, 0, 0, 3, 0, 1, 0,
160, 1, 0, 0, 2, 0, 1, 0,
9, 0, 0, 0, 3, 0, 0, 0,
0, 0, 1, 0, 6, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
157, 1, 0, 0, 106, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
156, 1, 0, 0, 3, 0, 1, 0,
168, 1, 0, 0, 2, 0, 1, 0,
10, 0, 0, 0, 3, 0, 0, 0,
0, 0, 1, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
165, 1, 0, 0, 50, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
160, 1, 0, 0, 3, 0, 1, 0,
172, 1, 0, 0, 2, 0, 1, 0,
11, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 8, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
169, 1, 0, 0, 122, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
168, 1, 0, 0, 3, 0, 1, 0,
180, 1, 0, 0, 2, 0, 1, 0,
12, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 9, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
149, 1, 0, 0, 146, 0, 0, 0,
177, 1, 0, 0, 146, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
152, 1, 0, 0, 3, 0, 1, 0,
164, 1, 0, 0, 2, 0, 1, 0,
12, 0, 0, 0, 2, 0, 0, 0,
180, 1, 0, 0, 3, 0, 1, 0,
192, 1, 0, 0, 2, 0, 1, 0,
13, 0, 0, 0, 2, 0, 0, 0,
0, 0, 1, 0, 10, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
161, 1, 0, 0, 178, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
164, 1, 0, 0, 3, 0, 1, 0,
176, 1, 0, 0, 2, 0, 1, 0,
1, 0, 0, 0, 3, 0, 0, 0,
0, 0, 1, 0, 11, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
173, 1, 0, 0, 186, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
176, 1, 0, 0, 3, 0, 1, 0,
188, 1, 0, 0, 2, 0, 1, 0,
2, 0, 0, 0, 8, 0, 0, 0,
0, 0, 1, 0, 12, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
185, 1, 0, 0, 98, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
184, 1, 0, 0, 3, 0, 1, 0,
196, 1, 0, 0, 2, 0, 1, 0,
3, 0, 0, 0, 9, 0, 0, 0,
0, 0, 1, 0, 13, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
193, 1, 0, 0, 130, 0, 0, 0,
189, 1, 0, 0, 178, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
192, 1, 0, 0, 3, 0, 1, 0,
204, 1, 0, 0, 2, 0, 1, 0,
4, 0, 0, 0, 4, 0, 0, 0,
0, 0, 1, 0, 14, 0, 0, 0,
2, 0, 0, 0, 3, 0, 0, 0,
0, 0, 1, 0, 11, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
201, 1, 0, 0, 170, 0, 0, 0,
201, 1, 0, 0, 194, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
204, 1, 0, 0, 3, 0, 1, 0,
216, 1, 0, 0, 2, 0, 1, 0,
3, 0, 0, 0, 8, 0, 0, 0,
0, 0, 1, 0, 12, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
213, 1, 0, 0, 98, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
212, 1, 0, 0, 3, 0, 1, 0,
224, 1, 0, 0, 2, 0, 1, 0,
4, 0, 0, 0, 9, 0, 0, 0,
0, 0, 1, 0, 13, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
221, 1, 0, 0, 130, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
220, 1, 0, 0, 3, 0, 1, 0,
232, 1, 0, 0, 2, 0, 1, 0,
5, 0, 0, 0, 4, 0, 0, 0,
0, 0, 1, 0, 14, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
229, 1, 0, 0, 170, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
232, 1, 0, 0, 3, 0, 1, 0,
244, 1, 0, 0, 2, 0, 1, 0,
1, 0, 0, 0, 10, 0, 0, 0,
0, 0, 1, 0, 15, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
241, 1, 0, 0, 106, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
240, 1, 0, 0, 3, 0, 1, 0,
252, 1, 0, 0, 2, 0, 1, 0,
108, 111, 99, 107, 111, 117, 116, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -25848,9 +25860,9 @@ static const ::capnp::_::AlignedData<261> b_a0df507d7df1052d = {
16, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
108, 111, 99, 107, 111, 117, 116, 82,
101, 99, 111, 118, 101, 114, 121, 80,
101, 114, 99, 101, 110, 116, 0, 0,
108, 111, 99, 107, 111, 117, 116, 77,
105, 110, 117, 116, 101, 115, 82, 101,
109, 97, 105, 110, 105, 110, 103, 0,
2, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -25885,6 +25897,15 @@ static const ::capnp::_::AlignedData<261> b_a0df507d7df1052d = {
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
108, 111, 99, 107, 111, 117, 116, 67,
111, 117, 110, 116, 0, 0, 0, 0,
2, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
2, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, }
};
::capnp::word const* const bp_a0df507d7df1052d = b_a0df507d7df1052d.words;
@@ -25897,11 +25918,11 @@ static const ::capnp::_::RawSchema* const d_a0df507d7df1052d[] = {
&s_f35f5f0c8b6ed5fc,
&s_fc59c1779c0b5d25,
};
static const uint16_t m_a0df507d7df1052d[] = {5, 11, 4, 2, 3, 1, 6, 0, 10, 12, 13, 7, 8, 9};
static const uint16_t i_a0df507d7df1052d[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
static const uint16_t m_a0df507d7df1052d[] = {5, 11, 4, 2, 3, 1, 6, 0, 14, 10, 12, 13, 7, 8, 9};
static const uint16_t i_a0df507d7df1052d[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
const ::capnp::_::RawSchema s_a0df507d7df1052d = {
0xa0df507d7df1052d, b_a0df507d7df1052d.words, 261, d_a0df507d7df1052d, m_a0df507d7df1052d,
6, 14, i_a0df507d7df1052d, nullptr, nullptr, { &s_a0df507d7df1052d, nullptr, nullptr, 0, 0, nullptr }, false
0xa0df507d7df1052d, b_a0df507d7df1052d.words, 277, d_a0df507d7df1052d, m_a0df507d7df1052d,
6, 15, i_a0df507d7df1052d, nullptr, nullptr, { &s_a0df507d7df1052d, nullptr, nullptr, 0, 0, nullptr }, false
};
#endif // !CAPNP_LITE
static const ::capnp::_::AlignedData<36> b_96090816b1289c99 = {
+26 -6
View File
@@ -373,6 +373,7 @@ enum class AudibleAlert_e9e600c8b9e6b62d: uint16_t {
PROMPT_REPEAT,
PROMPT_DISTRACTED,
PRE_ALERT,
COMPLETE,
};
CAPNP_DECLARE_ENUM(AudibleAlert, e9e600c8b9e6b62d);
CAPNP_DECLARE_SCHEMA(dbe58b96d2d1ac61);
@@ -19013,7 +19014,7 @@ public:
inline bool hasWheeltouchPolicyState() const;
inline ::cereal::DriverMonitoringState::WheeltouchPolicyState::Reader getWheeltouchPolicyState() const;
inline ::int8_t getLockoutRecoveryPercent() const;
inline ::int8_t getLockoutMinutesRemaining() const;
inline ::int8_t getAlert3Count() const;
@@ -19021,6 +19022,8 @@ public:
inline bool getNoResponseForceDecel() const;
inline ::int8_t getLockoutCount() const;
private:
::capnp::_::StructReader _reader;
template <typename, ::capnp::Kind>
@@ -19091,8 +19094,8 @@ public:
inline void adoptWheeltouchPolicyState(::capnp::Orphan< ::cereal::DriverMonitoringState::WheeltouchPolicyState>&& value);
inline ::capnp::Orphan< ::cereal::DriverMonitoringState::WheeltouchPolicyState> disownWheeltouchPolicyState();
inline ::int8_t getLockoutRecoveryPercent();
inline void setLockoutRecoveryPercent( ::int8_t value);
inline ::int8_t getLockoutMinutesRemaining();
inline void setLockoutMinutesRemaining( ::int8_t value);
inline ::int8_t getAlert3Count();
inline void setAlert3Count( ::int8_t value);
@@ -19103,6 +19106,9 @@ public:
inline bool getNoResponseForceDecel();
inline void setNoResponseForceDecel(bool value);
inline ::int8_t getLockoutCount();
inline void setLockoutCount( ::int8_t value);
private:
::capnp::_::StructBuilder _builder;
template <typename, ::capnp::Kind>
@@ -47899,16 +47905,16 @@ inline ::capnp::Orphan< ::cereal::DriverMonitoringState::WheeltouchPolicyState>
::capnp::bounded<2>() * ::capnp::POINTERS));
}
inline ::int8_t DriverMonitoringState::Reader::getLockoutRecoveryPercent() const {
inline ::int8_t DriverMonitoringState::Reader::getLockoutMinutesRemaining() const {
return _reader.getDataField< ::int8_t>(
::capnp::bounded<3>() * ::capnp::ELEMENTS);
}
inline ::int8_t DriverMonitoringState::Builder::getLockoutRecoveryPercent() {
inline ::int8_t DriverMonitoringState::Builder::getLockoutMinutesRemaining() {
return _builder.getDataField< ::int8_t>(
::capnp::bounded<3>() * ::capnp::ELEMENTS);
}
inline void DriverMonitoringState::Builder::setLockoutRecoveryPercent( ::int8_t value) {
inline void DriverMonitoringState::Builder::setLockoutMinutesRemaining( ::int8_t value) {
_builder.setDataField< ::int8_t>(
::capnp::bounded<3>() * ::capnp::ELEMENTS, value);
}
@@ -47955,6 +47961,20 @@ inline void DriverMonitoringState::Builder::setNoResponseForceDecel(bool value)
::capnp::bounded<4>() * ::capnp::ELEMENTS, value);
}
inline ::int8_t DriverMonitoringState::Reader::getLockoutCount() const {
return _reader.getDataField< ::int8_t>(
::capnp::bounded<10>() * ::capnp::ELEMENTS);
}
inline ::int8_t DriverMonitoringState::Builder::getLockoutCount() {
return _builder.getDataField< ::int8_t>(
::capnp::bounded<10>() * ::capnp::ELEMENTS);
}
inline void DriverMonitoringState::Builder::setLockoutCount( ::int8_t value) {
_builder.setDataField< ::int8_t>(
::capnp::bounded<10>() * ::capnp::ELEMENTS, value);
}
inline ::int8_t DriverMonitoringState::VisionPolicyState::Reader::getAwarenessPercent() const {
return _reader.getDataField< ::int8_t>(
::capnp::bounded<0>() * ::capnp::ELEMENTS);
+3 -1
View File
@@ -812,6 +812,7 @@ struct SelfdriveState {
promptDistracted @8;
preAlert @9;
complete @10;
}
enum OpenpilotState @0xdbe58b96d2d1ac61 {
@@ -2160,7 +2161,8 @@ struct DriverMonitoringStateDEPRECATED @0xb83cda094a1da284 {
struct DriverMonitoringState {
lockout @0 :Bool;
lockoutRecoveryPercent @11 :Int8;
lockoutCount @15 :Int8;
lockoutMinutesRemaining @11 :Int8;
alert3Count @12 :Int8;
noResponseCount @13 :Int8;
noResponseForceDecel @14 :Bool;
+55 -24
View File
@@ -7,12 +7,43 @@ import os
import capnp
import time
from typing import Optional, List, Union, Dict
from typing import Union
from openpilot.cereal import log
from openpilot.cereal.services import SERVICE_LIST
from openpilot.common.utils import MovingAverage
__all__ = (
"NO_TRAVERSAL_LIMIT",
"Context",
"FrequencyTracker",
"IpcError",
"MultiplePublishersError",
"Poller",
"PubMaster",
"PubSocket",
"SocketEventHandle",
"SubMaster",
"SubSocket",
"delete_fake_prefix",
"drain_sock",
"drain_sock_raw",
"fake_event_handle",
"get_fake_prefix",
"log_from_bytes",
"new_message",
"pub_sock",
"recv_one",
"recv_one_or_none",
"recv_one_retry",
"recv_sock",
"reset_context",
"set_fake_prefix",
"sub_sock",
"toggle_fake_events",
"wait_for_one_event",
)
NO_TRAVERSAL_LIMIT = 2**64-1
@@ -22,8 +53,8 @@ def pub_sock(endpoint: str) -> PubSocket:
return msgq.pub_sock(endpoint, segment_size)
def sub_sock(endpoint: str, poller: Optional[Poller] = None, addr: str = "127.0.0.1",
conflate: bool = False, timeout: Optional[int] = None) -> SubSocket:
def sub_sock(endpoint: str, poller: Poller | None = None, addr: str = "127.0.0.1",
conflate: bool = False, timeout: int | None = None) -> SubSocket:
service = SERVICE_LIST.get(endpoint)
segment_size = service.queue_size if service else 0
return msgq.sub_sock(endpoint, poller=poller, addr=addr, conflate=conflate,
@@ -39,7 +70,7 @@ def log_from_bytes(dat: bytes, struct: capnp.lib.capnp._StructModule = log.Event
return msg
def new_message(service: Optional[str], size: Optional[int] = None, **kwargs) -> capnp.lib.capnp._DynamicStructBuilder:
def new_message(service: str | None, size: int | None = None, **kwargs) -> capnp.lib.capnp._DynamicStructBuilder:
args = {
'valid': False,
'logMonoTime': int(time.monotonic() * 1e9),
@@ -54,14 +85,14 @@ def new_message(service: Optional[str], size: Optional[int] = None, **kwargs) ->
return dat
def drain_sock(sock: SubSocket, wait_for_one: bool = False) -> List[capnp.lib.capnp._DynamicStructReader]:
def drain_sock(sock: SubSocket, wait_for_one: bool = False) -> list[capnp.lib.capnp._DynamicStructReader]:
"""Receive all message currently available on the queue"""
msgs = drain_sock_raw(sock, wait_for_one=wait_for_one)
return [log_from_bytes(m) for m in msgs]
# TODO: print when we drop packets?
def recv_sock(sock: SubSocket, wait: bool = False) -> Optional[capnp.lib.capnp._DynamicStructReader]:
def recv_sock(sock: SubSocket, wait: bool = False) -> capnp.lib.capnp._DynamicStructReader | None:
"""Same as drain sock, but only returns latest message. Consider using conflate instead."""
dat = None
@@ -82,14 +113,14 @@ def recv_sock(sock: SubSocket, wait: bool = False) -> Optional[capnp.lib.capnp._
return dat
def recv_one(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]:
def recv_one(sock: SubSocket) -> capnp.lib.capnp._DynamicStructReader | None:
dat = sock.receive()
if dat is not None:
dat = log_from_bytes(dat)
return dat
def recv_one_or_none(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]:
def recv_one_or_none(sock: SubSocket) -> capnp.lib.capnp._DynamicStructReader | None:
dat = sock.receive(non_blocking=True)
if dat is not None:
dat = log_from_bytes(dat)
@@ -148,27 +179,27 @@ class FrequencyTracker:
class SubMaster:
def __init__(self, services: List[str], poll: Optional[str] = None,
ignore_alive: Optional[List[str]] = None, ignore_avg_freq: Optional[List[str]] = None,
ignore_valid: Optional[List[str]] = None, addr: str = "127.0.0.1", frequency: Optional[float] = None):
def __init__(self, services: list[str], poll: str | None = None,
ignore_alive: list[str] | None = None, ignore_avg_freq: list[str] | None = None,
ignore_valid: list[str] | None = None, addr: str = "127.0.0.1", frequency: float | None = None):
self.frame = -1
self.services = services
self.seen = {s: False for s in services}
self.updated = {s: False for s in services}
self.recv_time = {s: 0. for s in services}
self.recv_frame = {s: 0 for s in services}
self.seen = dict.fromkeys(services, False)
self.updated = dict.fromkeys(services, False)
self.recv_time = dict.fromkeys(services, 0.0)
self.recv_frame = dict.fromkeys(services, 0)
self.sock = {}
self.data = {}
self.logMonoTime = {s: 0 for s in services}
self.logMonoTime = dict.fromkeys(services, 0)
# zero-frequency / on-demand services are always alive and presumed valid; all others must pass checks
on_demand = {s: SERVICE_LIST[s].frequency <= 1e-5 for s in services}
self.static_freq_services = set(s for s in services if not on_demand[s])
self.static_freq_services = {s for s in services if not on_demand[s]}
self.alive = {s: on_demand[s] for s in services}
self.freq_ok = {s: on_demand[s] for s in services}
self.valid = {s: on_demand[s] for s in services}
self.freq_tracker: Dict[str, FrequencyTracker] = {}
self.freq_tracker: dict[str, FrequencyTracker] = {}
self.poller = Poller()
polled_services = set([poll, ] if poll is not None else services)
self.non_polled_services = set(services) - polled_services
@@ -211,7 +242,7 @@ class SubMaster:
msgs.append(recv_one_or_none(self.sock[s]))
self.update_msgs(time.monotonic(), msgs)
def update_msgs(self, cur_time: float, msgs: List[capnp.lib.capnp._DynamicStructReader]) -> None:
def update_msgs(self, cur_time: float, msgs: list[capnp.lib.capnp._DynamicStructReader]) -> None:
self.frame += 1
self.updated = dict.fromkeys(self.services, False)
for msg in msgs:
@@ -234,21 +265,21 @@ class SubMaster:
self.alive[s] = (cur_time - self.recv_time[s]) < (10. / SERVICE_LIST[s].frequency) or (self.seen[s] and self.simulation)
self.freq_ok[s] = self.freq_tracker[s].valid or self.simulation
def all_alive(self, service_list: Optional[List[str]] = None) -> bool:
def all_alive(self, service_list: list[str] | None = None) -> bool:
return all(self.alive[s] for s in (service_list or self.services) if s not in self.ignore_alive)
def all_freq_ok(self, service_list: Optional[List[str]] = None) -> bool:
def all_freq_ok(self, service_list: list[str] | None = None) -> bool:
return all(self.freq_ok[s] for s in (service_list or self.services) if self._check_avg_freq(s))
def all_valid(self, service_list: Optional[List[str]] = None) -> bool:
def all_valid(self, service_list: list[str] | None = None) -> bool:
return all(self.valid[s] for s in (service_list or self.services) if s not in self.ignore_valid)
def all_checks(self, service_list: Optional[List[str]] = None) -> bool:
def all_checks(self, service_list: list[str] | None = None) -> bool:
return self.all_alive(service_list) and self.all_freq_ok(service_list) and self.all_valid(service_list)
class PubMaster:
def __init__(self, services: List[str]):
def __init__(self, services: list[str]):
self.sock = {}
for s in services:
self.sock[s] = pub_sock(s)
@@ -1,4 +1,3 @@
import os
import capnp
import multiprocessing
import numbers
@@ -6,7 +5,6 @@ import random
import threading
import time
from openpilot.common.parameterized import parameterized
import pytest
from openpilot.cereal import log
from opendbc.car.structs import car
@@ -24,10 +22,6 @@ def random_socks(num_socks=10):
def random_bytes(length=1000):
return bytes([random.randrange(0xFF) for _ in range(length)])
def zmq_sleep(t=1):
if "ZMQ" in os.environ:
time.sleep(t)
# TODO: this should take any capnp struct and returrn a msg with random populated data
def random_carstate():
@@ -53,16 +47,6 @@ def delayed_send(delay, sock, dat):
class TestMessaging:
def setUp(self):
# TODO: ZMQ tests are too slow; all sleeps will need to be
# replaced with logic to block on the necessary condition
if "ZMQ" in os.environ:
pytest.skip()
# ZMQ pub socket takes too long to die
# sleep to prevent multiple publishers error between tests
zmq_sleep()
@parameterized.expand(events)
def test_new_message(self, evt):
try:
@@ -89,7 +73,6 @@ class TestMessaging:
sock = "carState"
pub_sock = messaging.pub_sock(sock)
sub_sock = messaging.sub_sock(sock, timeout=1000)
zmq_sleep()
# no wait and no msgs in queue
msgs = func(sub_sock)
@@ -110,7 +93,6 @@ class TestMessaging:
sock = "carState"
pub_sock = messaging.pub_sock(sock)
sub_sock = messaging.sub_sock(sock, timeout=100)
zmq_sleep()
# no wait and no msg in queue, socket should timeout
recvd = messaging.recv_sock(sub_sock)
@@ -129,7 +111,6 @@ class TestMessaging:
sock = "carState"
pub_sock = messaging.pub_sock(sock)
sub_sock = messaging.sub_sock(sock, timeout=1000)
zmq_sleep()
# no msg in queue, socket should timeout
recvd = messaging.recv_one(sub_sock)
@@ -142,12 +123,10 @@ class TestMessaging:
assert isinstance(recvd, capnp._DynamicStructReader)
assert_carstate(msg.carState, recvd.carState)
@pytest.mark.xfail(condition="ZMQ" in os.environ, reason='ZMQ detected')
def test_recv_one_or_none(self):
sock = "carState"
pub_sock = messaging.pub_sock(sock)
sub_sock = messaging.sub_sock(sock)
zmq_sleep()
# no msg in queue, socket shouldn't block
recvd = messaging.recv_one_or_none(sub_sock)
@@ -165,16 +144,13 @@ class TestMessaging:
sock_timeout = 0.1
pub_sock = messaging.pub_sock(sock)
sub_sock = messaging.sub_sock(sock, timeout=round(sock_timeout*1000))
zmq_sleep()
# this test doesn't work with ZMQ since multiprocessing interrupts it
if "ZMQ" not in os.environ:
# wait 5 socket timeouts and make sure it's still retrying
p = multiprocessing.Process(target=messaging.recv_one_retry, args=(sub_sock,))
p.start()
time.sleep(sock_timeout*5)
assert p.is_alive()
p.terminate()
# wait 5 socket timeouts and make sure it's still retrying
p = multiprocessing.Process(target=messaging.recv_one_retry, args=(sub_sock,))
p.start()
time.sleep(sock_timeout*5)
assert p.is_alive()
p.terminate()
# wait 5 socket timeouts before sending
msg = random_carstate()
@@ -1,21 +1,16 @@
import random
import time
from typing import Sized, cast
from typing import cast
from collections.abc import Sized
import openpilot.cereal.messaging as messaging
from openpilot.cereal.messaging.tests.test_messaging import events, random_sock, random_socks, \
random_bytes, random_carstate, assert_carstate, \
zmq_sleep
random_bytes, random_carstate, assert_carstate
from openpilot.cereal.services import SERVICE_LIST
class TestSubMaster:
def setup_method(self):
# ZMQ pub socket takes too long to die
# sleep to prevent multiple publishers error between tests
zmq_sleep(3)
def test_init(self):
sm = messaging.SubMaster(events)
for p in [sm.updated, sm.recv_time, sm.recv_frame, sm.alive,
@@ -42,7 +37,6 @@ class TestSubMaster:
sock = "carState"
pub_sock = messaging.pub_sock(sock)
sm = messaging.SubMaster([sock,])
zmq_sleep()
msg = random_carstate()
pub_sock.send(msg.to_bytes())
@@ -54,7 +48,6 @@ class TestSubMaster:
sock = "carState"
pub_sock = messaging.pub_sock(sock)
sm = messaging.SubMaster([sock,])
zmq_sleep()
for i in range(10):
msg = messaging.new_message(sock)
@@ -91,21 +84,13 @@ class TestSubMaster:
for service, (max_freq, min_freq) in checks.items():
if max_freq is not None:
assert min_freq is not None
assert sm._check_avg_freq(service)
assert sm.freq_tracker[service].max_freq == max_freq*1.2
assert sm.freq_tracker[service].min_freq == min_freq*0.8
else:
assert not sm._check_avg_freq(service)
def test_alive(self):
pass
def test_ignore_alive(self):
pass
def test_valid(self):
pass
# SubMaster should always conflate
def test_conflate(self):
sock = "carState"
@@ -124,11 +109,6 @@ class TestSubMaster:
class TestPubMaster:
def setup_method(self):
# ZMQ pub socket takes too long to die
# sleep to prevent multiple publishers error between tests
zmq_sleep(3)
def test_init(self):
messaging.PubMaster(events)
@@ -136,7 +116,6 @@ class TestPubMaster:
socks = random_socks()
pm = messaging.PubMaster(socks)
sub_socks = {s: messaging.sub_sock(s, conflate=True, timeout=1000) for s in socks}
zmq_sleep()
# PubMaster accepts either a capnp msg builder or bytes
for capnp in [True, False]:
+2 -4
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env python3
from enum import IntEnum
from typing import Optional
# TODO: this should be automatically determined using the capnp schema
@@ -11,7 +10,7 @@ class QueueSize(IntEnum):
class Service:
def __init__(self, should_log: bool, frequency: float, decimation: Optional[int] = None,
def __init__(self, should_log: bool, frequency: float, decimation: int | None = None,
queue_size: QueueSize = QueueSize.SMALL):
self.should_log = should_log
self.frequency = frequency
@@ -125,8 +124,7 @@ def build_header():
for k, v in SERVICE_LIST.items():
should_log = "true" if v.should_log else "false"
decimation = -1 if v.decimation is None else v.decimation
h += ' { "%s", {"%s", %s, %f, %d, %d}},\n' % \
(k, k, should_log, v.frequency, decimation, v.queue_size)
h += f' {{ "{k}", {{"{k}", {should_log}, {v.frequency:f}, {decimation:d}, {v.queue_size:d}}}}},\n'
h += "};\n"
h += "#endif\n"
+1
View File
@@ -38,6 +38,7 @@ class BaseApi:
}
if payload_extra is not None:
payload.update(payload_extra)
assert self.private_key is not None
token = jwt.encode(payload, self.private_key, algorithm=self.jwt_algorithm)
if isinstance(token, bytes):
token = token.decode('utf8')
+9 -8
View File
@@ -42,25 +42,26 @@ def get_existing_chunks(path):
class ChunkStream(io.RawIOBase):
def __init__(self, paths):
self._paths = iter(paths)
self._buf = memoryview(b'')
self._f = None
def readable(self):
return True
def readinto(self, b):
n = 0
view = memoryview(b)
while n < len(b):
if not self._buf:
if self._f is None:
p = next(self._paths, None)
if p is None:
break
with open(p, 'rb') as f:
self._buf = memoryview(f.read())
self._f = open(p, 'rb')
count = self._f.readinto(view[n:])
if not count:
self._f.close()
self._f = None
continue
take = min(len(b) - n, len(self._buf))
b[n:n + take] = self._buf[:take]
self._buf = self._buf[take:]
n += take
n += count
return n
def open_file_chunked(path):
+10 -10
View File
@@ -56,28 +56,28 @@
},
{
"name": "boot",
"url": "https://commadist.azureedge.net/agnosupdate/boot-8806802b195a5b1396a3ae8dd92a8b7711dc522f6aceafd820e871bae5c8a6d8.img.xz",
"hash": "8806802b195a5b1396a3ae8dd92a8b7711dc522f6aceafd820e871bae5c8a6d8",
"hash_raw": "8806802b195a5b1396a3ae8dd92a8b7711dc522f6aceafd820e871bae5c8a6d8",
"url": "https://commadist.azureedge.net/agnosupdate/boot-19ff57b68e219e4503fcaca716967098d5d0a1de8af833f04dbf13b99aeb4d39.img.xz",
"hash": "19ff57b68e219e4503fcaca716967098d5d0a1de8af833f04dbf13b99aeb4d39",
"hash_raw": "19ff57b68e219e4503fcaca716967098d5d0a1de8af833f04dbf13b99aeb4d39",
"size": 17487872,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "edca8bee1531e66953d107eeceeed2dc7b3ca46417e49d55508f94e58bf95db8"
"ondevice_hash": "ddfe93cc6a8531af92ee331d9bbaeae2f1d933bdb38e579769dc9fe7998eb626"
},
{
"name": "system",
"url": "https://commadist.azureedge.net/agnosupdate/system-ef0d879302cb29e72110e9c8d3f947c830fd7d37c8192744fc9dbea1af78501f.img.xz",
"hash": "78acfe16a7b62a3a91fc7a81f40a693e4468cec1c69df7d0b1e550aacc646113",
"hash_raw": "ef0d879302cb29e72110e9c8d3f947c830fd7d37c8192744fc9dbea1af78501f",
"url": "https://commadist.azureedge.net/agnosupdate/system-a396dd98ffd49614fb198d1b022a0c7a6d0a1e563c20ce11b0a975105ab50724.img.xz",
"hash": "4dc41c2c072f5f5d5cd484cd6173049cd96acfb9a67bc20049775585fe881539",
"hash_raw": "a396dd98ffd49614fb198d1b022a0c7a6d0a1e563c20ce11b0a975105ab50724",
"size": 4718592000,
"sparse": true,
"full_check": false,
"has_ab": true,
"ondevice_hash": "743142c5a898f27b2a1029cca42c8a5d5d1fc0096414422b850fe84c8d0b8342",
"ondevice_hash": "cf1229630b7a2b8497705bca4ba947dbf0c217418ff4febff571aa4f4a878134",
"alt": {
"hash": "ef0d879302cb29e72110e9c8d3f947c830fd7d37c8192744fc9dbea1af78501f",
"url": "https://commadist.azureedge.net/agnosupdate/system-ef0d879302cb29e72110e9c8d3f947c830fd7d37c8192744fc9dbea1af78501f.img",
"hash": "a396dd98ffd49614fb198d1b022a0c7a6d0a1e563c20ce11b0a975105ab50724",
"url": "https://commadist.azureedge.net/agnosupdate/system-a396dd98ffd49614fb198d1b022a0c7a6d0a1e563c20ce11b0a975105ab50724.img",
"size": 4718592000
}
}
+1 -1
View File
@@ -19,7 +19,7 @@ class StreamingDecompressor:
def __init__(self, url: str) -> None:
self.buf = b""
self.req = requests.get(url, stream=True, headers={'Accept-Encoding': None}, timeout=60)
self.req = requests.get(url, stream=True, headers={'Accept-Encoding': 'identity'}, timeout=60)
self.it = self.req.iter_content(chunk_size=1024 * 1024)
self.decompressor = lzma.LZMADecompressor(format=lzma.FORMAT_AUTO)
self.eof = False
+8 -8
View File
@@ -339,7 +339,7 @@ class Tici(HardwareBase):
# Ensure fan gpio is enabled so fan runs until shutdown, also turned on at boot by the ABL
gpio_init(GPIO.SOM_ST_IO, True)
gpio_set(GPIO.SOM_ST_IO, 1)
gpio_set(GPIO.SOM_ST_IO, True)
# *** IRQ config ***
@@ -389,21 +389,21 @@ class Tici(HardwareBase):
gpio_init(GPIO.STM_RST_N, True)
gpio_init(GPIO.STM_BOOT0, True)
gpio_set(GPIO.STM_RST_N, 1)
gpio_set(GPIO.STM_BOOT0, 0)
gpio_set(GPIO.STM_RST_N, True)
gpio_set(GPIO.STM_BOOT0, False)
time.sleep(0.01)
gpio_set(GPIO.STM_RST_N, 0)
gpio_set(GPIO.STM_RST_N, False)
def recover_internal_panda(self):
gpio_init(GPIO.STM_RST_N, True)
gpio_init(GPIO.STM_BOOT0, True)
gpio_set(GPIO.STM_RST_N, 1)
gpio_set(GPIO.STM_BOOT0, 1)
gpio_set(GPIO.STM_RST_N, True)
gpio_set(GPIO.STM_BOOT0, True)
time.sleep(0.01)
gpio_set(GPIO.STM_RST_N, 0)
gpio_set(GPIO.STM_RST_N, False)
time.sleep(0.01)
gpio_set(GPIO.STM_BOOT0, 0)
gpio_set(GPIO.STM_BOOT0, False)
def booted(self):
# this normally boots within 8s, but on rare occasions takes 30+s
+1 -1
View File
@@ -52,7 +52,7 @@ PPPD_CMD = [
"novj", "novjccomp", "ipcp-accept-local", "ipcp-accept-remote", "nomagic",
"user", '""', "password", '""',
]
INITIAL_STATE = {
INITIAL_STATE: dict[str, object] = {
"seconds_since_boot": 0,
"state": "INITIALIZING",
"connected": False, "ip_address": "",
+1
View File
@@ -37,6 +37,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"DoShutdown", {CLEAR_ON_MANAGER_START, BOOL}},
{"DoUninstall", {CLEAR_ON_MANAGER_START, BOOL}},
{"DriverTooDistracted", {CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON, BOOL}},
{"DriverLockoutCount", {CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON, INT, "0"}},
{"AlphaLongitudinalEnabled", {PERSISTENT | DEVELOPMENT_ONLY | BACKUP, BOOL}},
{"ExperimentalMode", {PERSISTENT | BACKUP, BOOL}},
{"ExperimentalModeConfirmed", {PERSISTENT | BACKUP, BOOL}},
Binary file not shown.
+7 -5
View File
@@ -1,11 +1,13 @@
import numpy as np
from numbers import Number
from collections.abc import Sequence
Gain = int | float | tuple[Sequence[float], Sequence[float]] | list[list[float]]
class PIDController:
def __init__(self, k_p, k_i, k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100):
self._k_p: list[list[float]] = [[0], [k_p]] if isinstance(k_p, Number) else k_p
self._k_i: list[list[float]] = [[0], [k_i]] if isinstance(k_i, Number) else k_i
self._k_d: list[list[float]] = [[0], [k_d]] if isinstance(k_d, Number) else k_d
def __init__(self, k_p: Gain, k_i: Gain, k_d: Gain = 0., pos_limit=1e308, neg_limit=-1e308, rate=100):
self._k_p = ([0], [k_p]) if isinstance(k_p, (int, float)) else k_p
self._k_i = ([0], [k_i]) if isinstance(k_i, (int, float)) else k_i
self._k_d = ([0], [k_d]) if isinstance(k_d, (int, float)) else k_d
self.set_limits(pos_limit, neg_limit)
+2 -2
View File
@@ -27,7 +27,7 @@ class SwaglogRotatingFileHandler(BaseRotatingHandler):
self.log_files = self.get_existing_logfiles()
log_indexes = [f.split(".")[-1] for f in self.log_files]
self.last_file_idx = max([int(i) for i in log_indexes if i.isdigit()] or [-1])
self.last_rollover = None
self.last_rollover = 0.0
self.doRollover()
def _open(self):
@@ -39,7 +39,7 @@ class SwaglogRotatingFileHandler(BaseRotatingHandler):
return stream
def get_existing_logfiles(self):
log_files = list()
log_files = []
base_dir = os.path.dirname(self.base_filename)
for fn in os.listdir(base_dir):
fp = os.path.join(base_dir, fn)
+3 -3
View File
@@ -112,14 +112,14 @@ class TestParams:
def test_params_default_value(self):
self.params.remove("LanguageSetting")
self.params.remove("LongitudinalPersonality")
self.params.remove("LiveParameters")
self.params.remove("LiveParametersV2")
assert self.params.get("LanguageSetting") is None
assert self.params.get("LanguageSetting", return_default=False) is None
assert isinstance(self.params.get("LanguageSetting", return_default=True), str)
assert isinstance(self.params.get("LongitudinalPersonality", return_default=True), int)
assert self.params.get("LiveParameters") is None
assert self.params.get("LiveParameters", return_default=True) is None
assert self.params.get("LiveParametersV2") is None
assert self.params.get("LiveParametersV2", return_default=True) is None
def test_params_get_type(self):
# json
+1 -2
View File
@@ -52,7 +52,7 @@ _ar_ox_config = DeviceCameraConfig(CameraConfig(1928, 1208, 2648.0), _ar_ox_fish
_os_config = DeviceCameraConfig(CameraConfig(2688 // 2, 1520 // 2, 1522.0 * 3 / 4), _os_fisheye, _os_fisheye)
_neo_config = DeviceCameraConfig(CameraConfig(1164, 874, 910.0), CameraConfig(816, 612, 650.0), _NoneCameraConfig())
DEVICE_CAMERAS = {
DEVICE_CAMERAS: dict[tuple[str, str], DeviceCameraConfig] = {
# A "device camera" is defined by a device type and sensor
# sensor type was never set on eon/neo/two
@@ -176,4 +176,3 @@ def img_from_device(pt_device):
pt_img = pt_view/pt_view[:, 2:3]
return pt_img.reshape(input_shape)[:, :2]
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+5 -4
View File
@@ -3,7 +3,7 @@ import copy
import os
import pytest
import random
import unittest # noqa: TID251
import unittest
from collections import defaultdict, Counter
import hypothesis.strategies as st
from hypothesis import Phase, given, settings
@@ -22,6 +22,7 @@ from openpilot.selfdrive.pandad import can_capnp_to_list
from openpilot.selfdrive.test.helpers import read_segment_list
from openpilot.common.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
from openpilot.tools.lib.logreader import LogReader, LogsUnavailable, openpilotci_source, internal_source, comma_api_source
from openpilot.tools.lib.file_sources import Source
from openpilot.tools.lib.route import SegmentName
SafetyModel = car.CarParams.SafetyModel
@@ -131,7 +132,7 @@ class TestCarModelBase(unittest.TestCase):
segment_range = f"{cls.test_route.route}/{seg}"
try:
sources = [internal_source] if len(INTERNAL_SEG_LIST) else [openpilotci_source, comma_api_source]
sources: list[Source] = [internal_source] if len(INTERNAL_SEG_LIST) else [openpilotci_source, comma_api_source]
lr = LogReader(segment_range, sources=sources, sort_by_time=True)
return cls.get_testing_data_from_logreader(lr)
except (LogsUnavailable, AssertionError):
@@ -257,7 +258,7 @@ class TestCarModelBase(unittest.TestCase):
# Don't check relay malfunction on disabled routes (relay closed),
# or before fingerprinting is done (elm327 and noOutput)
if self.openpilot_enabled and t / 1e4 > self.car_safety_mode_frame:
if self.car_safety_mode_frame is not None and t / 1e4 > self.car_safety_mode_frame:
self.assertFalse(self.safety.get_relay_malfunction())
else:
self.safety.set_relay_malfunction(False)
@@ -451,7 +452,7 @@ class TestCarModelBase(unittest.TestCase):
# TODO: remove this exception once this mismatch is resolved
brake_pressed = CS.brakePressed
if CS.brakePressed and not self.safety.get_brake_pressed_prev():
if self.CP.carFingerprint in (HONDA.HONDA_PILOT, HONDA.HONDA_RIDGELINE) and CS.brakeDEPRECATED > 0.05:
if self.CP.carFingerprint in (HONDA.HONDA_PILOT, HONDA.HONDA_RIDGELINE) and CS.deprecated.brake > 0.05:
brake_pressed = False
checks['brakePressed'] += brake_pressed != self.safety.get_brake_pressed_prev()
checks['regenBraking'] += CS.regenBraking != self.safety.get_regen_braking_prev()
@@ -15,6 +15,9 @@ MAX_LATERAL_JERK = 5.0 # m/s^3
MAX_LATERAL_ACCEL_NO_ROLL = 3.0 # m/s^2
def should_stop(v_ego: float, a_target: float) -> bool:
return bool(v_ego < 0.25 and a_target < 0.1)
def clamp(val, min_val, max_val):
clamped_val = float(np.clip(val, min_val, max_val))
return clamped_val, clamped_val != val
@@ -40,7 +43,7 @@ def clip_curvature(v_ego, prev_curvature, new_curvature, roll) -> tuple[float, b
return float(new_curvature), limited_accel or limited_max_curv
def get_accel_from_plan(speeds, accels, t_idxs, action_t=DT_MDL, vEgoStopping=0.3):
def get_accel_from_plan(speeds, accels, t_idxs, action_t=DT_MDL):
if len(speeds) == len(t_idxs):
v_now = speeds[0]
a_now = accels[0]
@@ -53,8 +56,7 @@ def get_accel_from_plan(speeds, accels, t_idxs, action_t=DT_MDL, vEgoStopping=0.
v_now = 0.0
v_target = 0.0
a_target = 0.0
should_stop = (v_now < vEgoStopping and a_target < 0.1)
return a_target, should_stop
return a_target, should_stop(v_now, a_target)
def curv_from_psis(psi_target, psi_rate, vego, action_t):
vego = np.clip(vego, MIN_SPEED, np.inf)
@@ -14,7 +14,7 @@ class LatControl(ABC):
self.steer_max = 1.0
@abstractmethod
def update(self, active: bool, CS, VM, params, steer_limited_by_safety: bool, desired_curvature: float, calibrated_pose: Pose,
def update(self, active: bool, CS, VM, params, steer_limited_by_safety: bool, desired_curvature: float, calibrated_pose: Pose | None,
curvature_limited: bool, lat_delay: float):
pass
@@ -10,7 +10,7 @@ CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N]
LongCtrlState = car.CarControl.Actuators.LongControlState
def long_control_state_trans(CP, CP_SP, active, long_control_state, v_ego,
def long_control_state_trans(CP_SP, active, long_control_state,
should_stop, brake_pressed, cruise_standstill):
# Gas Interceptor
cruise_standstill = cruise_standstill and not CP_SP.enableGasInterceptor
@@ -26,22 +26,17 @@ def long_control_state_trans(CP, CP_SP, active, long_control_state, v_ego,
if long_control_state == LongCtrlState.off:
if not starting_condition:
long_control_state = LongCtrlState.stopping
elif CP.startingState:
long_control_state = LongCtrlState.starting
else:
long_control_state = LongCtrlState.pid
elif long_control_state == LongCtrlState.stopping:
if starting_condition and CP.startingState:
long_control_state = LongCtrlState.starting
elif starting_condition:
if starting_condition:
long_control_state = LongCtrlState.pid
elif long_control_state in [LongCtrlState.starting, LongCtrlState.pid]:
elif long_control_state == LongCtrlState.pid:
if should_stop:
long_control_state = LongCtrlState.stopping
elif v_ego > CP.vEgoStarting:
long_control_state = LongCtrlState.pid
return long_control_state
class LongControl:
@@ -62,7 +57,7 @@ class LongControl:
self.pid.neg_limit = accel_limits[0]
self.pid.pos_limit = accel_limits[1]
self.long_control_state = long_control_state_trans(self.CP, self.CP_SP, active, self.long_control_state, CS.vEgo,
self.long_control_state = long_control_state_trans(self.CP_SP, active, self.long_control_state,
should_stop, CS.brakePressed,
CS.cruiseState.standstill)
if self.long_control_state == LongCtrlState.off:
@@ -73,11 +68,8 @@ class LongControl:
output_accel = self.last_output_accel
if output_accel > self.CP.stopAccel:
output_accel = min(output_accel, 0.0)
output_accel -= self.CP.stoppingDecelRate * DT_CTRL
self.reset()
elif self.long_control_state == LongCtrlState.starting:
output_accel = self.CP.startAccel
# TODO: can we just go straight to stopAccel?
output_accel -= 1.0 * DT_CTRL # m/s^2/s while trying to stop
self.reset()
else: # LongCtrlState.pid
@@ -137,7 +137,7 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
action_t = self.CP.longitudinalActuatorDelay + DT_MDL
output_a_target_mpc, output_should_stop_mpc = get_accel_from_plan(self.v_desired_trajectory, self.a_desired_trajectory, CONTROL_N_T_IDX,
action_t=action_t, vEgoStopping=self.CP.vEgoStopping)
action_t=action_t)
output_a_target_e2e = sm['modelV2'].action.desiredAcceleration
output_should_stop_e2e = sm['modelV2'].action.shouldStop
+2 -1
View File
@@ -23,13 +23,14 @@ def main():
cloudlog.info("plannerd got CarParamsSP")
gps_location_service = get_gps_location_service(params)
ignore_services = ["liveMapDataSP", gps_location_service]
ldw = LaneDepartureWarning()
longitudinal_planner = LongitudinalPlanner(CP, CP_SP)
pm = messaging.PubMaster(['longitudinalPlan', 'driverAssistance', 'longitudinalPlanSP'])
sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'liveParameters', 'radarState', 'modelV2', 'selfdriveState',
'liveMapDataSP', 'carStateSP', gps_location_service],
poll='carState')
poll='carState', ignore_alive=ignore_services, ignore_avg_freq=ignore_services, ignore_valid=ignore_services)
while True:
sm.update()
@@ -1,60 +1,43 @@
from openpilot.cereal import custom
from opendbc.car.structs import car
from openpilot.selfdrive.controls.lib.longcontrol import LongCtrlState, long_control_state_trans
class TestLongControlStateTransition:
def test_stay_stopped(self):
CP = car.CarParams.new_message()
CP_SP = custom.CarParamsSP.new_message()
active = True
current_state = LongCtrlState.stopping
next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1,
next_state = long_control_state_trans(CP_SP, active, current_state,
should_stop=True, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.stopping
next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1,
next_state = long_control_state_trans(CP_SP, active, current_state,
should_stop=False, brake_pressed=True, cruise_standstill=False)
assert next_state == LongCtrlState.stopping
next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1,
next_state = long_control_state_trans(CP_SP, active, current_state,
should_stop=False, brake_pressed=False, cruise_standstill=True)
assert next_state == LongCtrlState.stopping
next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=1.0,
next_state = long_control_state_trans(CP_SP, active, current_state,
should_stop=False, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.pid
active = False
next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=1.0,
next_state = long_control_state_trans(CP_SP, active, current_state,
should_stop=False, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.off
def test_engage():
CP = car.CarParams.new_message()
CP_SP = custom.CarParamsSP.new_message()
active = True
current_state = LongCtrlState.off
next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1,
next_state = long_control_state_trans(CP_SP, active, current_state,
should_stop=True, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.stopping
next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1,
next_state = long_control_state_trans(CP_SP, active, current_state,
should_stop=False, brake_pressed=True, cruise_standstill=False)
assert next_state == LongCtrlState.stopping
next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1,
next_state = long_control_state_trans(CP_SP, active, current_state,
should_stop=False, brake_pressed=False, cruise_standstill=True)
assert next_state == LongCtrlState.stopping
next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1,
should_stop=False, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.pid
def test_starting():
CP = car.CarParams.new_message(startingState=True, vEgoStarting=0.5)
CP_SP = custom.CarParamsSP.new_message()
active = True
current_state = LongCtrlState.starting
next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1,
should_stop=False, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.starting
next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=1.0,
next_state = long_control_state_trans(CP_SP, active, current_state,
should_stop=False, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.pid
@@ -7,8 +7,6 @@ from opendbc.car.lateral import get_friction, FRICTION_THRESHOLD
from openpilot.common.realtime import DT_MDL
from openpilot.selfdrive.locationd.torqued import TorqueEstimator, MIN_BUCKET_POINTS, POINTS_PER_BUCKET, STEER_BUCKET_BOUNDS
np.random.seed(0)
LA_ERR_STD = 1.0
INPUT_NOISE_STD = 0.08
V_EGO = 30.0
@@ -58,16 +56,17 @@ def simulate_straight_road_msgs(est):
for which, msg in (('carControl', carControl), ('carOutput', carOutput), ('carState', carState), ('livePose', livePose)):
est.handle_log(t, which, msg)
def test_estimated_offset():
steer_torques, lat_accels = generate_inputs(TORQUE_TUNE_BIASED, la_err_std=LA_ERR_STD, input_noise_std=INPUT_NOISE_STD)
est = get_warmed_up_estimator(steer_torques, lat_accels)
msg = est.get_msg()
# TODO add lataccelfactor and friction check when we have more accurate estimates
assert abs(msg.liveTorqueParameters.latAccelOffsetRaw - TORQUE_TUNE_BIASED.latAccelOffset) < 0.1
class TestTorquedLatAccelOffset:
def test_estimated_offset(self):
steer_torques, lat_accels = generate_inputs(TORQUE_TUNE_BIASED, la_err_std=LA_ERR_STD, input_noise_std=INPUT_NOISE_STD)
est = get_warmed_up_estimator(steer_torques, lat_accels)
msg = est.get_msg()
# TODO add lataccelfactor and friction check when we have more accurate estimates
assert abs(msg.liveTorqueParameters.latAccelOffsetRaw - TORQUE_TUNE_BIASED.latAccelOffset) < 0.1
def test_straight_road_roll_bias():
steer_torques, lat_accels = generate_inputs(TORQUE_TUNE, la_err_std=LA_ERR_STD, input_noise_std=INPUT_NOISE_STD)
est = get_warmed_up_estimator(steer_torques, lat_accels)
simulate_straight_road_msgs(est)
msg = est.get_msg()
assert (msg.liveTorqueParameters.latAccelOffsetRaw < -0.05) and np.isfinite(msg.liveTorqueParameters.latAccelOffsetRaw)
def test_straight_road_roll_bias(self):
steer_torques, lat_accels = generate_inputs(TORQUE_TUNE, la_err_std=LA_ERR_STD, input_noise_std=INPUT_NOISE_STD)
est = get_warmed_up_estimator(steer_torques, lat_accels)
simulate_straight_road_msgs(est)
msg = est.get_msg()
assert (msg.liveTorqueParameters.latAccelOffsetRaw < -0.05) and np.isfinite(msg.liveTorqueParameters.latAccelOffsetRaw)
+5 -3
View File
@@ -1,4 +1,5 @@
import numpy as np
from collections.abc import Sequence
from typing import Any
from functools import cache
@@ -68,7 +69,8 @@ class NPQueue:
class PointBuckets:
def __init__(self, x_bounds: list[tuple[float, float]], min_points: list[float], min_points_total: int, points_per_bucket: int, rowsize: int) -> None:
def __init__(self, x_bounds: list[tuple[float, float]], min_points: Sequence[float], min_points_total: int, points_per_bucket: int, rowsize: int) -> None:
self._rng = np.random.default_rng()
self.x_bounds = x_bounds
self.buckets = {bounds: NPQueue(maxlen=points_per_bucket, rowsize=rowsize) for bounds in x_bounds}
self.buckets_min_points = dict(zip(x_bounds, min_points, strict=True))
@@ -98,9 +100,9 @@ class PointBuckets:
points = np.vstack([x.arr for x in self.buckets.values()])
if num_points is None:
return points
return points[np.random.choice(np.arange(len(points)), min(len(points), num_points), replace=False)]
return points[self._rng.choice(np.arange(len(points)), min(len(points), num_points), replace=False)]
def load_points(self, points: list[list[float]]) -> None:
def load_points(self, points: Sequence[Sequence[float]]) -> None:
for point in points:
self.add_point(*point)
+1 -1
View File
@@ -66,7 +66,7 @@ class LocationEstimator:
self.observations = {kind: np.zeros(3, dtype=np.float32) for kind in obs_kinds}
self.observation_errors = {kind: np.zeros(3, dtype=np.float32) for kind in obs_kinds}
def reset(self, t: float, x_initial: np.ndarray = PoseKalman.initial_x, P_initial: np.ndarray = PoseKalman.initial_P):
def reset(self, t: float | None, x_initial: np.ndarray = PoseKalman.initial_x, P_initial: np.ndarray = PoseKalman.initial_P):
self.kf.init_state(x_initial, covs=P_initial, filter_time=t)
def _validate_sensor_source(self, source: log.SensorEventData.SensorSource):
@@ -45,326 +45,326 @@ const static double MAHA_THRESH_31 = 3.8414588206941227;
* *
* This file is part of 'ekf' *
******************************************************************************/
void err_fun(double *nom_x, double *delta_x, double *out_4503132331689013745) {
out_4503132331689013745[0] = delta_x[0] + nom_x[0];
out_4503132331689013745[1] = delta_x[1] + nom_x[1];
out_4503132331689013745[2] = delta_x[2] + nom_x[2];
out_4503132331689013745[3] = delta_x[3] + nom_x[3];
out_4503132331689013745[4] = delta_x[4] + nom_x[4];
out_4503132331689013745[5] = delta_x[5] + nom_x[5];
out_4503132331689013745[6] = delta_x[6] + nom_x[6];
out_4503132331689013745[7] = delta_x[7] + nom_x[7];
out_4503132331689013745[8] = delta_x[8] + nom_x[8];
void err_fun(double *nom_x, double *delta_x, double *out_3010729618614624127) {
out_3010729618614624127[0] = delta_x[0] + nom_x[0];
out_3010729618614624127[1] = delta_x[1] + nom_x[1];
out_3010729618614624127[2] = delta_x[2] + nom_x[2];
out_3010729618614624127[3] = delta_x[3] + nom_x[3];
out_3010729618614624127[4] = delta_x[4] + nom_x[4];
out_3010729618614624127[5] = delta_x[5] + nom_x[5];
out_3010729618614624127[6] = delta_x[6] + nom_x[6];
out_3010729618614624127[7] = delta_x[7] + nom_x[7];
out_3010729618614624127[8] = delta_x[8] + nom_x[8];
}
void inv_err_fun(double *nom_x, double *true_x, double *out_5519222819843562437) {
out_5519222819843562437[0] = -nom_x[0] + true_x[0];
out_5519222819843562437[1] = -nom_x[1] + true_x[1];
out_5519222819843562437[2] = -nom_x[2] + true_x[2];
out_5519222819843562437[3] = -nom_x[3] + true_x[3];
out_5519222819843562437[4] = -nom_x[4] + true_x[4];
out_5519222819843562437[5] = -nom_x[5] + true_x[5];
out_5519222819843562437[6] = -nom_x[6] + true_x[6];
out_5519222819843562437[7] = -nom_x[7] + true_x[7];
out_5519222819843562437[8] = -nom_x[8] + true_x[8];
void inv_err_fun(double *nom_x, double *true_x, double *out_3985552318855446440) {
out_3985552318855446440[0] = -nom_x[0] + true_x[0];
out_3985552318855446440[1] = -nom_x[1] + true_x[1];
out_3985552318855446440[2] = -nom_x[2] + true_x[2];
out_3985552318855446440[3] = -nom_x[3] + true_x[3];
out_3985552318855446440[4] = -nom_x[4] + true_x[4];
out_3985552318855446440[5] = -nom_x[5] + true_x[5];
out_3985552318855446440[6] = -nom_x[6] + true_x[6];
out_3985552318855446440[7] = -nom_x[7] + true_x[7];
out_3985552318855446440[8] = -nom_x[8] + true_x[8];
}
void H_mod_fun(double *state, double *out_99880963271144866) {
out_99880963271144866[0] = 1.0;
out_99880963271144866[1] = 0.0;
out_99880963271144866[2] = 0.0;
out_99880963271144866[3] = 0.0;
out_99880963271144866[4] = 0.0;
out_99880963271144866[5] = 0.0;
out_99880963271144866[6] = 0.0;
out_99880963271144866[7] = 0.0;
out_99880963271144866[8] = 0.0;
out_99880963271144866[9] = 0.0;
out_99880963271144866[10] = 1.0;
out_99880963271144866[11] = 0.0;
out_99880963271144866[12] = 0.0;
out_99880963271144866[13] = 0.0;
out_99880963271144866[14] = 0.0;
out_99880963271144866[15] = 0.0;
out_99880963271144866[16] = 0.0;
out_99880963271144866[17] = 0.0;
out_99880963271144866[18] = 0.0;
out_99880963271144866[19] = 0.0;
out_99880963271144866[20] = 1.0;
out_99880963271144866[21] = 0.0;
out_99880963271144866[22] = 0.0;
out_99880963271144866[23] = 0.0;
out_99880963271144866[24] = 0.0;
out_99880963271144866[25] = 0.0;
out_99880963271144866[26] = 0.0;
out_99880963271144866[27] = 0.0;
out_99880963271144866[28] = 0.0;
out_99880963271144866[29] = 0.0;
out_99880963271144866[30] = 1.0;
out_99880963271144866[31] = 0.0;
out_99880963271144866[32] = 0.0;
out_99880963271144866[33] = 0.0;
out_99880963271144866[34] = 0.0;
out_99880963271144866[35] = 0.0;
out_99880963271144866[36] = 0.0;
out_99880963271144866[37] = 0.0;
out_99880963271144866[38] = 0.0;
out_99880963271144866[39] = 0.0;
out_99880963271144866[40] = 1.0;
out_99880963271144866[41] = 0.0;
out_99880963271144866[42] = 0.0;
out_99880963271144866[43] = 0.0;
out_99880963271144866[44] = 0.0;
out_99880963271144866[45] = 0.0;
out_99880963271144866[46] = 0.0;
out_99880963271144866[47] = 0.0;
out_99880963271144866[48] = 0.0;
out_99880963271144866[49] = 0.0;
out_99880963271144866[50] = 1.0;
out_99880963271144866[51] = 0.0;
out_99880963271144866[52] = 0.0;
out_99880963271144866[53] = 0.0;
out_99880963271144866[54] = 0.0;
out_99880963271144866[55] = 0.0;
out_99880963271144866[56] = 0.0;
out_99880963271144866[57] = 0.0;
out_99880963271144866[58] = 0.0;
out_99880963271144866[59] = 0.0;
out_99880963271144866[60] = 1.0;
out_99880963271144866[61] = 0.0;
out_99880963271144866[62] = 0.0;
out_99880963271144866[63] = 0.0;
out_99880963271144866[64] = 0.0;
out_99880963271144866[65] = 0.0;
out_99880963271144866[66] = 0.0;
out_99880963271144866[67] = 0.0;
out_99880963271144866[68] = 0.0;
out_99880963271144866[69] = 0.0;
out_99880963271144866[70] = 1.0;
out_99880963271144866[71] = 0.0;
out_99880963271144866[72] = 0.0;
out_99880963271144866[73] = 0.0;
out_99880963271144866[74] = 0.0;
out_99880963271144866[75] = 0.0;
out_99880963271144866[76] = 0.0;
out_99880963271144866[77] = 0.0;
out_99880963271144866[78] = 0.0;
out_99880963271144866[79] = 0.0;
out_99880963271144866[80] = 1.0;
void H_mod_fun(double *state, double *out_4306310304618992202) {
out_4306310304618992202[0] = 1.0;
out_4306310304618992202[1] = 0.0;
out_4306310304618992202[2] = 0.0;
out_4306310304618992202[3] = 0.0;
out_4306310304618992202[4] = 0.0;
out_4306310304618992202[5] = 0.0;
out_4306310304618992202[6] = 0.0;
out_4306310304618992202[7] = 0.0;
out_4306310304618992202[8] = 0.0;
out_4306310304618992202[9] = 0.0;
out_4306310304618992202[10] = 1.0;
out_4306310304618992202[11] = 0.0;
out_4306310304618992202[12] = 0.0;
out_4306310304618992202[13] = 0.0;
out_4306310304618992202[14] = 0.0;
out_4306310304618992202[15] = 0.0;
out_4306310304618992202[16] = 0.0;
out_4306310304618992202[17] = 0.0;
out_4306310304618992202[18] = 0.0;
out_4306310304618992202[19] = 0.0;
out_4306310304618992202[20] = 1.0;
out_4306310304618992202[21] = 0.0;
out_4306310304618992202[22] = 0.0;
out_4306310304618992202[23] = 0.0;
out_4306310304618992202[24] = 0.0;
out_4306310304618992202[25] = 0.0;
out_4306310304618992202[26] = 0.0;
out_4306310304618992202[27] = 0.0;
out_4306310304618992202[28] = 0.0;
out_4306310304618992202[29] = 0.0;
out_4306310304618992202[30] = 1.0;
out_4306310304618992202[31] = 0.0;
out_4306310304618992202[32] = 0.0;
out_4306310304618992202[33] = 0.0;
out_4306310304618992202[34] = 0.0;
out_4306310304618992202[35] = 0.0;
out_4306310304618992202[36] = 0.0;
out_4306310304618992202[37] = 0.0;
out_4306310304618992202[38] = 0.0;
out_4306310304618992202[39] = 0.0;
out_4306310304618992202[40] = 1.0;
out_4306310304618992202[41] = 0.0;
out_4306310304618992202[42] = 0.0;
out_4306310304618992202[43] = 0.0;
out_4306310304618992202[44] = 0.0;
out_4306310304618992202[45] = 0.0;
out_4306310304618992202[46] = 0.0;
out_4306310304618992202[47] = 0.0;
out_4306310304618992202[48] = 0.0;
out_4306310304618992202[49] = 0.0;
out_4306310304618992202[50] = 1.0;
out_4306310304618992202[51] = 0.0;
out_4306310304618992202[52] = 0.0;
out_4306310304618992202[53] = 0.0;
out_4306310304618992202[54] = 0.0;
out_4306310304618992202[55] = 0.0;
out_4306310304618992202[56] = 0.0;
out_4306310304618992202[57] = 0.0;
out_4306310304618992202[58] = 0.0;
out_4306310304618992202[59] = 0.0;
out_4306310304618992202[60] = 1.0;
out_4306310304618992202[61] = 0.0;
out_4306310304618992202[62] = 0.0;
out_4306310304618992202[63] = 0.0;
out_4306310304618992202[64] = 0.0;
out_4306310304618992202[65] = 0.0;
out_4306310304618992202[66] = 0.0;
out_4306310304618992202[67] = 0.0;
out_4306310304618992202[68] = 0.0;
out_4306310304618992202[69] = 0.0;
out_4306310304618992202[70] = 1.0;
out_4306310304618992202[71] = 0.0;
out_4306310304618992202[72] = 0.0;
out_4306310304618992202[73] = 0.0;
out_4306310304618992202[74] = 0.0;
out_4306310304618992202[75] = 0.0;
out_4306310304618992202[76] = 0.0;
out_4306310304618992202[77] = 0.0;
out_4306310304618992202[78] = 0.0;
out_4306310304618992202[79] = 0.0;
out_4306310304618992202[80] = 1.0;
}
void f_fun(double *state, double dt, double *out_4490574509847198287) {
out_4490574509847198287[0] = state[0];
out_4490574509847198287[1] = state[1];
out_4490574509847198287[2] = state[2];
out_4490574509847198287[3] = state[3];
out_4490574509847198287[4] = state[4];
out_4490574509847198287[5] = dt*((-state[4] + (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(mass*state[4]))*state[6] - 9.8100000000000005*state[8] + stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(mass*state[1]) + (-stiffness_front*state[0] - stiffness_rear*state[0])*state[5]/(mass*state[4])) + state[5];
out_4490574509847198287[6] = dt*(center_to_front*stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(rotational_inertia*state[1]) + (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])*state[5]/(rotational_inertia*state[4]) + (-pow(center_to_front, 2)*stiffness_front*state[0] - pow(center_to_rear, 2)*stiffness_rear*state[0])*state[6]/(rotational_inertia*state[4])) + state[6];
out_4490574509847198287[7] = state[7];
out_4490574509847198287[8] = state[8];
void f_fun(double *state, double dt, double *out_841039768515563673) {
out_841039768515563673[0] = state[0];
out_841039768515563673[1] = state[1];
out_841039768515563673[2] = state[2];
out_841039768515563673[3] = state[3];
out_841039768515563673[4] = state[4];
out_841039768515563673[5] = dt*((-state[4] + (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(mass*state[4]))*state[6] - 9.8100000000000005*state[8] + stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(mass*state[1]) + (-stiffness_front*state[0] - stiffness_rear*state[0])*state[5]/(mass*state[4])) + state[5];
out_841039768515563673[6] = dt*(center_to_front*stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(rotational_inertia*state[1]) + (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])*state[5]/(rotational_inertia*state[4]) + (-pow(center_to_front, 2)*stiffness_front*state[0] - pow(center_to_rear, 2)*stiffness_rear*state[0])*state[6]/(rotational_inertia*state[4])) + state[6];
out_841039768515563673[7] = state[7];
out_841039768515563673[8] = state[8];
}
void F_fun(double *state, double dt, double *out_5588273031121660281) {
out_5588273031121660281[0] = 1;
out_5588273031121660281[1] = 0;
out_5588273031121660281[2] = 0;
out_5588273031121660281[3] = 0;
out_5588273031121660281[4] = 0;
out_5588273031121660281[5] = 0;
out_5588273031121660281[6] = 0;
out_5588273031121660281[7] = 0;
out_5588273031121660281[8] = 0;
out_5588273031121660281[9] = 0;
out_5588273031121660281[10] = 1;
out_5588273031121660281[11] = 0;
out_5588273031121660281[12] = 0;
out_5588273031121660281[13] = 0;
out_5588273031121660281[14] = 0;
out_5588273031121660281[15] = 0;
out_5588273031121660281[16] = 0;
out_5588273031121660281[17] = 0;
out_5588273031121660281[18] = 0;
out_5588273031121660281[19] = 0;
out_5588273031121660281[20] = 1;
out_5588273031121660281[21] = 0;
out_5588273031121660281[22] = 0;
out_5588273031121660281[23] = 0;
out_5588273031121660281[24] = 0;
out_5588273031121660281[25] = 0;
out_5588273031121660281[26] = 0;
out_5588273031121660281[27] = 0;
out_5588273031121660281[28] = 0;
out_5588273031121660281[29] = 0;
out_5588273031121660281[30] = 1;
out_5588273031121660281[31] = 0;
out_5588273031121660281[32] = 0;
out_5588273031121660281[33] = 0;
out_5588273031121660281[34] = 0;
out_5588273031121660281[35] = 0;
out_5588273031121660281[36] = 0;
out_5588273031121660281[37] = 0;
out_5588273031121660281[38] = 0;
out_5588273031121660281[39] = 0;
out_5588273031121660281[40] = 1;
out_5588273031121660281[41] = 0;
out_5588273031121660281[42] = 0;
out_5588273031121660281[43] = 0;
out_5588273031121660281[44] = 0;
out_5588273031121660281[45] = dt*(stiffness_front*(-state[2] - state[3] + state[7])/(mass*state[1]) + (-stiffness_front - stiffness_rear)*state[5]/(mass*state[4]) + (-center_to_front*stiffness_front + center_to_rear*stiffness_rear)*state[6]/(mass*state[4]));
out_5588273031121660281[46] = -dt*stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(mass*pow(state[1], 2));
out_5588273031121660281[47] = -dt*stiffness_front*state[0]/(mass*state[1]);
out_5588273031121660281[48] = -dt*stiffness_front*state[0]/(mass*state[1]);
out_5588273031121660281[49] = dt*((-1 - (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(mass*pow(state[4], 2)))*state[6] - (-stiffness_front*state[0] - stiffness_rear*state[0])*state[5]/(mass*pow(state[4], 2)));
out_5588273031121660281[50] = dt*(-stiffness_front*state[0] - stiffness_rear*state[0])/(mass*state[4]) + 1;
out_5588273031121660281[51] = dt*(-state[4] + (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(mass*state[4]));
out_5588273031121660281[52] = dt*stiffness_front*state[0]/(mass*state[1]);
out_5588273031121660281[53] = -9.8100000000000005*dt;
out_5588273031121660281[54] = dt*(center_to_front*stiffness_front*(-state[2] - state[3] + state[7])/(rotational_inertia*state[1]) + (-center_to_front*stiffness_front + center_to_rear*stiffness_rear)*state[5]/(rotational_inertia*state[4]) + (-pow(center_to_front, 2)*stiffness_front - pow(center_to_rear, 2)*stiffness_rear)*state[6]/(rotational_inertia*state[4]));
out_5588273031121660281[55] = -center_to_front*dt*stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(rotational_inertia*pow(state[1], 2));
out_5588273031121660281[56] = -center_to_front*dt*stiffness_front*state[0]/(rotational_inertia*state[1]);
out_5588273031121660281[57] = -center_to_front*dt*stiffness_front*state[0]/(rotational_inertia*state[1]);
out_5588273031121660281[58] = dt*(-(-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])*state[5]/(rotational_inertia*pow(state[4], 2)) - (-pow(center_to_front, 2)*stiffness_front*state[0] - pow(center_to_rear, 2)*stiffness_rear*state[0])*state[6]/(rotational_inertia*pow(state[4], 2)));
out_5588273031121660281[59] = dt*(-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(rotational_inertia*state[4]);
out_5588273031121660281[60] = dt*(-pow(center_to_front, 2)*stiffness_front*state[0] - pow(center_to_rear, 2)*stiffness_rear*state[0])/(rotational_inertia*state[4]) + 1;
out_5588273031121660281[61] = center_to_front*dt*stiffness_front*state[0]/(rotational_inertia*state[1]);
out_5588273031121660281[62] = 0;
out_5588273031121660281[63] = 0;
out_5588273031121660281[64] = 0;
out_5588273031121660281[65] = 0;
out_5588273031121660281[66] = 0;
out_5588273031121660281[67] = 0;
out_5588273031121660281[68] = 0;
out_5588273031121660281[69] = 0;
out_5588273031121660281[70] = 1;
out_5588273031121660281[71] = 0;
out_5588273031121660281[72] = 0;
out_5588273031121660281[73] = 0;
out_5588273031121660281[74] = 0;
out_5588273031121660281[75] = 0;
out_5588273031121660281[76] = 0;
out_5588273031121660281[77] = 0;
out_5588273031121660281[78] = 0;
out_5588273031121660281[79] = 0;
out_5588273031121660281[80] = 1;
void F_fun(double *state, double dt, double *out_3325406224632462615) {
out_3325406224632462615[0] = 1;
out_3325406224632462615[1] = 0;
out_3325406224632462615[2] = 0;
out_3325406224632462615[3] = 0;
out_3325406224632462615[4] = 0;
out_3325406224632462615[5] = 0;
out_3325406224632462615[6] = 0;
out_3325406224632462615[7] = 0;
out_3325406224632462615[8] = 0;
out_3325406224632462615[9] = 0;
out_3325406224632462615[10] = 1;
out_3325406224632462615[11] = 0;
out_3325406224632462615[12] = 0;
out_3325406224632462615[13] = 0;
out_3325406224632462615[14] = 0;
out_3325406224632462615[15] = 0;
out_3325406224632462615[16] = 0;
out_3325406224632462615[17] = 0;
out_3325406224632462615[18] = 0;
out_3325406224632462615[19] = 0;
out_3325406224632462615[20] = 1;
out_3325406224632462615[21] = 0;
out_3325406224632462615[22] = 0;
out_3325406224632462615[23] = 0;
out_3325406224632462615[24] = 0;
out_3325406224632462615[25] = 0;
out_3325406224632462615[26] = 0;
out_3325406224632462615[27] = 0;
out_3325406224632462615[28] = 0;
out_3325406224632462615[29] = 0;
out_3325406224632462615[30] = 1;
out_3325406224632462615[31] = 0;
out_3325406224632462615[32] = 0;
out_3325406224632462615[33] = 0;
out_3325406224632462615[34] = 0;
out_3325406224632462615[35] = 0;
out_3325406224632462615[36] = 0;
out_3325406224632462615[37] = 0;
out_3325406224632462615[38] = 0;
out_3325406224632462615[39] = 0;
out_3325406224632462615[40] = 1;
out_3325406224632462615[41] = 0;
out_3325406224632462615[42] = 0;
out_3325406224632462615[43] = 0;
out_3325406224632462615[44] = 0;
out_3325406224632462615[45] = dt*(stiffness_front*(-state[2] - state[3] + state[7])/(mass*state[1]) + (-stiffness_front - stiffness_rear)*state[5]/(mass*state[4]) + (-center_to_front*stiffness_front + center_to_rear*stiffness_rear)*state[6]/(mass*state[4]));
out_3325406224632462615[46] = -dt*stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(mass*pow(state[1], 2));
out_3325406224632462615[47] = -dt*stiffness_front*state[0]/(mass*state[1]);
out_3325406224632462615[48] = -dt*stiffness_front*state[0]/(mass*state[1]);
out_3325406224632462615[49] = dt*((-1 - (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(mass*pow(state[4], 2)))*state[6] - (-stiffness_front*state[0] - stiffness_rear*state[0])*state[5]/(mass*pow(state[4], 2)));
out_3325406224632462615[50] = dt*(-stiffness_front*state[0] - stiffness_rear*state[0])/(mass*state[4]) + 1;
out_3325406224632462615[51] = dt*(-state[4] + (-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(mass*state[4]));
out_3325406224632462615[52] = dt*stiffness_front*state[0]/(mass*state[1]);
out_3325406224632462615[53] = -9.8100000000000005*dt;
out_3325406224632462615[54] = dt*(center_to_front*stiffness_front*(-state[2] - state[3] + state[7])/(rotational_inertia*state[1]) + (-center_to_front*stiffness_front + center_to_rear*stiffness_rear)*state[5]/(rotational_inertia*state[4]) + (-pow(center_to_front, 2)*stiffness_front - pow(center_to_rear, 2)*stiffness_rear)*state[6]/(rotational_inertia*state[4]));
out_3325406224632462615[55] = -center_to_front*dt*stiffness_front*(-state[2] - state[3] + state[7])*state[0]/(rotational_inertia*pow(state[1], 2));
out_3325406224632462615[56] = -center_to_front*dt*stiffness_front*state[0]/(rotational_inertia*state[1]);
out_3325406224632462615[57] = -center_to_front*dt*stiffness_front*state[0]/(rotational_inertia*state[1]);
out_3325406224632462615[58] = dt*(-(-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])*state[5]/(rotational_inertia*pow(state[4], 2)) - (-pow(center_to_front, 2)*stiffness_front*state[0] - pow(center_to_rear, 2)*stiffness_rear*state[0])*state[6]/(rotational_inertia*pow(state[4], 2)));
out_3325406224632462615[59] = dt*(-center_to_front*stiffness_front*state[0] + center_to_rear*stiffness_rear*state[0])/(rotational_inertia*state[4]);
out_3325406224632462615[60] = dt*(-pow(center_to_front, 2)*stiffness_front*state[0] - pow(center_to_rear, 2)*stiffness_rear*state[0])/(rotational_inertia*state[4]) + 1;
out_3325406224632462615[61] = center_to_front*dt*stiffness_front*state[0]/(rotational_inertia*state[1]);
out_3325406224632462615[62] = 0;
out_3325406224632462615[63] = 0;
out_3325406224632462615[64] = 0;
out_3325406224632462615[65] = 0;
out_3325406224632462615[66] = 0;
out_3325406224632462615[67] = 0;
out_3325406224632462615[68] = 0;
out_3325406224632462615[69] = 0;
out_3325406224632462615[70] = 1;
out_3325406224632462615[71] = 0;
out_3325406224632462615[72] = 0;
out_3325406224632462615[73] = 0;
out_3325406224632462615[74] = 0;
out_3325406224632462615[75] = 0;
out_3325406224632462615[76] = 0;
out_3325406224632462615[77] = 0;
out_3325406224632462615[78] = 0;
out_3325406224632462615[79] = 0;
out_3325406224632462615[80] = 1;
}
void h_25(double *state, double *unused, double *out_4633670035125740311) {
out_4633670035125740311[0] = state[6];
void h_25(double *state, double *unused, double *out_8501492422434664386) {
out_8501492422434664386[0] = state[6];
}
void H_25(double *state, double *unused, double *out_9153674884526169513) {
out_9153674884526169513[0] = 0;
out_9153674884526169513[1] = 0;
out_9153674884526169513[2] = 0;
out_9153674884526169513[3] = 0;
out_9153674884526169513[4] = 0;
out_9153674884526169513[5] = 0;
out_9153674884526169513[6] = 1;
out_9153674884526169513[7] = 0;
out_9153674884526169513[8] = 0;
void H_25(double *state, double *unused, double *out_7217655417465113750) {
out_7217655417465113750[0] = 0;
out_7217655417465113750[1] = 0;
out_7217655417465113750[2] = 0;
out_7217655417465113750[3] = 0;
out_7217655417465113750[4] = 0;
out_7217655417465113750[5] = 0;
out_7217655417465113750[6] = 1;
out_7217655417465113750[7] = 0;
out_7217655417465113750[8] = 0;
}
void h_24(double *state, double *unused, double *out_4147879785077922233) {
out_4147879785077922233[0] = state[4];
out_4147879785077922233[1] = state[5];
void h_24(double *state, double *unused, double *out_2528371558444461081) {
out_2528371558444461081[0] = state[4];
out_2528371558444461081[1] = state[5];
}
void H_24(double *state, double *unused, double *out_7067361405204513541) {
out_7067361405204513541[0] = 0;
out_7067361405204513541[1] = 0;
out_7067361405204513541[2] = 0;
out_7067361405204513541[3] = 0;
out_7067361405204513541[4] = 1;
out_7067361405204513541[5] = 0;
out_7067361405204513541[6] = 0;
out_7067361405204513541[7] = 0;
out_7067361405204513541[8] = 0;
out_7067361405204513541[9] = 0;
out_7067361405204513541[10] = 0;
out_7067361405204513541[11] = 0;
out_7067361405204513541[12] = 0;
out_7067361405204513541[13] = 0;
out_7067361405204513541[14] = 1;
out_7067361405204513541[15] = 0;
out_7067361405204513541[16] = 0;
out_7067361405204513541[17] = 0;
void H_24(double *state, double *unused, double *out_7688112899508452474) {
out_7688112899508452474[0] = 0;
out_7688112899508452474[1] = 0;
out_7688112899508452474[2] = 0;
out_7688112899508452474[3] = 0;
out_7688112899508452474[4] = 1;
out_7688112899508452474[5] = 0;
out_7688112899508452474[6] = 0;
out_7688112899508452474[7] = 0;
out_7688112899508452474[8] = 0;
out_7688112899508452474[9] = 0;
out_7688112899508452474[10] = 0;
out_7688112899508452474[11] = 0;
out_7688112899508452474[12] = 0;
out_7688112899508452474[13] = 0;
out_7688112899508452474[14] = 1;
out_7688112899508452474[15] = 0;
out_7688112899508452474[16] = 0;
out_7688112899508452474[17] = 0;
}
void h_30(double *state, double *unused, double *out_8271119563379762661) {
out_8271119563379762661[0] = state[4];
void h_30(double *state, double *unused, double *out_8776686484719170275) {
out_8776686484719170275[0] = state[4];
}
void H_30(double *state, double *unused, double *out_2376378847691765348) {
out_2376378847691765348[0] = 0;
out_2376378847691765348[1] = 0;
out_2376378847691765348[2] = 0;
out_2376378847691765348[3] = 0;
out_2376378847691765348[4] = 1;
out_2376378847691765348[5] = 0;
out_2376378847691765348[6] = 0;
out_2376378847691765348[7] = 0;
out_2376378847691765348[8] = 0;
void H_30(double *state, double *unused, double *out_6701392326116829668) {
out_6701392326116829668[0] = 0;
out_6701392326116829668[1] = 0;
out_6701392326116829668[2] = 0;
out_6701392326116829668[3] = 0;
out_6701392326116829668[4] = 1;
out_6701392326116829668[5] = 0;
out_6701392326116829668[6] = 0;
out_6701392326116829668[7] = 0;
out_6701392326116829668[8] = 0;
}
void h_26(double *state, double *unused, double *out_749423849060713781) {
out_749423849060713781[0] = state[7];
void h_26(double *state, double *unused, double *out_8173370600042692758) {
out_8173370600042692758[0] = state[7];
}
void H_26(double *state, double *unused, double *out_5412171565652113289) {
out_5412171565652113289[0] = 0;
out_5412171565652113289[1] = 0;
out_5412171565652113289[2] = 0;
out_5412171565652113289[3] = 0;
out_5412171565652113289[4] = 0;
out_5412171565652113289[5] = 0;
out_5412171565652113289[6] = 0;
out_5412171565652113289[7] = 1;
out_5412171565652113289[8] = 0;
void H_26(double *state, double *unused, double *out_7487585337370381642) {
out_7487585337370381642[0] = 0;
out_7487585337370381642[1] = 0;
out_7487585337370381642[2] = 0;
out_7487585337370381642[3] = 0;
out_7487585337370381642[4] = 0;
out_7487585337370381642[5] = 0;
out_7487585337370381642[6] = 0;
out_7487585337370381642[7] = 1;
out_7487585337370381642[8] = 0;
}
void h_27(double *state, double *unused, double *out_2801473399302960502) {
out_2801473399302960502[0] = state[3];
void h_27(double *state, double *unused, double *out_4943578383614041585) {
out_4943578383614041585[0] = state[3];
}
void H_27(double *state, double *unused, double *out_6849572625582504532) {
out_6849572625582504532[0] = 0;
out_6849572625582504532[1] = 0;
out_6849572625582504532[2] = 0;
out_6849572625582504532[3] = 1;
out_6849572625582504532[4] = 0;
out_6849572625582504532[5] = 0;
out_6849572625582504532[6] = 0;
out_6849572625582504532[7] = 0;
out_6849572625582504532[8] = 0;
void H_27(double *state, double *unused, double *out_8924986397300772885) {
out_8924986397300772885[0] = 0;
out_8924986397300772885[1] = 0;
out_8924986397300772885[2] = 0;
out_8924986397300772885[3] = 1;
out_8924986397300772885[4] = 0;
out_8924986397300772885[5] = 0;
out_8924986397300772885[6] = 0;
out_8924986397300772885[7] = 0;
out_8924986397300772885[8] = 0;
}
void h_29(double *state, double *unused, double *out_5173951242668943310) {
out_5173951242668943310[0] = state[1];
void h_29(double *state, double *unused, double *out_4668384321329535696) {
out_4668384321329535696[0] = state[1];
}
void H_29(double *state, double *unused, double *out_8912176792012229989) {
out_8912176792012229989[0] = 0;
out_8912176792012229989[1] = 1;
out_8912176792012229989[2] = 0;
out_8912176792012229989[3] = 0;
out_8912176792012229989[4] = 0;
out_8912176792012229989[5] = 0;
out_8912176792012229989[6] = 0;
out_8912176792012229989[7] = 0;
out_8912176792012229989[8] = 0;
void H_29(double *state, double *unused, double *out_7211623670431221852) {
out_7211623670431221852[0] = 0;
out_7211623670431221852[1] = 1;
out_7211623670431221852[2] = 0;
out_7211623670431221852[3] = 0;
out_7211623670431221852[4] = 0;
out_7211623670431221852[5] = 0;
out_7211623670431221852[6] = 0;
out_7211623670431221852[7] = 0;
out_7211623670431221852[8] = 0;
}
void h_28(double *state, double *unused, double *out_5994836064963036638) {
out_5994836064963036638[0] = state[0];
void h_28(double *state, double *unused, double *out_6247021973002058322) {
out_6247021973002058322[0] = state[0];
}
void H_28(double *state, double *unused, double *out_6948546520446903738) {
out_6948546520446903738[0] = 1;
out_6948546520446903738[1] = 0;
out_6948546520446903738[2] = 0;
out_6948546520446903738[3] = 0;
out_6948546520446903738[4] = 0;
out_6948546520446903738[5] = 0;
out_6948546520446903738[6] = 0;
out_6948546520446903738[7] = 0;
out_6948546520446903738[8] = 0;
void H_28(double *state, double *unused, double *out_9175253941996548103) {
out_9175253941996548103[0] = 1;
out_9175253941996548103[1] = 0;
out_9175253941996548103[2] = 0;
out_9175253941996548103[3] = 0;
out_9175253941996548103[4] = 0;
out_9175253941996548103[5] = 0;
out_9175253941996548103[6] = 0;
out_9175253941996548103[7] = 0;
out_9175253941996548103[8] = 0;
}
void h_31(double *state, double *unused, double *out_6352515274334922980) {
out_6352515274334922980[0] = state[8];
void h_31(double *state, double *unused, double *out_1448590970011147238) {
out_1448590970011147238[0] = state[8];
}
void H_31(double *state, double *unused, double *out_9184320846403129941) {
out_9184320846403129941[0] = 0;
out_9184320846403129941[1] = 0;
out_9184320846403129941[2] = 0;
out_9184320846403129941[3] = 0;
out_9184320846403129941[4] = 0;
out_9184320846403129941[5] = 0;
out_9184320846403129941[6] = 0;
out_9184320846403129941[7] = 0;
out_9184320846403129941[8] = 1;
void H_31(double *state, double *unused, double *out_7187009455588153322) {
out_7187009455588153322[0] = 0;
out_7187009455588153322[1] = 0;
out_7187009455588153322[2] = 0;
out_7187009455588153322[3] = 0;
out_7187009455588153322[4] = 0;
out_7187009455588153322[5] = 0;
out_7187009455588153322[6] = 0;
out_7187009455588153322[7] = 0;
out_7187009455588153322[8] = 1;
}
#include <eigen3/Eigen/Dense>
#include <iostream>
@@ -518,68 +518,68 @@ void car_update_28(double *in_x, double *in_P, double *in_z, double *in_R, doubl
void car_update_31(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea) {
update<1, 3, 0>(in_x, in_P, h_31, H_31, NULL, in_z, in_R, in_ea, MAHA_THRESH_31);
}
void car_err_fun(double *nom_x, double *delta_x, double *out_4503132331689013745) {
err_fun(nom_x, delta_x, out_4503132331689013745);
void car_err_fun(double *nom_x, double *delta_x, double *out_3010729618614624127) {
err_fun(nom_x, delta_x, out_3010729618614624127);
}
void car_inv_err_fun(double *nom_x, double *true_x, double *out_5519222819843562437) {
inv_err_fun(nom_x, true_x, out_5519222819843562437);
void car_inv_err_fun(double *nom_x, double *true_x, double *out_3985552318855446440) {
inv_err_fun(nom_x, true_x, out_3985552318855446440);
}
void car_H_mod_fun(double *state, double *out_99880963271144866) {
H_mod_fun(state, out_99880963271144866);
void car_H_mod_fun(double *state, double *out_4306310304618992202) {
H_mod_fun(state, out_4306310304618992202);
}
void car_f_fun(double *state, double dt, double *out_4490574509847198287) {
f_fun(state, dt, out_4490574509847198287);
void car_f_fun(double *state, double dt, double *out_841039768515563673) {
f_fun(state, dt, out_841039768515563673);
}
void car_F_fun(double *state, double dt, double *out_5588273031121660281) {
F_fun(state, dt, out_5588273031121660281);
void car_F_fun(double *state, double dt, double *out_3325406224632462615) {
F_fun(state, dt, out_3325406224632462615);
}
void car_h_25(double *state, double *unused, double *out_4633670035125740311) {
h_25(state, unused, out_4633670035125740311);
void car_h_25(double *state, double *unused, double *out_8501492422434664386) {
h_25(state, unused, out_8501492422434664386);
}
void car_H_25(double *state, double *unused, double *out_9153674884526169513) {
H_25(state, unused, out_9153674884526169513);
void car_H_25(double *state, double *unused, double *out_7217655417465113750) {
H_25(state, unused, out_7217655417465113750);
}
void car_h_24(double *state, double *unused, double *out_4147879785077922233) {
h_24(state, unused, out_4147879785077922233);
void car_h_24(double *state, double *unused, double *out_2528371558444461081) {
h_24(state, unused, out_2528371558444461081);
}
void car_H_24(double *state, double *unused, double *out_7067361405204513541) {
H_24(state, unused, out_7067361405204513541);
void car_H_24(double *state, double *unused, double *out_7688112899508452474) {
H_24(state, unused, out_7688112899508452474);
}
void car_h_30(double *state, double *unused, double *out_8271119563379762661) {
h_30(state, unused, out_8271119563379762661);
void car_h_30(double *state, double *unused, double *out_8776686484719170275) {
h_30(state, unused, out_8776686484719170275);
}
void car_H_30(double *state, double *unused, double *out_2376378847691765348) {
H_30(state, unused, out_2376378847691765348);
void car_H_30(double *state, double *unused, double *out_6701392326116829668) {
H_30(state, unused, out_6701392326116829668);
}
void car_h_26(double *state, double *unused, double *out_749423849060713781) {
h_26(state, unused, out_749423849060713781);
void car_h_26(double *state, double *unused, double *out_8173370600042692758) {
h_26(state, unused, out_8173370600042692758);
}
void car_H_26(double *state, double *unused, double *out_5412171565652113289) {
H_26(state, unused, out_5412171565652113289);
void car_H_26(double *state, double *unused, double *out_7487585337370381642) {
H_26(state, unused, out_7487585337370381642);
}
void car_h_27(double *state, double *unused, double *out_2801473399302960502) {
h_27(state, unused, out_2801473399302960502);
void car_h_27(double *state, double *unused, double *out_4943578383614041585) {
h_27(state, unused, out_4943578383614041585);
}
void car_H_27(double *state, double *unused, double *out_6849572625582504532) {
H_27(state, unused, out_6849572625582504532);
void car_H_27(double *state, double *unused, double *out_8924986397300772885) {
H_27(state, unused, out_8924986397300772885);
}
void car_h_29(double *state, double *unused, double *out_5173951242668943310) {
h_29(state, unused, out_5173951242668943310);
void car_h_29(double *state, double *unused, double *out_4668384321329535696) {
h_29(state, unused, out_4668384321329535696);
}
void car_H_29(double *state, double *unused, double *out_8912176792012229989) {
H_29(state, unused, out_8912176792012229989);
void car_H_29(double *state, double *unused, double *out_7211623670431221852) {
H_29(state, unused, out_7211623670431221852);
}
void car_h_28(double *state, double *unused, double *out_5994836064963036638) {
h_28(state, unused, out_5994836064963036638);
void car_h_28(double *state, double *unused, double *out_6247021973002058322) {
h_28(state, unused, out_6247021973002058322);
}
void car_H_28(double *state, double *unused, double *out_6948546520446903738) {
H_28(state, unused, out_6948546520446903738);
void car_H_28(double *state, double *unused, double *out_9175253941996548103) {
H_28(state, unused, out_9175253941996548103);
}
void car_h_31(double *state, double *unused, double *out_6352515274334922980) {
h_31(state, unused, out_6352515274334922980);
void car_h_31(double *state, double *unused, double *out_1448590970011147238) {
h_31(state, unused, out_1448590970011147238);
}
void car_H_31(double *state, double *unused, double *out_9184320846403129941) {
H_31(state, unused, out_9184320846403129941);
void car_H_31(double *state, double *unused, double *out_7187009455588153322) {
H_31(state, unused, out_7187009455588153322);
}
void car_predict(double *in_x, double *in_P, double *in_Q, double dt) {
predict(in_x, in_P, in_Q, dt);
@@ -9,27 +9,27 @@ void car_update_27(double *in_x, double *in_P, double *in_z, double *in_R, doubl
void car_update_29(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea);
void car_update_28(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea);
void car_update_31(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea);
void car_err_fun(double *nom_x, double *delta_x, double *out_4503132331689013745);
void car_inv_err_fun(double *nom_x, double *true_x, double *out_5519222819843562437);
void car_H_mod_fun(double *state, double *out_99880963271144866);
void car_f_fun(double *state, double dt, double *out_4490574509847198287);
void car_F_fun(double *state, double dt, double *out_5588273031121660281);
void car_h_25(double *state, double *unused, double *out_4633670035125740311);
void car_H_25(double *state, double *unused, double *out_9153674884526169513);
void car_h_24(double *state, double *unused, double *out_4147879785077922233);
void car_H_24(double *state, double *unused, double *out_7067361405204513541);
void car_h_30(double *state, double *unused, double *out_8271119563379762661);
void car_H_30(double *state, double *unused, double *out_2376378847691765348);
void car_h_26(double *state, double *unused, double *out_749423849060713781);
void car_H_26(double *state, double *unused, double *out_5412171565652113289);
void car_h_27(double *state, double *unused, double *out_2801473399302960502);
void car_H_27(double *state, double *unused, double *out_6849572625582504532);
void car_h_29(double *state, double *unused, double *out_5173951242668943310);
void car_H_29(double *state, double *unused, double *out_8912176792012229989);
void car_h_28(double *state, double *unused, double *out_5994836064963036638);
void car_H_28(double *state, double *unused, double *out_6948546520446903738);
void car_h_31(double *state, double *unused, double *out_6352515274334922980);
void car_H_31(double *state, double *unused, double *out_9184320846403129941);
void car_err_fun(double *nom_x, double *delta_x, double *out_3010729618614624127);
void car_inv_err_fun(double *nom_x, double *true_x, double *out_3985552318855446440);
void car_H_mod_fun(double *state, double *out_4306310304618992202);
void car_f_fun(double *state, double dt, double *out_841039768515563673);
void car_F_fun(double *state, double dt, double *out_3325406224632462615);
void car_h_25(double *state, double *unused, double *out_8501492422434664386);
void car_H_25(double *state, double *unused, double *out_7217655417465113750);
void car_h_24(double *state, double *unused, double *out_2528371558444461081);
void car_H_24(double *state, double *unused, double *out_7688112899508452474);
void car_h_30(double *state, double *unused, double *out_8776686484719170275);
void car_H_30(double *state, double *unused, double *out_6701392326116829668);
void car_h_26(double *state, double *unused, double *out_8173370600042692758);
void car_H_26(double *state, double *unused, double *out_7487585337370381642);
void car_h_27(double *state, double *unused, double *out_4943578383614041585);
void car_H_27(double *state, double *unused, double *out_8924986397300772885);
void car_h_29(double *state, double *unused, double *out_4668384321329535696);
void car_H_29(double *state, double *unused, double *out_7211623670431221852);
void car_h_28(double *state, double *unused, double *out_6247021973002058322);
void car_H_28(double *state, double *unused, double *out_9175253941996548103);
void car_h_31(double *state, double *unused, double *out_1448590970011147238);
void car_H_31(double *state, double *unused, double *out_7187009455588153322);
void car_predict(double *in_x, double *in_P, double *in_Q, double dt);
void car_set_mass(double x);
void car_set_rotational_inertia(double x);
File diff suppressed because it is too large Load Diff
@@ -5,18 +5,18 @@ void pose_update_4(double *in_x, double *in_P, double *in_z, double *in_R, doubl
void pose_update_10(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea);
void pose_update_13(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea);
void pose_update_14(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea);
void pose_err_fun(double *nom_x, double *delta_x, double *out_8799966904452395012);
void pose_inv_err_fun(double *nom_x, double *true_x, double *out_1661397671847398073);
void pose_H_mod_fun(double *state, double *out_2131008325054536789);
void pose_f_fun(double *state, double dt, double *out_884777716370448931);
void pose_F_fun(double *state, double dt, double *out_6755798908020795646);
void pose_h_4(double *state, double *unused, double *out_4561759232303120700);
void pose_H_4(double *state, double *unused, double *out_5331418226156006813);
void pose_h_10(double *state, double *unused, double *out_8855709713594721197);
void pose_H_10(double *state, double *unused, double *out_3758101988975610904);
void pose_h_13(double *state, double *unused, double *out_6255148116667054704);
void pose_H_13(double *state, double *unused, double *out_2279212982160694116);
void pose_h_14(double *state, double *unused, double *out_5422638595254952120);
void pose_H_14(double *state, double *unused, double *out_8414206658451379109);
void pose_err_fun(double *nom_x, double *delta_x, double *out_342973137176612241);
void pose_inv_err_fun(double *nom_x, double *true_x, double *out_4414887224430184744);
void pose_H_mod_fun(double *state, double *out_824354775938542426);
void pose_f_fun(double *state, double dt, double *out_432270031952541382);
void pose_F_fun(double *state, double dt, double *out_6844361959189325516);
void pose_h_4(double *state, double *unused, double *out_948512472116913193);
void pose_H_4(double *state, double *unused, double *out_4098576854729491679);
void pose_h_10(double *state, double *unused, double *out_8780443367168833320);
void pose_H_10(double *state, double *unused, double *out_7022073385523406729);
void pose_h_13(double *state, double *unused, double *out_3854432803415109726);
void pose_H_13(double *state, double *unused, double *out_3512054353587209250);
void pose_h_14(double *state, double *unused, double *out_3383842427869284419);
void pose_H_14(double *state, double *unused, double *out_135335998390007150);
void pose_predict(double *in_x, double *in_P, double *in_Q, double dt);
}
-21
View File
@@ -200,25 +200,6 @@ def check_valid_with_hysteresis(current_valid: bool, val: float, threshold: floa
return current_valid
# TODO: Remove this function after few releases (added in 0.9.9)
def migrate_cached_vehicle_params_if_needed(params: Params):
last_parameters_data_old = params.get("LiveParameters")
last_parameters_data = params.get("LiveParametersV2")
if last_parameters_data_old is None or last_parameters_data is not None:
return
try:
last_parameters_msg = messaging.new_message('liveParameters')
last_parameters_msg.liveParameters.valid = True
last_parameters_msg.liveParameters.steerRatio = last_parameters_data_old['steerRatio']
last_parameters_msg.liveParameters.stiffnessFactor = last_parameters_data_old['stiffnessFactor']
last_parameters_msg.liveParameters.angleOffsetAverageDeg = last_parameters_data_old['angleOffsetAverageDeg']
params.put("LiveParametersV2", last_parameters_msg.to_bytes(), block=True)
except Exception as e:
cloudlog.error(f"Failed to perform parameter migration: {e}")
params.remove("LiveParameters")
def retrieve_initial_vehicle_params(params: Params, CP: car.CarParams, replay: bool, debug: bool):
last_parameters_data = params.get("LiveParametersV2")
last_carparams_data = params.get("CarParamsPrevRoute")
@@ -273,8 +254,6 @@ def main():
params = Params()
CP = messaging.log_from_bytes(params.get("CarParams", block=True), car.CarParams)
migrate_cached_vehicle_params_if_needed(params)
steer_ratio, stiffness_factor, angle_offset_deg, pInitial = retrieve_initial_vehicle_params(params, CP, REPLAY, DEBUG)
learner = VehicleParamsLearner(CP, steer_ratio, stiffness_factor, np.radians(angle_offset_deg), pInitial)
@@ -81,6 +81,7 @@ class TestLagd:
assert retrieve_initial_lag(params, CP) is None
def test_ncc(self):
rng = np.random.default_rng()
lag_frames = random.randint(1, 19)
desired_sig = np.sin(np.arange(0.0, 10.0, 0.1))
@@ -91,15 +92,15 @@ class TestLagd:
assert np.argmax(corr) == lag_frames
# add some noise
desired_sig += np.random.normal(0, 0.05, len(desired_sig))
actual_sig += np.random.normal(0, 0.05, len(actual_sig))
desired_sig += rng.normal(0, 0.05, len(desired_sig))
actual_sig += rng.normal(0, 0.05, len(actual_sig))
corr = masked_normalized_cross_correlation(desired_sig, actual_sig, mask, 200)[len(desired_sig) - 1:len(desired_sig) + 20]
assert np.argmax(corr) in range(lag_frames - MAX_ERR_FRAMES, lag_frames + MAX_ERR_FRAMES + 1)
# mask out 40% of the values, and make them noise
mask = np.random.choice([True, False], size=len(desired_sig), p=[0.6, 0.4])
desired_sig[~mask] = np.random.normal(0, 1, size=np.sum(~mask))
actual_sig[~mask] = np.random.normal(0, 1, size=np.sum(~mask))
mask = rng.choice([True, False], size=len(desired_sig), p=[0.6, 0.4])
desired_sig[~mask] = rng.normal(0, 1, size=np.sum(~mask))
actual_sig[~mask] = rng.normal(0, 1, size=np.sum(~mask))
corr = masked_normalized_cross_correlation(desired_sig, actual_sig, mask, 200)[len(desired_sig) - 1:len(desired_sig) + 20]
assert np.argmax(corr) in range(lag_frames - MAX_ERR_FRAMES, lag_frames + MAX_ERR_FRAMES + 1)
@@ -37,9 +37,9 @@ def get_select_fields_data(logs):
def sig_smooth(signal):
return masked_symmetric_moving_average(signal, np.ones_like(signal), 5, 1.0)
def get_nested_keys(msg, keys):
val = None
val = msg
for key in keys:
val = getattr(msg if val is None else val, key) if isinstance(key, str) else val[key]
val = getattr(val, key) if isinstance(key, str) else val[key]
return val
lp = [x.livePose for x in logs if x.which() == 'livePose']
data = defaultdict(list)
@@ -2,7 +2,7 @@ import random
import numpy as np
from openpilot.cereal import messaging
from openpilot.selfdrive.locationd.paramsd import retrieve_initial_vehicle_params, migrate_cached_vehicle_params_if_needed
from openpilot.selfdrive.locationd.paramsd import retrieve_initial_vehicle_params
from openpilot.selfdrive.locationd.models.car_kf import CarKalman
from openpilot.selfdrive.locationd.test.test_locationd_scenarios import TEST_ROUTE
from openpilot.selfdrive.test.process_replay.migration import migrate, migrate_carParams
@@ -30,38 +30,9 @@ class TestParamsd:
params.put("LiveParametersV2", msg.to_bytes(), block=True)
params.put("CarParamsPrevRoute", CP.as_builder().to_bytes(), block=True)
migrate_cached_vehicle_params_if_needed(params) # this is not tested here but should not mess anything up or throw an error
sr, sf, offset, p_init = retrieve_initial_vehicle_params(params, CP, replay=True, debug=True)
np.testing.assert_allclose(sr, msg.liveParameters.steerRatio)
np.testing.assert_allclose(sf, msg.liveParameters.stiffnessFactor)
np.testing.assert_allclose(offset, msg.liveParameters.angleOffsetAverageDeg)
np.testing.assert_equal(p_init.shape, CarKalman.P_initial.shape)
np.testing.assert_allclose(np.diagonal(p_init), msg.liveParameters.debugFilterState.std)
# TODO Remove this test after the support for old format is removed
def test_read_saved_params_old_format(self):
params = Params()
lr = migrate(LogReader(TEST_ROUTE), [migrate_carParams])
CP = next(m for m in lr if m.which() == "carParams").carParams
msg = get_random_live_parameters(CP)
params.put("LiveParameters", msg.liveParameters.to_dict(), block=True)
params.put("CarParamsPrevRoute", CP.as_builder().to_bytes(), block=True)
params.remove("LiveParametersV2")
migrate_cached_vehicle_params_if_needed(params)
sr, sf, offset, _ = retrieve_initial_vehicle_params(params, CP, replay=True, debug=True)
np.testing.assert_allclose(sr, msg.liveParameters.steerRatio)
np.testing.assert_allclose(sf, msg.liveParameters.stiffnessFactor)
np.testing.assert_allclose(offset, msg.liveParameters.angleOffsetAverageDeg)
assert params.get("LiveParametersV2") is not None
def test_read_saved_params_corrupted_old_format(self):
params = Params()
params.put("LiveParameters", {}, block=True)
params.remove("LiveParametersV2")
migrate_cached_vehicle_params_if_needed(params)
assert params.get("LiveParameters") is None
assert params.get("LiveParametersV2") is None
@@ -2,24 +2,25 @@ from opendbc.car.structs import car
from openpilot.selfdrive.locationd.torqued import TorqueEstimator
def test_cal_percent():
est = TorqueEstimator(car.CarParams())
msg = est.get_msg()
assert msg.liveTorqueParameters.calPerc == 0
class TestTorqued:
def test_cal_percent(self):
est = TorqueEstimator(car.CarParams())
msg = est.get_msg()
assert msg.liveTorqueParameters.calPerc == 0
for (low, high), min_pts in zip(est.filtered_points.buckets.keys(),
est.filtered_points.buckets_min_points.values(), strict=True):
for _ in range(int(min_pts)):
est.filtered_points.add_point((low + high) / 2.0, 0.0)
for (low, high), min_pts in zip(est.filtered_points.buckets.keys(),
est.filtered_points.buckets_min_points.values(), strict=True):
for _ in range(int(min_pts)):
est.filtered_points.add_point((low + high) / 2.0, 0.0)
# enough bucket points, but not enough total points
msg = est.get_msg()
assert msg.liveTorqueParameters.calPerc == (len(est.filtered_points) / est.min_points_total * 100 + 100) / 2
# enough bucket points, but not enough total points
msg = est.get_msg()
assert msg.liveTorqueParameters.calPerc == (len(est.filtered_points) / est.min_points_total * 100 + 100) / 2
# add enough points to bucket with most capacity
key = list(est.filtered_points.buckets)[0]
for _ in range(est.min_points_total - len(est.filtered_points)):
est.filtered_points.add_point((key[0] + key[1]) / 2.0, 0.0)
# add enough points to bucket with most capacity
key = list(est.filtered_points.buckets)[0]
for _ in range(est.min_points_total - len(est.filtered_points)):
est.filtered_points.add_point((key[0] + key[1]) / 2.0, 0.0)
msg = est.get_msg()
assert msg.liveTorqueParameters.calPerc == 100
msg = est.get_msg()
assert msg.liveTorqueParameters.calPerc == 100
+5 -4
View File
@@ -62,14 +62,14 @@ class TorqueEstimator(ParameterEstimator, TorqueEstimatorExt):
self.lag = 0.0
self.track_all_points = track_all_points # for offline analysis, without max lateral accel or max steer torque filters
if decimated:
self.min_bucket_points = MIN_BUCKET_POINTS / 10
self.min_bucket_points: list[float] = (MIN_BUCKET_POINTS / 10).tolist()
self.min_points_total = MIN_POINTS_TOTAL_QLOG
self.fit_points = FIT_POINTS_TOTAL_QLOG
self.factor_sanity = FACTOR_SANITY_QLOG
self.friction_sanity = FRICTION_SANITY_QLOG
else:
self.min_bucket_points = MIN_BUCKET_POINTS
self.min_bucket_points = MIN_BUCKET_POINTS.tolist()
self.min_points_total = MIN_POINTS_TOTAL
self.fit_points = FIT_POINTS_TOTAL
self.factor_sanity = FACTOR_SANITY
@@ -120,9 +120,10 @@ class TorqueEstimator(ParameterEstimator, TorqueEstimatorExt):
'latAccelOffset': cache_ltp.latAccelOffsetFiltered,
'frictionCoefficient': cache_ltp.frictionCoefficientFiltered
}
initial_params['points'] = cache_ltp.points
cached_points: list[list[float]] = [list(point) for point in cache_ltp.points]
initial_params['points'] = cached_points
self.decay = cache_ltp.decay
self.filtered_points.load_points(initial_params['points'])
self.filtered_points.load_points(cached_points)
cloudlog.info("restored torque params from cache")
except Exception:
cloudlog.exception("failed to restore cached torque params")
+6 -2
View File
@@ -13,6 +13,7 @@ from collections import namedtuple
import numpy as np
from openpilot.selfdrive.modeld.helpers import dump_oob, load_oob
from openpilot.selfdrive.modeld.usbgpu_link import wait_usbgpu_link
def _patch_tinygrad_fetch_fw():
import hashlib
@@ -242,7 +243,7 @@ def compile_jit(jit, make_random_inputs, input_keys, make_queues):
SEED = 42
def random_inputs_run(fn, seed, test_val=None, test_buffers=None, expect_match=True):
input_queues, npy = make_queues(Device.DEFAULT)
np.random.seed(seed)
rng = np.random.default_rng(seed)
Tensor.manual_seed(seed)
testing = test_val is not None or test_buffers is not None
@@ -250,7 +251,7 @@ def compile_jit(jit, make_random_inputs, input_keys, make_queues):
for i in range(n_runs):
for v in npy.values():
v[:] = np.random.randn(*v.shape).astype(v.dtype)
v[:] = rng.standard_normal(v.shape).astype(v.dtype)
Device.default.synchronize()
random_inputs = make_random_inputs()
st = time.perf_counter()
@@ -311,6 +312,9 @@ if __name__ == "__main__":
p.add_argument('--frame-skip', type=int, required=True)
args = p.parse_args()
if 'USB+AMD' in os.environ.get('DEV', ''):
wait_usbgpu_link()
model_path = read_file_chunked_to_disk(args.onnx)
model_w, model_h = args.model_size
+4 -1
View File
@@ -25,6 +25,7 @@ from openpilot.selfdrive.modeld.fill_model_msg import fill_model_msg, fill_drivi
from openpilot.common.file_chunker import open_file_chunked, get_manifest_path
from openpilot.selfdrive.modeld.constants import ModelConstants, Plan
from openpilot.selfdrive.modeld.helpers import usbgpu_present, modeld_pkl_path, get_tg_input_devices, load_oob
from openpilot.selfdrive.modeld.usbgpu_link import wait_usbgpu_link
from openpilot.sunnypilot.livedelay.helpers import get_lat_delay
from openpilot.sunnypilot.modeld_v2.modeld_base import ModelStateBase
@@ -94,7 +95,7 @@ class ModelState(ModelStateBase):
self.frame_skip = ModelConstants.MODEL_RUN_FREQ // ModelConstants.MODEL_CONTEXT_FREQ
self.input_queues, self.npy = make_input_queues(self.input_shapes, self.frame_skip, device=self.QUEUE_DEV)
self.full_frames: dict[str, Tensor] = {}
self._blob_cache: dict[int, Tensor] = {}
self._blob_cache: dict[tuple[str, int], Tensor] = {}
self.parser = Parser()
self.frame_buf_params = {k: get_nv12_info(cam_w, cam_h) for k in ('img', 'big_img')}
self.run_policy = jits['run_policy']
@@ -173,6 +174,8 @@ def main(demo=False):
if use_extra_client:
cloudlog.warning(f"connected extra cam with buffer size: {vipc_client_extra.buffer_len} ({vipc_client_extra.width} x {vipc_client_extra.height})")
if USBGPU:
wait_usbgpu_link()
st = time.monotonic()
cloudlog.warning("loading model")
model = ModelState(vipc_client_main.width, vipc_client_main.height, USBGPU)
@@ -41,7 +41,7 @@ class Parser:
raw = outs[name]
outs[name] = sigmoid(raw)
def parse_mdn(self, name, outs, in_N=0, out_N=1, out_shape=None):
def parse_mdn(self, name, outs, in_N=0, out_N=1, out_shape=()):
if self.check_missing(outs, name):
return
raw = outs[name]
+34
View File
@@ -0,0 +1,34 @@
import time
from pathlib import Path
from openpilot.common.swaglog import cloudlog
from openpilot.common.hardware.usb import CHESTNUT_VENDOR_ID, CHESTNUT_PRODUCT_ID, usb_devices, controller, read_int
STABLE_SECONDS = 2.0
STABLE_THRESHOLD = 5.0 # link errors per second
def _chestnut_portli() -> Path | None:
for device in usb_devices():
if read_int(device / "idVendor", 16) == CHESTNUT_VENDOR_ID and \
read_int(device / "idProduct", 16) == CHESTNUT_PRODUCT_ID:
ctrl = controller(device)
if ctrl is not None and (ctrl / "portli").exists():
return ctrl / "portli"
return None
def wait_usbgpu_link(timeout: float = 30.0) -> None:
portli = _chestnut_portli()
if portli is None:
return
t0 = time.monotonic()
while time.monotonic() - t0 < timeout:
start = read_int(portli, 0)
time.sleep(STABLE_SECONDS)
rate = (read_int(portli, 0) - start) / STABLE_SECONDS
if rate <= STABLE_THRESHOLD:
return
cloudlog.warning(f"usbgpu link not stable: {rate:.0f} errors/s")
cloudlog.error("usbgpu link never stabilized")
+19 -11
View File
@@ -41,7 +41,7 @@ class DRIVER_MONITOR_SETTINGS:
# lockout specs
self._MAX_ALERT_3 = 2
self._MAX_NO_RESPONSE = 1
self._LOCKOUT_TIME = int(1800 / DT_DMON)
self._LOCKOUT_TIMES = [int(60 * n_min / DT_DMON) for n_min in [1, 5, 15, 30]]
self._TIMEOUT_RECOVERY_FACTOR_MAX = 5.
self._TIMEOUT_RECOVERY_FACTOR_MIN = 1.25
@@ -152,7 +152,10 @@ class DriverMonitoring:
self.cnt_since_alert_3 = 0
self.no_response_timeout = int(self.settings._NO_RESPONSE_TIMEOUT / DT_DMON)
self.no_response_cnt = 0
self.lockout_time = 0
self.lockout_active = Params().get_bool("DriverTooDistracted")
self.lockout_count = Params().get("DriverLockoutCount") or 0
self.lockout_duration = self.settings._LOCKOUT_TIMES[min(max(self.lockout_count - 1, 0), len(self.settings._LOCKOUT_TIMES) - 1)]
self.lockout_time_elapsed = 0
self.step_change = 0.
self.active_policy = MonitoringPolicy.vision
self.driver_interacting = False
@@ -163,7 +166,6 @@ class DriverMonitoring:
self.threshold_alert_2 = 0.
self.dcam_uncertain_cnt = 0
self.dcam_reset_cnt = 0
self.too_distracted = Params().get_bool("DriverTooDistracted")
self._reset_awareness()
self._set_policy(MonitoringPolicy.vision)
@@ -310,16 +312,20 @@ class DriverMonitoring:
self.driver_interacting = driver_engaged
if self.alert_3_cnt >= self.settings._MAX_ALERT_3 or self.no_response_cnt >= self.settings._MAX_NO_RESPONSE:
self.too_distracted = True
if not self.lockout_active:
self.lockout_count += 1
self.lockout_duration = self.settings._LOCKOUT_TIMES[min(self.lockout_count - 1, len(self.settings._LOCKOUT_TIMES) - 1)]
Params().put("DriverLockoutCount", self.lockout_count)
self.lockout_active = True
if self.too_distracted:
self.lockout_time += 1
if self.lockout_time > self.settings._LOCKOUT_TIME:
self.too_distracted = False
if self.lockout_active:
self.lockout_time_elapsed += 1
if self.lockout_time_elapsed > self.lockout_duration:
self.lockout_active = False
self.alert_3_cnt = 0
self.cnt_since_alert_3 = 0
self.no_response_cnt = 0
self.lockout_time = 0
self.lockout_time_elapsed = 0
always_on_valid = self.always_on and not wrong_gear
if (self.driver_interacting and self.awareness > 0 and self.active_policy == MonitoringPolicy.wheeltouch) or \
@@ -379,8 +385,10 @@ class DriverMonitoring:
dat = messaging.new_message('driverMonitoringState', valid=valid)
dm = dat.driverMonitoringState
dm.lockout = self.too_distracted
dm.lockoutRecoveryPercent = to_percent(self.lockout_time / self.settings._LOCKOUT_TIME)
dm.lockout = self.lockout_active
dm.lockoutCount = self.lockout_count
if self.lockout_active:
dm.lockoutMinutesRemaining = max(1, round((self.lockout_duration - self.lockout_time_elapsed) * DT_DMON / 60.))
dm.alert3Count = self.alert_3_cnt
dm.noResponseCount = self.no_response_cnt
dm.noResponseForceDecel = self.alert_level == AlertLevel.three and self.cnt_since_alert_3 >= self.no_response_timeout
@@ -86,21 +86,17 @@ class TestMonitoring:
# engaged, distracted past red and beyond the no-response window -> unavailability response + lockout
def test_distracted_lockout(self):
alert_lvls, d_status = self._run_seq(always_distracted, always_false, always_true, always_false)
s = d_status.settings
assert alert_lvls[int(DISTRACTED_SECONDS_TO_RED / DT_DMON)] == 3
assert d_status.alert_3_cnt == 1
assert d_status.no_response_cnt == s._MAX_NO_RESPONSE
assert d_status.too_distracted
assert d_status.lockout_time > 0
assert d_status.lockout_active
assert d_status.lockout_time_elapsed > 0
assert d_status.lockout_count >= 1
# no face -> wheeltouch red, sustained past the no-response timeout -> unavailability response + lockout
def test_invisible_lockout(self):
_, d_status = self._run_seq(always_no_face, always_false, always_true, always_false)
s = d_status.settings
assert d_status.active_policy == log.DriverMonitoringState.MonitoringPolicy.wheeltouch
assert d_status.alert_3_cnt == 1
assert d_status.no_response_cnt == s._MAX_NO_RESPONSE
assert d_status.too_distracted
assert d_status.lockout_active
assert d_status.lockout_count >= 1
# engaged, no face detected the whole time, no action
def test_fully_invisible_driver(self):
@@ -275,7 +271,7 @@ def test_run_step_engagement(selfdrive_enabled, lat_active, steering, gas,
captured['op_engaged'] = op_engaged
return orig(driver_engaged, op_engaged, lowspeed, wrong_gear)
dm._update_events = spy
object.__setattr__(dm, '_update_events', spy)
dm.run_step(sm, demo=False)
assert captured['op_engaged'] == expected_op_engaged
assert captured['driver_engaged'] == expected_driver_engaged
Binary file not shown.
@@ -60,7 +60,7 @@ class TestPandad:
def test_in_reset(self):
gpio_init(GPIO.STM_RST_N, True)
gpio_set(GPIO.STM_RST_N, 1)
gpio_set(GPIO.STM_RST_N, True)
assert not Panda.list()
self._run_test()
@@ -38,10 +38,10 @@ class TestBoarddSpi:
total_recv_count = 0
total_sent_count = 0
sent_msgs = {bus: list() for bus in range(3)}
sent_msgs = {bus: [] for bus in range(3)}
st = time.monotonic()
ts = {s: list() for s in socks.keys()}
ts = {s: [] for s in socks.keys()}
for _ in range(int(os.getenv("TEST_TIME", "20"))):
# send some CAN messages
if not JUNGLE_SPAM:

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