day2
This commit is contained in:
Binary file not shown.
@@ -38,6 +38,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"DoUninstall", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||
{"DriverTooDistracted", {CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON, BOOL}},
|
||||
{"AlphaLongitudinalEnabled", {PERSISTENT, BOOL}},
|
||||
{"ExperimentalLongitudinalEnabled", {PERSISTENT, BOOL}},
|
||||
{"ExperimentalMode", {PERSISTENT, BOOL}},
|
||||
{"ExperimentalModeConfirmed", {PERSISTENT, BOOL}},
|
||||
{"FirmwareQueryDone", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||
|
||||
Binary file not shown.
@@ -37,13 +37,13 @@ class FrogPilotCard:
|
||||
def handle_button_event(self, key, sm, frogpilot_toggles):
|
||||
if sm["carControl"].longActive and getattr(frogpilot_toggles, f"experimental_mode_via_{key}"):
|
||||
self.handle_experimental_mode(sm, frogpilot_toggles)
|
||||
elif sm["carControl"].longActive and getattr(frogpilot_toggles, f"force_coast_via_{key}"):
|
||||
elif getattr(frogpilot_toggles, f"force_coast_via_{key}"):
|
||||
self.force_coast = not self.force_coast
|
||||
elif getattr(frogpilot_toggles, f"pause_lateral_via_{key}"):
|
||||
self.pause_lateral = not self.pause_lateral
|
||||
elif sm["carControl"].longActive and getattr(frogpilot_toggles, f"pause_longitudinal_via_{key}"):
|
||||
elif getattr(frogpilot_toggles, f"pause_longitudinal_via_{key}"):
|
||||
self.pause_longitudinal = not self.pause_longitudinal
|
||||
elif getattr(frogpilot_toggles, f"traffic_mode_via_{key}"):
|
||||
elif sm["carControl"].longActive and getattr(frogpilot_toggles, f"traffic_mode_via_{key}"):
|
||||
self.traffic_mode_enabled = not self.traffic_mode_enabled
|
||||
|
||||
def handle_experimental_mode(self, sm, frogpilot_toggles):
|
||||
@@ -83,6 +83,8 @@ class FrogPilotCard:
|
||||
if sm.updated["frogpilotPlan"] or any(be.type == ButtonType.decelCruise for be in carState.buttonEvents):
|
||||
self.decel_pressed = any(be.type == ButtonType.decelCruise for be in carState.buttonEvents)
|
||||
|
||||
frogpilotCarState.distancePressed |= self.params_memory.get_bool("OnroadDistanceButtonPressed")
|
||||
|
||||
if frogpilotCarState.distancePressed:
|
||||
self.gap_counter += 1
|
||||
elif not self.distancePressed_previously:
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
|
||||
import numpy as np
|
||||
|
||||
from openpilot.common.realtime import DT_MDL
|
||||
@@ -21,7 +23,11 @@ class CurveSpeedController:
|
||||
|
||||
self.training_timer = 0
|
||||
|
||||
self.curvature_data = self.frogpilot_planner.params.get("CurvatureData")
|
||||
curvature_data_raw = self.frogpilot_planner.params.get("CurvatureData", encoding="utf-8")
|
||||
try:
|
||||
self.curvature_data = json.loads(curvature_data_raw or "{}")
|
||||
except (TypeError, ValueError):
|
||||
self.curvature_data = {}
|
||||
|
||||
self.calculate_weights()
|
||||
self.update_lateral_acceleration()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# PFEIFER - SLC - Modified by FrogAi for FrogPilot
|
||||
import calendar
|
||||
import json
|
||||
import numpy as np
|
||||
import requests
|
||||
|
||||
@@ -36,6 +37,7 @@ OFFSET_MAP_METRIC = [
|
||||
class SpeedLimitController:
|
||||
def __init__(self, FrogPilotVCruise):
|
||||
self.frogpilot_planner = FrogPilotVCruise.frogpilot_planner
|
||||
self.frogpilot_toggles = None
|
||||
|
||||
self.calling_mapbox = False
|
||||
self.override_slc = False
|
||||
@@ -53,14 +55,18 @@ class SpeedLimitController:
|
||||
self.previous_source = "None"
|
||||
self.source = "None"
|
||||
|
||||
self.mapbox_requests = self.frogpilot_planner.params.get("MapBoxRequests")
|
||||
mapbox_requests_raw = self.frogpilot_planner.params.get("MapBoxRequests", encoding="utf-8")
|
||||
try:
|
||||
self.mapbox_requests = json.loads(mapbox_requests_raw or "{}")
|
||||
except (TypeError, ValueError):
|
||||
self.mapbox_requests = {}
|
||||
self.mapbox_requests.setdefault("total_requests", 0)
|
||||
self.mapbox_requests.setdefault("max_requests", FREE_MAPBOX_REQUESTS - (28 * 100))
|
||||
|
||||
self.mapbox_host = "https://api.mapbox.com"
|
||||
self.mapbox_token = self.frogpilot_planner.params.get("MapboxSecretKey")
|
||||
self.mapbox_token = self.frogpilot_planner.params.get("MapboxSecretKey", encoding="utf-8")
|
||||
|
||||
self.previous_target = self.frogpilot_planner.params.get("PreviousSpeedLimit")
|
||||
self.previous_target = self.frogpilot_planner.params.get_float("PreviousSpeedLimit")
|
||||
|
||||
self.executor = ThreadPoolExecutor(max_workers=1)
|
||||
|
||||
@@ -70,10 +76,12 @@ class SpeedLimitController:
|
||||
|
||||
@property
|
||||
def experimental_mode(self):
|
||||
return self.target == 0 and self.frogpilot_toggles.slc_fallback_experimental_mode
|
||||
return self.target == 0 and bool(getattr(self.frogpilot_toggles, "slc_fallback_experimental_mode", False))
|
||||
|
||||
@property
|
||||
def offset(self):
|
||||
if self.frogpilot_toggles is None:
|
||||
return 0
|
||||
offset_map = OFFSET_MAP_METRIC if self.frogpilot_toggles.is_metric else OFFSET_MAP_IMPERIAL
|
||||
return next((getattr(self.frogpilot_toggles, offset) for low, high, offset in offset_map if low < self.target < high), 0)
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class WeatherChecker:
|
||||
self.last_updated = None
|
||||
self.requesting = False
|
||||
|
||||
self.user_api_key = self.frogpilot_planner.params.get("WeatherToken")
|
||||
self.user_api_key = self.frogpilot_planner.params.get("WeatherToken", encoding="utf-8")
|
||||
|
||||
if self.user_api_key:
|
||||
self.check_interval = 60
|
||||
|
||||
@@ -20,6 +20,13 @@ CAMERA_CANCEL_DELAY_FRAMES = 10
|
||||
MIN_STEER_MSG_INTERVAL_MS = 15
|
||||
|
||||
|
||||
def get_stock_cc_active_for_cancel(CP, CS):
|
||||
stock_cc_active = CS.out.cruiseState.enabled or CS.pcm_acc_status != AccState.OFF
|
||||
if CP.carFingerprint == CAR.CHEVROLET_BOLT_ACC_2022_2023_PEDAL:
|
||||
return CS.out.cruiseState.enabled
|
||||
return stock_cc_active
|
||||
|
||||
|
||||
class CarController(CarControllerBase):
|
||||
def __init__(self, dbc_names, CP):
|
||||
super().__init__(dbc_names, CP)
|
||||
@@ -529,16 +536,12 @@ class CarController(CarControllerBase):
|
||||
can_sends += gmcan.create_adas_keepalive(CanBus.POWERTRAIN)
|
||||
|
||||
# - CC_LONG: cancel stock CC if OP is not active
|
||||
stock_cc_active = CS.out.cruiseState.enabled or CS.pcm_acc_status != AccState.OFF
|
||||
# Pedal-long cancel should only run while stock cruise is actually enabled.
|
||||
# Using pcm_acc_status here causes cancel spam even after disable, which can
|
||||
# intermittently knock CruiseMain off.
|
||||
stock_cc_active_pedal = CS.out.cruiseState.enabled
|
||||
stock_cc_active = get_stock_cc_active_for_cancel(self.CP, CS)
|
||||
pedal_cancel = bool(self.CP.flags & GMFlags.PEDAL_LONG.value)
|
||||
if self.CP.carFingerprint == CAR.CHEVROLET_MALIBU_HYBRID_CC:
|
||||
pedal_cancel = pedal_cancel and CC.longActive
|
||||
|
||||
if ((pedal_cancel and stock_cc_active_pedal) or
|
||||
if ((pedal_cancel and stock_cc_active) or
|
||||
(((self.CP.flags & GMFlags.CC_LONG.value) and not CC.enabled) and stock_cc_active)):
|
||||
if self.CP.carFingerprint == CAR.CHEVROLET_MALIBU_HYBRID_CC:
|
||||
malibu_cancel_requested = True
|
||||
|
||||
@@ -319,9 +319,16 @@ class CarState(CarStateBase):
|
||||
self.cruise_buttons in (CruiseButtons.CANCEL, CruiseButtons.MAIN) or
|
||||
prev_cruise_buttons in (CruiseButtons.CANCEL, CruiseButtons.MAIN)
|
||||
)
|
||||
suppress_bolt_cancel_lkas = bolt_cancel_personality and (
|
||||
self.cruise_buttons == CruiseButtons.CANCEL or
|
||||
prev_cruise_buttons == CruiseButtons.CANCEL
|
||||
)
|
||||
distance_events = [] if suppress_malibu_side_buttons else create_button_events(
|
||||
self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}
|
||||
)
|
||||
lkas_events = [] if (suppress_malibu_side_buttons or suppress_bolt_cancel_lkas) else create_button_events(
|
||||
self.lkas_enabled, self.lkas_previously_enabled, {1: ButtonType.lkas}
|
||||
)
|
||||
|
||||
# Don't add events if transitioning from INIT, unless it's to an actual button.
|
||||
if self.cruise_buttons != CruiseButtons.UNPRESS or prev_cruise_buttons != CruiseButtons.INIT:
|
||||
@@ -329,6 +336,7 @@ class CarState(CarStateBase):
|
||||
*cruise_events,
|
||||
*cancel_gap_events,
|
||||
*distance_events,
|
||||
*lkas_events,
|
||||
]
|
||||
|
||||
if ret.vEgo < self.CP.minSteerSpeed:
|
||||
|
||||
@@ -116,23 +116,24 @@ def create_adas_keepalive(bus):
|
||||
|
||||
|
||||
def create_gas_regen_command(packer, bus, throttle, idx, enabled, at_full_stop, include_always_one3=False):
|
||||
# Legacy callsites may still pass include_always_one3; this DBC encodes ACC type explicitly instead.
|
||||
_ = include_always_one3
|
||||
values = {
|
||||
"GasRegenCmdActive": enabled,
|
||||
"RollingCounter": idx,
|
||||
"GasRegenCmd": throttle,
|
||||
"GasRegenFullStopActive": at_full_stop,
|
||||
"GasRegenAccType": 1,
|
||||
}
|
||||
# Keep GM camera-long GasRegen bytes aligned with StarPilot's legacy layout.
|
||||
# The regenerated DBC shape does not pack to the same wire format on Global A.
|
||||
dat = bytearray(8)
|
||||
dat[0] = ((idx & 0x3) << 6) | int(enabled)
|
||||
dat[1] = 0x42 | (0x20 if at_full_stop else 0x00)
|
||||
|
||||
dat = packer.make_can_msg("ASCMGasRegenCmd", bus, values)[1]
|
||||
values["GasRegenChecksum"] = ((1 - int(enabled)) << 24) | \
|
||||
(((0xff - dat[1]) & 0xff) << 16) | \
|
||||
(((0xff - dat[2]) & 0xff) << 8) | \
|
||||
((0x100 - dat[3] - idx) & 0xff)
|
||||
cmd = int(throttle) << 3
|
||||
dat[2] = (cmd >> 8) & 0xFF
|
||||
dat[3] = cmd & 0xFF
|
||||
if include_always_one3:
|
||||
dat[2] |= 0x80
|
||||
|
||||
return packer.make_can_msg("ASCMGasRegenCmd", bus, values)
|
||||
dat[4] = 0x00 if enabled else 0x01
|
||||
dat[5] = (0xFF - dat[1]) & 0xFF
|
||||
dat[6] = (0xFF - dat[2]) & 0xFF
|
||||
dat[7] = (0x100 - dat[3] - idx) & 0xFF
|
||||
|
||||
return CanData(0x2CB, bytes(dat), bus)
|
||||
|
||||
|
||||
def create_ecm_cruise_control_command(packer, bus, enabled, target_speed_kph):
|
||||
|
||||
@@ -527,6 +527,10 @@ class CarInterface(CarInterfaceBase):
|
||||
else:
|
||||
ret.longitudinalTuning.kfDEPRECATED = 0.25
|
||||
|
||||
if is_bolt_2022_2023_pedal:
|
||||
# Gen2 Bolt pedal-long should follow the no-ACC panda path like StarPilot.
|
||||
ret.safetyConfigs[0].safetyParam |= GMSafetyFlags.FLAG_GM_NO_ACC.value
|
||||
|
||||
if candidate in (CAR.CHEVROLET_BOLT_ACC_2022_2023_PEDAL, CAR.CHEVROLET_MALIBU_HYBRID_CC):
|
||||
ret.safetyConfigs[0].safetyParam |= GMSafetyFlags.FLAG_GM_BOLT_2022_PEDAL.value
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ from opendbc.car import DT_CTRL, CanData, structs
|
||||
from opendbc.car.car_helpers import interfaces
|
||||
from opendbc.car.fingerprints import FW_VERSIONS
|
||||
from opendbc.car.fw_versions import FW_QUERY_CONFIGS
|
||||
from opendbc.car.gm.values import CAR as GM_CAR, CanBus as GMCanBus, GMSafetyFlags
|
||||
from opendbc.car.interfaces import CarInterfaceBase, get_interface_attr
|
||||
from opendbc.car.mock.values import CAR as MOCK
|
||||
from opendbc.car.values import PLATFORMS
|
||||
@@ -57,6 +58,33 @@ def get_fuzzy_car_interface(car_name: str, draw: DrawType) -> CarInterfaceBase:
|
||||
|
||||
|
||||
class TestCarInterfaces:
|
||||
def test_gm_bolt_gen2_pedal_safety_flags(self):
|
||||
CarInterface = interfaces[GM_CAR.CHEVROLET_BOLT_ACC_2022_2023_PEDAL]
|
||||
|
||||
pedal_fingerprint = {bus: {} for bus in range(8)}
|
||||
pedal_fingerprint[GMCanBus.POWERTRAIN][0x201] = 6
|
||||
pedal_params = CarInterface.get_params(
|
||||
GM_CAR.CHEVROLET_BOLT_ACC_2022_2023_PEDAL,
|
||||
pedal_fingerprint,
|
||||
[],
|
||||
alpha_long=False,
|
||||
is_release=False,
|
||||
docs=False,
|
||||
)
|
||||
assert pedal_params.safetyConfigs[0].safetyParam & GMSafetyFlags.FLAG_GM_NO_ACC.value
|
||||
assert pedal_params.safetyConfigs[0].safetyParam & GMSafetyFlags.FLAG_GM_BOLT_2022_PEDAL.value
|
||||
|
||||
acc_fingerprint = {bus: {} for bus in range(8)}
|
||||
acc_params = CarInterface.get_params(
|
||||
GM_CAR.CHEVROLET_BOLT_ACC_2022_2023,
|
||||
acc_fingerprint,
|
||||
[],
|
||||
alpha_long=False,
|
||||
is_release=False,
|
||||
docs=False,
|
||||
)
|
||||
assert not (acc_params.safetyConfigs[0].safetyParam & GMSafetyFlags.FLAG_GM_NO_ACC.value)
|
||||
|
||||
# FIXME: Due to the lists used in carParams, Phase.target is very slow and will cause
|
||||
# many generated examples to overrun when max_examples > ~20, don't use it
|
||||
@pytest.mark.parametrize("car_name", sorted(PLATFORMS))
|
||||
|
||||
@@ -51,6 +51,7 @@ typedef enum {
|
||||
GM_CAM
|
||||
} GmHardware;
|
||||
static GmHardware gm_hw = GM_ASCM;
|
||||
static bool gm_cam_long = false;
|
||||
static bool gm_pcm_cruise = false;
|
||||
static bool gm_sdgm = false;
|
||||
static bool gm_ascm_int = false;
|
||||
@@ -178,10 +179,6 @@ static void gm_try_send_3d1_spoof(uint32_t now_us) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gm_3d1_scheduler_ready(now_us)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((int32_t)(now_us - gm_3d1_next_tx_us) < 0) {
|
||||
return;
|
||||
}
|
||||
@@ -509,6 +506,33 @@ static bool gm_tx_hook(const CANPacket_t *msg) {
|
||||
return tx;
|
||||
}
|
||||
|
||||
static bool gm_fwd_hook(int bus_num, int addr) {
|
||||
bool block_msg = false;
|
||||
|
||||
if ((gm_hw == GM_CAM) || gm_sdgm) {
|
||||
if (bus_num == 0) {
|
||||
bool is_pscm_msg = addr == 0x184U;
|
||||
// Keep the camera side sourced only from OP's spoofed cruise status on non-ACC paths.
|
||||
bool is_ecm_cruise_status_msg = (addr == 0x3D1U) && !gm_has_acc;
|
||||
block_msg = is_pscm_msg || is_ecm_cruise_status_msg;
|
||||
} else if (bus_num == 2) {
|
||||
bool is_lkas_msg = addr == 0x180U;
|
||||
bool is_acc_status_msg = addr == 0x370U;
|
||||
bool is_acc_actuation_msg = (addr == 0x315U) || (addr == 0x2CBU);
|
||||
|
||||
block_msg = is_lkas_msg;
|
||||
if (gm_cam_long || gm_pedal_long) {
|
||||
block_msg |= is_acc_status_msg;
|
||||
}
|
||||
if (gm_cam_long) {
|
||||
block_msg |= is_acc_actuation_msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return block_msg;
|
||||
}
|
||||
|
||||
static safety_config gm_init(uint16_t param) {
|
||||
const uint16_t GM_PARAM_HW_CAM = 1;
|
||||
const uint16_t GM_PARAM_HW_CAM_LONG = 2;
|
||||
@@ -663,7 +687,7 @@ static safety_config gm_init(uint16_t param) {
|
||||
gm_prndl2_state.phase_locked = false;
|
||||
gm_zero_u8(gm_prndl2_state.spoof_data, 8U);
|
||||
|
||||
bool gm_cam_long = GET_FLAG(param, GM_PARAM_HW_CAM_LONG);
|
||||
gm_cam_long = GET_FLAG(param, GM_PARAM_HW_CAM_LONG) && !gm_cc_long;
|
||||
gm_pcm_cruise = (gm_hw == GM_CAM || gm_sdgm) && !gm_cam_long && !gm_force_ascm && !gm_pedal_long;
|
||||
gm_steer_limits = GET_FLAG(param, GM_PARAM_BOLT_2017) ? &GM_BOLT_2017_STEERING_LIMITS : &GM_STEERING_LIMITS;
|
||||
|
||||
@@ -707,7 +731,7 @@ static safety_config gm_init(uint16_t param) {
|
||||
}
|
||||
|
||||
// ASCM does not forward any messages
|
||||
if (gm_hw == GM_ASCM || gm_cc_long) {
|
||||
if (gm_hw == GM_ASCM) {
|
||||
ret.disable_forwarding = true;
|
||||
}
|
||||
return ret;
|
||||
@@ -717,4 +741,5 @@ const safety_hooks gm_hooks = {
|
||||
.init = gm_init,
|
||||
.rx = gm_rx_hook,
|
||||
.tx = gm_tx_hook,
|
||||
.fwd = gm_fwd_hook,
|
||||
};
|
||||
|
||||
@@ -246,6 +246,7 @@ def interceptor_msg(gas, addr):
|
||||
|
||||
class TestGmInterceptorSafety(common.GasInterceptorSafetyTest, TestGmCameraSafety, TestGmEVSafetyBase):
|
||||
INTERCEPTOR_THRESHOLD = 550
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0x180, 0x370], 0: [0x184, 0x3D1]}
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerPanda("gm_global_a_powertrain_generated")
|
||||
@@ -292,9 +293,6 @@ class TestGmInterceptorSafety(common.GasInterceptorSafetyTest, TestGmCameraSafet
|
||||
self.assertEqual(enabled, self._tx(self._button_msg(Buttons.CANCEL)))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_fwd_hook(self):
|
||||
pass
|
||||
|
||||
def test_disable_control_allowed_from_cruise(self):
|
||||
pass
|
||||
|
||||
@@ -314,7 +312,7 @@ class TestGmInterceptorSafety(common.GasInterceptorSafetyTest, TestGmCameraSafet
|
||||
|
||||
class TestGmCcLongitudinalSafety(TestGmCameraSafety):
|
||||
TX_MSGS = [[0x180, 0], [0x370, 0], [0x1E1, 0], [0x3D1, 0], [0xBD, 0], [0x1F5, 0], [0x184, 2], [0x1E1, 2]]
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0x180], 0: [0x184]} # block LKAS message and PSCMStatus
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0x180], 0: [0x184, 0x3D1]} # block LKAS, PSCMStatus, and stock cruise status
|
||||
BUTTONS_BUS = 0 # tx only
|
||||
|
||||
def setUp(self):
|
||||
@@ -328,9 +326,6 @@ class TestGmCcLongitudinalSafety(TestGmCameraSafety):
|
||||
values = {"CruiseActive": enable}
|
||||
return self.packer.make_can_msg_panda("ECMCruiseControl", 0, values)
|
||||
|
||||
def test_fwd_hook(self):
|
||||
pass
|
||||
|
||||
def test_buttons(self):
|
||||
self.safety.set_controls_allowed(0)
|
||||
for btn in range(8):
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,2 +1,2 @@
|
||||
extern const uint8_t gitversion[19];
|
||||
const uint8_t gitversion[19] = "DEV-9ec91aa7-DEBUG";
|
||||
const uint8_t gitversion[19] = "DEV-60a7fb11-DEBUG";
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
DEV-9ec91aa7-DEBUG
|
||||
DEV-60a7fb11-DEBUG
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -250,6 +250,21 @@ def migrate_param_type_canonicalization(params: Params) -> None:
|
||||
cloudlog.exception(f"Failed to write migration flag: {STARPILOT_PARAM_CANONICALIZATION_MIGRATION_FLAG}")
|
||||
|
||||
|
||||
def migrate_legacy_experimental_longitudinal(params: Params, params_cache: Params) -> None:
|
||||
legacy_value = params.get("ExperimentalLongitudinalEnabled")
|
||||
if legacy_value is None:
|
||||
return
|
||||
|
||||
if params.get("AlphaLongitudinalEnabled") is None:
|
||||
alpha_long_enabled = params.get_bool("ExperimentalLongitudinalEnabled")
|
||||
params.put_bool("AlphaLongitudinalEnabled", alpha_long_enabled)
|
||||
params_cache.put_bool("AlphaLongitudinalEnabled", alpha_long_enabled)
|
||||
cloudlog.warning("Migrated legacy ExperimentalLongitudinalEnabled to AlphaLongitudinalEnabled")
|
||||
|
||||
params.remove("ExperimentalLongitudinalEnabled")
|
||||
params_cache.remove("ExperimentalLongitudinalEnabled")
|
||||
|
||||
|
||||
def manager_init() -> None:
|
||||
save_bootlog()
|
||||
|
||||
@@ -272,6 +287,9 @@ def manager_init() -> None:
|
||||
cache_params_path = os.path.join(Paths.comma_home(), "cache", "params")
|
||||
params_cache = Params(cache_params_path, return_defaults=True)
|
||||
|
||||
# Preserve StarPilot's legacy longitudinal toggle when switching branches.
|
||||
migrate_legacy_experimental_longitudinal(params, params_cache)
|
||||
|
||||
# Canonicalize legacy string encodings (e.g. INT params stored as "26.000000")
|
||||
# before bulk reads below to avoid repeated cast warnings and UI-side churn.
|
||||
migrate_param_type_canonicalization(params)
|
||||
|
||||
@@ -51,6 +51,40 @@ class TestManager:
|
||||
assert params.get("OpenpilotEnabledToggle")
|
||||
assert params.get("RouteCount") == 0
|
||||
|
||||
def test_migrate_legacy_experimental_longitudinal(self):
|
||||
class FakeParams:
|
||||
def __init__(self, values):
|
||||
self.values = dict(values)
|
||||
|
||||
def get(self, key):
|
||||
return self.values.get(key)
|
||||
|
||||
def get_bool(self, key):
|
||||
value = self.values.get(key)
|
||||
if value is None:
|
||||
return False
|
||||
if isinstance(value, bytes):
|
||||
value = value.decode("utf-8", errors="ignore")
|
||||
if isinstance(value, str):
|
||||
return value.strip().lower() in ("1", "true", "yes", "on")
|
||||
return bool(value)
|
||||
|
||||
def put_bool(self, key, value):
|
||||
self.values[key] = b"1" if value else b"0"
|
||||
|
||||
def remove(self, key):
|
||||
self.values.pop(key, None)
|
||||
|
||||
params = FakeParams({"ExperimentalLongitudinalEnabled": b"1"})
|
||||
params_cache = FakeParams({})
|
||||
|
||||
manager.migrate_legacy_experimental_longitudinal(params, params_cache)
|
||||
|
||||
assert params.get_bool("AlphaLongitudinalEnabled")
|
||||
assert params_cache.get_bool("AlphaLongitudinalEnabled")
|
||||
assert params.get("ExperimentalLongitudinalEnabled") is None
|
||||
assert params_cache.get("ExperimentalLongitudinalEnabled") is None
|
||||
|
||||
@pytest.mark.skip("this test is flaky the way it's currently written, should be moved to test_onroad")
|
||||
def test_clean_exit(self, subtests):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user