but you have heard of me

This commit is contained in:
firestar5683
2026-08-19 23:06:33 -05:00
parent d47be80928
commit 459d7c4099
102 changed files with 182 additions and 182 deletions
-1
View File
@@ -276,7 +276,6 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"DeveloperSidebarMetric7", {PERSISTENT, INT, "7", "0", 3}},
{"DeveloperUI", {PERSISTENT, BOOL, "0", "0", 3}},
{"GalaxyDeveloperMode", {PERSISTENT | DONT_LOG, BOOL, "0", "0", 0, SETTINGS_SIMPLE}},
{"TestModelLeadTrajectory", {PERSISTENT | DONT_LOG, BOOL, "0", "0", 0, SETTINGS_SIMPLE}},
{"DeveloperWidgets", {PERSISTENT, BOOL, "1", "0", 3}},
{"DeviceManagement", {PERSISTENT, BOOL, "1", "0", 1, SETTINGS_SIMPLE}},
{"DeviceShutdown", {PERSISTENT, INT, "6", "6", 1, SETTINGS_SIMPLE}},
@@ -706,30 +706,6 @@ class TestHyundaiFingerprint:
assert combined_safety_param & HyundaiSafetyFlags.LONG
assert combined_safety_param & HyundaiStarPilotSafetyFlags.AOL_LKAS_ON_ENGAGE
def test_sonata_hybrid_aol_main_lkas_sync_is_scoped(self):
toggles = SimpleNamespace(always_on_lateral_lkas=True, main_cruise_aol_toggle=True)
sonata_hybrid_cp = CarInterface.get_params(CAR.HYUNDAI_SONATA_HYBRID, gen_empty_fingerprint(), [], False, False, False, None)
sonata_hybrid_fpcp = CarInterface.get_starpilot_params(
CAR.HYUNDAI_SONATA_HYBRID, gen_empty_fingerprint(), [], sonata_hybrid_cp, toggles,
)
assert sonata_hybrid_fpcp.safetyConfigs[-1].safetyParam & HyundaiStarPilotSafetyFlags.AOL_MAIN_LKAS_SYNC
sonata_cp = CarInterface.get_params(CAR.HYUNDAI_SONATA, gen_empty_fingerprint(), [], False, False, False, None)
sonata_fpcp = CarInterface.get_starpilot_params(CAR.HYUNDAI_SONATA, gen_empty_fingerprint(), [], sonata_cp, toggles)
assert not (sonata_fpcp.safetyConfigs[-1].safetyParam & HyundaiStarPilotSafetyFlags.AOL_MAIN_LKAS_SYNC)
disabled_toggles = SimpleNamespace(always_on_lateral_lkas=True, main_cruise_aol_toggle=False)
disabled_fpcp = CarInterface.get_starpilot_params(
CAR.HYUNDAI_SONATA_HYBRID, gen_empty_fingerprint(), [], sonata_hybrid_cp, disabled_toggles,
)
assert not (disabled_fpcp.safetyConfigs[-1].safetyParam & HyundaiStarPilotSafetyFlags.AOL_MAIN_LKAS_SYNC)
minimal_fpcp = CarInterface.get_starpilot_params(
CAR.HYUNDAI_SONATA_HYBRID, gen_empty_fingerprint(), [], sonata_hybrid_cp, SimpleNamespace(),
)
assert not (minimal_fpcp.safetyConfigs[-1].safetyParam & HyundaiStarPilotSafetyFlags.AOL_MAIN_LKAS_SYNC)
@pytest.mark.parametrize("candidate", (CAR.HYUNDAI_ELANTRA_2021, CAR.HYUNDAI_SONATA_HYBRID))
def test_legacy_hyundai_long_does_not_gate_availability_on_main_cruise(self, candidate):
toggles = get_test_toggles()
@@ -111,7 +111,6 @@ class HyundaiSafetyFlags(IntFlag):
class HyundaiStarPilotSafetyFlags(IntFlag):
AOL_MAIN_LKAS_SYNC = 32
HAS_LDA_BUTTON = 1024
AOL_LKAS_ON_ENGAGE = 2048
+1 -4
View File
@@ -261,9 +261,6 @@ class CarInterfaceBase(ABC):
if params.get_bool("AlwaysOnLateral") and params.get_int("LKASButtonControl") == 9:
fp_ret.safetyConfigs[-1].safetyParam |= HyundaiStarPilotSafetyFlags.AOL_LKAS_ON_ENGAGE.value
if candidate == HYUNDAI.HYUNDAI_SONATA_HYBRID and getattr(starpilot_toggles, "always_on_lateral_lkas", False) and \
getattr(starpilot_toggles, "main_cruise_aol_toggle", False):
fp_ret.safetyConfigs[-1].safetyParam |= HyundaiStarPilotSafetyFlags.AOL_MAIN_LKAS_SYNC.value
elif platform in TOYOTA:
fp_ret.canUsePedal = not CP.autoResumeSng
fp_ret.canUseSDSU = candidate not in UNSUPPORTED_DSU_CAR and candidate not in TSS2_CAR
@@ -274,7 +271,7 @@ class CarInterfaceBase(ABC):
if 0x2FF in fingerprint[0] or (0x2AA in fingerprint[0] and candidate in NO_DSU_CAR):
fp_ret.flags |= ToyotaStarPilotFlags.SMART_DSU.value
if candidate == TOYOTA.TOYOTA_PRIUS:
if candidate in (TOYOTA.TOYOTA_PRIUS, TOYOTA.TOYOTA_PRIUS_RETROFIT):
if 0x23 in fingerprint[0]:
fp_ret.flags |= ToyotaStarPilotFlags.ZSS.value
@@ -27,7 +27,7 @@ class TestCanFingerprint:
fingerprint_iter = iter([can])
car_fingerprint, finger = can_fingerprint(lambda **kwargs: [next(fingerprint_iter, [])]) # noqa: B023
if car_model == TOYOTA.TOYOTA_MATRIX_RETROFIT:
if car_model in (TOYOTA.TOYOTA_MATRIX_RETROFIT, TOYOTA.TOYOTA_PRIUS_RETROFIT):
assert fingerprint == {}
assert car_fingerprint is None
elif car_fingerprint is None and str(car_model).startswith(("BUICK_", "CADILLAC_", "CHEVROLET_", "GMC_", "HOLDEN_")):
@@ -9,6 +9,7 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
"TOYOTA_ALPHARD_TSS2" = "TOYOTA_SIENNA"
"TOYOTA_PRIUS_V" = "TOYOTA_PRIUS"
"TOYOTA_PRIUS_RETROFIT" = "TOYOTA_PRIUS"
"TOYOTA_SIENNA_4TH_GEN" = "TOYOTA_RAV4_PRIME"
"LEXUS_IS" = "LEXUS_NX"
"LEXUS_CTH" = "LEXUS_NX"
@@ -11,7 +11,7 @@ from opendbc.car.interfaces import CarControllerBase
from opendbc.car.toyota import toyotacan
from opendbc.car.toyota.values import CAR, MIN_ACC_SPEED, NO_STOP_TIMER_CAR, PEDAL_TRANSITION, TSS2_CAR, \
CarControllerParams, ToyotaFlags, \
UNSUPPORTED_DSU_CAR
UNSUPPORTED_DSU_CAR, LEGACY_PRIUS_CAR
from opendbc.can import CANPacker
Ecu = structs.CarParams.Ecu
@@ -59,13 +59,17 @@ def is_camry_hybrid(CP) -> bool:
def is_ths_hybrid(CP) -> bool:
return CP.carFingerprint == CAR.TOYOTA_PRIUS or is_camry_hybrid(CP)
return CP.carFingerprint in LEGACY_PRIUS_CAR or is_camry_hybrid(CP)
def should_bypass_toyota_long_pid(CP) -> bool:
def should_bypass_toyota_long_pid(CP, starpilot_toggles=None) -> bool:
highlander_sdsu = (
CP.carFingerprint == CAR.TOYOTA_HIGHLANDER and
bool(getattr(starpilot_toggles, "has_sdsu", False))
)
return bool(CP.enableGasInterceptorDEPRECATED or (
CP.carFingerprint == CAR.TOYOTA_CAMRY and not is_camry_hybrid(CP)
))
) or highlander_sdsu)
def get_long_tune(CP, params):
@@ -74,7 +78,7 @@ def get_long_tune(CP, params):
k_f = 1.0
if is_ths_hybrid(CP):
k_f = 0.8 if CP.carFingerprint == CAR.TOYOTA_PRIUS else 1.0
k_f = 0.8 if CP.carFingerprint in LEGACY_PRIUS_CAR else 1.0
elif CP.carFingerprint not in TSS2_CAR:
kiBP = [0., 5., 35.]
kiV = [3.6, 2.4, 1.5]
@@ -454,7 +458,7 @@ class CarController(CarControllerBase):
a_ego_future = a_ego_blended + j_ego * future_t
if CC.longActive:
if should_bypass_toyota_long_pid(self.CP):
if should_bypass_toyota_long_pid(self.CP, starpilot_toggles):
# Pedal/SDSU Toyotas have shown better behavior when we trust the planner
# target directly instead of letting the Toyota longitudinal PID swing it
# around. Keep the shared rate limits above, but bypass the extra
@@ -477,7 +481,7 @@ class CarController(CarControllerBase):
pcm_accel_cmd += pitch_compensation
feedforward = pcm_accel_cmd
if self.CP.carFingerprint == CAR.TOYOTA_PRIUS:
if self.CP.carFingerprint in LEGACY_PRIUS_CAR:
feedforward = get_prius_feedforward(feedforward, CS.out.vEgo)
elif is_camry_hybrid(self.CP) and feedforward > 0.0:
# Preserve the established Camry Hybrid acceleration response while
@@ -507,7 +511,7 @@ class CarController(CarControllerBase):
else:
pcm_accel_cmd = limit_no_lead_cruise_sign_flip(pcm_accel_cmd, actuators.accel, stopping, CS.out.vEgo,
CS.out.cruiseState.speed, bool(hud_control.leadVisible))
if self.CP.carFingerprint == CAR.TOYOTA_PRIUS:
if self.CP.carFingerprint in LEGACY_PRIUS_CAR:
pcm_accel_cmd = limit_prius_stopping_accel(pcm_accel_cmd, actuators.accel, stopping, CS.out.vEgo, lead)
pcm_accel_cmd = float(np.clip(pcm_accel_cmd, self.params.ACCEL_MIN, self.params.ACCEL_MAX))
+2 -2
View File
@@ -8,7 +8,7 @@ from opendbc.car.common.filter_simple import FirstOrderFilter
from opendbc.car.interfaces import CarStateBase
from opendbc.car.toyota.values import ToyotaFlags, ToyotaStarPilotFlags, CAR, DBC, STEER_THRESHOLD, NO_STOP_TIMER_CAR, \
TSS2_CAR, RADAR_ACC_CAR, EPS_SCALE, UNSUPPORTED_DSU_CAR, \
SECOC_CAR
SECOC_CAR, LEGACY_PRIUS_CAR
ButtonType = structs.CarState.ButtonEvent.Type
SteerControlType = structs.CarParams.SteerControlType
@@ -23,7 +23,7 @@ TEMP_STEER_FAULTS = (0, 9, 11, 21, 25)
# - lka/lta msg drop out: 3 (recoverable)
# - prolonged high driver torque: 17 (permanent)
PERM_STEER_FAULTS = (3, 17)
LKAS_BUTTON_CAR = TSS2_CAR | {CAR.TOYOTA_PRIUS}
LKAS_BUTTON_CAR = TSS2_CAR | LEGACY_PRIUS_CAR
DISTANCE_BUTTON_CAR = {CAR.TOYOTA_SIENNA_4TH_GEN}
@@ -6,6 +6,7 @@ Ecu = CarParams.Ecu
FINGERPRINTS = {
CAR.TOYOTA_MATRIX_RETROFIT: [{}],
CAR.TOYOTA_PRIUS_RETROFIT: [{}],
}
FW_VERSIONS = {
+4 -4
View File
@@ -4,7 +4,7 @@ from opendbc.car.toyota.carcontroller import CarController
from opendbc.car.toyota.radar_interface import RadarInterface
from opendbc.car.toyota.values import Ecu, CAR, DBC, ToyotaFlags, CarControllerParams, TSS2_CAR, RADAR_ACC_CAR, SECOC_CAR, NO_DSU_CAR, \
MIN_ACC_SPEED, EPS_SCALE, NO_STOP_TIMER_CAR, ANGLE_CONTROL_CAR, \
ToyotaSafetyFlags
ToyotaSafetyFlags, LEGACY_PRIUS_CAR
from opendbc.car.disable_ecu import disable_ecu
from opendbc.car.interfaces import CarInterfaceBase
from opendbc.safety import ALTERNATIVE_EXPERIENCE
@@ -67,7 +67,7 @@ class CarInterface(CarInterfaceBase):
# These messages are normally absent there on pre-TSS2 platforms.
camera_fingerprint = fingerprint.get(2, {})
has_dsu_bypass = 0x343 in camera_fingerprint or 0x4CB in camera_fingerprint
late_prius_camera = candidate == CAR.TOYOTA_PRIUS and any(
late_prius_camera = candidate in LEGACY_PRIUS_CAR and any(
fw.ecu == Ecu.fwdCamera and bytes(fw.fwVersion).startswith(b'8646F4705') for fw in car_fw
)
if candidate in (CAR.LEXUS_IS, CAR.TOYOTA_CAMRY) or late_prius_camera:
@@ -83,7 +83,7 @@ class CarInterface(CarInterfaceBase):
if Ecu.hybrid in found_ecus:
ret.flags |= ToyotaFlags.HYBRID.value
if candidate == CAR.TOYOTA_PRIUS:
if candidate in LEGACY_PRIUS_CAR:
stop_and_go = True
ret.flags |= ToyotaFlags.HYBRID.value
# Only give steer angle deadzone to for bad angle sensor prius
@@ -175,7 +175,7 @@ class CarInterface(CarInterfaceBase):
# to a negative value, so it won't matter.
ret.minEnableSpeed = -1. if (stop_and_go or ret.enableGasInterceptorDEPRECATED) else MIN_ACC_SPEED
prius_long_defaults = candidate == CAR.TOYOTA_PRIUS and ret.openpilotLongitudinalControl
prius_long_defaults = candidate in LEGACY_PRIUS_CAR and ret.openpilotLongitudinalControl
camry_hybrid_long_defaults = (candidate == CAR.TOYOTA_CAMRY and ret.openpilotLongitudinalControl and
bool(ret.flags & ToyotaFlags.HYBRID.value))
@@ -75,6 +75,22 @@ class TestToyotaInterfaces:
assert default_params.lateralTuning.torque.steeringAngleDeadzoneDeg == pytest.approx(0.3)
assert forced_params.lateralTuning.torque.steeringAngleDeadzoneDeg == pytest.approx(0.3)
def test_prius_tss2_eps_retrofit_uses_legacy_body_and_eps_scale(self):
params = CarInterface.get_params(
CAR.TOYOTA_PRIUS_RETROFIT,
{bus: {} for bus in range(8)},
[],
False,
False,
False,
SimpleNamespace(force_torque_controller=False, nnff=False, nnff_lite=False),
)
assert params.lateralTuning.which() == "torque"
assert params.safetyConfigs[0].safetyParam & 0xFF == 73
assert params.flags & ToyotaFlags.TSS2.value == 0
assert params.steerRatio == pytest.approx(15.74)
def test_sienna_4th_gen_uses_torque_controller(self):
params = CarInterface.get_params(
CAR.TOYOTA_SIENNA_4TH_GEN,
@@ -469,6 +485,15 @@ class TestToyotaInterfaces:
assert not should_bypass_toyota_long_pid(car_params)
def test_highlander_sdsu_bypasses_toyota_longitudinal_pid(self):
car_params = SimpleNamespace(
carFingerprint=CAR.TOYOTA_HIGHLANDER,
enableGasInterceptorDEPRECATED=False,
)
assert should_bypass_toyota_long_pid(car_params, SimpleNamespace(has_sdsu=True))
assert not should_bypass_toyota_long_pid(car_params, SimpleNamespace(has_sdsu=False))
def test_camry_continental_radar_converts_absolute_target_speed(self):
radar_interface = RadarInterface.__new__(RadarInterface)
radar_interface.CP = SimpleNamespace(wheelSpeedFactor=1.0)
+8 -1
View File
@@ -250,6 +250,11 @@ class CAR(Platforms):
CarSpecs(mass=3045. * CV.LB_TO_KG, wheelbase=2.7, steerRatio=15.74, tireStiffnessFactor=0.6371),
dbc_dict('toyota_nodsu_pt_generated', 'toyota_adas'),
)
TOYOTA_PRIUS_RETROFIT = PlatformConfig(
[ToyotaCommunityCarDocs("Toyota Prius 2016-20 with TSS2 EPS retrofit", package="Custom retrofit")],
TOYOTA_PRIUS.specs,
dbc_dict('toyota_nodsu_pt_generated', 'toyota_adas'),
)
TOYOTA_PRIUS_V = PlatformConfig(
[ToyotaCarDocs("Toyota Prius v 2017", "Toyota Safety Sense P", min_enable_speed=MIN_ACC_SPEED)],
CarSpecs(mass=3340. * CV.LB_TO_KG, wheelbase=2.78, steerRatio=17.4, tireStiffnessFactor=0.5533),
@@ -599,9 +604,11 @@ STEER_THRESHOLD = 100
# These cars have non-standard EPS torque scale factors. All others are 73
EPS_SCALE = defaultdict(lambda: 73,
{CAR.TOYOTA_PRIUS: 66, CAR.TOYOTA_COROLLA: 88, CAR.TOYOTA_MATRIX_RETROFIT: 88,
{CAR.TOYOTA_PRIUS: 66, CAR.TOYOTA_PRIUS_RETROFIT: 73, CAR.TOYOTA_COROLLA: 88, CAR.TOYOTA_MATRIX_RETROFIT: 88,
CAR.LEXUS_IS: 77, CAR.LEXUS_RC: 77, CAR.LEXUS_CTH: 100, CAR.TOYOTA_PRIUS_V: 100})
LEGACY_PRIUS_CAR = frozenset((CAR.TOYOTA_PRIUS, CAR.TOYOTA_PRIUS_RETROFIT))
# Toyota/Lexus Safety Sense 2.0 and 2.5
TSS2_CAR = CAR.with_flags(ToyotaFlags.TSS2)
+1 -9
View File
@@ -90,7 +90,6 @@ static const CanMsg HYUNDAI_LONG_REFRESH_TX_MSGS[] = {
static bool hyundai_legacy = false;
static bool hyundai_can_canfd_blended_hda2 = false;
static bool hyundai_acc_main_on_rx_prev = false;
#define HYUNDAI_CAN_CANFD_BLENDED_HDA2_COMMON_RX_CHECKS() \
{.msg = {{0x260, 1, 8, 100U, .max_counter = 3U, .ignore_quality_flag = true}, \
@@ -194,12 +193,7 @@ static void hyundai_rx_hook(const CANPacket_t *msg) {
if (msg->addr == 0x420U) {
if (msg->bus == scc_bus) {
if (!hyundai_longitudinal) {
const bool acc_main_on_rx = GET_BIT(msg, hyundai_can_canfd_blended ? 27U : 0U);
if (hyundai_aol_main_lkas_sync && (acc_main_on_rx != hyundai_acc_main_on_rx_prev)) {
lkas_on = false;
}
acc_main_on = acc_main_on_rx;
hyundai_acc_main_on_rx_prev = acc_main_on_rx;
acc_main_on = GET_BIT(msg, hyundai_can_canfd_blended ? 27U : 0U);
}
}
}
@@ -448,8 +442,6 @@ static safety_config hyundai_init(uint16_t param) {
hyundai_common_init(param);
hyundai_legacy = false;
hyundai_can_canfd_blended_hda2 = hyundai_can_canfd_blended && hyundai_canfd_lka_steering;
hyundai_aol_main_lkas_sync = GET_FLAG(param, 32U);
hyundai_acc_main_on_rx_prev = false;
if (hyundai_can_canfd_blended) {
gen_crc_lookup_table_16(0x1021, hyundai_canfd_crc_lut);
@@ -60,9 +60,6 @@ bool hyundai_cancel_button_enable = false;
extern bool hyundai_can_refresh_msgs;
bool hyundai_can_refresh_msgs = false;
extern bool hyundai_aol_main_lkas_sync;
bool hyundai_aol_main_lkas_sync = false;
static uint8_t hyundai_last_button_interaction; // button messages since the user pressed an enable button
static bool acc_main_on_prev;
static bool acc_main_on_tx;
@@ -98,7 +95,6 @@ void hyundai_common_init(uint16_t param) {
hyundai_non_scc = GET_FLAG(param, HYUNDAI_PARAM_NON_SCC);
hyundai_cancel_button_enable = GET_FLAG(param, HYUNDAI_PARAM_CANCEL_BTN_ENABLE);
hyundai_can_refresh_msgs = GET_FLAG(param, HYUNDAI_PARAM_CAN_REFRESH_MSGS);
hyundai_aol_main_lkas_sync = false;
hyundai_last_button_interaction = HYUNDAI_PREV_BUTTON_SAMPLES;
acc_main_on_prev = false;
@@ -164,9 +160,7 @@ void hyundai_common_cruise_buttons_check(const int cruise_button, const bool mai
}
if (main_button && !main_button_prev) {
if (!hyundai_aol_main_lkas_sync) {
acc_main_on = !acc_main_on;
}
acc_main_on = !acc_main_on;
}
main_button_prev = main_button;
}
@@ -4,7 +4,6 @@ import unittest
from opendbc.car.hyundai.values import HyundaiSafetyFlags, HyundaiStarPilotSafetyFlags
from opendbc.car.structs import CarParams
from opendbc.safety import ALTERNATIVE_EXPERIENCE
from opendbc.safety.tests.libsafety import libsafety_py
import opendbc.safety.tests.common as common
from opendbc.safety.tests.common import CANPackerSafety
@@ -622,65 +621,5 @@ class TestHyundaiAolLkasOnEngageStockSafety(HyundaiAolLkasOnEngageStockBase, Tes
self.safety.init_tests()
class TestHyundaiAolMainLkasSyncSafety(TestHyundaiSafety):
def setUp(self):
self.packer = CANPackerSafety("hyundai_kia_generic")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(
CarParams.SafetyModel.hyundai,
HyundaiStarPilotSafetyFlags.HAS_LDA_BUTTON | HyundaiStarPilotSafetyFlags.AOL_MAIN_LKAS_SYNC,
)
self.safety.init_tests()
@staticmethod
def _lkas_button_msg(pressed):
dat = bytearray(8)
dat[0] = int(pressed) << 4
return libsafety_py.make_CANPacket(0x391, 0, bytes(dat))
def test_confirmed_main_state_rephases_lkas_button(self):
self.safety.set_alternative_experience(ALTERNATIVE_EXPERIENCE.ALWAYS_ON_LATERAL)
self.safety.set_controls_allowed(False)
self._rx(self._lkas_button_msg(True))
self._rx(self._lkas_button_msg(False))
self.assertTrue(self.safety.get_lkas_on())
self.assertTrue(self.safety.get_aol_allowed())
self._set_prev_torque(0)
self.assertTrue(self._tx(self._torque_cmd_msg(self.MAX_RATE_UP)))
self._rx(self._button_msg(Buttons.NONE, main_button=True))
self._rx(self._button_msg(Buttons.NONE, main_button=False))
self.assertFalse(self.safety.get_acc_main_on())
self.assertTrue(self.safety.get_lkas_on())
self.assertTrue(self.safety.get_aol_allowed())
self._rx(self._acc_state_msg(True))
self.assertFalse(self.safety.get_lkas_on())
self.assertTrue(self.safety.get_aol_allowed())
self._set_prev_torque(0)
self.assertTrue(self._tx(self._torque_cmd_msg(self.MAX_RATE_UP)))
self._rx(self._button_msg(Buttons.NONE, main_button=True))
self._rx(self._button_msg(Buttons.NONE, main_button=False))
self.assertTrue(self.safety.get_acc_main_on())
self.assertTrue(self.safety.get_aol_allowed())
self._rx(self._acc_state_msg(False))
self.assertFalse(self.safety.get_controls_allowed())
self.assertFalse(self.safety.get_acc_main_on())
self.assertFalse(self.safety.get_lkas_on())
self.assertFalse(self.safety.get_aol_allowed())
self._set_prev_torque(0)
self.assertFalse(self._tx(self._torque_cmd_msg(self.MAX_RATE_UP)))
self._rx(self._lkas_button_msg(True))
self._rx(self._lkas_button_msg(False))
self.assertTrue(self.safety.get_lkas_on())
self.assertTrue(self.safety.get_aol_allowed())
self._set_prev_torque(0)
self.assertTrue(self._tx(self._torque_cmd_msg(self.MAX_RATE_UP)))
if __name__ == "__main__":
unittest.main()
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
View File
@@ -1,2 +1,2 @@
extern const uint8_t gitversion[19];
const uint8_t gitversion[19] = "DEV-4078e6fc-DEBUG";
const uint8_t gitversion[19] = "DEV-d47be809-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.
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
View File
@@ -1 +1 @@
DEV-4078e6fc-DEBUG
DEV-d47be809-DEBUG
@@ -169,6 +169,7 @@ KONA_NON_SCC_CARS = (
)
PRIUS_CARS = (
TOYOTA_CAR.TOYOTA_PRIUS,
TOYOTA_CAR.TOYOTA_PRIUS_RETROFIT,
)
CAMRY_CARS = (
@@ -627,11 +627,10 @@ class LongitudinalMpc:
return lead_xv
def process_lead(self, lead, tracking_lead=True, t_follow=None, *, lead_index=0,
smooth_duplicate_vision=False, model_lead=None,
use_model_lead_trajectory=False):
smooth_duplicate_vision=False, model_lead=None):
v_ego = self.x0[1]
lead_active = lead is not None and lead.status and tracking_lead
if lead_active and use_model_lead_trajectory:
if lead_active:
model_lead_xv = build_model_lead_trajectory(model_lead, lead, v_ego)
if model_lead_xv is not None:
return model_lead_xv
@@ -924,23 +923,18 @@ class LongitudinalMpc:
def update(self, radarstate, v_cruise, x, v, a, j, danger_factor, t_follow,
personality=log.LongitudinalPersonality.standard, tracking_lead=True,
optional_far_lead_comfort=True, smooth_duplicate_vision=False,
stop_x=None, silverado_early_follow=False, modelV2=None,
use_model_lead_trajectory=False):
stop_x=None, silverado_early_follow=False, modelV2=None):
v_ego = self.x0[1]
lead_one = radarstate.leadOne
lead_two = radarstate.leadTwo
self.status = tracking_lead and (lead_one.status or lead_two.status)
model_leads = ()
if use_model_lead_trajectory and modelV2 is not None:
model_leads = getattr(modelV2, "leadsV3", ())
model_leads = getattr(modelV2, "leadsV3", ()) if modelV2 is not None else ()
lead_xv_0 = self.process_lead(lead_one, tracking_lead, t_follow=t_follow, lead_index=0,
smooth_duplicate_vision=smooth_duplicate_vision,
model_lead=model_leads[0] if len(model_leads) > 0 else None,
use_model_lead_trajectory=use_model_lead_trajectory)
model_lead=model_leads[0] if len(model_leads) > 0 else None)
lead_xv_1 = self.process_lead(lead_two, tracking_lead, t_follow=t_follow, lead_index=1,
smooth_duplicate_vision=smooth_duplicate_vision,
model_lead=model_leads[1] if len(model_leads) > 1 else None,
use_model_lead_trajectory=use_model_lead_trajectory)
model_lead=model_leads[1] if len(model_leads) > 1 else None)
self.lead_xv_0 = lead_xv_0
self.lead_xv_1 = lead_xv_1
@@ -2208,8 +2208,7 @@ class LongitudinalPlanner:
smooth_duplicate_vision=nonurgent_duplicate_vision_follow and not panic_bypass,
stop_x=force_stop_x,
silverado_early_follow=early_truck_follow,
modelV2=sm['modelV2'],
use_model_lead_trajectory=bool(getattr(starpilot_toggles, "test_model_lead_trajectory", False)))
modelV2=sm['modelV2'])
self.a_desired_trajectory_full = np.interp(CONTROL_N_T_IDX, T_IDXS_MPC, self.mpc.a_solution)
self.v_desired_trajectory = np.interp(CONTROL_N_T_IDX, T_IDXS_MPC, self.mpc.v_solution)
@@ -329,20 +329,16 @@ def make_model_lead(*, prob: float = 0.99, x=None, v=None):
return model, lead
def test_model_lead_trajectory_is_opt_in_and_disabled_path_is_unchanged():
def test_model_lead_trajectory_is_default_for_stable_lead():
lead = make_lead(status=True, d_rel=42.0, v_lead=18.0, model_prob=0.99)
_, model_lead = make_model_lead()
legacy_mpc = LongitudinalMpc()
disabled_mpc = LongitudinalMpc()
legacy_mpc.set_cur_state(20.0, 0.0)
disabled_mpc.set_cur_state(20.0, 0.0)
mpc = LongitudinalMpc()
mpc.set_cur_state(20.0, 0.0)
legacy = legacy_mpc.process_lead(lead)
disabled = disabled_mpc.process_lead(
lead, model_lead=model_lead, use_model_lead_trajectory=False,
)
np.testing.assert_allclose(disabled, legacy)
actual = mpc.process_lead(lead, model_lead=model_lead)
expected = build_model_lead_trajectory(model_lead, lead, 20.0)
np.testing.assert_allclose(actual, expected)
def test_model_lead_trajectory_uses_raw_current_anchor_and_future_deltas():
@@ -221,14 +221,17 @@ def test_pulse_and_glide_coasts_at_set_speed_then_resumes_below_delta():
accel.update(set_speed, make_sm(set_speed_kph=100.0, pulse_and_glide=True), toggles)
assert accel.pulse_glide_coasting is True
assert accel.pulse_glide_target == pytest.approx(set_speed - delta)
assert accel.min_accel == pytest.approx(A_CRUISE_MIN_ECO)
accel.update((90.0 * CV.KPH_TO_MS) - 0.05, make_sm(set_speed_kph=100.0, pulse_and_glide=True), toggles)
assert accel.pulse_glide_coasting is False
assert accel.pulse_glide_target is None
assert accel.min_accel == pytest.approx(A_CRUISE_MIN)
accel.update(99.8 * CV.KPH_TO_MS, make_sm(set_speed_kph=100.0, pulse_and_glide=True), toggles)
assert accel.pulse_glide_coasting is True
assert accel.pulse_glide_target == pytest.approx(set_speed - delta)
assert accel.min_accel == pytest.approx(A_CRUISE_MIN_ECO)
@@ -239,4 +242,5 @@ def test_pulse_and_glide_is_inert_when_disabled():
accel.update(100.0 * CV.KPH_TO_MS, sm, make_toggles(deceleration_profile=DECELERATION_PROFILES["STANDARD"], pulse_glide_speed_delta=10.0))
assert accel.pulse_glide_coasting is False
assert accel.pulse_glide_target is None
assert accel.min_accel == pytest.approx(A_CRUISE_MIN)
@@ -2,6 +2,7 @@ import math
from pathlib import Path
from types import SimpleNamespace
from openpilot.common.constants import CV
from openpilot.common.realtime import DT_MDL
from openpilot.starpilot.controls.starpilot_planner import StarPilotPlanner, get_force_stop_jerk_scale
from openpilot.selfdrive.controls.lib.longitudinal_vehicle_tunes import get_lead_follow_jerk_scale
@@ -119,6 +120,25 @@ def test_standstill_without_turn_signal_keeps_lateral_allowed(monkeypatch):
planner.shutdown()
def test_pulse_glide_target_is_published_after_vcruise_update(monkeypatch):
planner = make_planner(monkeypatch)
try:
normal_target = 65.0 * CV.MPH_TO_MS
glide_target = 60.0 * CV.MPH_TO_MS
monkeypatch.setattr(planner.starpilot_vcruise, "update", lambda *args, **kwargs: normal_target)
def publish_glide_target(*args, **kwargs):
planner.starpilot_acceleration.pulse_glide_target = glide_target
monkeypatch.setattr(planner.starpilot_acceleration, "update", publish_glide_target)
planner.update(0.0, False, make_sm(planner, frame=1, v_ego=normal_target, left_blinker=False), make_toggles())
assert planner.v_cruise == glide_target
finally:
planner.shutdown()
def test_lateral_resume_delay_holds_resume_after_low_speed_turn(monkeypatch):
planner = make_planner(monkeypatch)
+10 -1
View File
@@ -66,6 +66,12 @@ def _model_smooth_seconds(params, key, default):
return default
value = params.get_float(key, return_default=True, default=default)
return round(min(max(value, SMOOTH_SECONDS_STEP), 2.0) / SMOOTH_SECONDS_STEP) * SMOOTH_SECONDS_STEP
def _should_publish_model_output(model_output, vipc_dropped_frames: int) -> bool:
return model_output is not None and vipc_dropped_frames == 0
MIN_LAT_CONTROL_SPEED = 0.3
BIG_MODEL_LOAD_WAIT_TIMEOUT_MS = 30000
BIG_MODEL_RUN_WAIT_TIMEOUT_MS = 3000
@@ -933,7 +939,10 @@ def main(demo=False):
mt2 = time.perf_counter()
model_execution_time = mt2 - mt1
if model_output is not None:
if model_output is not None and vipc_dropped_frames > 0:
cloudlog.error(f"suppressing model output after dropping {vipc_dropped_frames} frames")
if _should_publish_model_output(model_output, vipc_dropped_frames):
modelv2_send = messaging.new_message('modelV2')
starpilot_modelv2_send = messaging.new_message('starpilotModelV2')
drivingdata_send = messaging.new_message('drivingModelData')
@@ -11,6 +11,16 @@ class FakeParams:
self.values[key] = value
@pytest.mark.parametrize(("model_output", "dropped_frames", "expected"), [
(object(), 0, True),
(object(), 1, False),
(object(), 2, False),
(None, 0, False),
])
def test_model_output_is_suppressed_after_vipc_drop(model_output, dropped_frames, expected):
assert modeld._should_publish_model_output(model_output, dropped_frames) is expected
def test_incompatible_downloaded_model_falls_back_to_builtin(monkeypatch):
calls = []
builtin_model = object()
+7 -2
View File
@@ -76,6 +76,11 @@ def _lkas_allowed_for_aol(car_make, cp_flags, fpcp_safety_configs) -> bool:
)
return hyundai_can_use_lkas_for_aol or car_make == "honda"
def _main_cruise_aol_allowed(button_control: float) -> bool:
return button_control == BUTTON_FUNCTIONS["AOL_TOGGLE"]
LEGACY_CARMODEL_MIGRATIONS = {
"CHEVROLET_BOLT_CC_2019_2021": "CHEVROLET_BOLT_CC_2018_2021",
}
@@ -105,6 +110,7 @@ PRIUS_CLUSTER_OFFSET_DEFAULT = 1.015
PRIUS_CLUSTER_OFFSET_MIGRATION_KEY = "PriusClusterOffsetMigrated"
PRIUS_CLUSTER_OFFSET_CARS = {
str(TOYOTA_CAR.TOYOTA_PRIUS),
str(TOYOTA_CAR.TOYOTA_PRIUS_RETROFIT),
str(TOYOTA_CAR.TOYOTA_PRIUS_V),
str(TOYOTA_CAR.TOYOTA_PRIUS_TSS2),
}
@@ -780,7 +786,7 @@ class StarPilotVariables:
toggle.always_on_lateral_pause_speed = self.get_value("PauseAOLOnBrake", cast=float, condition=toggle.always_on_lateral)
main_cruise_button_control = self.get_button_function("MainCruiseButtonControl")
toggle.main_cruise_aol_toggle = main_cruise_button_control == BUTTON_FUNCTIONS["AOL_TOGGLE"]
toggle.main_cruise_aol_toggle = _main_cruise_aol_allowed(main_cruise_button_control)
toggle.main_cruise_slc_adopt = main_cruise_button_control == BUTTON_FUNCTIONS["SLC_ADOPT"]
toggle.automatic_updates = self.get_value("AutomaticUpdates") and not BACKUP_PATH.is_file()
@@ -953,7 +959,6 @@ class StarPilotVariables:
)
developer_feature_access = self.params.get_bool("DeveloperUI") or self.params.get_bool("GalaxyDeveloperMode")
toggle.test_model_lead_trajectory = self.get_value("TestModelLeadTrajectory", condition=developer_feature_access)
toggle.pulse_and_glide_available = toggle.openpilot_longitudinal and developer_feature_access
toggle.pulse_glide_speed_delta = self.get_value(
"PulseGlideSpeedDelta",
@@ -21,6 +21,13 @@ def test_hyundai_and_honda_keep_lkas_aol_button_path():
assert spv._lkas_allowed_for_aol("hyundai", spv.HyundaiFlags.CANFD, []) is True
def test_explicit_main_cruise_aol_mapping_is_not_disabled_by_longitudinal_gate():
aol_button = spv.BUTTON_FUNCTIONS["AOL_TOGGLE"]
# An explicit Galaxy mapping remains valid on both longitudinal paths.
assert spv._main_cruise_aol_allowed(aol_button) is True
def test_jeep_brake_hold_scope_is_grand_cherokee_only():
assert {str(car) for car in spv.CHRYSLER_JEEPS} == {
"JEEP_GRAND_CHEROKEE",
@@ -152,8 +152,10 @@ class StarPilotAcceleration:
self.last_gear_state = "init"
self.pulse_glide_coasting = False
self.pulse_glide_target = None
def _update_pulse_glide(self, v_ego, sm, starpilot_toggles):
self.pulse_glide_target = None
pulse_glide_enabled = bool(getattr(sm["starpilotCarState"], "pulseAndGlide", False))
if not pulse_glide_enabled:
self.pulse_glide_coasting = False
@@ -183,7 +185,9 @@ class StarPilotAcceleration:
delta = max(0.0, float(getattr(starpilot_toggles, "pulse_glide_speed_delta", 0.0)))
lower_target = v_target - delta
if v_target <= PULSE_GLIDE_MIN_TARGET_SPEED or lower_target < PULSE_GLIDE_MIN_LOWER_SPEED:
if (delta <= 0.0 or
v_target <= PULSE_GLIDE_MIN_TARGET_SPEED or
lower_target < PULSE_GLIDE_MIN_LOWER_SPEED):
self.pulse_glide_coasting = False
return False
@@ -205,6 +209,9 @@ class StarPilotAcceleration:
elif v_ego >= v_target - PULSE_GLIDE_HYSTERESIS:
self.pulse_glide_coasting = True
if self.pulse_glide_coasting:
self.pulse_glide_target = lower_target
return self.pulse_glide_coasting
def update(self, v_ego, sm, starpilot_toggles):
+8 -6
View File
@@ -124,12 +124,6 @@ class StarPilotPlanner:
v_cruise = v_cruise_kph * CV.KPH_TO_MS
v_ego = max(sm["carState"].vEgo, 0)
if controls_enabled:
self.starpilot_acceleration.update(v_ego, sm, starpilot_toggles)
else:
self.starpilot_acceleration.max_accel = 0
self.starpilot_acceleration.min_accel = 0
gps_location = sm[self.gps_location_service]
self.gps_position = {
"latitude": gps_location.latitude,
@@ -241,6 +235,14 @@ class StarPilotPlanner:
self.v_cruise = self.starpilot_vcruise.update(controls_enabled, now, time_validated, v_cruise, v_ego, sm, starpilot_toggles)
if controls_enabled:
self.starpilot_acceleration.update(v_ego, sm, starpilot_toggles)
if self.starpilot_acceleration.pulse_glide_target is not None:
self.v_cruise = self.starpilot_acceleration.pulse_glide_target
else:
self.starpilot_acceleration.max_accel = 0
self.starpilot_acceleration.min_accel = 0
self.starpilot_events.update(controls_enabled, v_cruise, sm, starpilot_toggles)
if self.gps_valid and time_validated and starpilot_toggles.weather_presets:
@@ -4191,16 +4191,6 @@
"is_parent_toggle": true,
"settings_tier": "simple"
},
{
"key": "TestModelLeadTrajectory",
"label": "Test Model-Predicted Lead Trajectory",
"description": "Experimental: use the model's predicted lead path as the MPC lead trajectory. Raw lead safety and stop logic remain active.",
"data_type": "bool",
"ui_type": "toggle",
"parent_key": "GalaxyDeveloperMode",
"requires_offroad": true,
"settings_tier": "advanced"
},
{
"key": "AlphaLongitudinalEnabled",
"label": "openpilot Longitudinal Control (Alpha)",

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