From d8cc751cef1600e352c8b9824cf089a418da27e8 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Mon, 5 Oct 2026 05:15:59 -0500 Subject: [PATCH] Volt One-Pedal --- opendbc_repo/opendbc/car/gm/aol.py | 2 + opendbc_repo/opendbc/car/gm/auto_hold.py | 5 +- opendbc_repo/opendbc/car/gm/carcontroller.py | 55 ++++- opendbc_repo/opendbc/car/gm/carstate.py | 37 +++- opendbc_repo/opendbc/car/gm/lateral.py | 3 +- opendbc_repo/opendbc/car/gm/one_pedal.py | 80 +++++++ .../opendbc/car/gm/startup_preferences.py | 3 + .../car/gm/tests/test_volt_alternate_brake.py | 194 ++++++++++++++++ .../gm/tests/volt_one_pedal_default_off.json | 1 + .../tests/volt_one_pedal_original_oracle.json | 1 + opendbc_repo/opendbc/car/gm/values.py | 59 ++++- opendbc_repo/opendbc/safety/modes/gm.h | 4 +- opendbc_repo/opendbc/safety/modes/gm_aol.h | 6 + .../opendbc/safety/modes/gm_bolt_cc.h | 1 + .../opendbc/safety/modes/gm_volt_auto_hold.h | 51 ++++- .../opendbc/safety/modes/gm_volt_one_pedal.h | 101 +++++++++ .../safety/tests/test_gm_volt_auto_hold.py | 10 +- .../tests/test_gm_volt_gateway_mapping.py | 3 + .../safety/tests/test_gm_volt_one_pedal.py | 209 ++++++++++++++++++ openpilot/common/params_keys.h | 1 + .../pandad/tests/test_aol_protocol.cc | 16 +- openpilot/starpilot/aol/tests/test_gm.py | 7 +- openpilot/starpilot/car/gm/aol_policy.h | 6 + openpilot/starpilot/car/gm/auto_hold.py | 13 +- openpilot/starpilot/controller_extensions.py | 5 +- .../starpilot/galaxy/vehicle_configuration.py | 2 +- .../tests/test_gm_pitch_preferences.py | 12 +- .../tests/test_vehicle_preferences.py | 98 ++++++-- .../starpilot/ui/feature_settings_owner.py | 13 +- openpilot/starpilot/ui/vehicle_bool.py | 8 +- openpilot/starpilot/vehicle_preferences.py | 18 +- 31 files changed, 934 insertions(+), 90 deletions(-) create mode 100644 opendbc_repo/opendbc/car/gm/one_pedal.py create mode 100644 opendbc_repo/opendbc/car/gm/tests/volt_one_pedal_default_off.json create mode 100644 opendbc_repo/opendbc/car/gm/tests/volt_one_pedal_original_oracle.json create mode 100644 opendbc_repo/opendbc/safety/modes/gm_volt_one_pedal.h create mode 100644 opendbc_repo/opendbc/safety/tests/test_gm_volt_one_pedal.py diff --git a/opendbc_repo/opendbc/car/gm/aol.py b/opendbc_repo/opendbc/car/gm/aol.py index 695f87c322..98428851f7 100644 --- a/opendbc_repo/opendbc/car/gm/aol.py +++ b/opendbc_repo/opendbc/car/gm/aol.py @@ -16,6 +16,8 @@ GM_BASE_GATEWAY_IDS = frozenset((CAR.GMC_ACADIA, CAR.BUICK_LACROSSE, CAR.CADILLA CAR.CADILLAC_ESCALADE_ESV, CAR.CADILLAC_ESCALADE_ESV_2019, CAR.CHEVROLET_SUBURBAN)) GM_AOL_WORDS = frozenset(( 0, 0x80, + 0xD100, 0xD101, 0xD102, 0xD103, 0xD104, 0xD105, 0xD106, 0xD107, 0xD108, 0xD109, 0xD10A, + 0xD110, 0xD111, 0xD112, 0xD113, 0xD114, 0xD115, 0xD116, 0xD117, 0xD118, 0xD119, 0xD11A, 0x1001, 0x1401, 0x3001, 0x3401, 0x1003, 0x1403, 0x201, 0x601, 0xA01, 0xE01, 0x203, 0x603, 0xA03, 0xE03, 5, 7, 20, 0xBD, 0x9D, 0x19D, 0x1CD, diff --git a/opendbc_repo/opendbc/car/gm/auto_hold.py b/opendbc_repo/opendbc/car/gm/auto_hold.py index 684c434042..3b542934f8 100644 --- a/opendbc_repo/opendbc/car/gm/auto_hold.py +++ b/opendbc_repo/opendbc/car/gm/auto_hold.py @@ -18,7 +18,10 @@ class AutoHoldConfig: def config_for(cp) -> AutoHoldConfig: from opendbc.car.gm.values import is_gm_auto_hold, is_volt_sdgm_profile - return AutoHoldConfig(100, .25) if is_gm_auto_hold(cp) and is_volt_sdgm_profile(cp, longitudinal=True) else AutoHoldConfig() + if is_gm_auto_hold(cp) and is_volt_sdgm_profile(cp, longitudinal=True): + solo = 0xD100 <= int(cp.safetyConfigs[0].safetyParam) <= 0xD10A + return AutoHoldConfig(100, .02 if solo else .25) + return AutoHoldConfig() def stopped_for_hold(cs, config: AutoHoldConfig, sent_hold: bool) -> bool: diff --git a/opendbc_repo/opendbc/car/gm/carcontroller.py b/opendbc_repo/opendbc/car/gm/carcontroller.py index 9c302bb38c..dde618d091 100644 --- a/opendbc_repo/opendbc/car/gm/carcontroller.py +++ b/opendbc_repo/opendbc/car/gm/carcontroller.py @@ -1,5 +1,7 @@ +from opendbc.car.gm.one_pedal import VoltOnePedal +from opendbc.car.gm.values import gm_control_word, is_volt_one_pedal from opendbc.car.gm.longitudinal import volt_sng_release -from opendbc.car.gm.auto_hold import AutoHold, config_for as auto_hold_config_for +from opendbc.car.gm.auto_hold import AutoHold, config_for as auto_hold_config_for, hold_brake as estimate_hold_brake from opendbc.car.gm.values import is_gm_auto_hold from opendbc.car.gm.ordinary import demands as ascm_demands import math @@ -225,6 +227,8 @@ class CarController(CarControllerBase): self.pedal_active_last = False self.volt_sng = False self.volt_sng_plan_input = None + self.volt_one_pedal = False + self.volt_one_pedal_input = None self.gm_auto_hold = False self.gm_auto_hold_input = None self.gm_auto_hold_state = AutoHold(config=auto_hold_config_for(CP)) @@ -242,6 +246,7 @@ class CarController(CarControllerBase): self.lka_icon_status_last = (False, False) self.params = CarControllerParams(self.CP) + self.volt_one_pedal_state = VoltOnePedal(CP, self.params) if is_volt_one_pedal(CP) else None self.volt_gateway_profile = is_volt_gateway_profile(self.CP) self.volt_gateway_long = is_volt_gateway_longitudinal(self.CP) self.volt_ascm_long = is_volt_ascm_longitudinal(self.CP) @@ -348,16 +353,36 @@ class CarController(CarControllerBase): def update(self, CC, CS, now_nanos): # Sample physical hold dwell at parser/controller cadence, before current brake demands. hold_brake = None + one_pedal_enabled = (self.volt_one_pedal and is_volt_one_pedal(self.CP) and self.volt_one_pedal_input is not None and + self.volt_one_pedal_input.update(now_nanos)) + one_pedal_active = False if is_gm_auto_hold(self.CP): hold_enabled = self.gm_auto_hold and self.gm_auto_hold_input is not None and self.gm_auto_hold_input.update(now_nanos) + physical_current = (bool(CS.gm_auto_hold_sources) and + all(0 < stamp <= now_nanos and now_nanos - stamp <= limit for stamp, limit in CS.gm_auto_hold_sources) and + not CS.gm_auto_hold_unavailable) + one_pedal_ready = (one_pedal_enabled and physical_current and CS.volt_one_pedal_mode and + 0 < CS.volt_one_pedal_mode_ns <= now_nanos and now_nanos - CS.volt_one_pedal_mode_ns <= 300_000_000 and + CS.out.cruiseState.available and CS.gm_auto_hold_forward and + not CS.out.gasPressed and not CS.out.brakePressed and not CS.out.regenBraking) hold_brake = self.gm_auto_hold_state.update( - CS.out, enabled=hold_enabled, sources_current=all(0 < stamp <= now_nanos and now_nanos - stamp <= limit + CS.out, enabled=hold_enabled or one_pedal_enabled, sources_current=all(0 < stamp <= now_nanos and now_nanos - stamp <= limit for stamp, limit in CS.gm_auto_hold_sources) and bool(CS.gm_auto_hold_sources) and not CS.gm_auto_hold_unavailable, long_active=CC.longActive, driver_brake=CS.gm_auto_hold_brake, controller_brake=self.apply_brake, wheel_ns=CS.gm_auto_hold_wheel_ns, now_ns=now_nanos, physical_forward=CS.gm_auto_hold_forward, moving=CS.gm_auto_hold_moving, sent_hold=CS.gm_auto_hold_engaged) - if hold_brake is None: + if not hold_enabled: + hold_brake = None + one_pedal_active = (one_pedal_ready and self.gm_auto_hold_state.drive_ns >= 3_000_000_000 and + CS.out.canValid and not CS.out.canTimeout and not CC.longActive and + (CS.volt_one_pedal_moving or CS.volt_one_pedal_stopped)) + if hold_brake is None and not (one_pedal_active and CS.volt_one_pedal_stopped and + (CS.out.standstill or CS.out.vEgo < .02)): CS.gm_auto_hold_engaged = False + if self.volt_one_pedal_state is not None: + self.volt_one_pedal_state.observe(eligible=one_pedal_ready and self.gm_auto_hold_state.drive_ns >= 3_000_000_000 and + not CC.longActive, gas_pressed=CS.out.gasPressed, + speed=CS.out.vEgo) actuators = CC.actuators hud_control = CC.hudControl hud_alert = hud_control.visualAlert @@ -630,6 +655,25 @@ class CarController(CarControllerBase): self.ordinary_camera_long and not self.ordinary_camera_removed): can_sends.append(gmcan.create_acc_2cd_command(CanBus.POWERTRAIN, idx)) + if self.volt_one_pedal_state is not None: + one_pedal_brake = self.volt_one_pedal_state.update( + eligible=one_pedal_active, speed=CS.out.vEgo, acceleration=CS.out.aEgo, + steering_angle=CS.out.steeringAngleDeg, orientation=CC.orientationNED) + if one_pedal_active: + one_pedal_stop = CS.volt_one_pedal_stopped and (CS.out.standstill or CS.out.vEgo < .02) + if hold_brake is None and one_pedal_stop and one_pedal_brake > 0: + hold_brake = max(one_pedal_brake, self.gm_auto_hold_state.brake or estimate_hold_brake( + 0., one_pedal_brake, self.gm_auto_hold_state.config.minimum_brake)) + elif hold_brake is not None: + hold_brake = max(hold_brake, one_pedal_brake) + self.apply_gas = self.params.INACTIVE_REGEN + self.apply_brake = max(self.apply_brake, one_pedal_brake) + + one_pedal_braking = one_pedal_active and self.volt_one_pedal_state is not None and self.volt_one_pedal_state.brake > 0 + if one_pedal_braking: + at_full_stop = at_full_stop or CS.out.cruiseState.standstill + near_stop = near_stop or CS.out.vEgo < self.params.NEAR_STOP_BRAKE_PHASE + # Resume releases only the gas/regen ACC-state bit; friction remains separately owned. acc_engaged = CC.enabled and not volt_sng_release( self.CP, self.volt_sng, CC, CS, now_nanos, @@ -641,7 +685,8 @@ class CarController(CarControllerBase): at_full_stop = CS.out.cruiseState.standstill near_stop = CS.out.vEgo < self.params.NEAR_STOP_BRAKE_PHASE can_sends.append(gmcan.create_friction_brake_command(self.packer_ch, friction_brake_bus, self.apply_brake, - idx, CC.enabled, near_stop, at_full_stop, self.CP, auto_hold=hold_brake is not None)) + idx, CC.enabled, near_stop, at_full_stop, self.CP, + auto_hold=hold_brake is not None or one_pedal_braking)) CS.gm_auto_hold_engaged = hold_brake is not None if self.bolt_euv_long: @@ -708,7 +753,7 @@ class CarController(CarControllerBase): if self.cancel_counter > CAMERA_CANCEL_DELAY_FRAMES and (not cc_gateway or (button_fresh and stock_cruise_fresh and CS.out.cruiseState.available and CS.out.cruiseState.enabled)): self.last_button_frame = self.frame - cancel_bus = (CanBus.POWERTRAIN if cc_gateway or self.CP.safetyConfigs[0].safetyParam & GMSafetyFlags.SDGM_CANCEL_PT.value + cancel_bus = (CanBus.POWERTRAIN if cc_gateway or gm_control_word(self.CP) & GMSafetyFlags.SDGM_CANCEL_PT.value else CanBus.CAMERA) can_sends.append(gmcan.create_buttons(self.packer_pt, cancel_bus, CS.buttons_counter, CruiseButtons.CANCEL)) diff --git a/opendbc_repo/opendbc/car/gm/carstate.py b/opendbc_repo/opendbc/car/gm/carstate.py index 6e500ff18b..a13a955338 100644 --- a/opendbc_repo/opendbc/car/gm/carstate.py +++ b/opendbc_repo/opendbc/car/gm/carstate.py @@ -1,3 +1,4 @@ +from opendbc.car.gm.values import gm_control_word, is_volt_one_pedal from opendbc.car.gm.values import is_volt_longitudinal, is_gm_auto_hold from opendbc.car.gm.auto_hold import config_for as auto_hold_config_for, stopped_for_hold import copy @@ -66,6 +67,10 @@ class CarState(CarStateBase): self.gm_auto_hold_wheel_ns = 0 self.gm_auto_hold_unavailable = True self.gm_auto_hold_engaged = False + self.volt_one_pedal_mode = False + self.volt_one_pedal_mode_ns = 0 + self.volt_one_pedal_moving = False + self.volt_one_pedal_stopped = False self.cc_gateway_cruise_ts_nanos = 0 self.cc_gateway_buttons_ts_nanos = 0 self.camera_stock_status_ts_nanos = 0 @@ -200,8 +205,8 @@ class CarState(CarStateBase): alternate = is_volt_gateway_alternate_brake(self.CP) or ( is_volt_camera_removed(self.CP) and bool(self.CP.flags & GMFlags.NO_ACCELERATOR_POS_MSG)) c9 = self.CP.networkLocation == NetworkLocation.fwdCamera and not ( - self.CP.safetyConfigs[0].safetyParam & (GMSafetyFlags.ASCM_INTERCEPT | GMSafetyFlags.SDGM) and - not self.CP.safetyConfigs[0].safetyParam & GMSafetyFlags.BRAKE_C9) + gm_control_word(self.CP) & (GMSafetyFlags.ASCM_INTERCEPT | GMSafetyFlags.SDGM) and + not gm_control_word(self.CP) & GMSafetyFlags.BRAKE_C9) brake = (("EBCMBrakePedalPosition", "BrakePedalPosition") if alternate else ("ECMEngineStatus", "BrakePressed") if c9 else ("ECMAcceleratorPos", "BrakePedalPos")) names = (("AcceleratorPedal2", "CruiseState", 100_000_000), @@ -219,8 +224,8 @@ class CarState(CarStateBase): alternate = is_volt_gateway_alternate_brake(self.CP) alternate_force = alternate or (is_volt_camera_removed(self.CP) and bool(self.CP.flags & GMFlags.NO_ACCELERATOR_POS_MSG)) c9 = self.CP.networkLocation == NetworkLocation.fwdCamera and ( - not self.CP.safetyConfigs[0].safetyParam & (GMSafetyFlags.ASCM_INTERCEPT | GMSafetyFlags.SDGM) or - bool(self.CP.safetyConfigs[0].safetyParam & GMSafetyFlags.BRAKE_C9)) + not gm_control_word(self.CP) & (GMSafetyFlags.ASCM_INTERCEPT | GMSafetyFlags.SDGM) or + bool(gm_control_word(self.CP) & GMSafetyFlags.BRAKE_C9)) brake_name, brake_signal = (("EBCMBrakePedalPosition", "BrakePedalPosition") if alternate else ("ECMEngineStatus", "BrakePressed") if c9 else ("ECMAcceleratorPos", "BrakePedalPos")) names = (("ECMEngineStatus", "CruiseMainOn"), ("ECMPRDNL2", "PRNDL2"), (brake_name, brake_signal), @@ -232,7 +237,7 @@ class CarState(CarStateBase): pt_cp.vl[name] self.gm_auto_hold_sources = tuple((pt_cp.ts_nanos[name][signal], 300_000_000) for name, signal in names) # C9 is pressed authority, never analog force; missing-BE profiles retain minimum hold. - absent_be = c9 and bool(self.CP.safetyConfigs[0].safetyParam & (GMSafetyFlags.ASCM_INTERCEPT | GMSafetyFlags.SDGM)) + absent_be = c9 and bool(gm_control_word(self.CP) & (GMSafetyFlags.ASCM_INTERCEPT | GMSafetyFlags.SDGM)) if alternate_force: self.gm_auto_hold_brake = pt_cp.vl["EBCMBrakePedalPosition"]["BrakePedalPosition"] / 208. if c9: @@ -247,6 +252,16 @@ class CarState(CarStateBase): self.gm_auto_hold_moving = wheels["RLWheelSpd"] >= 12 * .0311 and wheels["RRWheelSpd"] >= 12 * .0311 self.gm_auto_hold_wheel_ns = pt_cp.ts_nanos["EBCMWheelSpdRear"]["RLWheelSpd"] self.gm_auto_hold_unavailable = bool(pt_cp.vl["EBCMFrictionBrakeStatus"]["FrictionBrakeUnavailable"]) + if is_volt_one_pedal(self.CP): + gear = pt_cp.vl["ECMPRDNL2"] + low = gear["PRNDL2"] == 6 and not gear["ManualMode"] + mode_ns = pt_cp.ts_nanos["EVDriveMode"]["SinglePedalModeActive"] + mode_current = 0 < mode_ns <= pt_cp._last_update_nanos and pt_cp._last_update_nanos - mode_ns <= 300_000_000 + self.volt_one_pedal_mode_ns = pt_cp.ts_nanos["ECMPRDNL2"]["PRNDL2"] if low else mode_ns + self.volt_one_pedal_mode = low or (mode_current and bool(pt_cp.vl["EVDriveMode"]["SinglePedalModeActive"])) + rear = pt_cp.vl["EBCMWheelSpdRear"] + self.volt_one_pedal_moving = rear["RLWheelSpd"] > 10 * .0311 and rear["RRWheelSpd"] > 10 * .0311 + self.volt_one_pedal_stopped = rear["RLWheelSpd"] <= 10 * .0311 and rear["RRWheelSpd"] <= 10 * .0311 self.pscm_status = copy.copy(pt_cp.vl["PSCMStatus"]) # Variables used for avoiding LKAS faults @@ -283,9 +298,9 @@ class CarState(CarStateBase): else: ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(pt_cp.vl["ECMPRDNL2"]["PRNDL2"], None)) - source_be_brake = (self.CP.safetyConfigs[0].safetyParam & + source_be_brake = (gm_control_word(self.CP) & (GMSafetyFlags.ASCM_INTERCEPT | GMSafetyFlags.SDGM).value and - not self.CP.safetyConfigs[0].safetyParam & GMSafetyFlags.BRAKE_C9.value) + not gm_control_word(self.CP) & GMSafetyFlags.BRAKE_C9.value) if is_conventional_cc_pedal_profile(self.CP) and self.CP.carFingerprint == CAR.CHEVROLET_MALIBU_CC: ret.brakePressed = (pt_cp.vl["EBCMBrakePedalPosition"]["BrakePedalPosition"] / 0xD0 >= .10 if self.CP.flags & GMFlags.NO_ACCELERATOR_POS_MSG else @@ -451,6 +466,8 @@ class CarState(CarStateBase): hold_sources_current and not self.gm_auto_hold_unavailable and self.gm_auto_hold_forward and ret.cruiseState.available and hold_stopped and not ret.gasPressed and not ret.regenBraking) + if is_volt_one_pedal(self.CP) and int(self.CP.safetyConfigs[0].safetyParam) < 0xD110: + hold_current = hold_current and self.volt_one_pedal_mode and self.volt_one_pedal_stopped and not ret.brakePressed if not hold_current: self.gm_auto_hold_engaged = False ret.brakeHoldActive = bool(hold_current and self.gm_auto_hold_engaged and ret.standstill) @@ -468,6 +485,8 @@ class CarState(CarStateBase): pt_messages.append(("ECMAcceleratorPos", 10)) if is_volt_gateway_alternate_brake(CP): pt_messages.append(("EBCMBrakePedalPosition", 100)) + if is_volt_one_pedal(CP): + pt_messages.append(("EVDriveMode", float('nan'))) if CP.carFingerprint in VOLT_BSM_CAR and CP.flags & GMFlags.HAS_BSM.value: pt_messages.append(("BCMBlindSpotMonitor", float('nan'))) if CP.flags & GMFlags.PEDAL_LONG.value: @@ -490,7 +509,7 @@ class CarState(CarStateBase): ("BCMDoorBeltStatus", 10), ("BCMGeneralPlatformStatus", 10), ("ASCMSteeringButton", 33), ] - if not CP.safetyConfigs[0].safetyParam & GMSafetyFlags.BRAKE_C9.value: + if not gm_control_word(CP) & GMSafetyFlags.BRAKE_C9.value: pt_messages.append(("ECMAcceleratorPos", 80)) if (CP.carFingerprint in CC_GATEWAY_STOCK_CAR or CP.carFingerprint == CAR.CHEVROLET_VOLT_CC): # No camera or ACC status dependency on this gateway conventional-cruise path. @@ -538,7 +557,7 @@ class CarState(CarStateBase): ("ECMEngineStatus", 100), ("AcceleratorPedal2", 33), ("ECMPRDNL2", 10), ("EBCMWheelSpdRear", 20), ("EBCMRegenPaddle", 40)] - if CP.carFingerprint == CAR.CHEVROLET_VOLT_2019 and CP.safetyConfigs[0].safetyParam & GMSafetyFlags.BRAKE_C9.value: + if CP.carFingerprint == CAR.CHEVROLET_VOLT_2019 and gm_control_word(CP) & GMSafetyFlags.BRAKE_C9.value: pt_messages = [(name, frequency) for name, frequency in pt_messages if name != "ECMAcceleratorPos"] if is_conventional_cc_pedal_profile(CP): diff --git a/opendbc_repo/opendbc/car/gm/lateral.py b/opendbc_repo/opendbc/car/gm/lateral.py index f21db793dc..934ce92fb8 100644 --- a/opendbc_repo/opendbc/car/gm/lateral.py +++ b/opendbc_repo/opendbc/car/gm/lateral.py @@ -1,3 +1,4 @@ +from opendbc.car.gm.values import gm_control_word """Exact finalized GM configurations for shared lateral preferences.""" import math from opendbc.car.structs import CarParams @@ -35,7 +36,7 @@ def lane_centering_supported(cp) -> bool: if (len(cp.safetyConfigs) != 1 or cp.safetyConfigs[0].safetyModel != CarParams.SafetyModel.gm or cp.networkLocation != CarParams.NetworkLocation.fwdCamera or control_flags(cp) != 0): return False - word = int(cp.safetyConfigs[0].safetyParam) + word = gm_control_word(cp) if cp.carFingerprint == CAR.CHEVROLET_VOLT_CAMERA: return ((word == 5 and cp.pcmCruise and not cp.openpilotLongitudinalControl) or (word in (0x4007, 0x4087) and not cp.pcmCruise and cp.openpilotLongitudinalControl and cp.alphaLongitudinalAvailable)) diff --git a/opendbc_repo/opendbc/car/gm/one_pedal.py b/opendbc_repo/opendbc/car/gm/one_pedal.py new file mode 100644 index 0000000000..b3b50c83f0 --- /dev/null +++ b/opendbc_repo/opendbc/car/gm/one_pedal.py @@ -0,0 +1,80 @@ +"""Volt moving one-pedal braking with vehicle-owned physical admission.""" +import math + +import numpy as np + +from opendbc.car import ACCELERATION_DUE_TO_GRAVITY +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.gm.values import CAR + + +class _VoltPid: + # Original openpilot/common/pid.py arithmetic, with unused derivative/override API removed. + def __init__(self, kp, ki): + self.kp, self.ki = kp, ki + self.reset() + + def reset(self): + self.i = 0.0 + + def update(self, error, *, speed, feedforward): + proportional = float(np.interp(speed, *self.kp)) * error + integral = self.i + float(np.interp(speed, *self.ki)) * 0.04 * error + candidate = proportional + integral + feedforward + upper = self.i if candidate > 0.0 else 0.0 + lower = self.i if candidate < -3.5 else -3.5 + self.i = float(np.clip(integral, lower, upper)) + return float(np.clip(proportional + self.i + feedforward, -3.5, 0.0)) + + +class VoltOnePedal: + def __init__(self, cp, params): + self.params = params + self.stopping_speed = .75 if cp.carFingerprint == CAR.CHEVROLET_VOLT else .25 + self.pid = _VoltPid(((0.,), (0.,)), + (cp.longitudinalTuning.kiBP, cp.longitudinalTuning.kiV)) + self.decel = 0.0 + self.brake = 0 + self.lift_frames = 0 + self.gas_last = False + + def observe(self, *, eligible, gas_pressed, speed): + # Called at controller cadence; preserve a gas-release edge until the next 25 Hz sender. + if eligible and self.gas_last and not gas_pressed and speed < 2.0 * CV.MPH_TO_MS: + self.lift_frames = 8 + elif gas_pressed or not eligible: + self.lift_frames = 0 + self.gas_last = gas_pressed + + def update(self, *, eligible, speed, acceleration, steering_angle, orientation): + # Called only at the existing gas/friction sender cadence, with qualified physical inputs. + finite = all(math.isfinite(value) for value in (speed, acceleration, steering_angle, *orientation)) + if not eligible or not finite or speed < 0: + self.pid.reset() + self.decel = min(0.0, acceleration) if math.isfinite(acceleration) else 0.0 + self.brake = 0 + self.lift_frames = 0 + return 0 + pitch_accel = 0.0 + if len(orientation) == 3 and speed > self.stopping_speed: + pitch_accel = math.sin(orientation[1]) * ACCELERATION_DUE_TO_GRAVITY + pitch_values = [0.4, 1.0] if pitch_accel <= 0 else [0.2, 1.0] + pitch_accel *= float(np.interp(speed, [4.0, 8.0], pitch_values)) + target = float(np.interp(speed, [0.5 * CV.MPH_TO_MS, 6.0 * CV.MPH_TO_MS], [-1.0, -1.1])) + measured = min(0.0, acceleration + pitch_accel) + error = (target - measured) * float(np.interp(speed, [1.5, 20.0], [0.4, 0.2])) + raw = float(self.pid.update(error, speed=speed, feedforward=target)) + factor = min(float(np.interp(speed, [0.0, 10.0 * CV.MPH_TO_MS], [0.2, 1.0])), + float(np.interp(abs(steering_angle), [20.0, 120.0], [1.0, 0.2]))) + lower = min(self.decel, measured) - 0.032 * factor + # Preserve the original asymmetric upper expression; this is not a tuning change. + upper = max(self.decel, measured) + 0.032 + factor + self.decel = max(float(np.clip(raw, lower, upper)), -2.1) + self.brake = int(round(np.clip(np.interp(self.decel, [self.params.ACCEL_MIN, 0.], + [self.params.MAX_BRAKE, 0.]), 0, self.params.MAX_BRAKE))) + if self.lift_frames > 0: + lift = 0 if speed > 2.0 * CV.MPH_TO_MS else int(round(np.interp( + speed, [0.0, self.params.NEAR_STOP_BRAKE_PHASE, 2.0 * CV.MPH_TO_MS], [80.0, 80.0, 20.0]))) + self.brake = max(self.brake, lift) + self.lift_frames -= 1 + return self.brake diff --git a/opendbc_repo/opendbc/car/gm/startup_preferences.py b/opendbc_repo/opendbc/car/gm/startup_preferences.py index 28cdeb27ff..7e9ed23e30 100644 --- a/opendbc_repo/opendbc/car/gm/startup_preferences.py +++ b/opendbc_repo/opendbc/car/gm/startup_preferences.py @@ -1,3 +1,4 @@ +from opendbc.car.gm.values import gm_control_word, is_volt_one_pedal """Finalized GM speed-control choices; existing native envelopes are retained.""" from opendbc.car.gm.values import (is_volt_gateway_profile, is_volt_cc_profile, is_ordinary_cc_profile, @@ -14,6 +15,8 @@ def disable_long_supported(cp) -> bool: def prepare_disable_longitudinal(cp, requested: bool) -> None: + if requested and is_volt_one_pedal(cp): + cp.safetyConfigs[0].safetyParam = gm_control_word(cp) if requested and is_volt_camera_removed(cp, longitudinal=True): cp.safetyConfigs[0].safetyParam = 0xC150 cp.openpilotLongitudinalControl = False diff --git a/opendbc_repo/opendbc/car/gm/tests/test_volt_alternate_brake.py b/opendbc_repo/opendbc/car/gm/tests/test_volt_alternate_brake.py index d27f571fea..542257a5af 100644 --- a/opendbc_repo/opendbc/car/gm/tests/test_volt_alternate_brake.py +++ b/opendbc_repo/opendbc/car/gm/tests/test_volt_alternate_brake.py @@ -11,7 +11,201 @@ from opendbc.car.gm.tests.test_bolt_volt_configurations import controller_messag from opendbc.car.gm.values import CAR, DBC, GMSafetyFlags, is_volt_gateway_alternate_brake +def one_pedal_profiles(*, release=False): + from opendbc.car.gm.tests.test_ascm_intercept import params as ascm_params + from opendbc.car.gm.tests.test_volt_camera_control import camera_params + from opendbc.car.gm.tests.test_volt_sdgm_control import sdgm_params + from opendbc.car.gm.tests.test_volt_camera_removed import removed_params + for be in (True, False): + yield f'gateway-{int(be)}', ordinary_params(CAR.CHEVROLET_VOLT, radar=True, accelerator=be), be + for be in (True, False): + for radar in (False, True): + yield (f'ascm-{int(be)}-{int(radar)}', ascm_params(CAR.CHEVROLET_VOLT_ASCM, sascm=True, alpha=True, + accelerator=be, radar=radar, release=release), be) + yield 'camera', camera_params(release=release), True + for c9 in (False, True): + yield f'sdgm-{int(c9)}', sdgm_params(brake_c9=c9, radar=True, release=release), True + for alternate in (False, True): + yield f'removed-{int(alternate)}', removed_params(alternate=alternate, release=release), not alternate + + class TestVoltAlternateBrake(unittest.TestCase): + def test_one_pedal_matches_pinned_original_scalar_histories(self): + import json + from pathlib import Path + from types import SimpleNamespace + from opendbc.car.gm.one_pedal import VoltOnePedal, _VoltPid + reference = json.loads(Path(__file__).with_name('volt_one_pedal_original_oracle.json').read_text()) + params = SimpleNamespace(**reference['params']) + for history in reference['histories']: + cp = SimpleNamespace(carFingerprint=CAR.CHEVROLET_VOLT_CAMERA, longitudinalTuning=SimpleNamespace( + kpBP=history['kp'][0], kpV=history['kp'][1], kiBP=history['ki'][0], kiV=history['ki'][1])) + controller = VoltOnePedal(cp, params) + controller.pid = _VoltPid(history['kp'], history['ki']) + controller.lift_frames = history['initial_lift_frames'] + for tick, step in enumerate(history['steps']): + with self.subTest(history=history['name'], tick=tick): + result = controller.update(**step['input']) + self.assertEqual(result, step['expected']['brake']) + self.assertAlmostEqual(controller.pid.i, step['expected']['integral'], places=12) + self.assertAlmostEqual(controller.decel, step['expected']['decel'], places=12) + self.assertEqual(controller.lift_frames, step['expected']['lift_frames']) + + def test_one_pedal_default_off_preserves_committed_sender_bytes(self): + import json + from pathlib import Path + from types import SimpleNamespace + from opendbc.car import structs + from opendbc.car.gm.interface import CarInterface + from opendbc.car.gm.tests.test_bolt_cc import feed, control + from opendbc.car.gm.values import is_volt_camera_removed + reference = json.loads(Path(__file__).with_name('volt_one_pedal_default_off.json').read_text()) + cases = list(one_pedal_profiles()) + self.assertEqual(len(cases), len(reference['profiles'])) + for (name, cp, be), baseline in zip(cases, reference['profiles'], strict=True): + with self.subTest(profile=name): + self.assertEqual((name, cp.carFingerprint, cp.safetyConfigs[0].safetyParam), + (baseline['name'], baseline['identity'], baseline['word'])) + ci = CarInterface(cp) + packer = CANPacker(DBC[cp.carFingerprint][Bus.pt]) + for tick, expected in enumerate(baseline['tx']): + now = 1_000_000_000 + tick * 10_000_000 + speed = 20. if tick < 40 or tick >= 100 else 0. if tick < 80 else 6. + active, brake, gas = tick < 60 or tick >= 90, 60 <= tick < 65, 65 <= tick < 70 + _, packets = feed(SimpleNamespace(update=lambda _: None), packer, now, counter=tick % 4, speed=speed, + brake=brake, gas=gas, camera=cp.networkLocation == structs.CarParams.NetworkLocation.fwdCamera and + not is_volt_camera_removed(cp)) + packets = [packet for packet in packets if packet[0] not in (0xBE, 0xF1, 0x1C4)] + packets.append(packer.make_can_msg('AcceleratorPedal2', 0, {'CruiseState': 2 if active else 0, + 'AcceleratorPedal2': 30 if gas else 0})) + if be: + packets.append(packer.make_can_msg('ECMAcceleratorPos', 0, {'BrakePedalPos': 20 if brake else 0})) + else: + packets.append(packer.make_can_msg('EBCMBrakePedalPosition', 0, {'BrakePedalPosition': 104 if brake else 0})) + if cp.networkLocation == structs.CarParams.NetworkLocation.fwdCamera and not is_volt_camera_removed(cp): + packets.append(packer.make_can_msg('ASCMActiveCruiseControlStatus', 2, {'ACCCruiseState': 3, 'ACCSpeedSetpoint': 60})) + ci.update([(now - 1_000_000, packets)]) + self.assertTrue(ci.update([(now, packets)]).canValid) + command = control(enabled=active, long_active=active) + command.latActive = active + command.actuators.accel = -.5 if tick < 40 else 1. + command.actuators.torque = .02 + _, messages = ci.apply(command.as_reader(), now) + self.assertEqual([[address, data.hex(), bus] for address, data, bus in messages], expected, (name, tick)) + + def test_one_pedal_actual_parser_controller_all_tx(self): + from tempfile import TemporaryDirectory + from types import SimpleNamespace + from opendbc.car import structs + from opendbc.car.gm.interface import CarInterface + from opendbc.car.gm.tests.test_bolt_cc import feed, setup, native + from opendbc.car.gm.values import gm_control_word, is_volt_camera_removed + from opendbc.safety.tests.libsafety import libsafety_py + from openpilot.common.params import Params + from openpilot.starpilot.controller_extensions import configure_controller + from openpilot.starpilot.vehicle_preferences import VehicleStartupPreferences + release = libsafety_py.libsafety.set_safety_hooks(structs.CarParams.SafetyModel.allOutput, 0) != 0 + indexes = {'gateway-1': 0, 'gateway-0': 1, 'ascm-1-0': 2, 'ascm-0-0': 3, + 'ascm-1-1': 4, 'ascm-0-1': 5, 'camera': 6, 'sdgm-0': 7, + 'sdgm-1': 8, 'removed-0': 9, 'removed-1': 10} + for name, original, be in one_pedal_profiles(release=release): + for paired in (False, True): + with self.subTest(profile=name, paired=paired), TemporaryDirectory() as directory: + cp = original.as_reader().as_builder() + params = Params(directory) + for key, value in [('OpenpilotEnabledToggle', True), ('VoltOnePedalMode', True), ('GMAutoHold', paired)]: + params.put_bool(key, value, block=True) + preferences = VehicleStartupPreferences.read(params, enabled=True) + preferences.prepare(cp) + preferences.finalize(cp) + if release and indexes[name] >= 2: + self.assertEqual(cp.safetyConfigs[0].safetyParam, original.safetyConfigs[0].safetyParam) + self._hold_release_factory(cp, camera=False, alternative=0) + continue + self.assertEqual(cp.safetyConfigs[0].safetyParam, 0xD100 + indexes[name] + (0x10 if paired else 0)) + self.assertNotEqual(gm_control_word(cp), cp.safetyConfigs[0].safetyParam) + ci = CarInterface(cp) + preferences.configure_controller(ci) + configure_controller(ci, params) + self.assertTrue(ci.CC.volt_one_pedal) + packer = CANPacker(DBC[cp.carFingerprint][Bus.pt]) + setup(cp) + self.assertEqual(libsafety_py.libsafety.set_safety_hooks(int(structs.CarParams.SafetyModel.gm), cp.safetyConfigs[0].safetyParam), 0) + removed = is_volt_camera_removed(cp) + positive = stopped_positive = immediate_release = False + for tick in range(2680 if name == 'gateway-1' and not paired else 940): + now = 1_000_000_000 + tick * 10_000_000 + stopped = 360 <= tick < 410 or 440 <= tick < 490 or 550 <= tick < 660 + regen = 410 <= tick < 420 + mode_off = 490 <= tick < 550 or 610 <= tick < 660 or 730 <= tick < 940 + manual = 760 <= tick < 800 + fault = 800 <= tick < 820 + physical_brake = 820 <= tick < 840 + unknown_gear = 840 <= tick < 860 + main_off = 860 <= tick < 880 + stale_status = 880 <= tick < 940 + live_changes = {1280: ('VoltOnePedalMode', False), 1320: ('VoltOnePedalMode', True), + 1720: ('OpenpilotEnabledToggle', False), 1760: ('OpenpilotEnabledToggle', True), + 2160: ('SafeMode', True), 2200: ('SafeMode', False), + 2600: ('DisableOpenpilotLongitudinal', True)} + if tick in live_changes: + key, value = live_changes[tick] + params.put_bool(key, value, block=True) + live_withdrawn = 1305 <= tick < 1320 or 1745 <= tick < 1760 or 2185 <= tick < 2200 or tick >= 2625 + gas = 310 <= tick < 320 + speed = 0. if stopped else .15 if 420 <= tick < 440 else .5 if tick >= 310 else 2. + _, rx = feed(SimpleNamespace(update=lambda _: None), packer, now, speed=speed, gas=gas, regen=regen, + camera=cp.networkLocation == structs.CarParams.NetworkLocation.fwdCamera and not removed) + rx = [message for message in rx if message[0] not in (0xBE, 0xF1, 0x1C4, 0xC9, 0x1F5, 0x232)] + brake_name, signal = ('ECMAcceleratorPos', 'BrakePedalPos') if be else ('EBCMBrakePedalPosition', 'BrakePedalPosition') + rx += [packer.make_can_msg(brake_name, 0, {signal: 20 if physical_brake else 0}), + packer.make_can_msg('AcceleratorPedal2', 0, {'CruiseState': 4 if stopped else 2, 'AcceleratorPedal2': 30 if gas else 0}), + packer.make_can_msg('ECMEngineStatus', 0, {'CruiseMainOn': int(not main_off), 'BrakePressed': int(physical_brake)}), + packer.make_can_msg('ECMPRDNL2', 0, {'PRNDL2': 8 if unknown_gear else + 6 if manual or not mode_off and (tick < 660 or tick >= 940) else 4, 'ManualMode': int(manual)}), + packer.make_can_msg('EBCMFrictionBrakeStatus', 0, {'FrictionBrakeUnavailable': int(fault)})] + if 660 <= tick < 700: + rx.append(packer.make_can_msg('EVDriveMode', 0, {'SinglePedalModeActive': 1})) + if stale_status: + rx = [message for message in rx if message[0] != 0x232] + if cp.networkLocation == structs.CarParams.NetworkLocation.fwdCamera and not removed: + rx.append(packer.make_can_msg('ASCMActiveCruiseControlStatus', 2, {'ACCCruiseState': 3, 'ACCSpeedSetpoint': 60})) + ci.update([(now - 1_000_000, rx)]) + out = ci.update([(now, rx)]) + if not stale_status: + self.assertTrue(out.canValid, (name, tick)) + self.assertEqual(ci.CS.volt_one_pedal_mode, not mode_off, tick) + for message in rx: + native('rx', message, now // 1000) + libsafety_py.libsafety.safety_tick() + _, commands = ci.apply(structs.CarControl(enabled=False, longActive=False).as_reader(), now) + for message in commands: + self.assertTrue(native('tx', message, now // 1000), (name, paired, tick, message)) + brakes = [message for message in commands if message[0] == 0x315] + self.assertLessEqual(len(brakes), 1) + if not brakes: + continue + data = brakes[0][1] + self.assertEqual(int.from_bytes(data[2:4], 'big'), + (0x10000 - int.from_bytes(data[:2], 'big') - (data[4] & 3)) & 0xFFFF) + amount = (0x1000 - (((data[0] & 15) << 8) | data[1])) & 0xFFF + if (gas or regen or tick < 300 or mode_off and not paired or fault or physical_brake or + unknown_gear or main_off or 910 <= tick < 940 or live_withdrawn): + self.assertEqual(amount, 0, (name, paired, tick)) + if tick in (1260, 1716, 2156, 2596): + self.assertGreater(amount, 0, (name, paired, tick)) + if 330 <= tick < 360 and amount: + positive = True + if 390 <= tick < 410 and amount: + stopped_positive = True + self.assertEqual(data[0] >> 4, 0xD) + self.assertFalse(any(message[0] == 0x2CB for message in commands)) + if 420 <= tick < 440 and amount: + immediate_release = True + if out.vEgo < ci.CC.params.NEAR_STOP_BRAKE_PHASE: + self.assertEqual(data[0] >> 4, 0xB) + self.assertTrue(positive and stopped_positive and immediate_release, (name, paired)) + def test_auto_hold_actual_gateway_parser_controller_native(self): from itertools import product for accelerator, alternative in product((True, False), (0, 32)): diff --git a/opendbc_repo/opendbc/car/gm/tests/volt_one_pedal_default_off.json b/opendbc_repo/opendbc/car/gm/tests/volt_one_pedal_default_off.json new file mode 100644 index 0000000000..74ed36cbc0 --- /dev/null +++ b/opendbc_repo/opendbc/car/gm/tests/volt_one_pedal_default_off.json @@ -0,0 +1 @@ +{"source_commit":"d4beaba255","values_sha256":"97c63fd565e75bd6378b38f925c6eadf4d60894b1b914b36caeeb4d12517eb67","frames_per_profile":120,"profiles":[{"name":"gateway-1","identity":"CHEVROLET_VOLT","word":16388,"cp":{"brand":"gm","carFingerprint":"CHEVROLET_VOLT","deprecated":{"enableGasInterceptor":false,"enableCamera":false,"enableDsu":false,"enableApgs":false,"safetyModel":"silent","safetyParam":0,"steerLimitAlert":false,"vEgoStopping":0.0,"directAccelControl":false,"stoppingControl":false,"startAccel":0.0,"steerRateCost":0.0,"isPandaBlack":false,"safetyModelPassive":"silent","radarTimeStep":0.05000000074505806,"communityFeature":false,"minSpeedCan":0.0,"stoppingDecelRate":0.0,"startingAccelRate":0.0,"maxSteeringAngleDeg":0.0,"enableBsm":false,"hasStockCamera":false,"vEgoStarting":0.0,"longitudinalActuatorDelayLowerBound":0.0,"startingState":false},"pcmCruise":false,"minEnableSpeed":-1.0,"minSteerSpeed":3.1292800903320312,"mass":1743.0,"wheelbase":2.690000057220459,"centerToFront":1.2105000019073486,"steerRatio":15.699999809265137,"steerRatioRear":0.0,"rotationalInertia":2958.46923828125,"tireStiffnessFront":209991.5625,"tireStiffnessRear":271598.625,"longitudinalTuning":{"deprecated":{"kf":0.0},"kiBP":[5.0,35.0],"kiV":[0.5,0.5]},"lateralTuning":{"torque":{"deprecated":{"useSteeringAngle":false,"kp":0.0,"ki":0.0,"kf":0.0,"kd":0.0},"friction":0.1572393923997879,"steeringAngleDeadzoneDeg":0.0,"latAccelFactor":1.5961527824401855,"latAccelOffset":0.0}},"steerControlType":"torque","radarUnavailable":false,"steerActuatorDelay":0.20000000298023224,"openpilotLongitudinalControl":true,"dashcamOnly":false,"transmissionType":"direct","steerLimitTimer":0.4000000059604645,"fingerprintSource":"can","networkLocation":"gateway","fuzzyFingerprint":false,"longitudinalActuatorDelay":0.5,"stopAccel":-1.5,"safetyConfigs":[{"safetyModel":"gm","deprecated":{"safetyParam":0,"safetyParam2":0},"safetyParam":16388}],"wheelSpeedFactor":1.0,"flags":16,"alternativeExperience":0,"notCar":false,"maxLateralAccel":1.842265248298645,"autoResumeSng":false,"alphaLongitudinalAvailable":false,"tireStiffnessFactor":1.0,"passive":false,"radarDelay":0.0,"secOcRequired":false,"secOcKeyAvailable":false,"steerAtStandstill":false},"tx":[[[715,"0142b95000bd46b0",0],[789,"1000f00000",2],[880,"010086c00100",0],[161,"00000000400012",1],[784,"4204",1],[774,"00f0200000000170",1],[776,"0813f00000116e",1],[1033,"00000000000000",0],[1034,"00000000000000",0]],[],[[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[[384,"180607f9",0]],[[715,"4142b95000bd46af",0],[789,"1000efff01",2],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[],[[384,"180607f9",0],[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[],[[715,"8142b95000bd46ae",0],[789,"1000effe02",2],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0813f00000116e",1]],[[384,"180607f9",0]],[[161,"000000644f9c12",1],[784,"4204",1],[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[],[[384,"180607f9",0],[715,"c142b95000bd46ad",0],[789,"1000effd03",2],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[],[[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[[384,"180607f9",0]],[[715,"0142b95000bd46b0",0],[789,"1000f00000",2],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0813f00000116e",1]],[],[[384,"180607f9",0],[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[],[[715,"4142b95000bd46af",0],[789,"1000efff01",2],[880,"010086c00100",0],[161,"000000c84f3812",1],[784,"4204",1],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[[384,"180607f9",0]],[[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[],[[384,"180607f9",0],[715,"8142b95000bd46ae",0],[789,"1000effe02",2],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0813f00000116e",1]],[],[[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[[384,"180607f9",0]],[[715,"c142b95000bd46ad",0],[789,"1000effd03",2],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[],[[384,"180607f9",0],[161,"0000012c4fd312",1],[784,"4204",1],[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[],[[715,"0142b95000bd46b0",0],[789,"1000f00000",2],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0813f00000116e",1]],[[384,"180607f9",0]],[[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[],[[384,"180607f9",0],[715,"4142b95000bd46af",0],[789,"1000efff01",2],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[],[[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[[384,"180607f9",0]],[[715,"8162e010009d1fee",0],[789,"1000effe02",2],[880,"010086c00100",0],[161,"000001804f7f12",1],[784,"4204",1],[774,"00f0200000000170",1],[776,"0800000000086a",1]],[],[[384,"180607f9",0],[774,"40f02000000001b0",1],[776,"0800000000286e",1]],[],[[715,"c162e010009d1fed",0],[789,"1000effd03",2],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"08000000004872",1]],[[384,"180607f9",0]],[[774,"c0f0200000000230",1],[776,"08000000006876",1]],[],[[384,"180607f9",0],[715,"0162e010009d1ff0",0],[789,"1000f00000",2],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0800000000086a",1]],[],[[161,"000001e44f1b12",1],[784,"4204",1],[774,"40f02000000001b0",1],[776,"0800000000286e",1]],[[384,"180607f9",0]],[[715,"4162e010009d1fef",0],[789,"1000efff01",2],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"08000000004872",1]],[],[[384,"180607f9",0],[774,"c0f0200000000230",1],[776,"08000000006876",1]],[],[[715,"8162e010009d1fee",0],[789,"1000effe02",2],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0800000000086a",1]],[[384,"180607f9",0]],[[774,"40f02000000001b0",1],[776,"0800000000286e",1]],[],[[715,"c042abe001bd541d",0],[789,"1000effd03",2],[880,"010006c00100",0],[161,"000002484fb612",1],[784,"4204",1],[774,"80f02000000001f0",1],[776,"08000000004872",1]],[],[[774,"c0f0200000000230",1],[776,"08000000006876",1]],[],[[715,"0042abe001bd5420",0],[789,"1000f00000",2],[880,"010006c00100",0],[774,"00f0200000000170",1],[776,"0800000000086a",1]],[],[[774,"40f02000000001b0",1],[776,"0800000000286e",1]],[[384,"10000fff",0]],[[715,"4042abe001bd541f",0],[789,"1000efff01",2],[880,"010006c00100",0],[774,"80f02000000001f0",1],[776,"08000000004872",1]],[],[[161,"000002ac4f5212",1],[784,"4204",1],[774,"c0f0200000000230",1],[776,"08000000006876",1]],[],[[715,"8042abe001bd541e",0],[789,"1000effe02",2],[880,"010006c00100",0],[774,"00f0200000000170",1],[776,"0800000000086a",1]],[],[[774,"40f02000000001b0",1],[776,"0800000000286e",1]],[],[[715,"c042abe001bd541d",0],[789,"1000effd03",2],[880,"010006c00100",0],[774,"80f02000000001f0",1],[776,"08000000004872",1]],[[384,"10000fff",0]],[[774,"c0f0200000000230",1],[776,"08000000006876",1]],[],[[715,"0042abe001bd5420",0],[789,"1000f00000",2],[880,"010006c00100",0],[161,"000003004ffd12",1],[784,"4204",1],[774,"00f0200000000170",1],[776,"08060000001071",1]],[],[[774,"40f02000000001b0",1],[776,"08060000003075",1]],[],[[715,"4042abe001bd541f",0],[789,"1000efff01",2],[880,"010006c00100",0],[774,"80f02000000001f0",1],[776,"08060000005079",1]],[],[[774,"c0f0200000000230",1],[776,"0806000000707d",1]],[[384,"10000fff",0]],[[715,"8042abe001bd541e",0],[789,"1000effe02",2],[880,"010006c00100",0],[774,"00f0200000000170",1],[776,"08060000001071",1]],[],[[384,"180607f9",0],[161,"000003644f9912",1],[784,"4204",1],[774,"40f02000000001b0",1],[776,"08060000003075",1]],[],[[715,"c142e07000bd1f8d",0],[789,"1000effd03",2],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"08060000005079",1]],[[384,"180607f9",0]],[[774,"c0f0200000000230",1],[776,"0806000000707d",1]],[],[[384,"180607f9",0],[715,"0142e07000bd1f90",0],[789,"1000f00000",2],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"08060000001071",1]],[],[[774,"40f02000000001b0",1],[776,"08060000003075",1]],[[384,"180607f9",0]],[[715,"4142e3f800bd1c07",0],[789,"1000efff01",2],[880,"010086c00100",0],[161,"000003c84f3512",1],[784,"4204",1],[774,"80f02000000001f0",1],[776,"0813f000005176",1],[1033,"00000000000000",0],[1034,"00000000000000",0]],[],[[384,"180607f9",0],[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[],[[715,"8142e3f800bd1c06",0],[789,"1000effe02",2],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0813f00000116e",1]],[[384,"180607f9",0]],[[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[],[[384,"180607f9",0],[715,"c142e3f800bd1c05",0],[789,"1000effd03",2],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[],[[161,"0000042c4fd012",1],[784,"4204",1],[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[[384,"180607f9",0]],[[715,"0142e3f800bd1c08",0],[789,"1000f00000",2],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0813f00000116e",1]],[],[[384,"180607f9",0],[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[],[[715,"4142e3f800bd1c07",0],[789,"1000efff01",2],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[[384,"180607f9",0]],[[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[]]},{"name":"gateway-0","identity":"CHEVROLET_VOLT","word":49156,"cp":{"brand":"gm","carFingerprint":"CHEVROLET_VOLT","deprecated":{"enableGasInterceptor":false,"enableCamera":false,"enableDsu":false,"enableApgs":false,"safetyModel":"silent","safetyParam":0,"steerLimitAlert":false,"vEgoStopping":0.0,"directAccelControl":false,"stoppingControl":false,"startAccel":0.0,"steerRateCost":0.0,"isPandaBlack":false,"safetyModelPassive":"silent","radarTimeStep":0.05000000074505806,"communityFeature":false,"minSpeedCan":0.0,"stoppingDecelRate":0.0,"startingAccelRate":0.0,"maxSteeringAngleDeg":0.0,"enableBsm":false,"hasStockCamera":false,"vEgoStarting":0.0,"longitudinalActuatorDelayLowerBound":0.0,"startingState":false},"pcmCruise":false,"minEnableSpeed":-1.0,"minSteerSpeed":3.1292800903320312,"mass":1743.0,"wheelbase":2.690000057220459,"centerToFront":1.2105000019073486,"steerRatio":15.699999809265137,"steerRatioRear":0.0,"rotationalInertia":2958.46923828125,"tireStiffnessFront":209991.5625,"tireStiffnessRear":271598.625,"longitudinalTuning":{"deprecated":{"kf":0.0},"kiBP":[5.0,35.0],"kiV":[0.5,0.5]},"lateralTuning":{"torque":{"deprecated":{"useSteeringAngle":false,"kp":0.0,"ki":0.0,"kf":0.0,"kd":0.0},"friction":0.1572393923997879,"steeringAngleDeadzoneDeg":0.0,"latAccelFactor":1.5961527824401855,"latAccelOffset":0.0}},"steerControlType":"torque","radarUnavailable":false,"steerActuatorDelay":0.20000000298023224,"openpilotLongitudinalControl":true,"dashcamOnly":false,"transmissionType":"direct","steerLimitTimer":0.4000000059604645,"fingerprintSource":"can","networkLocation":"gateway","fuzzyFingerprint":false,"longitudinalActuatorDelay":0.5,"stopAccel":-1.5,"safetyConfigs":[{"safetyModel":"gm","deprecated":{"safetyParam":0,"safetyParam2":0},"safetyParam":49156}],"wheelSpeedFactor":1.0,"flags":16,"alternativeExperience":0,"notCar":false,"maxLateralAccel":1.842265248298645,"autoResumeSng":false,"alphaLongitudinalAvailable":false,"tireStiffnessFactor":1.0,"passive":false,"radarDelay":0.0,"secOcRequired":false,"secOcKeyAvailable":false,"steerAtStandstill":false},"tx":[[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0],[161,"00000000400012",1],[784,"4204",1],[774,"00f0200000000170",1],[776,"0813f00000116e",1],[1033,"00000000000000",0],[1034,"00000000000000",0]],[],[[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[[384,"180607f9",0]],[[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[],[[384,"180607f9",0],[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[],[[715,"8142b95000bd46ae",0],[789,"1000effe02",0],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0813f00000116e",1]],[[384,"180607f9",0]],[[161,"000000644f9c12",1],[784,"4204",1],[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[],[[384,"180607f9",0],[715,"c142b95000bd46ad",0],[789,"1000effd03",0],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[],[[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[[384,"180607f9",0]],[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0813f00000116e",1]],[],[[384,"180607f9",0],[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[],[[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0],[161,"000000c84f3812",1],[784,"4204",1],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[[384,"180607f9",0]],[[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[],[[384,"180607f9",0],[715,"8142b95000bd46ae",0],[789,"1000effe02",0],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0813f00000116e",1]],[],[[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[[384,"180607f9",0]],[[715,"c142b95000bd46ad",0],[789,"1000effd03",0],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[],[[384,"180607f9",0],[161,"0000012c4fd312",1],[784,"4204",1],[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[],[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0813f00000116e",1]],[[384,"180607f9",0]],[[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[],[[384,"180607f9",0],[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[],[[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[[384,"180607f9",0]],[[715,"8162e010009d1fee",0],[789,"1000effe02",0],[880,"010086c00100",0],[161,"000001804f7f12",1],[784,"4204",1],[774,"00f0200000000170",1],[776,"0800000000086a",1]],[],[[384,"180607f9",0],[774,"40f02000000001b0",1],[776,"0800000000286e",1]],[],[[715,"c162e010009d1fed",0],[789,"1000effd03",0],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"08000000004872",1]],[[384,"180607f9",0]],[[774,"c0f0200000000230",1],[776,"08000000006876",1]],[],[[384,"180607f9",0],[715,"0162e010009d1ff0",0],[789,"1000f00000",0],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0800000000086a",1]],[],[[161,"000001e44f1b12",1],[784,"4204",1],[774,"40f02000000001b0",1],[776,"0800000000286e",1]],[[384,"180607f9",0]],[[715,"4162e010009d1fef",0],[789,"1000efff01",0],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"08000000004872",1]],[],[[384,"180607f9",0],[774,"c0f0200000000230",1],[776,"08000000006876",1]],[],[[715,"8162e010009d1fee",0],[789,"1000effe02",0],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0800000000086a",1]],[[384,"180607f9",0]],[[774,"40f02000000001b0",1],[776,"0800000000286e",1]],[],[[715,"c042abe001bd541d",0],[789,"1000effd03",0],[880,"010006c00100",0],[161,"000002484fb612",1],[784,"4204",1],[774,"80f02000000001f0",1],[776,"08000000004872",1]],[],[[774,"c0f0200000000230",1],[776,"08000000006876",1]],[],[[715,"0042abe001bd5420",0],[789,"1000f00000",0],[880,"010006c00100",0],[774,"00f0200000000170",1],[776,"0800000000086a",1]],[],[[774,"40f02000000001b0",1],[776,"0800000000286e",1]],[[384,"10000fff",0]],[[715,"4042abe001bd541f",0],[789,"1000efff01",0],[880,"010006c00100",0],[774,"80f02000000001f0",1],[776,"08000000004872",1]],[],[[161,"000002ac4f5212",1],[784,"4204",1],[774,"c0f0200000000230",1],[776,"08000000006876",1]],[],[[715,"8042abe001bd541e",0],[789,"1000effe02",0],[880,"010006c00100",0],[774,"00f0200000000170",1],[776,"0800000000086a",1]],[],[[774,"40f02000000001b0",1],[776,"0800000000286e",1]],[],[[715,"c042abe001bd541d",0],[789,"1000effd03",0],[880,"010006c00100",0],[774,"80f02000000001f0",1],[776,"08000000004872",1]],[[384,"10000fff",0]],[[774,"c0f0200000000230",1],[776,"08000000006876",1]],[],[[715,"0042abe001bd5420",0],[789,"1000f00000",0],[880,"010006c00100",0],[161,"000003004ffd12",1],[784,"4204",1],[774,"00f0200000000170",1],[776,"08060000001071",1]],[],[[774,"40f02000000001b0",1],[776,"08060000003075",1]],[],[[715,"4042abe001bd541f",0],[789,"1000efff01",0],[880,"010006c00100",0],[774,"80f02000000001f0",1],[776,"08060000005079",1]],[],[[774,"c0f0200000000230",1],[776,"0806000000707d",1]],[[384,"10000fff",0]],[[715,"8042abe001bd541e",0],[789,"1000effe02",0],[880,"010006c00100",0],[774,"00f0200000000170",1],[776,"08060000001071",1]],[],[[384,"180607f9",0],[161,"000003644f9912",1],[784,"4204",1],[774,"40f02000000001b0",1],[776,"08060000003075",1]],[],[[715,"c142e07000bd1f8d",0],[789,"1000effd03",0],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"08060000005079",1]],[[384,"180607f9",0]],[[774,"c0f0200000000230",1],[776,"0806000000707d",1]],[],[[384,"180607f9",0],[715,"0142e07000bd1f90",0],[789,"1000f00000",0],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"08060000001071",1]],[],[[774,"40f02000000001b0",1],[776,"08060000003075",1]],[[384,"180607f9",0]],[[715,"4142e3f800bd1c07",0],[789,"1000efff01",0],[880,"010086c00100",0],[161,"000003c84f3512",1],[784,"4204",1],[774,"80f02000000001f0",1],[776,"0813f000005176",1],[1033,"00000000000000",0],[1034,"00000000000000",0]],[],[[384,"180607f9",0],[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[],[[715,"8142e3f800bd1c06",0],[789,"1000effe02",0],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0813f00000116e",1]],[[384,"180607f9",0]],[[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[],[[384,"180607f9",0],[715,"c142e3f800bd1c05",0],[789,"1000effd03",0],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[],[[161,"0000042c4fd012",1],[784,"4204",1],[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[[384,"180607f9",0]],[[715,"0142e3f800bd1c08",0],[789,"1000f00000",0],[880,"010086c00100",0],[774,"00f0200000000170",1],[776,"0813f00000116e",1]],[],[[384,"180607f9",0],[774,"40f02000000001b0",1],[776,"0813f000003172",1]],[],[[715,"4142e3f800bd1c07",0],[789,"1000efff01",0],[880,"010086c00100",0],[774,"80f02000000001f0",1],[776,"0813f000005176",1]],[[384,"180607f9",0]],[[774,"c0f0200000000230",1],[776,"0813f00000717a",1]],[]]},{"name":"ascm-1-0","identity":"CHEVROLET_VOLT_ASCM","word":16903,"cp":{"brand":"gm","carFingerprint":"CHEVROLET_VOLT_ASCM","deprecated":{"enableGasInterceptor":false,"enableCamera":false,"enableDsu":false,"enableApgs":false,"safetyModel":"silent","safetyParam":0,"steerLimitAlert":false,"vEgoStopping":0.0,"directAccelControl":false,"stoppingControl":false,"startAccel":0.0,"steerRateCost":0.0,"isPandaBlack":false,"safetyModelPassive":"silent","radarTimeStep":0.05000000074505806,"communityFeature":false,"minSpeedCan":0.0,"stoppingDecelRate":0.0,"startingAccelRate":0.0,"maxSteeringAngleDeg":0.0,"enableBsm":false,"hasStockCamera":false,"vEgoStarting":0.0,"longitudinalActuatorDelayLowerBound":0.0,"startingState":false},"pcmCruise":false,"minEnableSpeed":1.3888888359069824,"minSteerSpeed":3.1292800903320312,"mass":1743.0,"wheelbase":2.690000057220459,"centerToFront":1.2105000019073486,"steerRatio":15.699999809265137,"steerRatioRear":0.0,"rotationalInertia":2958.46923828125,"tireStiffnessFront":209991.5625,"tireStiffnessRear":271598.625,"longitudinalTuning":{"deprecated":{"kf":0.0},"kiBP":[5.0,35.0],"kiV":[0.5,0.5]},"lateralTuning":{"torque":{"deprecated":{"useSteeringAngle":false,"kp":0.0,"ki":0.0,"kf":0.0,"kd":0.0},"friction":0.1572393923997879,"steeringAngleDeadzoneDeg":0.0,"latAccelFactor":1.5961527824401855,"latAccelOffset":0.0}},"steerControlType":"torque","radarUnavailable":true,"steerActuatorDelay":0.20000000298023224,"openpilotLongitudinalControl":true,"dashcamOnly":false,"transmissionType":"direct","steerLimitTimer":0.4000000059604645,"fingerprintSource":"can","networkLocation":"fwdCamera","fuzzyFingerprint":false,"longitudinalActuatorDelay":0.5,"stopAccel":-0.25,"safetyConfigs":[{"safetyModel":"gm","deprecated":{"safetyParam":0,"safetyParam2":0},"safetyParam":16903}],"wheelSpeedFactor":1.0,"flags":16,"alternativeExperience":0,"notCar":false,"maxLateralAccel":1.842265248298645,"autoResumeSng":false,"alphaLongitudinalAvailable":true,"tireStiffnessFactor":1.0,"passive":false,"radarDelay":0.0,"secOcRequired":false,"secOcKeyAvailable":false,"steerAtStandstill":false},"tx":[[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[],[],[[384,"180607f9",0]],[[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142b95000bd46ae",0],[789,"1000effe02",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[[388,"0000200000200000",2]],[],[[384,"180607f9",0],[715,"c142b95000bd46ad",0],[789,"1000effd03",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"8142b95000bd46ae",0],[789,"1000effe02",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"c142b95000bd46ad",0],[789,"1000effd03",0],[880,"010086c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"8142e01000bd1fee",0],[789,"1000effe02",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"c142e01000bd1fed",0],[789,"1000effd03",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142e01000bd1ff0",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"4142e01000bd1fef",0],[789,"1000efff01",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142e01000bd1fee",0],[789,"1000effe02",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"10000fff",0],[715,"c042abe001bd541d",0],[789,"1000effd03",0],[880,"010006c00100",0],[388,"0000200000200000",2]],[],[],[[384,"10000fff",0]],[[715,"0042abe001bd5420",0],[789,"1000f00000",0],[880,"010006c00100",0]],[],[[384,"10000fff",0]],[],[[715,"4042abe001bd541f",0],[789,"1000efff01",0],[880,"010006c00100",0]],[[384,"10000fff",0]],[[388,"0000200000200000",2]],[],[[384,"10000fff",0],[715,"8042abe001bd541e",0],[789,"1000effe02",0],[880,"010006c00100",0]],[],[],[[384,"10000fff",0]],[[715,"c042abe001bd541d",0],[789,"1000effd03",0],[880,"010006c00100",0]],[],[[384,"10000fff",0]],[],[[715,"0042abe001bd5420",0],[789,"1000f00000",0],[880,"010006c00100",0],[388,"0000200000200000",2]],[[384,"10000fff",0]],[],[],[[384,"10000fff",0],[715,"4042abe001bd541f",0],[789,"1000efff01",0],[880,"010006c00100",0]],[],[],[[384,"10000fff",0]],[[715,"8042abe001bd541e",0],[789,"1000effe02",0],[880,"010006c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"c142e07000bd1f8d",0],[789,"1000effd03",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142e07000bd1f90",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"4142e3f800bd1c07",0],[789,"1000efff01",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"8142e3f800bd1c06",0],[789,"1000effe02",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"c142e3f800bd1c05",0],[789,"1000effd03",0],[880,"010086c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"0142e3f800bd1c08",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142e3f800bd1c07",0],[789,"1000efff01",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[]]},{"name":"ascm-1-1","identity":"CHEVROLET_VOLT_ASCM","word":18951,"cp":{"brand":"gm","carFingerprint":"CHEVROLET_VOLT_ASCM","deprecated":{"enableGasInterceptor":false,"enableCamera":false,"enableDsu":false,"enableApgs":false,"safetyModel":"silent","safetyParam":0,"steerLimitAlert":false,"vEgoStopping":0.0,"directAccelControl":false,"stoppingControl":false,"startAccel":0.0,"steerRateCost":0.0,"isPandaBlack":false,"safetyModelPassive":"silent","radarTimeStep":0.05000000074505806,"communityFeature":false,"minSpeedCan":0.0,"stoppingDecelRate":0.0,"startingAccelRate":0.0,"maxSteeringAngleDeg":0.0,"enableBsm":false,"hasStockCamera":false,"vEgoStarting":0.0,"longitudinalActuatorDelayLowerBound":0.0,"startingState":false},"pcmCruise":false,"minEnableSpeed":1.3888888359069824,"minSteerSpeed":3.1292800903320312,"mass":1743.0,"wheelbase":2.690000057220459,"centerToFront":1.2105000019073486,"steerRatio":15.699999809265137,"steerRatioRear":0.0,"rotationalInertia":2958.46923828125,"tireStiffnessFront":209991.5625,"tireStiffnessRear":271598.625,"longitudinalTuning":{"deprecated":{"kf":0.0},"kiBP":[5.0,35.0],"kiV":[0.5,0.5]},"lateralTuning":{"torque":{"deprecated":{"useSteeringAngle":false,"kp":0.0,"ki":0.0,"kf":0.0,"kd":0.0},"friction":0.1572393923997879,"steeringAngleDeadzoneDeg":0.0,"latAccelFactor":1.5961527824401855,"latAccelOffset":0.0}},"steerControlType":"torque","radarUnavailable":false,"steerActuatorDelay":0.20000000298023224,"openpilotLongitudinalControl":true,"dashcamOnly":false,"transmissionType":"direct","steerLimitTimer":0.4000000059604645,"fingerprintSource":"can","networkLocation":"fwdCamera","fuzzyFingerprint":false,"longitudinalActuatorDelay":0.5,"stopAccel":-0.25,"safetyConfigs":[{"safetyModel":"gm","deprecated":{"safetyParam":0,"safetyParam2":0},"safetyParam":18951}],"wheelSpeedFactor":1.0,"flags":16,"alternativeExperience":0,"notCar":false,"maxLateralAccel":1.842265248298645,"autoResumeSng":false,"alphaLongitudinalAvailable":true,"tireStiffnessFactor":1.0,"passive":false,"radarDelay":0.0,"secOcRequired":false,"secOcKeyAvailable":false,"steerAtStandstill":false},"tx":[[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[],[],[[384,"180607f9",0]],[[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142b95000bd46ae",0],[789,"1000effe02",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[[388,"0000200000200000",2]],[],[[384,"180607f9",0],[715,"c142b95000bd46ad",0],[789,"1000effd03",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"8142b95000bd46ae",0],[789,"1000effe02",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"c142b95000bd46ad",0],[789,"1000effd03",0],[880,"010086c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"8142e01000bd1fee",0],[789,"1000effe02",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"c142e01000bd1fed",0],[789,"1000effd03",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142e01000bd1ff0",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"4142e01000bd1fef",0],[789,"1000efff01",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142e01000bd1fee",0],[789,"1000effe02",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"10000fff",0],[715,"c042abe001bd541d",0],[789,"1000effd03",0],[880,"010006c00100",0],[388,"0000200000200000",2]],[],[],[[384,"10000fff",0]],[[715,"0042abe001bd5420",0],[789,"1000f00000",0],[880,"010006c00100",0]],[],[[384,"10000fff",0]],[],[[715,"4042abe001bd541f",0],[789,"1000efff01",0],[880,"010006c00100",0]],[[384,"10000fff",0]],[[388,"0000200000200000",2]],[],[[384,"10000fff",0],[715,"8042abe001bd541e",0],[789,"1000effe02",0],[880,"010006c00100",0]],[],[],[[384,"10000fff",0]],[[715,"c042abe001bd541d",0],[789,"1000effd03",0],[880,"010006c00100",0]],[],[[384,"10000fff",0]],[],[[715,"0042abe001bd5420",0],[789,"1000f00000",0],[880,"010006c00100",0],[388,"0000200000200000",2]],[[384,"10000fff",0]],[],[],[[384,"10000fff",0],[715,"4042abe001bd541f",0],[789,"1000efff01",0],[880,"010006c00100",0]],[],[],[[384,"10000fff",0]],[[715,"8042abe001bd541e",0],[789,"1000effe02",0],[880,"010006c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"c142e07000bd1f8d",0],[789,"1000effd03",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142e07000bd1f90",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"4142e3f800bd1c07",0],[789,"1000efff01",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"8142e3f800bd1c06",0],[789,"1000effe02",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"c142e3f800bd1c05",0],[789,"1000effd03",0],[880,"010086c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"0142e3f800bd1c08",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142e3f800bd1c07",0],[789,"1000efff01",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[]]},{"name":"ascm-0-0","identity":"CHEVROLET_VOLT_ASCM","word":17927,"cp":{"brand":"gm","carFingerprint":"CHEVROLET_VOLT_ASCM","deprecated":{"enableGasInterceptor":false,"enableCamera":false,"enableDsu":false,"enableApgs":false,"safetyModel":"silent","safetyParam":0,"steerLimitAlert":false,"vEgoStopping":0.0,"directAccelControl":false,"stoppingControl":false,"startAccel":0.0,"steerRateCost":0.0,"isPandaBlack":false,"safetyModelPassive":"silent","radarTimeStep":0.05000000074505806,"communityFeature":false,"minSpeedCan":0.0,"stoppingDecelRate":0.0,"startingAccelRate":0.0,"maxSteeringAngleDeg":0.0,"enableBsm":false,"hasStockCamera":false,"vEgoStarting":0.0,"longitudinalActuatorDelayLowerBound":0.0,"startingState":false},"pcmCruise":false,"minEnableSpeed":1.3888888359069824,"minSteerSpeed":3.1292800903320312,"mass":1743.0,"wheelbase":2.690000057220459,"centerToFront":1.2105000019073486,"steerRatio":15.699999809265137,"steerRatioRear":0.0,"rotationalInertia":2958.46923828125,"tireStiffnessFront":209991.5625,"tireStiffnessRear":271598.625,"longitudinalTuning":{"deprecated":{"kf":0.0},"kiBP":[5.0,35.0],"kiV":[0.5,0.5]},"lateralTuning":{"torque":{"deprecated":{"useSteeringAngle":false,"kp":0.0,"ki":0.0,"kf":0.0,"kd":0.0},"friction":0.1572393923997879,"steeringAngleDeadzoneDeg":0.0,"latAccelFactor":1.5961527824401855,"latAccelOffset":0.0}},"steerControlType":"torque","radarUnavailable":true,"steerActuatorDelay":0.20000000298023224,"openpilotLongitudinalControl":true,"dashcamOnly":false,"transmissionType":"direct","steerLimitTimer":0.4000000059604645,"fingerprintSource":"can","networkLocation":"fwdCamera","fuzzyFingerprint":false,"longitudinalActuatorDelay":0.5,"stopAccel":-0.25,"safetyConfigs":[{"safetyModel":"gm","deprecated":{"safetyParam":0,"safetyParam2":0},"safetyParam":17927}],"wheelSpeedFactor":1.0,"flags":16,"alternativeExperience":0,"notCar":false,"maxLateralAccel":1.842265248298645,"autoResumeSng":false,"alphaLongitudinalAvailable":true,"tireStiffnessFactor":1.0,"passive":false,"radarDelay":0.0,"secOcRequired":false,"secOcKeyAvailable":false,"steerAtStandstill":false},"tx":[[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[],[],[[384,"180607f9",0]],[[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142b95000bd46ae",0],[789,"1000effe02",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[[388,"0000200000200000",2]],[],[[384,"180607f9",0],[715,"c142b95000bd46ad",0],[789,"1000effd03",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"8142b95000bd46ae",0],[789,"1000effe02",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"c142b95000bd46ad",0],[789,"1000effd03",0],[880,"010086c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"8142e01000bd1fee",0],[789,"1000effe02",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"c142e01000bd1fed",0],[789,"1000effd03",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142e01000bd1ff0",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"4142e01000bd1fef",0],[789,"1000efff01",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142e01000bd1fee",0],[789,"1000effe02",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"10000fff",0],[715,"c042abe001bd541d",0],[789,"1000effd03",0],[880,"010006c00100",0],[388,"0000200000200000",2]],[],[],[[384,"10000fff",0]],[[715,"0042abe001bd5420",0],[789,"1000f00000",0],[880,"010006c00100",0]],[],[[384,"10000fff",0]],[],[[715,"4042abe001bd541f",0],[789,"1000efff01",0],[880,"010006c00100",0]],[[384,"10000fff",0]],[[388,"0000200000200000",2]],[],[[384,"10000fff",0],[715,"8042abe001bd541e",0],[789,"1000effe02",0],[880,"010006c00100",0]],[],[],[[384,"10000fff",0]],[[715,"c042abe001bd541d",0],[789,"1000effd03",0],[880,"010006c00100",0]],[],[[384,"10000fff",0]],[],[[715,"0042abe001bd5420",0],[789,"1000f00000",0],[880,"010006c00100",0],[388,"0000200000200000",2]],[[384,"10000fff",0]],[],[],[[384,"10000fff",0],[715,"4042abe001bd541f",0],[789,"1000efff01",0],[880,"010006c00100",0]],[],[],[[384,"10000fff",0]],[[715,"8042abe001bd541e",0],[789,"1000effe02",0],[880,"010006c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"c142e07000bd1f8d",0],[789,"1000effd03",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142e07000bd1f90",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"4142e3f800bd1c07",0],[789,"1000efff01",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"8142e3f800bd1c06",0],[789,"1000effe02",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"c142e3f800bd1c05",0],[789,"1000effd03",0],[880,"010086c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"0142e3f800bd1c08",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142e3f800bd1c07",0],[789,"1000efff01",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[]]},{"name":"ascm-0-1","identity":"CHEVROLET_VOLT_ASCM","word":19975,"cp":{"brand":"gm","carFingerprint":"CHEVROLET_VOLT_ASCM","deprecated":{"enableGasInterceptor":false,"enableCamera":false,"enableDsu":false,"enableApgs":false,"safetyModel":"silent","safetyParam":0,"steerLimitAlert":false,"vEgoStopping":0.0,"directAccelControl":false,"stoppingControl":false,"startAccel":0.0,"steerRateCost":0.0,"isPandaBlack":false,"safetyModelPassive":"silent","radarTimeStep":0.05000000074505806,"communityFeature":false,"minSpeedCan":0.0,"stoppingDecelRate":0.0,"startingAccelRate":0.0,"maxSteeringAngleDeg":0.0,"enableBsm":false,"hasStockCamera":false,"vEgoStarting":0.0,"longitudinalActuatorDelayLowerBound":0.0,"startingState":false},"pcmCruise":false,"minEnableSpeed":1.3888888359069824,"minSteerSpeed":3.1292800903320312,"mass":1743.0,"wheelbase":2.690000057220459,"centerToFront":1.2105000019073486,"steerRatio":15.699999809265137,"steerRatioRear":0.0,"rotationalInertia":2958.46923828125,"tireStiffnessFront":209991.5625,"tireStiffnessRear":271598.625,"longitudinalTuning":{"deprecated":{"kf":0.0},"kiBP":[5.0,35.0],"kiV":[0.5,0.5]},"lateralTuning":{"torque":{"deprecated":{"useSteeringAngle":false,"kp":0.0,"ki":0.0,"kf":0.0,"kd":0.0},"friction":0.1572393923997879,"steeringAngleDeadzoneDeg":0.0,"latAccelFactor":1.5961527824401855,"latAccelOffset":0.0}},"steerControlType":"torque","radarUnavailable":false,"steerActuatorDelay":0.20000000298023224,"openpilotLongitudinalControl":true,"dashcamOnly":false,"transmissionType":"direct","steerLimitTimer":0.4000000059604645,"fingerprintSource":"can","networkLocation":"fwdCamera","fuzzyFingerprint":false,"longitudinalActuatorDelay":0.5,"stopAccel":-0.25,"safetyConfigs":[{"safetyModel":"gm","deprecated":{"safetyParam":0,"safetyParam2":0},"safetyParam":19975}],"wheelSpeedFactor":1.0,"flags":16,"alternativeExperience":0,"notCar":false,"maxLateralAccel":1.842265248298645,"autoResumeSng":false,"alphaLongitudinalAvailable":true,"tireStiffnessFactor":1.0,"passive":false,"radarDelay":0.0,"secOcRequired":false,"secOcKeyAvailable":false,"steerAtStandstill":false},"tx":[[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[],[],[[384,"180607f9",0]],[[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142b95000bd46ae",0],[789,"1000effe02",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[[388,"0000200000200000",2]],[],[[384,"180607f9",0],[715,"c142b95000bd46ad",0],[789,"1000effd03",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"8142b95000bd46ae",0],[789,"1000effe02",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"c142b95000bd46ad",0],[789,"1000effd03",0],[880,"010086c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"0142b95000bd46b0",0],[789,"1000f00000",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"4142b95000bd46af",0],[789,"1000efff01",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"8142e01000bd1fee",0],[789,"1000effe02",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"c142e01000bd1fed",0],[789,"1000effd03",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142e01000bd1ff0",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"4142e01000bd1fef",0],[789,"1000efff01",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142e01000bd1fee",0],[789,"1000effe02",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"10000fff",0],[715,"c042abe001bd541d",0],[789,"1000effd03",0],[880,"010006c00100",0],[388,"0000200000200000",2]],[],[],[[384,"10000fff",0]],[[715,"0042abe001bd5420",0],[789,"1000f00000",0],[880,"010006c00100",0]],[],[[384,"10000fff",0]],[],[[715,"4042abe001bd541f",0],[789,"1000efff01",0],[880,"010006c00100",0]],[[384,"10000fff",0]],[[388,"0000200000200000",2]],[],[[384,"10000fff",0],[715,"8042abe001bd541e",0],[789,"1000effe02",0],[880,"010006c00100",0]],[],[],[[384,"10000fff",0]],[[715,"c042abe001bd541d",0],[789,"1000effd03",0],[880,"010006c00100",0]],[],[[384,"10000fff",0]],[],[[715,"0042abe001bd5420",0],[789,"1000f00000",0],[880,"010006c00100",0],[388,"0000200000200000",2]],[[384,"10000fff",0]],[],[],[[384,"10000fff",0],[715,"4042abe001bd541f",0],[789,"1000efff01",0],[880,"010006c00100",0]],[],[],[[384,"10000fff",0]],[[715,"8042abe001bd541e",0],[789,"1000effe02",0],[880,"010006c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"c142e07000bd1f8d",0],[789,"1000effd03",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142e07000bd1f90",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[],[[384,"180607f9",0]],[[715,"4142e3f800bd1c07",0],[789,"1000efff01",0],[880,"010086c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"8142e3f800bd1c06",0],[789,"1000effe02",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"c142e3f800bd1c05",0],[789,"1000effd03",0],[880,"010086c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"0142e3f800bd1c08",0],[789,"1000f00000",0],[880,"010086c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142e3f800bd1c07",0],[789,"1000efff01",0],[880,"010086c00100",0]],[[384,"180607f9",0]],[],[]]},{"name":"camera","identity":"CHEVROLET_VOLT_CAMERA","word":16391,"cp":{"brand":"gm","carFingerprint":"CHEVROLET_VOLT_CAMERA","deprecated":{"enableGasInterceptor":false,"enableCamera":false,"enableDsu":false,"enableApgs":false,"safetyModel":"silent","safetyParam":0,"steerLimitAlert":false,"vEgoStopping":0.0,"directAccelControl":false,"stoppingControl":false,"startAccel":0.0,"steerRateCost":0.0,"isPandaBlack":false,"safetyModelPassive":"silent","radarTimeStep":0.05000000074505806,"communityFeature":false,"minSpeedCan":0.0,"stoppingDecelRate":0.0,"startingAccelRate":0.0,"maxSteeringAngleDeg":0.0,"enableBsm":false,"hasStockCamera":false,"vEgoStarting":0.0,"longitudinalActuatorDelayLowerBound":0.0,"startingState":false},"pcmCruise":false,"minEnableSpeed":-1.0,"minSteerSpeed":3.1292800903320312,"mass":1743.0,"wheelbase":2.690000057220459,"centerToFront":1.2105000019073486,"steerRatio":15.699999809265137,"steerRatioRear":0.0,"rotationalInertia":2958.46923828125,"tireStiffnessFront":209991.5625,"tireStiffnessRear":271598.625,"longitudinalTuning":{"deprecated":{"kf":0.0},"kiBP":[5.0,35.0],"kiV":[0.5,0.5]},"lateralTuning":{"torque":{"deprecated":{"useSteeringAngle":false,"kp":0.0,"ki":0.0,"kf":0.0,"kd":0.0},"friction":0.1572393923997879,"steeringAngleDeadzoneDeg":0.0,"latAccelFactor":1.5961527824401855,"latAccelOffset":0.0}},"steerControlType":"torque","radarUnavailable":true,"steerActuatorDelay":0.20000000298023224,"openpilotLongitudinalControl":true,"dashcamOnly":false,"transmissionType":"direct","steerLimitTimer":0.4000000059604645,"fingerprintSource":"can","networkLocation":"fwdCamera","fuzzyFingerprint":false,"longitudinalActuatorDelay":0.5,"stopAccel":-0.25,"safetyConfigs":[{"safetyModel":"gm","deprecated":{"safetyParam":0,"safetyParam2":0},"safetyParam":16391}],"wheelSpeedFactor":1.0,"flags":16,"alternativeExperience":0,"notCar":false,"maxLateralAccel":1.842265248298645,"autoResumeSng":false,"alphaLongitudinalAvailable":true,"tireStiffnessFactor":1.0,"passive":false,"radarDelay":0.0,"secOcRequired":false,"secOcKeyAvailable":false,"steerAtStandstill":false},"tx":[[[717,"002c03d3fd",0],[715,"0142ba7800bd4588",0],[789,"1000f00000",0],[880,"010286c00100",0],[388,"0000200000200000",2]],[],[],[[384,"180607f9",0]],[[717,"402c03d3fc",0],[715,"4142ba7800bd4587",0],[789,"1000efff01",0],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[717,"802c03d3fb",0],[715,"8142ba7800bd4586",0],[789,"1000effe02",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[[388,"0000200000200000",2]],[],[[384,"180607f9",0],[717,"c02c03d3fa",0],[715,"c142ba7800bd4585",0],[789,"1000effd03",0],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[717,"002c03d3fd",0],[715,"0142ba7800bd4588",0],[789,"1000f00000",0],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[717,"402c03d3fc",0],[715,"4142ba7800bd4587",0],[789,"1000efff01",0],[880,"010286c00100",0],[388,"0000200000200000",2]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[717,"802c03d3fb",0],[715,"8142ba7800bd4586",0],[789,"1000effe02",0],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[717,"c02c03d3fa",0],[715,"c142ba7800bd4585",0],[789,"1000effd03",0],[880,"010286c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[717,"002c03d3fd",0],[715,"0142ba7800bd4588",0],[789,"1000f00000",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[717,"402c03d3fc",0],[715,"4142ba7800bd4587",0],[789,"1000efff01",0],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[717,"802c03d3fb",0],[715,"8142ea5800bd15a6",0],[789,"1000effe02",0],[880,"010286c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[717,"c02c03d3fa",0],[715,"c142ea5800bd15a5",0],[789,"1000effd03",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[717,"002c03d3fd",0],[715,"0142ea5800bd15a8",0],[789,"1000f00000",0],[880,"010286c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[717,"402c03d3fc",0],[715,"4142ea5800bd15a7",0],[789,"1000efff01",0],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[717,"802c03d3fb",0],[715,"8142ea5800bd15a6",0],[789,"1000effe02",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"10000fff",0],[717,"c02c03d3fa",0],[715,"c042b09001bd4f6d",0],[789,"1000effd03",0],[880,"010206c00100",0],[388,"0000200000200000",2]],[],[],[[384,"10000fff",0]],[[717,"002c03d3fd",0],[715,"0042b09001bd4f70",0],[789,"1000f00000",0],[880,"010206c00100",0]],[],[[384,"10000fff",0]],[],[[717,"402c03d3fc",0],[715,"4042b09001bd4f6f",0],[789,"1000efff01",0],[880,"010206c00100",0]],[[384,"10000fff",0]],[[388,"0000200000200000",2]],[],[[384,"10000fff",0],[717,"802c03d3fb",0],[715,"8042b09001bd4f6e",0],[789,"1000effe02",0],[880,"010206c00100",0]],[],[],[[384,"10000fff",0]],[[717,"c02c03d3fa",0],[715,"c042b09001bd4f6d",0],[789,"1000effd03",0],[880,"010206c00100",0]],[],[[384,"10000fff",0]],[],[[717,"002c03d3fd",0],[715,"0042b09001bd4f70",0],[789,"1000f00000",0],[880,"010206c00100",0],[388,"0000200000200000",2]],[[384,"10000fff",0]],[],[],[[384,"10000fff",0],[717,"402c03d3fc",0],[715,"4042b09001bd4f6f",0],[789,"1000efff01",0],[880,"010206c00100",0]],[],[],[[384,"10000fff",0]],[[717,"802c03d3fb",0],[715,"8042b09001bd4f6e",0],[789,"1000effe02",0],[880,"010206c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[717,"c02c03d3fa",0],[715,"c142ead000bd152d",0],[789,"1000effd03",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[717,"002c03d3fd",0],[715,"0142ead000bd1530",0],[789,"1000f00000",0],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[717,"402c03d3fc",0],[715,"4142ef8000bd107f",0],[789,"1000efff01",0],[880,"010286c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[717,"802c03d3fb",0],[715,"8142ef8000bd107e",0],[789,"1000effe02",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[717,"c02c03d3fa",0],[715,"c142ef8000bd107d",0],[789,"1000effd03",0],[880,"010286c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[717,"002c03d3fd",0],[715,"0142ef8000bd1080",0],[789,"1000f00000",0],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[717,"402c03d3fc",0],[715,"4142ef8000bd107f",0],[789,"1000efff01",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[]]},{"name":"sdgm-0","identity":"CHEVROLET_VOLT_2019","word":20487,"cp":{"brand":"gm","carFingerprint":"CHEVROLET_VOLT_2019","deprecated":{"enableGasInterceptor":false,"enableCamera":false,"enableDsu":false,"enableApgs":false,"safetyModel":"silent","safetyParam":0,"steerLimitAlert":false,"vEgoStopping":0.0,"directAccelControl":false,"stoppingControl":false,"startAccel":0.0,"steerRateCost":0.0,"isPandaBlack":false,"safetyModelPassive":"silent","radarTimeStep":0.05000000074505806,"communityFeature":false,"minSpeedCan":0.0,"stoppingDecelRate":0.0,"startingAccelRate":0.0,"maxSteeringAngleDeg":0.0,"enableBsm":false,"hasStockCamera":false,"vEgoStarting":0.0,"longitudinalActuatorDelayLowerBound":0.0,"startingState":false},"pcmCruise":false,"minEnableSpeed":-1.0,"minSteerSpeed":3.1292800903320312,"mass":1743.0,"wheelbase":2.690000057220459,"centerToFront":1.2105000019073486,"steerRatio":15.699999809265137,"steerRatioRear":0.0,"rotationalInertia":2958.46923828125,"tireStiffnessFront":93236.2578125,"tireStiffnessRear":120589.7890625,"longitudinalTuning":{"deprecated":{"kf":0.0},"kiBP":[5.0,35.0],"kiV":[0.5,0.5]},"lateralTuning":{"torque":{"deprecated":{"useSteeringAngle":false,"kp":0.0,"ki":0.0,"kf":0.0,"kd":0.0},"friction":0.1572393923997879,"steeringAngleDeadzoneDeg":0.0,"latAccelFactor":1.5961527824401855,"latAccelOffset":0.0}},"steerControlType":"torque","radarUnavailable":false,"steerActuatorDelay":0.20000000298023224,"openpilotLongitudinalControl":true,"dashcamOnly":false,"transmissionType":"direct","steerLimitTimer":0.4000000059604645,"fingerprintSource":"can","networkLocation":"fwdCamera","fuzzyFingerprint":false,"longitudinalActuatorDelay":0.5,"stopAccel":-0.25,"safetyConfigs":[{"safetyModel":"gm","deprecated":{"safetyParam":0,"safetyParam2":0},"safetyParam":20487}],"wheelSpeedFactor":1.0,"flags":16,"alternativeExperience":0,"notCar":false,"maxLateralAccel":1.842265248298645,"autoResumeSng":false,"alphaLongitudinalAvailable":true,"tireStiffnessFactor":0.4440000057220459,"passive":false,"radarDelay":0.0,"secOcRequired":false,"secOcKeyAvailable":false,"steerAtStandstill":false},"tx":[[[715,"0142ba7800bd4588",0],[789,"1000f00000",2],[880,"010286c00100",0],[388,"0000200000200000",2]],[],[],[[384,"180607f9",0]],[[715,"4142ba7800bd4587",0],[789,"1000efff01",2],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142ba7800bd4586",0],[789,"1000effe02",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[[388,"0000200000200000",2]],[],[[384,"180607f9",0],[715,"c142ba7800bd4585",0],[789,"1000effd03",2],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"0142ba7800bd4588",0],[789,"1000f00000",2],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142ba7800bd4587",0],[789,"1000efff01",2],[880,"010286c00100",0],[388,"0000200000200000",2]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"8142ba7800bd4586",0],[789,"1000effe02",2],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"c142ba7800bd4585",0],[789,"1000effd03",2],[880,"010286c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"0142ba7800bd4588",0],[789,"1000f00000",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"4142ba7800bd4587",0],[789,"1000efff01",2],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"8142ea5800bd15a6",0],[789,"1000effe02",2],[880,"010286c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"c142ea5800bd15a5",0],[789,"1000effd03",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142ea5800bd15a8",0],[789,"1000f00000",2],[880,"010286c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"4142ea5800bd15a7",0],[789,"1000efff01",2],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142ea5800bd15a6",0],[789,"1000effe02",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"10000fff",0],[715,"c042b09001bd4f6d",0],[789,"1000effd03",2],[880,"010206c00100",0],[388,"0000200000200000",2]],[],[],[[384,"10000fff",0]],[[715,"0042b09001bd4f70",0],[789,"1000f00000",2],[880,"010206c00100",0]],[],[[384,"10000fff",0]],[],[[715,"4042b09001bd4f6f",0],[789,"1000efff01",2],[880,"010206c00100",0]],[[384,"10000fff",0]],[[388,"0000200000200000",2]],[],[[384,"10000fff",0],[715,"8042b09001bd4f6e",0],[789,"1000effe02",2],[880,"010206c00100",0]],[],[],[[384,"10000fff",0]],[[715,"c042b09001bd4f6d",0],[789,"1000effd03",2],[880,"010206c00100",0]],[],[[384,"10000fff",0]],[],[[715,"0042b09001bd4f70",0],[789,"1000f00000",2],[880,"010206c00100",0],[388,"0000200000200000",2]],[[384,"10000fff",0]],[],[],[[384,"10000fff",0],[715,"4042b09001bd4f6f",0],[789,"1000efff01",2],[880,"010206c00100",0]],[],[],[[384,"10000fff",0]],[[715,"8042b09001bd4f6e",0],[789,"1000effe02",2],[880,"010206c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"c142ead000bd152d",0],[789,"1000effd03",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142ead000bd1530",0],[789,"1000f00000",2],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"4142ef8000bd107f",0],[789,"1000efff01",2],[880,"010286c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"8142ef8000bd107e",0],[789,"1000effe02",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"c142ef8000bd107d",0],[789,"1000effd03",2],[880,"010286c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"0142ef8000bd1080",0],[789,"1000f00000",2],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142ef8000bd107f",0],[789,"1000efff01",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[]]},{"name":"sdgm-1","identity":"CHEVROLET_VOLT_2019","word":21511,"cp":{"brand":"gm","carFingerprint":"CHEVROLET_VOLT_2019","deprecated":{"enableGasInterceptor":false,"enableCamera":false,"enableDsu":false,"enableApgs":false,"safetyModel":"silent","safetyParam":0,"steerLimitAlert":false,"vEgoStopping":0.0,"directAccelControl":false,"stoppingControl":false,"startAccel":0.0,"steerRateCost":0.0,"isPandaBlack":false,"safetyModelPassive":"silent","radarTimeStep":0.05000000074505806,"communityFeature":false,"minSpeedCan":0.0,"stoppingDecelRate":0.0,"startingAccelRate":0.0,"maxSteeringAngleDeg":0.0,"enableBsm":false,"hasStockCamera":false,"vEgoStarting":0.0,"longitudinalActuatorDelayLowerBound":0.0,"startingState":false},"pcmCruise":false,"minEnableSpeed":-1.0,"minSteerSpeed":3.1292800903320312,"mass":1743.0,"wheelbase":2.690000057220459,"centerToFront":1.2105000019073486,"steerRatio":15.699999809265137,"steerRatioRear":0.0,"rotationalInertia":2958.46923828125,"tireStiffnessFront":93236.2578125,"tireStiffnessRear":120589.7890625,"longitudinalTuning":{"deprecated":{"kf":0.0},"kiBP":[5.0,35.0],"kiV":[0.5,0.5]},"lateralTuning":{"torque":{"deprecated":{"useSteeringAngle":false,"kp":0.0,"ki":0.0,"kf":0.0,"kd":0.0},"friction":0.1572393923997879,"steeringAngleDeadzoneDeg":0.0,"latAccelFactor":1.5961527824401855,"latAccelOffset":0.0}},"steerControlType":"torque","radarUnavailable":false,"steerActuatorDelay":0.20000000298023224,"openpilotLongitudinalControl":true,"dashcamOnly":false,"transmissionType":"direct","steerLimitTimer":0.4000000059604645,"fingerprintSource":"can","networkLocation":"fwdCamera","fuzzyFingerprint":false,"longitudinalActuatorDelay":0.5,"stopAccel":-0.25,"safetyConfigs":[{"safetyModel":"gm","deprecated":{"safetyParam":0,"safetyParam2":0},"safetyParam":21511}],"wheelSpeedFactor":1.0,"flags":16,"alternativeExperience":0,"notCar":false,"maxLateralAccel":1.842265248298645,"autoResumeSng":false,"alphaLongitudinalAvailable":true,"tireStiffnessFactor":0.4440000057220459,"passive":false,"radarDelay":0.0,"secOcRequired":false,"secOcKeyAvailable":false,"steerAtStandstill":false},"tx":[[[715,"0142ba7800bd4588",0],[789,"1000f00000",2],[880,"010286c00100",0],[388,"0000200000200000",2]],[],[],[[384,"180607f9",0]],[[715,"4142ba7800bd4587",0],[789,"1000efff01",2],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142ba7800bd4586",0],[789,"1000effe02",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[[388,"0000200000200000",2]],[],[[384,"180607f9",0],[715,"c142ba7800bd4585",0],[789,"1000effd03",2],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"0142ba7800bd4588",0],[789,"1000f00000",2],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142ba7800bd4587",0],[789,"1000efff01",2],[880,"010286c00100",0],[388,"0000200000200000",2]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"8142ba7800bd4586",0],[789,"1000effe02",2],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"c142ba7800bd4585",0],[789,"1000effd03",2],[880,"010286c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"0142ba7800bd4588",0],[789,"1000f00000",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"4142ba7800bd4587",0],[789,"1000efff01",2],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"8142ea5800bd15a6",0],[789,"1000effe02",2],[880,"010286c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"c142ea5800bd15a5",0],[789,"1000effd03",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142ea5800bd15a8",0],[789,"1000f00000",2],[880,"010286c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"4142ea5800bd15a7",0],[789,"1000efff01",2],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142ea5800bd15a6",0],[789,"1000effe02",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"10000fff",0],[715,"c042b09001bd4f6d",0],[789,"1000effd03",2],[880,"010206c00100",0],[388,"0000200000200000",2]],[],[],[[384,"10000fff",0]],[[715,"0042b09001bd4f70",0],[789,"1000f00000",2],[880,"010206c00100",0]],[],[[384,"10000fff",0]],[],[[715,"4042b09001bd4f6f",0],[789,"1000efff01",2],[880,"010206c00100",0]],[[384,"10000fff",0]],[[388,"0000200000200000",2]],[],[[384,"10000fff",0],[715,"8042b09001bd4f6e",0],[789,"1000effe02",2],[880,"010206c00100",0]],[],[],[[384,"10000fff",0]],[[715,"c042b09001bd4f6d",0],[789,"1000effd03",2],[880,"010206c00100",0]],[],[[384,"10000fff",0]],[],[[715,"0042b09001bd4f70",0],[789,"1000f00000",2],[880,"010206c00100",0],[388,"0000200000200000",2]],[[384,"10000fff",0]],[],[],[[384,"10000fff",0],[715,"4042b09001bd4f6f",0],[789,"1000efff01",2],[880,"010206c00100",0]],[],[],[[384,"10000fff",0]],[[715,"8042b09001bd4f6e",0],[789,"1000effe02",2],[880,"010206c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"c142ead000bd152d",0],[789,"1000effd03",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142ead000bd1530",0],[789,"1000f00000",2],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"4142ef8000bd107f",0],[789,"1000efff01",2],[880,"010286c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"8142ef8000bd107e",0],[789,"1000effe02",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"c142ef8000bd107d",0],[789,"1000effd03",2],[880,"010286c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"0142ef8000bd1080",0],[789,"1000f00000",2],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142ef8000bd107f",0],[789,"1000efff01",2],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[]]},{"name":"removed-0","identity":"CHEVROLET_VOLT_CAMERA","word":49489,"cp":{"brand":"gm","carFingerprint":"CHEVROLET_VOLT_CAMERA","deprecated":{"enableGasInterceptor":false,"enableCamera":false,"enableDsu":false,"enableApgs":false,"safetyModel":"silent","safetyParam":0,"steerLimitAlert":false,"vEgoStopping":0.0,"directAccelControl":false,"stoppingControl":false,"startAccel":0.0,"steerRateCost":0.0,"isPandaBlack":false,"safetyModelPassive":"silent","radarTimeStep":0.05000000074505806,"communityFeature":false,"minSpeedCan":0.0,"stoppingDecelRate":0.0,"startingAccelRate":0.0,"maxSteeringAngleDeg":0.0,"enableBsm":false,"hasStockCamera":false,"vEgoStarting":0.0,"longitudinalActuatorDelayLowerBound":0.0,"startingState":false},"pcmCruise":false,"minEnableSpeed":-1.0,"minSteerSpeed":3.1292800903320312,"mass":1743.0,"wheelbase":2.690000057220459,"centerToFront":1.2105000019073486,"steerRatio":15.699999809265137,"steerRatioRear":0.0,"rotationalInertia":2958.46923828125,"tireStiffnessFront":209991.5625,"tireStiffnessRear":271598.625,"longitudinalTuning":{"deprecated":{"kf":0.0},"kiBP":[5.0,35.0],"kiV":[0.5,0.5]},"lateralTuning":{"torque":{"deprecated":{"useSteeringAngle":false,"kp":0.0,"ki":0.0,"kf":0.0,"kd":0.0},"friction":0.1572393923997879,"steeringAngleDeadzoneDeg":0.0,"latAccelFactor":1.5961527824401855,"latAccelOffset":0.0}},"steerControlType":"torque","radarUnavailable":true,"steerActuatorDelay":0.20000000298023224,"openpilotLongitudinalControl":true,"dashcamOnly":false,"transmissionType":"direct","steerLimitTimer":0.4000000059604645,"fingerprintSource":"can","networkLocation":"fwdCamera","fuzzyFingerprint":false,"longitudinalActuatorDelay":0.5,"stopAccel":-0.25,"safetyConfigs":[{"safetyModel":"gm","deprecated":{"safetyParam":0,"safetyParam2":0},"safetyParam":49489}],"wheelSpeedFactor":1.0,"flags":20,"alternativeExperience":0,"notCar":false,"maxLateralAccel":1.842265248298645,"autoResumeSng":false,"alphaLongitudinalAvailable":true,"tireStiffnessFactor":1.0,"passive":false,"radarDelay":0.0,"secOcRequired":false,"secOcKeyAvailable":false,"steerAtStandstill":false},"tx":[[[715,"0142ba7800bd4588",0],[789,"1000f00000",0],[880,"010286c00100",0],[1033,"00000000000000",0],[1034,"00000000000000",0],[388,"0000200000200000",2]],[],[],[[384,"180607f9",0]],[[715,"4142ba7800bd4587",0],[789,"1000efff01",0],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142ba7800bd4586",0],[789,"1000effe02",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[[388,"0000200000200000",2]],[],[[384,"180607f9",0],[715,"c142ba7800bd4585",0],[789,"1000effd03",0],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"0142ba7800bd4588",0],[789,"1000f00000",0],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142ba7800bd4587",0],[789,"1000efff01",0],[880,"010286c00100",0],[388,"0000200000200000",2]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"8142ba7800bd4586",0],[789,"1000effe02",0],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"c142ba7800bd4585",0],[789,"1000effd03",0],[880,"010286c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"0142ba7800bd4588",0],[789,"1000f00000",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"4142ba7800bd4587",0],[789,"1000efff01",0],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"8142ea5800bd15a6",0],[789,"1000effe02",0],[880,"010286c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"c142ea5800bd15a5",0],[789,"1000effd03",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142ea5800bd15a8",0],[789,"1000f00000",0],[880,"010286c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"4142ea5800bd15a7",0],[789,"1000efff01",0],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142ea5800bd15a6",0],[789,"1000effe02",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"10000fff",0],[715,"c042b09001bd4f6d",0],[789,"1000effd03",0],[880,"010206c00100",0],[388,"0000200000200000",2]],[],[],[[384,"10000fff",0]],[[715,"0042b09001bd4f70",0],[789,"1000f00000",0],[880,"010206c00100",0]],[],[[384,"10000fff",0]],[],[[715,"4042b09001bd4f6f",0],[789,"1000efff01",0],[880,"010206c00100",0]],[[384,"10000fff",0]],[[388,"0000200000200000",2]],[],[[384,"10000fff",0],[715,"8042b09001bd4f6e",0],[789,"1000effe02",0],[880,"010206c00100",0]],[],[],[[384,"10000fff",0]],[[715,"c042b09001bd4f6d",0],[789,"1000effd03",0],[880,"010206c00100",0]],[],[[384,"10000fff",0]],[],[[715,"0042b09001bd4f70",0],[789,"1000f00000",0],[880,"010206c00100",0],[388,"0000200000200000",2]],[[384,"10000fff",0]],[],[],[[384,"10000fff",0],[715,"4042b09001bd4f6f",0],[789,"1000efff01",0],[880,"010206c00100",0]],[],[],[[384,"10000fff",0]],[[715,"8042b09001bd4f6e",0],[789,"1000effe02",0],[880,"010206c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"c142ead000bd152d",0],[789,"1000effd03",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142ead000bd1530",0],[789,"1000f00000",0],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"4142ef8000bd107f",0],[789,"1000efff01",0],[880,"010286c00100",0],[1033,"00000000000000",0],[1034,"00000000000000",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"8142ef8000bd107e",0],[789,"1000effe02",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"c142ef8000bd107d",0],[789,"1000effd03",0],[880,"010286c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"0142ef8000bd1080",0],[789,"1000f00000",0],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142ef8000bd107f",0],[789,"1000efff01",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[]]},{"name":"removed-1","identity":"CHEVROLET_VOLT_CAMERA","word":49489,"cp":{"brand":"gm","carFingerprint":"CHEVROLET_VOLT_CAMERA","deprecated":{"enableGasInterceptor":false,"enableCamera":false,"enableDsu":false,"enableApgs":false,"safetyModel":"silent","safetyParam":0,"steerLimitAlert":false,"vEgoStopping":0.0,"directAccelControl":false,"stoppingControl":false,"startAccel":0.0,"steerRateCost":0.0,"isPandaBlack":false,"safetyModelPassive":"silent","radarTimeStep":0.05000000074505806,"communityFeature":false,"minSpeedCan":0.0,"stoppingDecelRate":0.0,"startingAccelRate":0.0,"maxSteeringAngleDeg":0.0,"enableBsm":false,"hasStockCamera":false,"vEgoStarting":0.0,"longitudinalActuatorDelayLowerBound":0.0,"startingState":false},"pcmCruise":false,"minEnableSpeed":-1.0,"minSteerSpeed":3.1292800903320312,"mass":1743.0,"wheelbase":2.690000057220459,"centerToFront":1.2105000019073486,"steerRatio":15.699999809265137,"steerRatioRear":0.0,"rotationalInertia":2958.46923828125,"tireStiffnessFront":209991.5625,"tireStiffnessRear":271598.625,"longitudinalTuning":{"deprecated":{"kf":0.0},"kiBP":[5.0,35.0],"kiV":[0.5,0.5]},"lateralTuning":{"torque":{"deprecated":{"useSteeringAngle":false,"kp":0.0,"ki":0.0,"kf":0.0,"kd":0.0},"friction":0.1572393923997879,"steeringAngleDeadzoneDeg":0.0,"latAccelFactor":1.5961527824401855,"latAccelOffset":0.0}},"steerControlType":"torque","radarUnavailable":true,"steerActuatorDelay":0.20000000298023224,"openpilotLongitudinalControl":true,"dashcamOnly":false,"transmissionType":"direct","steerLimitTimer":0.4000000059604645,"fingerprintSource":"can","networkLocation":"fwdCamera","fuzzyFingerprint":false,"longitudinalActuatorDelay":0.5,"stopAccel":-0.25,"safetyConfigs":[{"safetyModel":"gm","deprecated":{"safetyParam":0,"safetyParam2":0},"safetyParam":49489}],"wheelSpeedFactor":1.0,"flags":28,"alternativeExperience":0,"notCar":false,"maxLateralAccel":1.842265248298645,"autoResumeSng":false,"alphaLongitudinalAvailable":true,"tireStiffnessFactor":1.0,"passive":false,"radarDelay":0.0,"secOcRequired":false,"secOcKeyAvailable":false,"steerAtStandstill":false},"tx":[[[715,"0142ba7800bd4588",0],[789,"1000f00000",0],[880,"010286c00100",0],[1033,"00000000000000",0],[1034,"00000000000000",0],[388,"0000200000200000",2]],[],[],[[384,"180607f9",0]],[[715,"4142ba7800bd4587",0],[789,"1000efff01",0],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142ba7800bd4586",0],[789,"1000effe02",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[[388,"0000200000200000",2]],[],[[384,"180607f9",0],[715,"c142ba7800bd4585",0],[789,"1000effd03",0],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"0142ba7800bd4588",0],[789,"1000f00000",0],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142ba7800bd4587",0],[789,"1000efff01",0],[880,"010286c00100",0],[388,"0000200000200000",2]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"8142ba7800bd4586",0],[789,"1000effe02",0],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"c142ba7800bd4585",0],[789,"1000effd03",0],[880,"010286c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"0142ba7800bd4588",0],[789,"1000f00000",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"4142ba7800bd4587",0],[789,"1000efff01",0],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"8142ea5800bd15a6",0],[789,"1000effe02",0],[880,"010286c00100",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"c142ea5800bd15a5",0],[789,"1000effd03",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142ea5800bd15a8",0],[789,"1000f00000",0],[880,"010286c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"4142ea5800bd15a7",0],[789,"1000efff01",0],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"8142ea5800bd15a6",0],[789,"1000effe02",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"10000fff",0],[715,"c042b09001bd4f6d",0],[789,"1000effd03",0],[880,"010206c00100",0],[388,"0000200000200000",2]],[],[],[[384,"10000fff",0]],[[715,"0042b09001bd4f70",0],[789,"1000f00000",0],[880,"010206c00100",0]],[],[[384,"10000fff",0]],[],[[715,"4042b09001bd4f6f",0],[789,"1000efff01",0],[880,"010206c00100",0]],[[384,"10000fff",0]],[[388,"0000200000200000",2]],[],[[384,"10000fff",0],[715,"8042b09001bd4f6e",0],[789,"1000effe02",0],[880,"010206c00100",0]],[],[],[[384,"10000fff",0]],[[715,"c042b09001bd4f6d",0],[789,"1000effd03",0],[880,"010206c00100",0]],[],[[384,"10000fff",0]],[],[[715,"0042b09001bd4f70",0],[789,"1000f00000",0],[880,"010206c00100",0],[388,"0000200000200000",2]],[[384,"10000fff",0]],[],[],[[384,"10000fff",0],[715,"4042b09001bd4f6f",0],[789,"1000efff01",0],[880,"010206c00100",0]],[],[],[[384,"10000fff",0]],[[715,"8042b09001bd4f6e",0],[789,"1000effe02",0],[880,"010206c00100",0]],[],[[384,"180607f9",0],[388,"0000200000200000",2]],[],[[715,"c142ead000bd152d",0],[789,"1000effd03",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"0142ead000bd1530",0],[789,"1000f00000",0],[880,"010286c00100",0]],[],[],[[384,"180607f9",0]],[[715,"4142ef8000bd107f",0],[789,"1000efff01",0],[880,"010286c00100",0],[1033,"00000000000000",0],[1034,"00000000000000",0],[388,"0000200000200000",2]],[],[[384,"180607f9",0]],[],[[715,"8142ef8000bd107e",0],[789,"1000effe02",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[],[[384,"180607f9",0],[715,"c142ef8000bd107d",0],[789,"1000effd03",0],[880,"010286c00100",0]],[],[[388,"0000200000200000",2]],[[384,"180607f9",0]],[[715,"0142ef8000bd1080",0],[789,"1000f00000",0],[880,"010286c00100",0]],[],[[384,"180607f9",0]],[],[[715,"4142ef8000bd107f",0],[789,"1000efff01",0],[880,"010286c00100",0]],[[384,"180607f9",0]],[],[]]}]} diff --git a/opendbc_repo/opendbc/car/gm/tests/volt_one_pedal_original_oracle.json b/opendbc_repo/opendbc/car/gm/tests/volt_one_pedal_original_oracle.json new file mode 100644 index 0000000000..371c49f9db --- /dev/null +++ b/opendbc_repo/opendbc/car/gm/tests/volt_one_pedal_original_oracle.json @@ -0,0 +1 @@ +{"provenance":{"common/pid.py":"67ae4b84e38a219a8997654c16832c2863d56c9458832678dee76497ba36145a","opendbc_repo/opendbc/car/gm/carcontroller.py":"871528f9fea82bad86ca12bf9ad9451693134e45f0f37e32d2980ce3b05adbe3","opendbc_repo/opendbc/car/gm/carstate.py":"458bbd337a1c2033479df21d38e42136e6d57aef2ec4ad94efd7785d8539377f","opendbc_repo/opendbc/car/gm/values.py":"d42eb0844c485e0f154840b54eec1a3084e604903349192fc7e355e3e1107360"},"method":"Reference scalar outputs","params":{"BRAKE_LOOKUP_BP":[-4.0,0.0],"BRAKE_LOOKUP_V":[400.0,0.0],"MAX_BRAKE":400,"NEAR_STOP_BRAKE_PHASE":0.25,"vEgoStopping":0.5,"ACCEL_MIN":-4.0},"histories":[{"name":"saturation-unwind","kp":[[0.0,10.0],[7.0,4.0]],"ki":[[0.0,10.0],[0.5,0.3]],"initial_lift_frames":0,"steps":[{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.006374054054054055,"decel":-0.032,"brake":3,"lift_frames":0,"raw_pid":-3.2974551351351358}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.01274810810810811,"decel":-0.064,"brake":6,"lift_frames":0,"raw_pid":-3.3038291891891896}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.019122162162162164,"decel":-0.096,"brake":10,"lift_frames":0,"raw_pid":-3.3102032432432438}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.02549621621621622,"decel":-0.128,"brake":13,"lift_frames":0,"raw_pid":-3.3165772972972976}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.03187027027027028,"decel":-0.16,"brake":16,"lift_frames":0,"raw_pid":-3.322951351351352}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.038244324324324334,"decel":-0.192,"brake":19,"lift_frames":0,"raw_pid":-3.329325405405406}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.04461837837837839,"decel":-0.224,"brake":22,"lift_frames":0,"raw_pid":-3.33569945945946}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.05099243243243245,"decel":-0.256,"brake":26,"lift_frames":0,"raw_pid":-3.342073513513514}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.057366486486486505,"decel":-0.28800000000000003,"brake":29,"lift_frames":0,"raw_pid":-3.3484475675675682}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.06374054054054056,"decel":-0.32000000000000006,"brake":32,"lift_frames":0,"raw_pid":-3.354821621621622}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.07011459459459461,"decel":-0.3520000000000001,"brake":35,"lift_frames":0,"raw_pid":-3.3611956756756762}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.07648864864864867,"decel":-0.3840000000000001,"brake":38,"lift_frames":0,"raw_pid":-3.36756972972973}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.08286270270270273,"decel":-0.41600000000000015,"brake":42,"lift_frames":0,"raw_pid":-3.3739437837837842}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.08923675675675678,"decel":-0.4480000000000002,"brake":45,"lift_frames":0,"raw_pid":-3.3803178378378385}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.09561081081081084,"decel":-0.4800000000000002,"brake":48,"lift_frames":0,"raw_pid":-3.3866918918918922}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.1019848648648649,"decel":-0.5120000000000002,"brake":51,"lift_frames":0,"raw_pid":-3.3930659459459465}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.10835891891891895,"decel":-0.5440000000000003,"brake":54,"lift_frames":0,"raw_pid":-3.3994400000000007}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.11473297297297301,"decel":-0.5760000000000003,"brake":58,"lift_frames":0,"raw_pid":-3.4058140540540545}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.12110702702702707,"decel":-0.6080000000000003,"brake":61,"lift_frames":0,"raw_pid":-3.4121881081081087}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.1274810810810811,"decel":-0.6400000000000003,"brake":64,"lift_frames":0,"raw_pid":-3.4185621621621625}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.13385513513513517,"decel":-0.6720000000000004,"brake":67,"lift_frames":0,"raw_pid":-3.4249362162162167}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.14022918918918922,"decel":-0.7040000000000004,"brake":70,"lift_frames":0,"raw_pid":-3.431310270270271}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.14660324324324328,"decel":-0.7360000000000004,"brake":74,"lift_frames":0,"raw_pid":-3.4376843243243247}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.15297729729729734,"decel":-0.7680000000000005,"brake":77,"lift_frames":0,"raw_pid":-3.444058378378379}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.1593513513513514,"decel":-0.8000000000000005,"brake":80,"lift_frames":0,"raw_pid":-3.450432432432433}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.16572540540540545,"decel":-0.8320000000000005,"brake":83,"lift_frames":0,"raw_pid":-3.456806486486487}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.1720994594594595,"decel":-0.8640000000000005,"brake":86,"lift_frames":0,"raw_pid":-3.463180540540541}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.17847351351351357,"decel":-0.8960000000000006,"brake":90,"lift_frames":0,"raw_pid":-3.469554594594595}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.18484756756756762,"decel":-0.9280000000000006,"brake":93,"lift_frames":0,"raw_pid":-3.475928648648649}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.19122162162162168,"decel":-0.9600000000000006,"brake":96,"lift_frames":0,"raw_pid":-3.4823027027027034}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.19759567567567574,"decel":-0.9920000000000007,"brake":99,"lift_frames":0,"raw_pid":-3.488676756756757}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.0240000000000007,"brake":102,"lift_frames":0,"raw_pid":-3.4950508108108114}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.0560000000000007,"brake":106,"lift_frames":0,"raw_pid":-3.4950508108108114}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.0880000000000007,"brake":109,"lift_frames":0,"raw_pid":-3.4950508108108114}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.1200000000000008,"brake":112,"lift_frames":0,"raw_pid":-3.4950508108108114}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.1520000000000008,"brake":115,"lift_frames":0,"raw_pid":-3.4950508108108114}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.1840000000000008,"brake":118,"lift_frames":0,"raw_pid":-3.4950508108108114}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.2160000000000009,"brake":122,"lift_frames":0,"raw_pid":-3.4950508108108114}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.2480000000000009,"brake":125,"lift_frames":0,"raw_pid":-3.4950508108108114}},{"input":{"eligible":true,"speed":5.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.280000000000001,"brake":128,"lift_frames":0,"raw_pid":-3.4950508108108114}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.2864000000000009,"brake":129,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.2928000000000008,"brake":129,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.2992000000000008,"brake":130,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3056000000000008,"brake":131,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3120000000000007,"brake":131,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3184000000000007,"brake":132,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3248000000000006,"brake":132,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3312000000000006,"brake":133,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3376000000000006,"brake":134,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3440000000000005,"brake":134,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3504000000000005,"brake":135,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3568000000000005,"brake":136,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3632000000000004,"brake":136,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3696000000000004,"brake":137,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3760000000000003,"brake":138,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3824000000000003,"brake":138,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3888000000000003,"brake":139,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.3952000000000002,"brake":140,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4016000000000002,"brake":140,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4080000000000001,"brake":141,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4144,"brake":141,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4208,"brake":142,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4272,"brake":143,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4336,"brake":143,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.44,"brake":144,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4464,"brake":145,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4527999999999999,"brake":145,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4591999999999998,"brake":146,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4655999999999998,"brake":147,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4719999999999998,"brake":147,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4783999999999997,"brake":148,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4847999999999997,"brake":148,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4911999999999996,"brake":149,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.4975999999999996,"brake":150,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.5039999999999996,"brake":150,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.5103999999999995,"brake":151,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.5167999999999995,"brake":152,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.5231999999999994,"brake":152,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.5295999999999994,"brake":153,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.5359999999999994,"brake":154,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.5423999999999993,"brake":154,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.5487999999999993,"brake":155,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.5551999999999992,"brake":156,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.5615999999999992,"brake":156,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.5679999999999992,"brake":157,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.5743999999999991,"brake":157,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.580799999999999,"brake":158,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.587199999999999,"brake":159,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.593599999999999,"brake":159,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.599999999999999,"brake":160,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.606399999999999,"brake":161,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.612799999999999,"brake":161,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.6191999999999989,"brake":162,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.6255999999999988,"brake":163,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.6319999999999988,"brake":163,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.6383999999999987,"brake":164,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.6447999999999987,"brake":164,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.6511999999999987,"brake":165,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.6575999999999986,"brake":166,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":0.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-1.6639999999999986,"brake":166,"lift_frames":0,"raw_pid":-3.5}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":-0.6319999999999986,"brake":63,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-5.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.2039697297297298,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.20165189189189195,"decel":-0.5048951351351354,"brake":50,"lift_frames":0,"raw_pid":-0.5048951351351354}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.1993340540540541,"decel":-0.5025772972972976,"brake":50,"lift_frames":0,"raw_pid":-0.5025772972972976}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.19701621621621626,"decel":-0.5002594594594597,"brake":50,"lift_frames":0,"raw_pid":-0.5002594594594597}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.19469837837837842,"decel":-0.4979416216216219,"brake":50,"lift_frames":0,"raw_pid":-0.4979416216216219}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.19238054054054057,"decel":-0.495623783783784,"brake":50,"lift_frames":0,"raw_pid":-0.495623783783784}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.19006270270270273,"decel":-0.49330594594594623,"brake":49,"lift_frames":0,"raw_pid":-0.49330594594594623}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.18774486486486489,"decel":-0.49098810810810833,"brake":49,"lift_frames":0,"raw_pid":-0.49098810810810833}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.18542702702702704,"decel":-0.48867027027027055,"brake":49,"lift_frames":0,"raw_pid":-0.48867027027027055}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.1831091891891892,"decel":-0.48635243243243265,"brake":49,"lift_frames":0,"raw_pid":-0.48635243243243265}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.18079135135135135,"decel":-0.48403459459459486,"brake":48,"lift_frames":0,"raw_pid":-0.48403459459459486}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.1784735135135135,"decel":-0.48171675675675696,"brake":48,"lift_frames":0,"raw_pid":-0.48171675675675696}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.17615567567567567,"decel":-0.47939891891891917,"brake":48,"lift_frames":0,"raw_pid":-0.47939891891891917}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.17383783783783782,"decel":-0.47708108108108127,"brake":48,"lift_frames":0,"raw_pid":-0.47708108108108127}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.17151999999999998,"decel":-0.4747632432432435,"brake":47,"lift_frames":0,"raw_pid":-0.4747632432432435}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.16920216216216213,"decel":-0.4724454054054056,"brake":47,"lift_frames":0,"raw_pid":-0.4724454054054056}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.1668843243243243,"decel":-0.4701275675675678,"brake":47,"lift_frames":0,"raw_pid":-0.4701275675675678}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.16456648648648645,"decel":-0.4678097297297299,"brake":47,"lift_frames":0,"raw_pid":-0.4678097297297299}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.1622486486486486,"decel":-0.4654918918918921,"brake":47,"lift_frames":0,"raw_pid":-0.4654918918918921}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.15993081081081076,"decel":-0.4631740540540542,"brake":46,"lift_frames":0,"raw_pid":-0.4631740540540542}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.15761297297297291,"decel":-0.4608562162162164,"brake":46,"lift_frames":0,"raw_pid":-0.4608562162162164}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.15529513513513507,"decel":-0.4585383783783785,"brake":46,"lift_frames":0,"raw_pid":-0.4585383783783785}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.15297729729729723,"decel":-0.45622054054054073,"brake":46,"lift_frames":0,"raw_pid":-0.45622054054054073}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.15065945945945938,"decel":-0.45390270270270283,"brake":45,"lift_frames":0,"raw_pid":-0.45390270270270283}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.14834162162162154,"decel":-0.45158486486486504,"brake":45,"lift_frames":0,"raw_pid":-0.45158486486486504}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.1460237837837837,"decel":-0.44926702702702714,"brake":45,"lift_frames":0,"raw_pid":-0.44926702702702714}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.14370594594594585,"decel":-0.44694918918918936,"brake":45,"lift_frames":0,"raw_pid":-0.44694918918918936}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.141388108108108,"decel":-0.44463135135135146,"brake":44,"lift_frames":0,"raw_pid":-0.44463135135135146}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.13907027027027016,"decel":-0.44231351351351367,"brake":44,"lift_frames":0,"raw_pid":-0.44231351351351367}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.13675243243243232,"decel":-0.43999567567567577,"brake":44,"lift_frames":0,"raw_pid":-0.43999567567567577}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.13443459459459448,"decel":-0.437677837837838,"brake":44,"lift_frames":0,"raw_pid":-0.437677837837838}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.13211675675675663,"decel":-0.4353600000000001,"brake":44,"lift_frames":0,"raw_pid":-0.4353600000000001}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.1297989189189188,"decel":-0.4330421621621623,"brake":43,"lift_frames":0,"raw_pid":-0.4330421621621623}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.12748108108108094,"decel":-0.4307243243243244,"brake":43,"lift_frames":0,"raw_pid":-0.4307243243243244}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.1251632432432431,"decel":-0.4284064864864866,"brake":43,"lift_frames":0,"raw_pid":-0.4284064864864866}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.12284540540540526,"decel":-0.4260886486486487,"brake":43,"lift_frames":0,"raw_pid":-0.4260886486486487}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.12052756756756741,"decel":-0.4237708108108109,"brake":42,"lift_frames":0,"raw_pid":-0.4237708108108109}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.11820972972972957,"decel":-0.421452972972973,"brake":42,"lift_frames":0,"raw_pid":-0.421452972972973}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.11589189189189172,"decel":-0.41913513513513523,"brake":42,"lift_frames":0,"raw_pid":-0.41913513513513523}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.11357405405405388,"decel":-0.41681729729729733,"brake":42,"lift_frames":0,"raw_pid":-0.41681729729729733}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.11125621621621604,"decel":-0.41449945945945954,"brake":41,"lift_frames":0,"raw_pid":-0.41449945945945954}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.10893837837837819,"decel":-0.41218162162162164,"brake":41,"lift_frames":0,"raw_pid":-0.41218162162162164}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.10662054054054035,"decel":-0.40986378378378385,"brake":41,"lift_frames":0,"raw_pid":-0.40986378378378385}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.1043027027027025,"decel":-0.40754594594594595,"brake":41,"lift_frames":0,"raw_pid":-0.40754594594594595}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.10198486486486466,"decel":-0.40522810810810816,"brake":41,"lift_frames":0,"raw_pid":-0.40522810810810816}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.09966702702702682,"decel":-0.40291027027027027,"brake":40,"lift_frames":0,"raw_pid":-0.40291027027027027}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.09734918918918897,"decel":-0.4005924324324325,"brake":40,"lift_frames":0,"raw_pid":-0.4005924324324325}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.09503135135135113,"decel":-0.3982745945945946,"brake":40,"lift_frames":0,"raw_pid":-0.3982745945945946}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.09271351351351328,"decel":-0.3959567567567568,"brake":40,"lift_frames":0,"raw_pid":-0.3959567567567568}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.09039567567567544,"decel":-0.3936389189189189,"brake":39,"lift_frames":0,"raw_pid":-0.3936389189189189}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.0880778378378376,"decel":-0.3913210810810811,"brake":39,"lift_frames":0,"raw_pid":-0.3913210810810811}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.08575999999999975,"decel":-0.3890032432432432,"brake":39,"lift_frames":0,"raw_pid":-0.3890032432432432}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.08344216216216191,"decel":-0.3866854054054054,"brake":39,"lift_frames":0,"raw_pid":-0.3866854054054054}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.08112432432432407,"decel":-0.3843675675675675,"brake":38,"lift_frames":0,"raw_pid":-0.3843675675675675}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.07880648648648622,"decel":-0.3820497297297297,"brake":38,"lift_frames":0,"raw_pid":-0.3820497297297297}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.07648864864864838,"decel":-0.3797318918918918,"brake":38,"lift_frames":0,"raw_pid":-0.3797318918918918}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.07417081081081053,"decel":-0.37741405405405404,"brake":38,"lift_frames":0,"raw_pid":-0.37741405405405404}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.07185297297297269,"decel":-0.37509621621621614,"brake":38,"lift_frames":0,"raw_pid":-0.37509621621621614}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.06953513513513485,"decel":-0.37277837837837835,"brake":37,"lift_frames":0,"raw_pid":-0.37277837837837835}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.067217297297297,"decel":-0.37046054054054045,"brake":37,"lift_frames":0,"raw_pid":-0.37046054054054045}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.06489945945945916,"decel":-0.36814270270270266,"brake":37,"lift_frames":0,"raw_pid":-0.36814270270270266}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.06258162162162131,"decel":-0.36582486486486476,"brake":37,"lift_frames":0,"raw_pid":-0.36582486486486476}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.06026378378378348,"decel":-0.363507027027027,"brake":36,"lift_frames":0,"raw_pid":-0.363507027027027}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.05794594594594564,"decel":-0.3611891891891891,"brake":36,"lift_frames":0,"raw_pid":-0.3611891891891891}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.0556281081081078,"decel":-0.3588713513513513,"brake":36,"lift_frames":0,"raw_pid":-0.3588713513513513}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.053310270270269966,"decel":-0.3565535135135134,"brake":36,"lift_frames":0,"raw_pid":-0.3565535135135134}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.05099243243243213,"decel":-0.3542356756756756,"brake":35,"lift_frames":0,"raw_pid":-0.3542356756756756}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.04867459459459429,"decel":-0.3519178378378378,"brake":35,"lift_frames":0,"raw_pid":-0.3519178378378378}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.046356756756756455,"decel":-0.3495999999999999,"brake":35,"lift_frames":0,"raw_pid":-0.3495999999999999}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.04403891891891862,"decel":-0.3472821621621621,"brake":35,"lift_frames":0,"raw_pid":-0.3472821621621621}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.04172108108108078,"decel":-0.3449643243243242,"brake":34,"lift_frames":0,"raw_pid":-0.3449643243243242}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.039403243243242944,"decel":-0.34264648648648643,"brake":34,"lift_frames":0,"raw_pid":-0.34264648648648643}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.03708540540540511,"decel":-0.34032864864864854,"brake":34,"lift_frames":0,"raw_pid":-0.34032864864864854}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.03476756756756727,"decel":-0.33801081081081075,"brake":34,"lift_frames":0,"raw_pid":-0.33801081081081075}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.03244972972972943,"decel":-0.33569297297297296,"brake":34,"lift_frames":0,"raw_pid":-0.33569297297297296}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.030131891891891596,"decel":-0.33337513513513506,"brake":33,"lift_frames":0,"raw_pid":-0.33337513513513506}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.02781405405405376,"decel":-0.33105729729729727,"brake":33,"lift_frames":0,"raw_pid":-0.33105729729729727}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.025496216216215922,"decel":-0.32873945945945937,"brake":33,"lift_frames":0,"raw_pid":-0.32873945945945937}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.023178378378378085,"decel":-0.3264216216216216,"brake":33,"lift_frames":0,"raw_pid":-0.3264216216216216}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.02086054054054025,"decel":-0.3241037837837837,"brake":32,"lift_frames":0,"raw_pid":-0.3241037837837837}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.01854270270270241,"decel":-0.3217859459459459,"brake":32,"lift_frames":0,"raw_pid":-0.3217859459459459}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.016224864864864574,"decel":-0.3194681081081081,"brake":32,"lift_frames":0,"raw_pid":-0.3194681081081081}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.013907027027026737,"decel":-0.3171502702702702,"brake":32,"lift_frames":0,"raw_pid":-0.3171502702702702}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.0115891891891889,"decel":-0.3148324324324324,"brake":31,"lift_frames":0,"raw_pid":-0.3148324324324324}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.009271351351351063,"decel":-0.3125145945945945,"brake":31,"lift_frames":0,"raw_pid":-0.3125145945945945}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.0069535135135132264,"decel":-0.31019675675675673,"brake":31,"lift_frames":0,"raw_pid":-0.31019675675675673}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.0046356756756753895,"decel":-0.30787891891891883,"brake":31,"lift_frames":0,"raw_pid":-0.30787891891891883}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.002317837837837552,"decel":-0.30556108108108104,"brake":31,"lift_frames":0,"raw_pid":-0.30556108108108104}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.3032432432432435,"brake":30,"lift_frames":0,"raw_pid":-0.3032432432432435}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.3032432432432435,"brake":30,"lift_frames":0,"raw_pid":-0.3032432432432435}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.3032432432432435,"brake":30,"lift_frames":0,"raw_pid":-0.3032432432432435}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.3032432432432435,"brake":30,"lift_frames":0,"raw_pid":-0.3032432432432435}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.3032432432432435,"brake":30,"lift_frames":0,"raw_pid":-0.3032432432432435}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.3032432432432435,"brake":30,"lift_frames":0,"raw_pid":-0.3032432432432435}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.3032432432432435,"brake":30,"lift_frames":0,"raw_pid":-0.3032432432432435}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.3032432432432435,"brake":30,"lift_frames":0,"raw_pid":-0.3032432432432435}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.3032432432432435,"brake":30,"lift_frames":0,"raw_pid":-0.3032432432432435}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.3032432432432435,"brake":30,"lift_frames":0,"raw_pid":-0.3032432432432435}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.3032432432432435,"brake":30,"lift_frames":0,"raw_pid":-0.3032432432432435}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.3032432432432435,"brake":30,"lift_frames":0,"raw_pid":-0.3032432432432435}},{"input":{"eligible":true,"speed":5.0,"acceleration":-1.5,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.3032432432432435,"brake":30,"lift_frames":0,"raw_pid":-0.3032432432432435}}]},{"name":"pitch-steering","kp":[[0.0,10.0],[0.7,0.4]],"ki":[[0.0,10.0],[0.5,0.3]],"initial_lift_frames":0,"steps":[{"input":{"eligible":true,"speed":0.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[0.0,-0.1,0.0]},"expected":{"integral":0.0,"decel":-0.44000000000000006,"brake":44,"lift_frames":0,"raw_pid":-0.44000000000000006}},{"input":{"eligible":true,"speed":0.2,"acceleration":0.0,"steering_angle":20.0,"orientation":[0.0,0.0,0.0]},"expected":{"integral":-0.007936,"decel":-0.4475453113815319,"brake":45,"lift_frames":0,"raw_pid":-1.285536}},{"input":{"eligible":true,"speed":1.0,"acceleration":-1.0,"steering_angle":120.0,"orientation":[0.0,0.1,0.0]},"expected":{"integral":-0.009682845363071577,"decel":-0.8105268365389231,"brake":81,"lift_frames":0,"raw_pid":-1.102221129867458}},{"input":{"eligible":true,"speed":4.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[0.0,-0.1,0.0]},"expected":{"integral":0.0,"decel":-0.6042395243058132,"brake":60,"lift_frames":0,"raw_pid":-0.6042395243058132}},{"input":{"eligible":true,"speed":8.0,"acceleration":0.0,"steering_angle":20.0,"orientation":[0.0,0.0,0.0]},"expected":{"integral":-0.004932756756756757,"decel":-0.6362395243058132,"brake":64,"lift_frames":0,"raw_pid":-1.271776}},{"input":{"eligible":true,"speed":20.0,"acceleration":-1.0,"steering_angle":120.0,"orientation":[0.0,0.1,0.0]},"expected":{"integral":-0.00752323471828968,"decel":-0.6426395243058132,"brake":64,"lift_frames":0,"raw_pid":-1.1938725001027206}},{"input":{"eligible":true,"speed":0.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[0.0,-0.1,0.0]},"expected":{"integral":0.0,"decel":-0.44000000000000006,"brake":44,"lift_frames":0,"raw_pid":-0.44000000000000006}},{"input":{"eligible":true,"speed":0.2,"acceleration":0.0,"steering_angle":20.0,"orientation":[0.0,0.0,0.0]},"expected":{"integral":-0.007936,"decel":-0.4475453113815319,"brake":45,"lift_frames":0,"raw_pid":-1.285536}},{"input":{"eligible":true,"speed":1.0,"acceleration":-1.0,"steering_angle":120.0,"orientation":[0.0,0.1,0.0]},"expected":{"integral":-0.009682845363071577,"decel":-0.8105268365389231,"brake":81,"lift_frames":0,"raw_pid":-1.102221129867458}},{"input":{"eligible":true,"speed":4.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[0.0,-0.1,0.0]},"expected":{"integral":0.0,"decel":-0.6042395243058132,"brake":60,"lift_frames":0,"raw_pid":-0.6042395243058132}},{"input":{"eligible":true,"speed":8.0,"acceleration":0.0,"steering_angle":20.0,"orientation":[0.0,0.0,0.0]},"expected":{"integral":-0.004932756756756757,"decel":-0.6362395243058132,"brake":64,"lift_frames":0,"raw_pid":-1.271776}},{"input":{"eligible":true,"speed":20.0,"acceleration":-1.0,"steering_angle":120.0,"orientation":[0.0,0.1,0.0]},"expected":{"integral":-0.00752323471828968,"decel":-0.6426395243058132,"brake":64,"lift_frames":0,"raw_pid":-1.1938725001027206}},{"input":{"eligible":true,"speed":0.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[0.0,-0.1,0.0]},"expected":{"integral":0.0,"decel":-0.44000000000000006,"brake":44,"lift_frames":0,"raw_pid":-0.44000000000000006}},{"input":{"eligible":true,"speed":0.2,"acceleration":0.0,"steering_angle":20.0,"orientation":[0.0,0.0,0.0]},"expected":{"integral":-0.007936,"decel":-0.4475453113815319,"brake":45,"lift_frames":0,"raw_pid":-1.285536}},{"input":{"eligible":true,"speed":1.0,"acceleration":-1.0,"steering_angle":120.0,"orientation":[0.0,0.1,0.0]},"expected":{"integral":-0.009682845363071577,"decel":-0.8105268365389231,"brake":81,"lift_frames":0,"raw_pid":-1.102221129867458}},{"input":{"eligible":true,"speed":4.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[0.0,-0.1,0.0]},"expected":{"integral":0.0,"decel":-0.6042395243058132,"brake":60,"lift_frames":0,"raw_pid":-0.6042395243058132}},{"input":{"eligible":true,"speed":8.0,"acceleration":0.0,"steering_angle":20.0,"orientation":[0.0,0.0,0.0]},"expected":{"integral":-0.004932756756756757,"decel":-0.6362395243058132,"brake":64,"lift_frames":0,"raw_pid":-1.271776}},{"input":{"eligible":true,"speed":20.0,"acceleration":-1.0,"steering_angle":120.0,"orientation":[0.0,0.1,0.0]},"expected":{"integral":-0.00752323471828968,"decel":-0.6426395243058132,"brake":64,"lift_frames":0,"raw_pid":-1.1938725001027206}},{"input":{"eligible":true,"speed":0.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[0.0,-0.1,0.0]},"expected":{"integral":0.0,"decel":-0.44000000000000006,"brake":44,"lift_frames":0,"raw_pid":-0.44000000000000006}},{"input":{"eligible":true,"speed":0.2,"acceleration":0.0,"steering_angle":20.0,"orientation":[0.0,0.0,0.0]},"expected":{"integral":-0.007936,"decel":-0.4475453113815319,"brake":45,"lift_frames":0,"raw_pid":-1.285536}},{"input":{"eligible":true,"speed":1.0,"acceleration":-1.0,"steering_angle":120.0,"orientation":[0.0,0.1,0.0]},"expected":{"integral":-0.009682845363071577,"decel":-0.8105268365389231,"brake":81,"lift_frames":0,"raw_pid":-1.102221129867458}},{"input":{"eligible":true,"speed":4.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[0.0,-0.1,0.0]},"expected":{"integral":0.0,"decel":-0.6042395243058132,"brake":60,"lift_frames":0,"raw_pid":-0.6042395243058132}},{"input":{"eligible":true,"speed":8.0,"acceleration":0.0,"steering_angle":20.0,"orientation":[0.0,0.0,0.0]},"expected":{"integral":-0.004932756756756757,"decel":-0.6362395243058132,"brake":64,"lift_frames":0,"raw_pid":-1.271776}},{"input":{"eligible":true,"speed":20.0,"acceleration":-1.0,"steering_angle":120.0,"orientation":[0.0,0.1,0.0]},"expected":{"integral":-0.00752323471828968,"decel":-0.6426395243058132,"brake":64,"lift_frames":0,"raw_pid":-1.1938725001027206}}]},{"name":"lift-exhaustion","kp":[[0.0,10.0],[0.7,0.4]],"ki":[[0.0,10.0],[0.5,0.3]],"initial_lift_frames":8,"steps":[{"input":{"eligible":true,"speed":0.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.44000000000000006,"brake":80,"lift_frames":7,"raw_pid":-0.44000000000000006}},{"input":{"eligible":true,"speed":0.2,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.007936,"decel":-0.4475453113815319,"brake":80,"lift_frames":6,"raw_pid":-1.285536}},{"input":{"eligible":true,"speed":1.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.008178539467690506,"decel":-1.0121265569076592,"brake":101,"lift_frames":5,"raw_pid":-1.0482228161645084}},{"input":{"eligible":true,"speed":4.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.6889837837837839,"brake":69,"lift_frames":4,"raw_pid":-0.6889837837837839}},{"input":{"eligible":true,"speed":8.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.004932756756756757,"decel":-0.7209837837837839,"brake":72,"lift_frames":3,"raw_pid":-1.271776}},{"input":{"eligible":true,"speed":20.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.005172756756756758,"decel":-1.032,"brake":103,"lift_frames":2,"raw_pid":-1.1131727567567569}},{"input":{"eligible":true,"speed":0.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.8,"brake":80,"lift_frames":1,"raw_pid":-0.44000000000000006}},{"input":{"eligible":true,"speed":0.2,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.007936,"decel":-0.8075453113815318,"brake":81,"lift_frames":0,"raw_pid":-1.285536}},{"input":{"eligible":true,"speed":1.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.008178539467690506,"decel":-1.0121265569076592,"brake":101,"lift_frames":0,"raw_pid":-1.0482228161645084}},{"input":{"eligible":true,"speed":4.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.6889837837837839,"brake":69,"lift_frames":0,"raw_pid":-0.6889837837837839}},{"input":{"eligible":true,"speed":8.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.004932756756756757,"decel":-0.7209837837837839,"brake":72,"lift_frames":0,"raw_pid":-1.271776}},{"input":{"eligible":true,"speed":20.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.005172756756756758,"decel":-1.032,"brake":103,"lift_frames":0,"raw_pid":-1.1131727567567569}},{"input":{"eligible":true,"speed":0.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.8,"brake":80,"lift_frames":0,"raw_pid":-0.44000000000000006}},{"input":{"eligible":true,"speed":0.2,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.007936,"decel":-0.8075453113815318,"brake":81,"lift_frames":0,"raw_pid":-1.285536}},{"input":{"eligible":true,"speed":1.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.008178539467690506,"decel":-1.0121265569076592,"brake":101,"lift_frames":0,"raw_pid":-1.0482228161645084}},{"input":{"eligible":true,"speed":4.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.6889837837837839,"brake":69,"lift_frames":0,"raw_pid":-0.6889837837837839}},{"input":{"eligible":true,"speed":8.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.004932756756756757,"decel":-0.7209837837837839,"brake":72,"lift_frames":0,"raw_pid":-1.271776}},{"input":{"eligible":true,"speed":20.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.005172756756756758,"decel":-1.032,"brake":103,"lift_frames":0,"raw_pid":-1.1131727567567569}},{"input":{"eligible":true,"speed":0.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.8,"brake":80,"lift_frames":0,"raw_pid":-0.44000000000000006}},{"input":{"eligible":true,"speed":0.2,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.007936,"decel":-0.8075453113815318,"brake":81,"lift_frames":0,"raw_pid":-1.285536}},{"input":{"eligible":true,"speed":1.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.008178539467690506,"decel":-1.0121265569076592,"brake":101,"lift_frames":0,"raw_pid":-1.0482228161645084}},{"input":{"eligible":true,"speed":4.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.6889837837837839,"brake":69,"lift_frames":0,"raw_pid":-0.6889837837837839}},{"input":{"eligible":true,"speed":8.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.004932756756756757,"decel":-0.7209837837837839,"brake":72,"lift_frames":0,"raw_pid":-1.271776}},{"input":{"eligible":true,"speed":20.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.005172756756756758,"decel":-1.032,"brake":103,"lift_frames":0,"raw_pid":-1.1131727567567569}}]},{"name":"reset","kp":[[0.0,10.0],[0.7,0.4]],"ki":[[0.0,10.0],[0.5,0.3]],"initial_lift_frames":0,"steps":[{"input":{"eligible":true,"speed":0.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.44000000000000006,"brake":44,"lift_frames":0,"raw_pid":-0.44000000000000006}},{"input":{"eligible":true,"speed":0.2,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.007936,"decel":-0.4475453113815319,"brake":45,"lift_frames":0,"raw_pid":-1.285536}},{"input":{"eligible":true,"speed":1.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.008178539467690506,"decel":-1.0121265569076592,"brake":101,"lift_frames":0,"raw_pid":-1.0482228161645084}},{"input":{"eligible":true,"speed":4.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.6889837837837839,"brake":69,"lift_frames":0,"raw_pid":-0.6889837837837839}},{"input":{"eligible":false,"speed":8.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":0.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":false,"speed":20.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-1.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":0.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.768,"brake":77,"lift_frames":0,"raw_pid":-0.44000000000000006}},{"input":{"eligible":true,"speed":0.2,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.007936,"decel":-0.7755453113815318,"brake":78,"lift_frames":0,"raw_pid":-1.285536}},{"input":{"eligible":true,"speed":1.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.008178539467690506,"decel":-1.0121265569076592,"brake":101,"lift_frames":0,"raw_pid":-1.0482228161645084}},{"input":{"eligible":true,"speed":4.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.6889837837837839,"brake":69,"lift_frames":0,"raw_pid":-0.6889837837837839}},{"input":{"eligible":true,"speed":8.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.004932756756756757,"decel":-0.7209837837837839,"brake":72,"lift_frames":0,"raw_pid":-1.271776}},{"input":{"eligible":true,"speed":20.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.005172756756756758,"decel":-1.032,"brake":103,"lift_frames":0,"raw_pid":-1.1131727567567569}},{"input":{"eligible":false,"speed":0.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-3.0,"brake":0,"lift_frames":0,"raw_pid":0.0}},{"input":{"eligible":true,"speed":0.2,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.007936,"decel":-1.285536,"brake":129,"lift_frames":0,"raw_pid":-1.285536}},{"input":{"eligible":true,"speed":1.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.008178539467690506,"decel":-1.0482228161645084,"brake":105,"lift_frames":0,"raw_pid":-1.0482228161645084}},{"input":{"eligible":true,"speed":4.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.6889837837837839,"brake":69,"lift_frames":0,"raw_pid":-0.6889837837837839}},{"input":{"eligible":true,"speed":8.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.004932756756756757,"decel":-0.7209837837837839,"brake":72,"lift_frames":0,"raw_pid":-1.271776}},{"input":{"eligible":true,"speed":20.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.005172756756756758,"decel":-1.032,"brake":103,"lift_frames":0,"raw_pid":-1.1131727567567569}},{"input":{"eligible":true,"speed":0.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.8,"brake":80,"lift_frames":0,"raw_pid":-0.44000000000000006}},{"input":{"eligible":true,"speed":0.2,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.007936,"decel":-0.8075453113815318,"brake":81,"lift_frames":0,"raw_pid":-1.285536}},{"input":{"eligible":true,"speed":1.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.008178539467690506,"decel":-1.0121265569076592,"brake":101,"lift_frames":0,"raw_pid":-1.0482228161645084}},{"input":{"eligible":true,"speed":4.0,"acceleration":-3.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":0.0,"decel":-0.6889837837837839,"brake":69,"lift_frames":0,"raw_pid":-0.6889837837837839}},{"input":{"eligible":true,"speed":8.0,"acceleration":0.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.004932756756756757,"decel":-0.7209837837837839,"brake":72,"lift_frames":0,"raw_pid":-1.271776}},{"input":{"eligible":true,"speed":20.0,"acceleration":-1.0,"steering_angle":0.0,"orientation":[]},"expected":{"integral":-0.005172756756756758,"decel":-1.032,"brake":103,"lift_frames":0,"raw_pid":-1.1131727567567569}}]}]} diff --git a/opendbc_repo/opendbc/car/gm/values.py b/opendbc_repo/opendbc/car/gm/values.py index 86fb54a4b8..f5ff4e5410 100644 --- a/opendbc_repo/opendbc/car/gm/values.py +++ b/opendbc_repo/opendbc/car/gm/values.py @@ -136,6 +136,43 @@ class GMFlags(IntFlag): VOLT_CAMERA_NO_ACCEL_POS = NO_ACCELERATOR_POS_MSG +VOLT_ONE_PEDAL_BASE_WORDS = (0x4084, 0xC084, 0x4287, 0x4687, 0x4A87, 0x4E87, 0x4087, 0x5087, 0x5487, 0xC1D1, 0xC1D3) +VOLT_ONE_PEDAL_WORDS = {start + index: word for start in (0xD100, 0xD110) + for index, word in enumerate(VOLT_ONE_PEDAL_BASE_WORDS)} + + +def gm_control_word(cp: CarParams) -> int: + word = int(cp.safetyConfigs[0].safetyParam) + if word not in VOLT_ONE_PEDAL_WORDS: + return word + index = word - (0xD110 if word >= 0xD110 else 0xD100) + identity = (CAR.CHEVROLET_VOLT if index < 2 else CAR.CHEVROLET_VOLT_ASCM if index < 6 else + CAR.CHEVROLET_VOLT_2019 if index in (7, 8) else CAR.CHEVROLET_VOLT_CAMERA) + network = CarParams.NetworkLocation.gateway if index < 2 else CarParams.NetworkLocation.fwdCamera + if (cp.brand == 'gm' and cp.transmissionType == CarParams.TransmissionType.direct and + cp.carFingerprint == identity and cp.networkLocation == network): + return VOLT_ONE_PEDAL_WORDS[word] + return word + + +def is_volt_one_pedal(cp: CarParams) -> bool: + try: + return (int(cp.safetyConfigs[0].safetyParam) in VOLT_ONE_PEDAL_WORDS and + cp.transmissionType == CarParams.TransmissionType.direct and is_volt_longitudinal(cp) and is_gm_auto_hold(cp)) + except (AttributeError, IndexError, TypeError, ValueError): + return False + + +def apply_volt_one_pedal(cp: CarParams, enabled: bool, auto_hold_enabled: bool) -> None: + if not is_volt_longitudinal(cp) or cp.transmissionType != CarParams.TransmissionType.direct: + return + cp.safetyConfigs[0].safetyParam = gm_control_word(cp) + apply_gm_auto_hold(cp, enabled or auto_hold_enabled) + word = int(cp.safetyConfigs[0].safetyParam) + if enabled and word in VOLT_ONE_PEDAL_BASE_WORDS: + cp.safetyConfigs[0].safetyParam = (0xD110 if auto_hold_enabled else 0xD100) + VOLT_ONE_PEDAL_BASE_WORDS.index(word) + + def control_flags(cp: CarParams) -> int: """Exclude only the informational BSM bit from exact control-profile admission.""" return int(cp.flags) & ~int(GMFlags.HAS_BSM) @@ -175,7 +212,7 @@ def is_volt_gateway_profile(cp: CarParams) -> bool: not cp.passive and not cp.dashcamOnly and not cp.notCar and not cp.radarUnavailable and control_flags(cp) == 0 and len(cp.safetyConfigs) == 1 and cp.safetyConfigs[0].safetyModel == CarParams.SafetyModel.gm and - int(cp.safetyConfigs[0].safetyParam) in ( + gm_control_word(cp) in ( int(GMSafetyFlags.EV | GMSafetyFlags.VOLT_GATEWAY_LONG), int(GMSafetyFlags.EV | GMSafetyFlags.VOLT_GATEWAY_LONG | GMSafetyFlags.VOLT_GATEWAY_ALT_BRAKE), 0x4084, 0xC084)) @@ -195,7 +232,7 @@ def is_lacrosse_gateway_profile(cp: CarParams) -> bool: cp.transmissionType == CarParams.TransmissionType.automatic and not cp.passive and not cp.dashcamOnly and not cp.notCar and not cp.radarUnavailable and control_flags(cp) == 0 and len(cp.safetyConfigs) == 1 and cp.safetyConfigs[0].safetyModel == CarParams.SafetyModel.gm and - cp.safetyConfigs[0].safetyParam in (0, 0x80)) + gm_control_word(cp) in (0, 0x80)) except (AttributeError, IndexError, TypeError, ValueError): return False @@ -204,7 +241,7 @@ def is_gm_auto_hold(cp: CarParams) -> bool: return ((is_volt_gateway_longitudinal(cp) or is_volt_ascm_longitudinal(cp) or is_volt_camera_longitudinal(cp) or is_volt_sdgm_profile(cp, longitudinal=True) or is_volt_camera_removed(cp, longitudinal=True) or is_lacrosse_gateway_profile(cp) and cp.openpilotLongitudinalControl) and - int(cp.safetyConfigs[0].safetyParam) in (0x4084, 0xC084, 0x4287, 0x4687, 0x4A87, 0x4E87, 0x4087, 0x5087, 0x5487, + gm_control_word(cp) in (0x4084, 0xC084, 0x4287, 0x4687, 0x4A87, 0x4E87, 0x4087, 0x5087, 0x5487, 0xC1D1, 0xC1D3, 0x80)) @@ -214,7 +251,7 @@ def apply_gm_auto_hold(cp: CarParams, enabled: bool) -> None: return if (is_volt_gateway_profile(cp) or is_volt_ascm_longitudinal(cp) or is_volt_camera_longitudinal(cp) or is_volt_sdgm_profile(cp, longitudinal=True) or is_lacrosse_gateway_profile(cp)): - word = int(cp.safetyConfigs[0].safetyParam) + word = gm_control_word(cp) cp.safetyConfigs[0].safetyParam = (word | int(GMSafetyFlags.VOLT_AUTO_HOLD)) if enabled and cp.openpilotLongitudinalControl else ( word & ~int(GMSafetyFlags.VOLT_AUTO_HOLD)) @@ -227,7 +264,7 @@ def is_volt_ascm_longitudinal(cp: CarParams) -> bool: optional = int(GMSafetyFlags.ASCM_BRAKE_C9 | GMSafetyFlags.ASCM_RADAR) if len(cp.safetyConfigs) != 1: return False - flags = int(cp.safetyConfigs[0].safetyParam) + flags = gm_control_word(cp) if flags in (0x4287, 0x4687, 0x4A87, 0x4E87): flags &= ~int(GMSafetyFlags.VOLT_AUTO_HOLD) return (cp.brand == 'gm' and cp.carFingerprint == CAR.CHEVROLET_VOLT_ASCM and @@ -253,8 +290,8 @@ def is_volt_camera_removed(cp: CarParams, *, longitudinal=None) -> bool: (not is_long or cp.alphaLongitudinalAvailable) and not cp.passive and not cp.dashcamOnly and not cp.notCar and len(cp.safetyConfigs) == 1 and cp.safetyConfigs[0].safetyModel == CarParams.SafetyModel.gm and - (cp.safetyConfigs[0].safetyParam == (0xC151 if is_long else 0xC150) or - is_long and cp.safetyConfigs[0].safetyParam == (0xC1D3 if cp.flags & GMFlags.NO_ACCELERATOR_POS_MSG else 0xC1D1))) + (gm_control_word(cp) == (0xC151 if is_long else 0xC150) or + is_long and gm_control_word(cp) == (0xC1D3 if cp.flags & GMFlags.NO_ACCELERATOR_POS_MSG else 0xC1D1))) except (AttributeError, IndexError, TypeError, ValueError): return False @@ -266,7 +303,7 @@ def is_volt_camera_stock(cp: CarParams) -> bool: cp.networkLocation == CarParams.NetworkLocation.fwdCamera and cp.pcmCruise and not cp.openpilotLongitudinalControl and not cp.passive and not cp.dashcamOnly and not cp.notCar and control_flags(cp) == 0 and len(cp.safetyConfigs) == 1 and - cp.safetyConfigs[0].safetyModel == CarParams.SafetyModel.gm and cp.safetyConfigs[0].safetyParam == 5) + cp.safetyConfigs[0].safetyModel == CarParams.SafetyModel.gm and gm_control_word(cp) == 5) except (AttributeError, IndexError, TypeError, ValueError): return False @@ -279,7 +316,7 @@ def is_volt_camera_longitudinal(cp: CarParams) -> bool: cp.openpilotLongitudinalControl and not cp.pcmCruise and not cp.passive and not cp.dashcamOnly and not cp.notCar and control_flags(cp) == 0 and len(cp.safetyConfigs) == 1 and cp.safetyConfigs[0].safetyModel == CarParams.SafetyModel.gm and - cp.safetyConfigs[0].safetyParam in (0x4007, 0x4087)) + gm_control_word(cp) in (0x4007, 0x4087)) except (AttributeError, IndexError, TypeError, ValueError): return False @@ -292,7 +329,7 @@ def is_volt_sdgm_profile(cp: CarParams, *, longitudinal=False) -> bool: not cp.notCar and control_flags(cp) == 0 and cp.openpilotLongitudinalControl == longitudinal and cp.pcmCruise != longitudinal and (not longitudinal or cp.alphaLongitudinalAvailable) and len(cp.safetyConfigs) == 1 and cp.safetyConfigs[0].safetyModel == CarParams.SafetyModel.gm and - cp.safetyConfigs[0].safetyParam in words) + gm_control_word(cp) in words) except (AttributeError, IndexError, TypeError, ValueError): return False @@ -304,7 +341,7 @@ def is_volt_longitudinal(cp: CarParams) -> bool: def is_volt_gateway_alternate_brake(cp: CarParams) -> bool: """The exact gateway Volt profile using EBCM pedal input and PT friction output.""" - return is_volt_gateway_profile(cp) and bool(cp.safetyConfigs[0].safetyParam & GMSafetyFlags.VOLT_GATEWAY_ALT_BRAKE) + return is_volt_gateway_profile(cp) and bool(gm_control_word(cp) & GMSafetyFlags.VOLT_GATEWAY_ALT_BRAKE) class Footnote(Enum): diff --git a/opendbc_repo/opendbc/safety/modes/gm.h b/opendbc_repo/opendbc/safety/modes/gm.h index 7df887169d..ced34ec417 100644 --- a/opendbc_repo/opendbc/safety/modes/gm.h +++ b/opendbc_repo/opendbc/safety/modes/gm.h @@ -3,6 +3,7 @@ #include "opendbc/safety/declarations.h" #include "opendbc/safety/can_tx.h" #include "gm_aol.h" +#include "gm_volt_one_pedal.h" #include "gm_bolt_cc.h" #include "gm_cc_pedal.h" #include "gm_volt_auto_hold.h" @@ -405,6 +406,7 @@ static void gm_rx_hook(const CANPacket_t *msg) { } gm_cc_pedal_rx(msg); + gm_one_pedal_observe(msg); gm_hold_rx(msg); } @@ -714,7 +716,7 @@ static bool gm_fwd_hook(int bus_num, int addr) { } static safety_config gm_init(uint16_t safety_param) { - uint16_t param = safety_param; + uint16_t param = gm_one_pedal_reset(safety_param); gm_cc_pedal_silverado = (safety_param == 0xC182U) || (safety_param == 0xC183U) || (safety_param == 0xC184U) || (safety_param == 0xC185U); gm_cc_pedal_ordinary_stock = (safety_param == 0xC186U) || (safety_param == 0xC187U); diff --git a/opendbc_repo/opendbc/safety/modes/gm_aol.h b/opendbc_repo/opendbc/safety/modes/gm_aol.h index 1e283ba47a..080dd972ec 100644 --- a/opendbc_repo/opendbc/safety/modes/gm_aol.h +++ b/opendbc_repo/opendbc/safety/modes/gm_aol.h @@ -72,6 +72,7 @@ static void gm_aol_initialize(bool profile_supported) { static bool gm_aol_profile_word(uint16_t word) { bool supported = false; switch (word) { + case 0xD100U: case 0xD101U: case 0xD110U: case 0xD111U: case 0U: case 0x80U: case 0x201U: case 0x601U: case 0xA01U: case 0xE01U: case 0xC171U: case 0xC172U: case 5U: @@ -87,6 +88,11 @@ static bool gm_aol_profile_word(uint16_t word) { case 0xC130U: case 0xC131U: case 0xC140U: case 0xC141U: case 0xC150U: #ifdef ALLOW_DEBUG + case 0xD102U: case 0xD103U: case 0xD104U: case 0xD105U: + case 0xD106U: case 0xD107U: case 0xD108U: case 0xD109U: + case 0xD10AU: case 0xD112U: case 0xD113U: case 0xD114U: + case 0xD115U: case 0xD116U: case 0xD117U: case 0xD118U: + case 0xD119U: case 0xD11AU: case 0x1003U: case 0x1403U: case 0x203U: case 0x603U: case 0xA03U: case 0xE03U: case 0xC170U: case 0xC173U: diff --git a/opendbc_repo/opendbc/safety/modes/gm_bolt_cc.h b/opendbc_repo/opendbc/safety/modes/gm_bolt_cc.h index bf6080853f..523b11a904 100644 --- a/opendbc_repo/opendbc/safety/modes/gm_bolt_cc.h +++ b/opendbc_repo/opendbc/safety/modes/gm_bolt_cc.h @@ -211,6 +211,7 @@ static void gm_bolt_cc_rx(const CANPacket_t *msg) { } static void gm_bolt_cc_optional_rx(const CANPacket_t *msg) { + gm_one_pedal_observe(msg); if (gm_bolt_cc_selected && (msg->addr == 0xBDU) && (msg->bus == 0U) && (GET_LEN(msg) == 7U)) { gm_bolt_cc_profile_rx(msg); } diff --git a/opendbc_repo/opendbc/safety/modes/gm_volt_auto_hold.h b/opendbc_repo/opendbc/safety/modes/gm_volt_auto_hold.h index b4cf074197..6f0c90d2f9 100644 --- a/opendbc_repo/opendbc/safety/modes/gm_volt_auto_hold.h +++ b/opendbc_repo/opendbc/safety/modes/gm_volt_auto_hold.h @@ -22,6 +22,7 @@ static bool gm_hold_regen; static bool gm_hold_stopped; static bool gm_hold_armed; static bool gm_hold_moving; +static bool gm_hold_one_pedal_moving; static uint8_t gm_hold_acc; static uint32_t gm_hold_drive_us; static uint32_t gm_hold_regen_release_us; @@ -29,6 +30,10 @@ static bool gm_hold_regen_released; static bool gm_hold_counter_seen; static uint8_t gm_hold_counter; +static void gm_one_pedal_withdraw(void) { + if (!gm_one_pedal_config.paired_auto_hold) { gm_hold_accepted = false; } +} + typedef struct { bool enabled; bool alternate; @@ -53,7 +58,7 @@ static void gm_hold_reset(const GMHoldConfig *config) { for (uint8_t i = 0U; i < 7U; i++) { gm_hold_seen[i] = false; gm_hold_us[i] = 0U; } gm_hold_brake_unavailable = true; gm_hold_main = false; gm_hold_forward = false; gm_hold_gas = false; - gm_hold_brake = false; gm_hold_regen = false; gm_hold_stopped = false; gm_hold_armed = false; gm_hold_moving = false; + gm_hold_brake = false; gm_hold_regen = false; gm_hold_stopped = false; gm_hold_armed = false; gm_hold_moving = false; gm_hold_one_pedal_moving = false; gm_hold_acc = 0U; gm_hold_drive_us = 0U; gm_hold_regen_release_us = 0U; gm_hold_regen_released = false; gm_hold_counter_seen = false; gm_hold_counter = 0U; } @@ -68,13 +73,20 @@ static bool gm_hold_sources_current(uint32_t now) { return current; } -static bool gm_hold_ready(uint32_t now) { +static bool gm_hold_physical_ready(uint32_t now) { if (gm_hold_regen_released && (safety_get_ts_elapsed(now, gm_hold_regen_release_us) >= 1000000U)) { gm_hold_regen_released = false; } - const bool cooldown = gm_hold_regen_released; return !safety_rx_checks_invalid && !relay_malfunction && gm_hold_sources_current(now) && gm_hold_main && gm_hold_forward && !gm_hold_gas && - !gm_hold_regen && !gm_hold_brake_unavailable && !cooldown && (gm_hold_drive_us >= 3000000U); + !gm_hold_regen && !gm_hold_brake_unavailable && (gm_hold_drive_us >= 3000000U); +} + +static bool gm_hold_ready(uint32_t now) { + return gm_hold_physical_ready(now) && !gm_hold_regen_released; +} + +static bool gm_one_pedal_physical_ready(uint32_t now) { + return gm_one_pedal_mode_qualified(now) && !gm_hold_brake && gm_hold_physical_ready(now); } static void gm_hold_rx(const CANPacket_t *msg) { @@ -106,6 +118,7 @@ static void gm_hold_rx(const CANPacket_t *msg) { gm_hold_stopped = (left <= 10U) && (right <= 10U); gm_hold_near_stop = (left <= 28U) && (right <= 28U); if (!gm_hold_near_stop) { gm_hold_accepted = false; } + gm_hold_one_pedal_moving = (left > 10U) && (right > 10U); gm_hold_moving = (left > 0U) || (right > 0U); const uint32_t elapsed = safety_get_ts_elapsed(now, gm_hold_us[4]); // Raw wheel units are .0311 km/h; twelve units exceed .1 m/s. @@ -123,10 +136,14 @@ static void gm_hold_rx(const CANPacket_t *msg) { // Unrelated or malformed traffic cannot refresh physical authority. } if (source >= 0) { gm_hold_seen[source] = true; gm_hold_us[source] = now; } - if (!gm_hold_ready(now)) { gm_hold_armed = false; gm_hold_accepted = false; } + if (!gm_hold_ready(now)) { + gm_hold_armed = false; + if (!gm_one_pedal_physical_ready(now)) { gm_hold_accepted = false; } + } else if (gm_hold_moving || gm_hold_brake) { gm_hold_armed = true; } else { /* Retain a previously armed stopped hold. */ } - if (get_longitudinal_allowed()) { gm_hold_accepted = false; } + if (get_longitudinal_allowed() || (gm_one_pedal_config.enabled && !gm_one_pedal_config.paired_auto_hold && + (!gm_one_pedal_mode_qualified(now) || gm_hold_brake))) { gm_hold_accepted = false; } } } @@ -142,15 +159,27 @@ static bool gm_hold_brake_tx(const CANPacket_t *msg, int brake) { (checksum == expected) && ((msg->data[4] & 0xFCU) == 0U) && (release || !gm_hold_counter_seen || (counter == ((gm_hold_counter + 1U) & 3U))); const bool hold_mode = (((mode == 0xAU) || (mode == 0xBU)) && (gm_hold_acc != 4U)) || ((mode == 0xDU) && (gm_hold_acc == 4U)); - if (!gm_hold_ready(now)) { gm_hold_armed = false; gm_hold_accepted = false; } - const bool stationary = gm_hold_stopped || (gm_hold_sdgm && gm_hold_accepted && gm_hold_near_stop); + if (!gm_hold_ready(now)) { + gm_hold_armed = false; + if (!gm_one_pedal_physical_ready(now)) { gm_hold_accepted = false; } + } const int minimum = gm_hold_sdgm ? 100 : 80; - const bool hold = gm_hold_armed && gm_hold_ready(now) && stationary && + const bool one_pedal_mode = gm_one_pedal_mode_qualified(now); + if (gm_one_pedal_config.enabled && !gm_one_pedal_config.paired_auto_hold && (!one_pedal_mode || gm_hold_brake)) { gm_hold_accepted = false; } + const bool stationary = gm_hold_stopped || (gm_hold_sdgm && gm_hold_accepted && gm_hold_near_stop); + const bool auto_hold_owner = (!gm_one_pedal_config.enabled || gm_one_pedal_config.paired_auto_hold) && + gm_hold_armed && gm_hold_ready(now); + const bool one_pedal_owner = gm_one_pedal_config.enabled && one_pedal_mode && !gm_hold_brake && gm_hold_physical_ready(now); + const bool hold = auto_hold_owner && stationary && (brake >= minimum) && (brake <= 240) && hold_mode; - const bool permitted = packet_valid && (release || hold); + const bool one_pedal_brake = one_pedal_owner && hold_mode && (brake <= 400) && + ((gm_hold_stopped && (brake >= minimum)) || (gm_hold_one_pedal_moving && (brake >= 0))); + const bool permitted = packet_valid && (release || hold || one_pedal_brake); if (permitted) { gm_hold_counter_seen = true; gm_hold_counter = counter; - gm_hold_accepted = !release; + if (release || !hold) { gm_hold_accepted = false; } + else if (gm_hold_stopped) { gm_hold_accepted = true; } + else { /* Retain credit only from an accepted stationary hold. */ } } return permitted; } diff --git a/opendbc_repo/opendbc/safety/modes/gm_volt_one_pedal.h b/opendbc_repo/opendbc/safety/modes/gm_volt_one_pedal.h new file mode 100644 index 0000000000..18a9146914 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/gm_volt_one_pedal.h @@ -0,0 +1,101 @@ +#pragma once + +#define GM_ONE_PEDAL_MODE_TIMEOUT_US 300000U + +typedef struct { + bool enabled; + bool paired_auto_hold; + uint16_t canonical_hold_word; +} GMOnePedalConfig; + +static GMOnePedalConfig gm_one_pedal_config = {0}; +static bool gm_one_pedal_low; +static bool gm_one_pedal_mode; +static bool gm_one_pedal_mode_seen; +static uint32_t gm_one_pedal_mode_us; + +static uint16_t gm_one_pedal_reset(uint16_t word) { + gm_one_pedal_config = (GMOnePedalConfig){0}; + gm_one_pedal_low = false; + gm_one_pedal_mode = false; + gm_one_pedal_mode_seen = false; + gm_one_pedal_mode_us = 0U; + switch (word) { + case 0xD100U: case 0xD110U: + gm_one_pedal_config.canonical_hold_word = 0x4084U; + gm_one_pedal_config.paired_auto_hold = word == 0xD110U; + break; + case 0xD101U: case 0xD111U: + gm_one_pedal_config.canonical_hold_word = 0xC084U; + gm_one_pedal_config.paired_auto_hold = word == 0xD111U; + break; +#ifdef ALLOW_DEBUG + case 0xD102U: case 0xD112U: + gm_one_pedal_config.canonical_hold_word = 0x4287U; + gm_one_pedal_config.paired_auto_hold = word == 0xD112U; + break; + case 0xD103U: case 0xD113U: + gm_one_pedal_config.canonical_hold_word = 0x4687U; + gm_one_pedal_config.paired_auto_hold = word == 0xD113U; + break; + case 0xD104U: case 0xD114U: + gm_one_pedal_config.canonical_hold_word = 0x4A87U; + gm_one_pedal_config.paired_auto_hold = word == 0xD114U; + break; + case 0xD105U: case 0xD115U: + gm_one_pedal_config.canonical_hold_word = 0x4E87U; + gm_one_pedal_config.paired_auto_hold = word == 0xD115U; + break; + case 0xD106U: case 0xD116U: + gm_one_pedal_config.canonical_hold_word = 0x4087U; + gm_one_pedal_config.paired_auto_hold = word == 0xD116U; + break; + case 0xD107U: case 0xD117U: + gm_one_pedal_config.canonical_hold_word = 0x5087U; + gm_one_pedal_config.paired_auto_hold = word == 0xD117U; + break; + case 0xD108U: case 0xD118U: + gm_one_pedal_config.canonical_hold_word = 0x5487U; + gm_one_pedal_config.paired_auto_hold = word == 0xD118U; + break; + case 0xD109U: case 0xD119U: + gm_one_pedal_config.canonical_hold_word = 0xC1D1U; + gm_one_pedal_config.paired_auto_hold = word == 0xD119U; + break; + case 0xD10AU: case 0xD11AU: + gm_one_pedal_config.canonical_hold_word = 0xC1D3U; + gm_one_pedal_config.paired_auto_hold = word == 0xD11AU; + break; +#endif + default: + break; + } + gm_one_pedal_config.enabled = gm_one_pedal_config.canonical_hold_word != 0U; + return gm_one_pedal_config.enabled ? gm_one_pedal_config.canonical_hold_word : word; +} + +static bool gm_one_pedal_mode_qualified(uint32_t now); +static void gm_one_pedal_withdraw(void); + +static void gm_one_pedal_observe(const CANPacket_t *msg) { + if (gm_one_pedal_config.enabled && (msg->bus == 0U)) { + if ((msg->addr == 0x1F5U) && (GET_LEN(msg) == 8U)) { + gm_one_pedal_low = ((msg->data[3] & 0xFU) == 6U) && !GET_BIT(msg, 41U); + } else if ((msg->addr == 0x3C7U) && (GET_LEN(msg) == 4U)) { + gm_one_pedal_mode = GET_BIT(msg, 7U); + gm_one_pedal_mode_seen = true; + gm_one_pedal_mode_us = microsecond_timer_get(); + } else { + // Other traffic cannot refresh mode or physical Low. + } + if (!gm_one_pedal_mode_qualified(microsecond_timer_get())) { gm_one_pedal_withdraw(); } + } +} + +static bool gm_one_pedal_mode_qualified(uint32_t now) { + // Cadence is unknown: this is a bounded observation, not a periodic RX claim. + if (gm_one_pedal_mode_seen && (safety_get_ts_elapsed(now, gm_one_pedal_mode_us) > GM_ONE_PEDAL_MODE_TIMEOUT_US)) { + gm_one_pedal_mode_seen = false; + } + return gm_one_pedal_config.enabled && (gm_one_pedal_low || (gm_one_pedal_mode_seen && gm_one_pedal_mode)); +} diff --git a/opendbc_repo/opendbc/safety/tests/test_gm_volt_auto_hold.py b/opendbc_repo/opendbc/safety/tests/test_gm_volt_auto_hold.py index b0227f00f6..167e9a8c06 100644 --- a/opendbc_repo/opendbc/safety/tests/test_gm_volt_auto_hold.py +++ b/opendbc_repo/opendbc/safety/tests/test_gm_volt_auto_hold.py @@ -11,9 +11,10 @@ from opendbc.safety.tests.libsafety import libsafety_py class TestVoltAutoHold(unittest.TestCase): - def init(self, alternate=False, extra=0, alternative=0, word=None): + def init(self, alternate=False, extra=0, alternative=0, word=None, physical_word=None): self.safety = libsafety_py.libsafety - self.alternate = alternate or word == 0xC1D3 + physical_word = word if physical_word is None else physical_word + self.alternate = alternate or physical_word in (0xC084, 0xC1D3) self.safety.set_alternative_experience(alternative) word = int(GMSafetyFlags.EV | GMSafetyFlags.VOLT_GATEWAY_LONG | GMSafetyFlags.VOLT_AUTO_HOLD) if word is None else word if alternate: @@ -23,8 +24,9 @@ class TestVoltAutoHold(unittest.TestCase): self.time = 1 self.counter = 0 self.packer = CANPacker(DBC[CAR.CHEVROLET_VOLT][Bus.pt]) - self.c9_brake = word in (0x4687, 0x4E87, 0x4087, 0x5487, 0xC1D1, 0xC1D3) - self.tx_bus = 0 if word in (0x4287, 0x4687, 0x4A87, 0x4E87, 0x4087, 0xC1D1, 0xC1D3) or alternate else 2 + physical_word = word if physical_word is None else physical_word + self.c9_brake = physical_word in (0x4687, 0x4E87, 0x4087, 0x5487, 0xC1D1, 0xC1D3) + self.tx_bus = 0 if physical_word in (0x4287, 0x4687, 0x4A87, 0x4E87, 0x4087, 0xC1D1, 0xC1D3) or self.alternate else 2 def tearDown(self): libsafety_py.libsafety.set_alternative_experience(0) diff --git a/opendbc_repo/opendbc/safety/tests/test_gm_volt_gateway_mapping.py b/opendbc_repo/opendbc/safety/tests/test_gm_volt_gateway_mapping.py index 0b629714f2..2fd5a0159e 100644 --- a/opendbc_repo/opendbc/safety/tests/test_gm_volt_gateway_mapping.py +++ b/opendbc_repo/opendbc/safety/tests/test_gm_volt_gateway_mapping.py @@ -43,7 +43,10 @@ class TestGmVoltGatewayMapping(unittest.TestCase): expected = [EXACT, EXACT | int(GMSafetyFlags.VOLT_GATEWAY_ALT_BRAKE), EXACT | int(GMSafetyFlags.VOLT_AUTO_HOLD), EXACT | int(GMSafetyFlags.VOLT_GATEWAY_ALT_BRAKE | GMSafetyFlags.VOLT_AUTO_HOLD)] + expected += [0xD100, 0xD101, 0xD110, 0xD111] if not release: + expected += [0xD102, 0xD103, 0xD104, 0xD105, 0xD106, 0xD107, 0xD108, 0xD109, 0xD10A, + 0xD112, 0xD113, 0xD114, 0xD115, 0xD116, 0xD117, 0xD118, 0xD119, 0xD11A] expected += [7, 515, 1539, 2563, 3587, 4099, 5123, 16391, 16903, 17927, 18951, 19975, 20487, 21511, 49489, 49520, 49523, 0x4287, 0x4687, 0x4A87, 0x4E87, 0x4087, 0x5087, 0x5487, 0xC1D1, 0xC1D3] self.assertEqual(accepted, sorted(expected)) diff --git a/opendbc_repo/opendbc/safety/tests/test_gm_volt_one_pedal.py b/opendbc_repo/opendbc/safety/tests/test_gm_volt_one_pedal.py new file mode 100644 index 0000000000..cff313167f --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_gm_volt_one_pedal.py @@ -0,0 +1,209 @@ +"""Exact Volt inactive OnePedal source, routing and stopped-owner contracts.""" +import unittest + +from opendbc.car.gm import gmcan +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +from opendbc.safety.tests import test_gm_volt_auto_hold as hold_fixture + +CANONICAL = (0x4084, 0xC084, 0x4287, 0x4687, 0x4A87, 0x4E87, 0x4087, 0x5087, 0x5487, 0xC1D1, 0xC1D3) + + +class TestVoltOnePedal(unittest.TestCase): + def fixture(self, index, paired=False, alternative=0): + self.release = libsafety_py.libsafety.set_safety_hooks(CarParams.SafetyModel.allOutput, 0) != 0 + f = hold_fixture.TestVoltAutoHold() + f.init(word=0xD100 + index + (0x10 if paired else 0), physical_word=CANONICAL[index], alternative=alternative) + return f + + def tearDown(self): + libsafety_py.libsafety.set_alternative_experience(0) + + def mode(self, f, active=True, bus=0, length=4): + frame = f.packer.make_can_msg('EVDriveMode', bus, {'SinglePedalModeActive': int(active)}) + self.assertEqual(frame[1][0] & 0x80, 0x80 if active else 0) + f.rx(frame[0], frame[1][:length], bus) + + def test_all_exact_profiles_moving_and_stopped_bounds(self): + for paired in (False, True): + for index in range(11): + with self.subTest(index=index, paired=paired): + f = self.fixture(index, paired) + denied = self.release and index >= 2 + for _ in range(32): + f.observations(gear=6, healthy=not denied) + self.assertEqual(f.tx(400), not denied) + self.assertFalse(f.tx(401)) + self.assertFalse(f.safety.safety_tx_hook(f.frame(bus=2 if f.tx_bus == 0 else 0))) + f.observations(speed=0, gear=6, healthy=not denied) + minimum = 100 if index in (7, 8) else 80 + self.assertFalse(f.tx(minimum - 1)) + self.assertEqual(f.tx(minimum), not denied) + self.assertEqual(f.tx(240), not denied) + self.assertEqual(f.tx(400), not denied) + self.assertFalse(f.tx(401)) + self.assertEqual(f.tx(0, 1), not denied) + + def test_solo_mode_and_paired_hold_are_distinct(self): + for index in range(11): + if self.release_mode() and index >= 2: + continue + for paired in (False, True): + f = self.fixture(index, paired) + f.dwell() + self.assertEqual(f.tx(), paired) + self.mode(f) + self.assertTrue(f.tx()) + f.observations(speed=0, brake=True) + self.assertEqual(f.tx(), paired) + f.observations(speed=0) + self.mode(f, False) + self.assertEqual(f.tx(), paired) + + @staticmethod + def release_mode(): + return libsafety_py.libsafety.set_safety_hooks(CarParams.SafetyModel.allOutput, 0) != 0 + + def test_mode_current_observation_low_and_physical_withdrawal(self): + for paired in (False, True): + f = self.fixture(0, paired) + f.dwell() + f.observations(speed=100) + self.mode(f, bus=2) + self.assertFalse(f.tx(400)) + self.mode(f, length=3) + self.assertFalse(f.tx(400)) + self.mode(f) + self.assertTrue(f.tx(400)) + for _ in range(4): + f.observations(speed=100) + self.assertFalse(f.tx(400)) + f.time = 0xFFFFFF00 - 100000 + f.observations(speed=100) + self.assertFalse(f.tx(400)) + f.time = 0 + f.observations(speed=100) + self.assertFalse(f.tx(400)) # Expired mode cannot revive at a 32-bit timer wrap. + f.observations(speed=100, gear=6) + self.assertTrue(f.tx(400)) # Fresh Low needs no drive-mode frame. + f.observations(speed=100, gear=6, manual=True) + self.assertFalse(f.tx(400)) + for changed in ({'main': False}, {'gas': True}, {'brake': True}, {'regen': True}, {'gear': 2}, {'brake_unavailable': True}): + f = self.fixture(0, paired) + for _ in range(32): + f.observations(gear=6) + self.assertTrue(f.tx(400)) + f.observations(gear=6, **changed) if 'gear' not in changed else f.observations(**changed) + self.assertFalse(f.tx(400)) + self.assertTrue(f.tx(0, 1)) + + def test_moving_does_not_seed_sdgm_hold_credit_or_mixed_wheels(self): + for index in (7, 8): + f = self.fixture(index) + if self.release: + self.assertFalse(f.tx()) + continue + for _ in range(32): + f.observations(gear=6) + self.assertTrue(f.tx(400)) + f.observations(speed=20, gear=4) + self.assertFalse(f.tx()) # No accepted stationary hold; mode withdrawn. + self.mode(f) + self.assertTrue(f.tx(400)) + f.observations(speed=0) + self.mode(f) + self.assertTrue(f.tx(100)) + f.observations(speed=20) + self.mode(f) + self.assertTrue(f.tx(240)) + self.assertTrue(f.tx(400)) + self.mode(f, False) + self.mode(f) + self.assertTrue(f.tx(400)) # Mode withdrawal cleared old stop credit before reactivation. + self.assertTrue(f.tx(0, 1)) + self.assertTrue(f.tx(400)) # Explicitly moving after released stop credit. + f = self.fixture(0) + for _ in range(32): + f.observations(gear=6) + f.rx(0x34A, [0, 20, 0, 0, 0]) + self.assertFalse(f.tx(400)) + + def test_no_positive_gas_and_unknown_tags_reset(self): + f = self.fixture(0, alternative=32) + for _ in range(32): + f.observations(gear=6) + f.safety.set_aol_test_heartbeat(True) + f.safety.aol_set_host_request(1) + self.assertTrue(f.tx(400)) + for gas, enabled, accepted in ((-650, False, True), (-649, False, False), (1, False, False), (-650, True, False)): + frame = gmcan.create_gas_regen_command(f.packer, 0, gas, 0, enabled, False) + self.assertEqual(f.safety.safety_tx_hook(libsafety_py.make_CANPacket(frame[0], frame[2], frame[1])), accepted) + for word in (0xD0FF, 0xD10B, 0xD10F, 0xD11B, 0xD11F, 0xD120): + f.init(word=word) + for _ in range(32): + f.observations(gear=6, healthy=False) + self.assertFalse(f.tx(400)) + f.init() + for _ in range(32): + f.observations(gear=6) + self.assertFalse(f.tx(400)) + f.observations(speed=0) + self.assertTrue(f.tx(80)) + + def test_one_pedal_release_is_immediate_but_independent_hold_keeps_cooldown(self): + for paired in (False, True): + for stopped in (False, True): + f = self.fixture(0, paired) + for _ in range(32): + f.observations(gear=6) + speed = 0 if stopped else 100 + f.observations(speed=speed, gear=6, regen=True) + self.assertFalse(f.tx(100)) + f.observations(speed=speed, gear=6) + self.assertTrue(f.tx(100)) + f = self.fixture(0, paired=True) + f.dwell() + f.observations(speed=0, brake=True, regen=True) + f.observations(speed=0, brake=True) + self.assertFalse(f.tx()) + for _ in range(10): + f.observations(speed=0, brake=True) + self.assertTrue(f.tx()) + + def test_independent_paired_hold_keeps_240_and_sdgm_credit(self): + for index in (0, 7, 8): + f = self.fixture(index, paired=True) + if self.release and index >= 2: + self.assertFalse(f.tx()) + continue + f.dwell() + self.assertTrue(f.tx(240)) + self.assertFalse(f.tx(241)) + if index in (7, 8): + f.observations(speed=20) + self.assertTrue(f.tx(240)) + self.assertFalse(f.tx(241)) + self.assertTrue(f.tx(0, 1)) + self.assertFalse(f.tx(240)) + f.observations(speed=0, gear=6) + self.assertTrue(f.tx(400)) + f.observations(speed=0, gear=6, brake=True) + self.assertTrue(f.tx(240)) + self.assertFalse(f.tx(241)) + + def test_only_independent_auto_hold_seeds_sdgm_mixed_wheel_credit(self): + for index in (7, 8): + for paired in (False, True): + with self.subTest(index=index, paired=paired): + f = self.fixture(index, paired) + if self.release: + self.assertFalse(f.tx(200)) + continue + for _ in range(32): + f.observations(gear=6) + f.observations(speed=0, gear=6) + self.assertTrue(f.tx(200)) + f.rx(0x34A, [0, 20, 0, 0, 0]) + self.assertEqual(f.tx(200), paired) + self.assertTrue(f.tx(0, 1)) + self.assertFalse(f.tx(200)) diff --git a/openpilot/common/params_keys.h b/openpilot/common/params_keys.h index a9f32b99a6..2adffd51dc 100644 --- a/openpilot/common/params_keys.h +++ b/openpilot/common/params_keys.h @@ -24,6 +24,7 @@ inline static std::unordered_map keys = { {"ToyotaAutoHold", {PERSISTENT, BOOL, "0"}}, {"VoltSNG", {PERSISTENT, BOOL, "0"}}, {"GMAutoHold", {PERSISTENT, BOOL, "0"}}, + {"VoltOnePedalMode", {PERSISTENT, BOOL, "0"}}, {"HondaBoschARadar", {PERSISTENT, BOOL, "1"}}, {"HondaGasFactorParams", {PERSISTENT, FLOAT, "1.0"}}, {"HondaWindFactorParams", {PERSISTENT, FLOAT, "1.0"}}, diff --git a/openpilot/selfdrive/pandad/tests/test_aol_protocol.cc b/openpilot/selfdrive/pandad/tests/test_aol_protocol.cc index b0400344c8..1688bafea8 100644 --- a/openpilot/selfdrive/pandad/tests/test_aol_protocol.cc +++ b/openpilot/selfdrive/pandad/tests/test_aol_protocol.cc @@ -180,7 +180,11 @@ int main() { forte.safety_mode = HYUNDAI_AOL_PROFILE.mode; assert(!aol_capable(forte, HYUNDAI_AOL_PROFILE.mode, VEHICLE_REGISTRY)); } - for (const uint16_t word : {0U, 0x80U}) { + for (const uint16_t word : {0U, 0x80U, + 0xD100U, 0xD101U, 0xD102U, 0xD103U, 0xD104U, 0xD105U, + 0xD106U, 0xD107U, 0xD108U, 0xD109U, 0xD10AU, + 0xD110U, 0xD111U, 0xD112U, 0xD113U, 0xD114U, 0xD115U, + 0xD116U, 0xD117U, 0xD118U, 0xD119U, 0xD11AU}) { AolAxisNegotiator negotiator(VEHICLE_REGISTRY); FakeTransport transport; auto gateway = status(); @@ -190,20 +194,26 @@ int main() { queue(transport, gateway, gateway); const auto first = run(negotiator, transport, axis("gateway"), NOW, GM_AOL_PROFILE.mode); assert(first.plan.capable && first.plan.request_mask == 0U && first.outcome.compatible); + assert(first.outcome.status && first.outcome.status->safety_param == word); auto active = gateway; active.request_mask = 3U; active.permission_mask = 1U; queue(transport, gateway, active); const auto second = run(negotiator, transport, axis("gateway", true, true), NOW, GM_AOL_PROFILE.mode); assert(second.plan.capable && second.plan.request_mask == 3U && second.outcome.compatible); - assert(second.outcome.status && second.outcome.status->permission_mask == 1U); + assert(second.outcome.status && second.outcome.status->permission_mask == 1U && second.outcome.status->safety_param == word); } - for (const uint16_t word : {0x40U, 0x81U, 0x82U, 0x84U, 0x180U}) { + for (const uint16_t word : {0x40U, 0x81U, 0x82U, 0x84U, 0x180U, 0xD0FFU, 0xD10BU, 0xD10FU, 0xD11BU, 0xD11FU, 0xD120U}) { assert(!gm_aol_param(word)); auto unknown = status(); unknown.safety_mode = GM_AOL_PROFILE.mode; unknown.safety_param = word; assert(!aol_capable(unknown, GM_AOL_PROFILE.mode, VEHICLE_REGISTRY)); + AolAxisNegotiator negotiator(VEHICLE_REGISTRY); + FakeTransport transport; + queue(transport, unknown, unknown); + const auto rejected = run(negotiator, transport, axis(), NOW, GM_AOL_PROFILE.mode); + assert(!rejected.plan.capable && rejected.plan.request_mask == 0U && !rejected.outcome.compatible); } for (uint32_t word = 0U; word <= 65535U; word++) { auto gm = status(); diff --git a/openpilot/starpilot/aol/tests/test_gm.py b/openpilot/starpilot/aol/tests/test_gm.py index 86c34dce0a..10fcf900fc 100644 --- a/openpilot/starpilot/aol/tests/test_gm.py +++ b/openpilot/starpilot/aol/tests/test_gm.py @@ -16,7 +16,7 @@ from opendbc.car.gm.tests.test_bolt_volt_configurations import ordinary_params from opendbc.car.gm.tests.test_volt_camera_control import camera_params from opendbc.car.gm.tests.test_volt_camera_removed import removed_params from opendbc.car.gm.tests.test_volt_sdgm_control import sdgm_params -from opendbc.car.gm.values import CAR, DBC, ORDINARY_ASCM_CAR, ORDINARY_SDGM_CAR, ORDINARY_CAMERA_CAR, ORDINARY_CC_CAR +from opendbc.car.gm.values import CAR, DBC, ORDINARY_ASCM_CAR, ORDINARY_SDGM_CAR, ORDINARY_CAMERA_CAR, ORDINARY_CC_CAR, is_volt_one_pedal from openpilot.cereal import messaging from openpilot.common.params import Params from openpilot.common.prefix import OpenpilotPrefix @@ -106,6 +106,11 @@ def configurations(): VehicleStartupPreferences(gm_auto_hold=True).prepare(selected) if selected.safetyConfigs[0].safetyParam != cp.safetyConfigs[0].safetyParam: yield selected + for paired in (False, True): + selected = cp.as_reader().as_builder() + VehicleStartupPreferences(volt_one_pedal=True, gm_auto_hold=paired).prepare(selected) + if is_volt_one_pedal(selected): + yield selected class TestGmAol(unittest.TestCase): diff --git a/openpilot/starpilot/car/gm/aol_policy.h b/openpilot/starpilot/car/gm/aol_policy.h index fc42cb3d34..76a5950891 100644 --- a/openpilot/starpilot/car/gm/aol_policy.h +++ b/openpilot/starpilot/car/gm/aol_policy.h @@ -4,6 +4,12 @@ inline bool gm_aol_param(uint16_t param) { switch (param) { + case 0xD100U: case 0xD101U: case 0xD102U: case 0xD103U: + case 0xD104U: case 0xD105U: case 0xD106U: case 0xD107U: + case 0xD108U: case 0xD109U: case 0xD10AU: case 0xD110U: + case 0xD111U: case 0xD112U: case 0xD113U: case 0xD114U: + case 0xD115U: case 0xD116U: case 0xD117U: case 0xD118U: + case 0xD119U: case 0xD11AU: case 0U: case 0x80U: case 0x201U: case 0x601U: case 0xA01U: case 0xE01U: case 0x203U: case 0x603U: case 0xA03U: case 0xE03U: diff --git a/openpilot/starpilot/car/gm/auto_hold.py b/openpilot/starpilot/car/gm/auto_hold.py index b0d455ee2d..56303fc5cc 100644 --- a/openpilot/starpilot/car/gm/auto_hold.py +++ b/openpilot/starpilot/car/gm/auto_hold.py @@ -1,15 +1,18 @@ -from opendbc.car.gm.values import is_gm_auto_hold +from opendbc.car.gm.values import is_gm_auto_hold, is_volt_one_pedal from openpilot.starpilot.saved_source import read_saved class AutoHoldPreference: - def __init__(self, cp, params): - self.cp, self.params = cp, params + def __init__(self, cp, params, key="GMAutoHold"): + if key not in ("GMAutoHold", "VoltOnePedalMode"): + raise ValueError("Unsupported GM stop preference") + self.cp, self.params, self.key = cp, params, key + self.supported = is_volt_one_pedal if key == "VoltOnePedalMode" else is_gm_auto_hold self.read_ns = 0 self.enabled = False def update(self, now_ns): - if type(now_ns) is not int or now_ns <= 0 or not is_gm_auto_hold(self.cp): + if type(now_ns) is not int or now_ns <= 0 or not self.supported(self.cp): self.enabled = False return False if now_ns < self.read_ns: @@ -19,7 +22,7 @@ class AutoHoldPreference: if self.read_ns == 0 or now_ns - self.read_ns >= 250_000_000: self.read_ns = now_ns try: - choice = read_saved(self.params, "GMAutoHold", 8) + choice = read_saved(self.params, self.key, 8) safe, safe_valid = read_saved(self.params, "SafeMode", 8) longitudinal, long_valid = read_saved(self.params, "DisableOpenpilotLongitudinal", 8) master = read_saved(self.params, "OpenpilotEnabledToggle", 8) diff --git a/openpilot/starpilot/controller_extensions.py b/openpilot/starpilot/controller_extensions.py index 5cceb1db7e..b53b210101 100644 --- a/openpilot/starpilot/controller_extensions.py +++ b/openpilot/starpilot/controller_extensions.py @@ -110,10 +110,13 @@ class ResumePlanInputs: def configure_controller(CI, params): cp = CI.CP controller = CI.CC - from opendbc.car.gm.values import is_gm_auto_hold + from opendbc.car.gm.values import is_gm_auto_hold, is_volt_one_pedal if controller is not None and is_gm_auto_hold(cp) and controller.gm_auto_hold: from openpilot.starpilot.car.gm.auto_hold import AutoHoldPreference controller.gm_auto_hold_input = AutoHoldPreference(cp, params) + if controller is not None and is_volt_one_pedal(cp) and controller.volt_one_pedal: + from openpilot.starpilot.car.gm.auto_hold import AutoHoldPreference + controller.volt_one_pedal_input = AutoHoldPreference(cp, params, "VoltOnePedalMode") from opendbc.car.gm.values import is_volt_longitudinal if controller is not None and is_volt_longitudinal(cp) and controller.volt_sng: try: diff --git a/openpilot/starpilot/galaxy/vehicle_configuration.py b/openpilot/starpilot/galaxy/vehicle_configuration.py index dd3c8c44b9..88880b53fb 100644 --- a/openpilot/starpilot/galaxy/vehicle_configuration.py +++ b/openpilot/starpilot/galaxy/vehicle_configuration.py @@ -5,7 +5,7 @@ from openpilot.starpilot.vehicle_selection import read_selection STARTUP_KEYS = ('AlphaLongitudinalEnabled', 'IsReleaseBranch', 'OpenpilotEnabledToggle', 'SafeMode', - 'DisableOpenpilotLongitudinal', 'ToyotaAutoHold', 'VoltSNG', 'GMAutoHold', 'TurnAssist', 'LongPitch', + 'DisableOpenpilotLongitudinal', 'ToyotaAutoHold', 'VoltSNG', 'GMAutoHold', 'VoltOnePedalMode', 'TurnAssist', 'LongPitch', 'HondaBoschARadar', 'NAPPedalEnabled', 'NAPRadarEnabled', 'NAPRadarBehindNosecone') diff --git a/openpilot/starpilot/tests/test_gm_pitch_preferences.py b/openpilot/starpilot/tests/test_gm_pitch_preferences.py index 4fb412c39a..e1eed71cb8 100644 --- a/openpilot/starpilot/tests/test_gm_pitch_preferences.py +++ b/openpilot/starpilot/tests/test_gm_pitch_preferences.py @@ -75,7 +75,10 @@ class TestGMPitchStartupAndSettings(unittest.TestCase): from opendbc.car.gm.interface import CarInterface from openpilot.starpilot.vehicle_selection import encode from openpilot.starpilot.ui.feature_settings_state import FeaturePage, row_change, row_default - settings = (("VoltSNG", "volt_sng", (CAR.CHEVROLET_VOLT, CAR.CHEVROLET_VOLT_ASCM, + from openpilot.starpilot.ui.vehicle_bool import confirmation_question + settings = (("VoltOnePedalMode", "volt_one_pedal", (CAR.CHEVROLET_VOLT, CAR.CHEVROLET_VOLT_ASCM, + CAR.CHEVROLET_VOLT_CAMERA, CAR.CHEVROLET_VOLT_2019)), + ("VoltSNG", "volt_sng", (CAR.CHEVROLET_VOLT, CAR.CHEVROLET_VOLT_ASCM, CAR.CHEVROLET_VOLT_CAMERA, CAR.CHEVROLET_VOLT_2019)), ("GMAutoHold", "gm_auto_hold", (CAR.CHEVROLET_VOLT, CAR.CHEVROLET_VOLT_ASCM, CAR.CHEVROLET_VOLT_CAMERA, CAR.CHEVROLET_VOLT_2019, CAR.BUICK_LACROSSE))) @@ -95,11 +98,16 @@ class TestGMPitchStartupAndSettings(unittest.TestCase): self.assertEqual("regen paddle" in row().reason, identity != CAR.BUICK_LACROSSE) change = row_change(row()) assert change is not None + question = confirmation_question(change) + if key == "GMAutoHold": + self.assertEqual("regen paddle" in question, identity != CAR.BUICK_LACROSSE) + elif key == "VoltOnePedalMode": + self.assertIn("Lifting off the accelerator can apply the brakes", question) self.assertTrue(owner.apply(replace(change, confirmation=True))) self.assertEqual(self.saved.get_bool(key), change.value == 'On') self.assertTrue(owner.apply(row_default(row()))) self.assertFalse(self.saved.get_bool(key)) - controller = SimpleNamespace(volt_sng=False, gm_auto_hold=False, long_pitch=True) + controller = SimpleNamespace(volt_sng=False, gm_auto_hold=False, volt_one_pedal=False, long_pitch=True) VehicleStartupPreferences(**{preference: True}).configure_controller(SimpleNamespace(CP=cp, CC=controller)) self.assertFalse(getattr(controller, preference)) fresh = row() diff --git a/openpilot/starpilot/tests/test_vehicle_preferences.py b/openpilot/starpilot/tests/test_vehicle_preferences.py index 517c6ac1cf..4f60fb5549 100644 --- a/openpilot/starpilot/tests/test_vehicle_preferences.py +++ b/openpilot/starpilot/tests/test_vehicle_preferences.py @@ -27,7 +27,7 @@ class TestVehicleStartupPreferences(unittest.TestCase): def test_gm_stop_preferences_require_strict_saved_opt_in(self): from openpilot.common.params import ParamKeyType - for key, name in (("VoltSNG", "volt_sng"), ("GMAutoHold", "gm_auto_hold")): + for key, name in (("VoltSNG", "volt_sng"), ("GMAutoHold", "gm_auto_hold"), ("VoltOnePedalMode", "volt_one_pedal")): self.raw("SafeMode", None) self.assertEqual(self.params.get_type(key), ParamKeyType.BOOL) self.assertIs(self.params.get_default_value(key), False) @@ -43,29 +43,31 @@ class TestVehicleStartupPreferences(unittest.TestCase): from opendbc.car.gm.tests.test_bolt_volt_configurations import ordinary_params from opendbc.car.gm.values import CAR as GM_CAR from openpilot.starpilot.car.gm.auto_hold import AutoHoldPreference - cp = ordinary_params(GM_CAR.CHEVROLET_VOLT, radar=True) - VehicleStartupPreferences(gm_auto_hold=True).prepare(cp) - now = 1_000_000_000 - for key in ("GMAutoHold", "OpenpilotEnabledToggle", "SafeMode", "DisableOpenpilotLongitudinal"): - for raw in (b"0", b"1", b"", b"true", None): - for clean_key, value in (("GMAutoHold", b"1"), ("OpenpilotEnabledToggle", b"1"), - ("SafeMode", b"0"), ("DisableOpenpilotLongitudinal", b"0")): - self.raw(clean_key, value) - owner = AutoHoldPreference(cp, self.params) - self.assertTrue(owner.update(now)) - self.raw(key, raw) - now += 250_000_000 - expected = raw == b"1" if key in ("GMAutoHold", "OpenpilotEnabledToggle") else raw in (None, b"0") - self.assertEqual(owner.update(now), expected, (key, raw)) - self.assertFalse(owner.update(now - 1)) - cp.passive = True - self.assertFalse(owner.update(now)) - cp.passive = False - preferences = VehicleStartupPreferences(gm_auto_hold=True, disable_bolt_long=True) - preferences.prepare(cp) - preferences.finalize(cp) - self.assertFalse(cp.openpilotLongitudinalControl) - self.assertEqual(cp.safetyConfigs[0].safetyParam, 0x4004) + for preference in ("GMAutoHold", "VoltOnePedalMode"): + cp = ordinary_params(GM_CAR.CHEVROLET_VOLT, radar=True) + VehicleStartupPreferences(gm_auto_hold=preference == "GMAutoHold", + volt_one_pedal=preference == "VoltOnePedalMode").prepare(cp) + now = 1_000_000_000 + for key in (preference, "OpenpilotEnabledToggle", "SafeMode", "DisableOpenpilotLongitudinal"): + for raw in (b"0", b"1", b"", b"true", None): + for clean_key, value in ((preference, b"1"), ("OpenpilotEnabledToggle", b"1"), + ("SafeMode", b"0"), ("DisableOpenpilotLongitudinal", b"0")): + self.raw(clean_key, value) + owner = AutoHoldPreference(cp, self.params, preference) + self.assertTrue(owner.update(now)) + self.raw(key, raw) + now += 250_000_000 + expected = raw == b"1" if key in (preference, "OpenpilotEnabledToggle") else raw in (None, b"0") + self.assertEqual(owner.update(now), expected, (preference, key, raw)) + self.assertFalse(owner.update(now - 1)) + cp.passive = True + self.assertFalse(owner.update(now)) + cp.passive = False + preferences = VehicleStartupPreferences(gm_auto_hold=True, volt_one_pedal=True, disable_bolt_long=True) + preferences.prepare(cp) + preferences.finalize(cp) + self.assertFalse(cp.openpilotLongitudinalControl) + self.assertEqual(cp.safetyConfigs[0].safetyParam, 0x4004) def test_suburban_saved_long_pitch_configures_exact_controller(self): from opendbc.car.gm.carcontroller import CarController @@ -156,6 +158,54 @@ class TestVehicleStartupPreferences(unittest.TestCase): else: self.assertEqual(published.safetyConfigs[0].safetyModel, structs.CarParams.SafetyModel.noOutput) + def test_volt_one_pedal_card_retains_exact_owner_and_withdrawal(self): + from opendbc.car.gm.values import CAR as GM_CAR, is_volt_one_pedal, gm_control_word + profiles = [ + (GM_CAR.CHEVROLET_VOLT, {0xBE: 6}, {0x460: 8}, {}, 0xD100), + (GM_CAR.CHEVROLET_VOLT, {}, {0x460: 8}, {}, 0xD101), + (GM_CAR.CHEVROLET_VOLT_ASCM, {0x2FF: 8, 0xBE: 6}, {}, {}, 0xD102), + (GM_CAR.CHEVROLET_VOLT_ASCM, {0x2FF: 8}, {}, {}, 0xD103), + (GM_CAR.CHEVROLET_VOLT_ASCM, {0x2FF: 8, 0xBE: 6}, {0x460: 8}, {}, 0xD104), + (GM_CAR.CHEVROLET_VOLT_ASCM, {0x2FF: 8}, {0x460: 8}, {}, 0xD105), + (GM_CAR.CHEVROLET_VOLT_CAMERA, {}, {}, {0x320: 6}, 0xD106), + (GM_CAR.CHEVROLET_VOLT_2019, {0x2FF: 8, 0xBE: 6}, {}, {}, 0xD107), + (GM_CAR.CHEVROLET_VOLT_2019, {0x2FF: 8}, {}, {}, 0xD108), + ] + for alternate in (False, True): + observed = {0x184: 8, 0x34A: 5, 0x1C4: 8, 0xC9: 8, 0x1E1: 7, 0xF1 if alternate else 0xBE: 6} + profiles.append((GM_CAR.CHEVROLET_VOLT_CAMERA, observed, {}, {}, 0xD109 + alternate)) + for candidate, pt, radar, camera, solo_word in profiles: + for paired in (False, True): + for state in ('on', 'off', 'live_off', 'master_off', 'safe', 'disable_long', 'release'): + with self.subTest(candidate=candidate, word=hex(solo_word), paired=paired, state=state): + observed = gen_empty_fingerprint() + observed[0], observed[1], observed[2] = dict(pt), dict(radar), dict(camera) + self.params.put_bool('AlphaLongitudinalEnabled', True, block=True) + self.params.put_bool('GMAutoHold', paired, block=True) + self.params.put_bool('SafeMode', state == 'safe', block=True) + self.params.put_bool('DisableOpenpilotLongitudinal', state == 'disable_long', block=True) + self.params.put_bool('IsReleaseBranch', state == 'release', block=True) + host, constructed, published = self.start(candidate, key='VoltOnePedalMode', observed=observed, + capture=lambda ci: int(ci.CS.CP.safetyConfigs[0].safetyParam), enabled=state != 'master_off', + requested=state != 'off', change_saved=state == 'live_off') + admitted = state in ('on', 'live_off') or state == 'release' and candidate == GM_CAR.CHEVROLET_VOLT + self.assertEqual(is_volt_one_pedal(published), admitted) + if admitted: + self.assertEqual(constructed, [solo_word + (0x10 if paired else 0)]) + self.assertEqual(published.safetyConfigs[0].safetyParam, constructed[0]) + self.assertTrue(host.CI.CC.volt_one_pedal) + self.assertEqual(host.CI.CC.volt_one_pedal_input.update(1_000_000_000), state != 'live_off') + self.assertEqual(host.CI.CC.gm_auto_hold, paired) + else: + self.assertFalse(host.CI.CC.volt_one_pedal) + self.assertIsNone(host.CI.CC.volt_one_pedal_input) + self.assertEqual(gm_control_word(host.CI.CP), host.CI.CP.safetyConfigs[0].safetyParam) + if state == 'master_off': + self.assertEqual(published.safetyConfigs[0].safetyModel, structs.CarParams.SafetyModel.noOutput) + if state == 'disable_long': + self.assertFalse(published.openpilotLongitudinalControl) + self.assertEqual(self.params.get_bool('VoltOnePedalMode'), state not in ('off', 'live_off')) + def test_camera_volt_hold_startup_retains_release_and_disable_longitudinal_owners(self): from opendbc.car.gm.values import CAR as GM_CAR, is_gm_auto_hold for candidate in (GM_CAR.CHEVROLET_VOLT_ASCM, GM_CAR.CHEVROLET_VOLT_CAMERA, GM_CAR.CHEVROLET_VOLT_2019): diff --git a/openpilot/starpilot/ui/feature_settings_owner.py b/openpilot/starpilot/ui/feature_settings_owner.py index bdd54b49aa..e707375d87 100644 --- a/openpilot/starpilot/ui/feature_settings_owner.py +++ b/openpilot/starpilot/ui/feature_settings_owner.py @@ -65,7 +65,8 @@ from openpilot.starpilot.controllers.toyota_cruise import capability as toyota_c BOOL_DEFAULTS = { "GMPedalLongitudinal": False, "ForceStops": False, "AlwaysAllowUploads": False, "TurnAssist": True, - "ReverseCruise": False, "ToyotaAutoHold": False, "VoltSNG": False, "GMAutoHold": False, "LongPitch": True, "DisableOpenpilotLongitudinal": False, + "ReverseCruise": False, "ToyotaAutoHold": False, "VoltSNG": False, "GMAutoHold": False, "VoltOnePedalMode": False, + "LongPitch": True, "DisableOpenpilotLongitudinal": False, "SpeedLimitController": False, "ShowSpeedLimits": False, "SLCConfirmation": False, "SLCConfirmationHigher": False, "SLCConfirmationLower": False, "LaneCentering": False, "LaneCenteringPauseOnSignal": True, @@ -255,7 +256,7 @@ class FeatureSettingsOwner: identities = {CAR.CHEVROLET_VOLT, CAR.CHEVROLET_VOLT_ASCM, CAR.CHEVROLET_VOLT_CAMERA, CAR.CHEVROLET_VOLT_2019} if key == "GMAutoHold": identities.add(CAR.BUICK_LACROSSE) - if key not in ("VoltSNG", "GMAutoHold") or cp is None or cp.brand != "gm" or cp.carFingerprint not in identities: + if key not in ("VoltSNG", "GMAutoHold", "VoltOnePedalMode") or cp is None or cp.brand != "gm" or cp.carFingerprint not in identities: return None selection = read_selection(self.params) if not selection.readable or not selection.valid: @@ -613,6 +614,12 @@ class FeatureSettingsOwner: row = self._bool_row("VoltSNG", "Volt Stop-and-Go Assistance", parked and self.authority("parked_preferences"), "Assists automatic resume from a cruise-controlled stop. Requires StarPilot speed control; applies after the next startup") rows.append(replace(row, available=row.available and self._readable("VoltSNG"), capability=sng_capability)) + one_pedal_capability = self._gm_stop_capability("VoltOnePedalMode") + if one_pedal_capability is not None: + row = self._bool_row("VoltOnePedalMode", "Volt One-Pedal Driving", parked and self.authority("parked_preferences"), + "With cruise main on and cruise disengaged, slows and holds when you lift off the accelerator in Low or single-pedal mode. " + + "Requires StarPilot speed control; applies after the next startup") + rows.append(replace(row, available=row.available and self._readable("VoltOnePedalMode"), capability=one_pedal_capability)) gm_hold_capability = self._gm_stop_capability("GMAutoHold") if gm_hold_capability is not None: from opendbc.car.gm.values import CAR @@ -993,7 +1000,7 @@ class FeatureSettingsOwner: return self._apply_pedal_setup(request) if key == "DisableOpenpilotLongitudinal": return self._apply_bolt_disable(request) - if key in ("VoltSNG", "GMAutoHold"): + if key in ("VoltSNG", "GMAutoHold", "VoltOnePedalMode"): return self._apply_gm_stop(request) if key == "LongPitch": return self._apply_long_pitch(request) diff --git a/openpilot/starpilot/ui/vehicle_bool.py b/openpilot/starpilot/ui/vehicle_bool.py index 83a69f4f33..eb91286026 100644 --- a/openpilot/starpilot/ui/vehicle_bool.py +++ b/openpilot/starpilot/ui/vehicle_bool.py @@ -1,6 +1,6 @@ """Confirmation text for parked vehicle preferences.""" -VEHICLE_BOOL_KEYS = frozenset(("GMPedalLongitudinal", "DisableOpenpilotLongitudinal", "LongPitch", "VoltSNG", "GMAutoHold")) +VEHICLE_BOOL_KEYS = frozenset(("GMPedalLongitudinal", "DisableOpenpilotLongitudinal", "LongPitch", "VoltSNG", "GMAutoHold", "VoltOnePedalMode")) def confirmation_question(request): @@ -16,7 +16,11 @@ def confirmation_question(request): if request.key == "VoltSNG": return f"{verb} Volt stop-and-go assistance after the next startup?" if request.key == "GMAutoHold": - return f"{verb} Automatic Brake Hold after the next startup? Press the gas or regen paddle to release a hold." + from opendbc.car.gm.values import CAR + release = "gas" if request.vehicle_fingerprint == CAR.BUICK_LACROSSE else "gas or regen paddle" + return f"{verb} Automatic Brake Hold after the next startup? Press the {release} to release a hold." + if request.key == "VoltOnePedalMode": + return f"{verb} Volt one-pedal driving after the next startup? Lifting off the accelerator can apply the brakes with cruise disengaged and cruise main on." if request.key == "LongPitch": return f"{verb} Grade Compensation after the next startup?" raise ValueError("Unsupported vehicle preference") diff --git a/openpilot/starpilot/vehicle_preferences.py b/openpilot/starpilot/vehicle_preferences.py index 775f39613b..d4dd5d7389 100644 --- a/openpilot/starpilot/vehicle_preferences.py +++ b/openpilot/starpilot/vehicle_preferences.py @@ -24,6 +24,7 @@ class VehicleStartupPreferences: tesla_preap_stock: bool = True volt_sng: bool = False gm_auto_hold: bool = False + volt_one_pedal: bool = False @classmethod def read(cls, params, *, enabled: bool): @@ -47,6 +48,8 @@ class VehicleStartupPreferences: readable and safe in (None, b"0")) gm_auto_hold = bool(enabled and not disable_bolt and read_saved(params, "GMAutoHold", 8) == (b"1", True) and readable and safe in (None, b"0")) + volt_one_pedal = bool(enabled and not disable_bolt and read_saved(params, "VoltOnePedalMode", 8) == (b"1", True) and + readable and safe in (None, b"0")) except (OSError, TypeError, ValueError): return cls(disable_bolt_long=disable_bolt, honda_bosch_a_radar=honda_radar, tesla_preap_stock=preap_stock) try: @@ -59,7 +62,7 @@ class VehicleStartupPreferences: assist = assist_readable and assist_raw in (None, b"1") except (OSError, TypeError, ValueError): assist = False - return cls(toyota_auto_hold=toyota, volt_sng=volt_sng, gm_auto_hold=gm_auto_hold, + return cls(toyota_auto_hold=toyota, volt_sng=volt_sng, gm_auto_hold=gm_auto_hold, volt_one_pedal=volt_one_pedal, turn_assist=bool(enabled and assist and readable and safe in (None, b"0")), gm_long_pitch=pitch_enabled, disable_bolt_long=disable_bolt, honda_bosch_a_radar=honda_radar, tesla_preap_stock=preap_stock) @@ -97,35 +100,40 @@ class VehicleStartupPreferences: cp.dashcamOnly = True def prepare(self, cp, *, fingerprints=None): - from opendbc.car.gm.values import apply_gm_auto_hold + from opendbc.car.gm.values import apply_gm_auto_hold, apply_volt_one_pedal from openpilot.starpilot.car.tesla.preap_preferences import prepare_stock prepare_stock(cp, self.tesla_preap_stock) self._prepare_honda_radar(cp) self._prepare_bolt(cp, fingerprints) prepare_disable_longitudinal(cp, self.disable_bolt_long) apply_gm_auto_hold(cp, self.gm_auto_hold) + apply_volt_one_pedal(cp, self.volt_one_pedal and not self.disable_bolt_long, self.gm_auto_hold) if cp.brand == "toyota": apply_toyota_auto_hold(cp, self.toyota_auto_hold) return cp def finalize(self, cp) -> None: - from opendbc.car.gm.values import apply_gm_auto_hold, is_gm_auto_hold + from opendbc.car.gm.values import apply_gm_auto_hold, is_gm_auto_hold, apply_volt_one_pedal, is_volt_one_pedal + admitted_one_pedal = is_volt_one_pedal(cp) + admitted_hold = is_gm_auto_hold(cp) from openpilot.starpilot.car.tesla.preap_preferences import prepare_stock prepare_stock(cp, self.tesla_preap_stock) self._prepare_honda_radar(cp) self._prepare_bolt(cp) prepare_disable_longitudinal(cp, self.disable_bolt_long) - apply_gm_auto_hold(cp, self.gm_auto_hold and is_gm_auto_hold(cp)) + apply_gm_auto_hold(cp, self.gm_auto_hold and admitted_hold) + apply_volt_one_pedal(cp, self.volt_one_pedal and admitted_one_pedal and not self.disable_bolt_long, self.gm_auto_hold and admitted_hold) if cp.brand == "toyota": admitted = bool(cp.flags & ToyotaFlags.AUTO_BRAKE_HOLD) apply_toyota_auto_hold(cp, self.toyota_auto_hold and admitted) def configure_controller(self, ci) -> None: - from opendbc.car.gm.values import CAR, is_bolt_euv_longitudinal, is_volt_longitudinal, is_gm_auto_hold + from opendbc.car.gm.values import CAR, is_bolt_euv_longitudinal, is_volt_longitudinal, is_gm_auto_hold, is_volt_one_pedal cp = ci.CP if ci.CC is not None and is_volt_longitudinal(cp): ci.CC.volt_sng = self.volt_sng if ci.CC is not None and cp.brand == "gm": ci.CC.gm_auto_hold = self.gm_auto_hold and is_gm_auto_hold(cp) + ci.CC.volt_one_pedal = self.volt_one_pedal and is_volt_one_pedal(cp) if ci.CC is not None and (is_bolt_euv_longitudinal(cp) or is_volt_longitudinal(cp) or cp.carFingerprint == CAR.CHEVROLET_SUBURBAN): ci.CC.long_pitch = self.gm_long_pitch