mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-08-24 01:33:46 +08:00
Compare commits
40 Commits
vasm-082026
...
Dom
| Author | SHA1 | Date | |
|---|---|---|---|
| 2db8d95905 | |||
| db5922db43 | |||
| 96f5819c6a | |||
| cfd221b89c | |||
| 013f8579d7 | |||
| 2b53b59bee | |||
| 33f6d69a32 | |||
| 58e919c264 | |||
| 17e5542b1b | |||
| e1458d4723 | |||
| 06f9e43e4e | |||
| f8e03a9fc5 | |||
| 7c6741a93e | |||
| 4b3372d006 | |||
| 9a9e7cd1e9 | |||
| 1d9fdc25ca | |||
| 05db925e93 | |||
| 2bd080821b | |||
| 651726bbb5 | |||
| 6eabec436d | |||
| 56d6a6ee47 | |||
| e9f4c6316c | |||
| 284dbddd8a | |||
| 0068d7a698 | |||
| f63ee3375a | |||
| 05e9dfd5d0 | |||
| 269562e73a | |||
| 3cefd789e5 | |||
| d477735c92 | |||
| 66893b27ae | |||
| e0d9e05f9f | |||
| 73f64ac754 | |||
| 5130168067 | |||
| 04a2530ace | |||
| 297358741a | |||
| 41b10d0184 | |||
| 49f061eee4 | |||
| d8090be19d | |||
| d78902d73b | |||
| a0cf285394 |
@@ -220,6 +220,7 @@ struct StarPilotPlan @0xf98d843bfd7004a3 {
|
||||
disableThrottle @35 :Bool;
|
||||
trackingLead @36 :Bool;
|
||||
stopSignConfirmed @37 :Bool;
|
||||
pulseGlideCoasting @38 :Bool; # developer-only P&G phase for on-road status UI
|
||||
}
|
||||
|
||||
struct StarPilotRadarState @0xb86e6369214c01c8 {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -2757,6 +2757,7 @@ struct Event {
|
||||
userBookmark @93 :UserBookmark;
|
||||
bookmarkButton @148 :UserBookmark;
|
||||
audioFeedback @149 :AudioFeedback;
|
||||
visionSpeedLimitBookmark @153 :UserBookmark;
|
||||
|
||||
lateralManeuverPlan @150 :LateralManeuverPlan;
|
||||
# *********** debug ***********
|
||||
|
||||
Binary file not shown.
@@ -69,6 +69,7 @@ static std::map<std::string, service> services = {
|
||||
{ "rawAudioData", {"rawAudioData", false, 20.000000, -1, 256000}},
|
||||
{ "bookmarkButton", {"bookmarkButton", true, 0.000000, 1, 256000}},
|
||||
{ "audioFeedback", {"audioFeedback", true, 0.000000, 1, 256000}},
|
||||
{ "visionSpeedLimitBookmark", {"visionSpeedLimitBookmark", false, 0.000000, 1, 256000}},
|
||||
{ "roadEncodeData", {"roadEncodeData", false, 20.000000, -1, 10485760}},
|
||||
{ "driverEncodeData", {"driverEncodeData", false, 20.000000, -1, 10485760}},
|
||||
{ "wideRoadEncodeData", {"wideRoadEncodeData", false, 20.000000, -1, 10485760}},
|
||||
|
||||
@@ -86,6 +86,7 @@ _services: dict[str, tuple] = {
|
||||
"rawAudioData": (False, 20.),
|
||||
"bookmarkButton": (True, 0., 1),
|
||||
"audioFeedback": (True, 0., 1),
|
||||
"visionSpeedLimitBookmark": (False, 0., 1),
|
||||
"roadEncodeData": (False, 20., None, QueueSize.BIG),
|
||||
"driverEncodeData": (False, 20., None, QueueSize.BIG),
|
||||
"wideRoadEncodeData": (False, 20., None, QueueSize.BIG),
|
||||
|
||||
Binary file not shown.
@@ -345,6 +345,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"FordCurvatureBlendHigh", {PERSISTENT, FLOAT, "0.4", "0.4", 2}},
|
||||
{"FordCurvatureBlendLow", {PERSISTENT, FLOAT, "0.4", "0.4", 2}},
|
||||
{"FordCurvatureLaneChangeFactor", {PERSISTENT, FLOAT, "0.85", "0.85", 2}},
|
||||
{"FordHandsFreeCluster", {PERSISTENT, BOOL, "0", "0", 2}},
|
||||
{"FordHumanTurnDetection", {PERSISTENT, BOOL, "1", "1", 2}},
|
||||
{"FordLateralMode", {PERSISTENT, INT, "1", "1", 2}},
|
||||
{"FLMActiveOverrides", {PERSISTENT, JSON, "{}", "{}", 2}},
|
||||
@@ -679,6 +680,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"TuningLevel", {PERSISTENT, INT, "0", "0", 0}},
|
||||
{"TuningLevelConfirmed", {PERSISTENT, BOOL, "0", "0", 0}},
|
||||
{"TurnDesires", {PERSISTENT, BOOL, "0", "0", 2}},
|
||||
{"TurnSteeringLimitMuteSpeed", {PERSISTENT, INT, "0", "0", 0}},
|
||||
{"UnlockDoors", {PERSISTENT, BOOL, "1", "0", 0}},
|
||||
{"Updated", {PERSISTENT, STRING, "0", "0"}},
|
||||
{"UpdateSpeedLimits", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}},
|
||||
|
||||
Binary file not shown.
@@ -29,20 +29,6 @@ function agnos_init {
|
||||
# set success flag for current boot slot
|
||||
sudo abctl --set_success
|
||||
|
||||
# Restore SSH access after a user-triggered reset if keys were backed up to /cache.
|
||||
SSH_BACKUP_DIR="/cache/reset_backup"
|
||||
if [ -d "$SSH_BACKUP_DIR" ]; then
|
||||
sudo mkdir -p /data/params/d
|
||||
for key in GithubSshKeys SshEnabled; do
|
||||
if [ -f "$SSH_BACKUP_DIR/$key" ]; then
|
||||
sudo cp "$SSH_BACKUP_DIR/$key" "/data/params/d/$key"
|
||||
fi
|
||||
done
|
||||
sudo chown comma:comma /data/params/d/GithubSshKeys /data/params/d/SshEnabled 2>/dev/null || true
|
||||
sudo chmod 600 /data/params/d/GithubSshKeys /data/params/d/SshEnabled 2>/dev/null || true
|
||||
sudo rm -rf "$SSH_BACKUP_DIR"
|
||||
fi
|
||||
|
||||
# TODO: do this without udev in AGNOS
|
||||
# udev does this, but sometimes we startup faster
|
||||
sudo chgrp gpu /dev/adsprpc-smd /dev/ion /dev/kgsl-3d0
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ fi
|
||||
export QCOM_PRIORITY=12
|
||||
|
||||
if [ -z "$AGNOS_VERSION" ]; then
|
||||
export AGNOS_VERSION="19.6.1"
|
||||
export AGNOS_VERSION="19.6.3"
|
||||
fi
|
||||
|
||||
if [ -z "$AGNOS_ACCEPTED_VERSIONS" ]; then
|
||||
|
||||
@@ -255,9 +255,15 @@ class CarController(CarControllerBase):
|
||||
|
||||
if (self.frame % CarControllerParams.ACC_UI_STEP) == 0 or send_ui:
|
||||
show_distance_bars = self.frame - self.distance_bar_frame < 400
|
||||
hands_free_cluster = bool(
|
||||
self.ford_lateral is not None
|
||||
and self.ford_lateral.mode != FordLateralMode.native
|
||||
and self.ford_lateral.mode == self.ford_lateral_announced_mode
|
||||
and self.ford_lateral.hands_free_cluster_enabled)
|
||||
can_sends.append(fordcan.create_acc_ui_msg(self.packer, self.CAN, self.CP, main_on, CC.latActive,
|
||||
fcw_alert, CS.out.cruiseState.standstill, show_distance_bars,
|
||||
hud_control, CS.acc_tja_status_stock_values))
|
||||
hud_control, CS.acc_tja_status_stock_values,
|
||||
hands_free_cluster))
|
||||
|
||||
self.main_on_last = main_on
|
||||
self.lkas_enabled_last = CC.latActive
|
||||
|
||||
@@ -181,7 +181,7 @@ def create_acc_msg(packer, CAN: CanBus, long_active: bool, gas: float, accel: fl
|
||||
|
||||
|
||||
def create_acc_ui_msg(packer, CAN: CanBus, CP, main_on: bool, enabled: bool, fcw_alert: bool, standstill: bool,
|
||||
show_distance_bars: bool, hud_control, stock_values: dict):
|
||||
show_distance_bars: bool, hud_control, stock_values: dict, hands_free_cluster: bool = False):
|
||||
"""
|
||||
Creates a CAN message for the Ford IPC adaptive cruise, forward collision warning and traffic jam
|
||||
assist status.
|
||||
@@ -197,6 +197,8 @@ def create_acc_ui_msg(packer, CAN: CanBus, CP, main_on: bool, enabled: bool, fcw
|
||||
status = 3 # ActiveInterventionLeft
|
||||
elif hud_control.rightLaneDepart:
|
||||
status = 4 # ActiveInterventionRight
|
||||
elif hands_free_cluster:
|
||||
status = 7 # Hands-free assistance display
|
||||
else:
|
||||
status = 2 # Active
|
||||
elif main_on:
|
||||
|
||||
@@ -54,10 +54,10 @@ class CarInterface(CarInterfaceBase):
|
||||
cfgs.insert(0, get_safety_config(structs.CarParams.SafetyModel.noOutput))
|
||||
ret.safetyConfigs = cfgs
|
||||
|
||||
ret.alphaLongitudinalAvailable = ret.radarUnavailable
|
||||
if alpha_long or not ret.radarUnavailable:
|
||||
ret.alphaLongitudinalAvailable = True
|
||||
ret.openpilotLongitudinalControl = bool(alpha_long)
|
||||
if ret.openpilotLongitudinalControl:
|
||||
ret.safetyConfigs[-1].safetyParam |= FordSafetyFlags.LONG_CONTROL.value
|
||||
ret.openpilotLongitudinalControl = True
|
||||
|
||||
if ret.flags & FordFlags.CANFD:
|
||||
ret.safetyConfigs[-1].safetyParam |= FordSafetyFlags.CANFD.value
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
import random
|
||||
from collections.abc import Iterable
|
||||
from types import SimpleNamespace
|
||||
|
||||
from hypothesis import settings, given, strategies as st
|
||||
from parameterized import parameterized
|
||||
|
||||
from opendbc.car import gen_empty_fingerprint
|
||||
from opendbc.can import CANPacker
|
||||
from opendbc.car.ford import fordcan
|
||||
from opendbc.car.structs import CarParams
|
||||
from opendbc.car.fw_versions import build_fw_dict
|
||||
from opendbc.car.ford.values import CAR, FW_QUERY_CONFIG, FW_PATTERN, get_platform_codes, match_vin_to_car
|
||||
from opendbc.car.ford.interface import CarInterface
|
||||
from opendbc.car.ford.values import CAR, FW_QUERY_CONFIG, FW_PATTERN, FordSafetyFlags, get_platform_codes, match_vin_to_car
|
||||
from opendbc.car.ford.fingerprints import FW_VERSIONS
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
@@ -154,3 +159,45 @@ class TestFordFW:
|
||||
live_fw[(0x760, None)] = {b"M1MC-2D053-XX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}
|
||||
candidates = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(live_fw, '', {expected_fingerprint: offline_fw})
|
||||
assert len(candidates) == 0, "Should not match new model year hint"
|
||||
|
||||
|
||||
def test_mach_e_longitudinal_toggle_controls_stock_acc_selection():
|
||||
stock = CarInterface.get_params(
|
||||
CAR.FORD_MUSTANG_MACH_E_MK1, gen_empty_fingerprint(), [], False, False, False, None)
|
||||
enhanced = CarInterface.get_params(
|
||||
CAR.FORD_MUSTANG_MACH_E_MK1, gen_empty_fingerprint(), [], True, False, False, None)
|
||||
|
||||
assert stock.alphaLongitudinalAvailable
|
||||
assert not stock.openpilotLongitudinalControl
|
||||
assert stock.pcmCruise
|
||||
assert not (stock.safetyConfigs[-1].safetyParam & FordSafetyFlags.LONG_CONTROL)
|
||||
|
||||
assert enhanced.alphaLongitudinalAvailable
|
||||
assert enhanced.openpilotLongitudinalControl
|
||||
assert enhanced.safetyConfigs[-1].safetyParam & FordSafetyFlags.LONG_CONTROL
|
||||
|
||||
|
||||
def test_hands_free_cluster_status_is_opt_in():
|
||||
packer = CANPacker("ford_lincoln_base_pt")
|
||||
CAN = SimpleNamespace(main=0)
|
||||
CP = SimpleNamespace(openpilotLongitudinalControl=False)
|
||||
hud = SimpleNamespace(leftLaneDepart=False, rightLaneDepart=False)
|
||||
stock_values = dict.fromkeys([
|
||||
"HaDsply_No_Cs", "HaDsply_No_Cnt", "AccStopStat_D_Dsply", "AccTrgDist2_D_Dsply",
|
||||
"AccStopRes_B_Dsply", "TjaWarn_D_Rq", "TjaMsgTxt_D_Dsply", "IaccLamp_D_Rq",
|
||||
"AccMsgTxt_D2_Rq", "FcwDeny_B_Dsply", "FcwMemStat_B_Actl", "AccTGap_B_Dsply",
|
||||
"CadsAlignIncplt_B_Actl", "AccFllwMde_B_Dsply", "CadsRadrBlck_B_Actl",
|
||||
"CmbbPostEvnt_B_Dsply", "AccStopMde_B_Dsply", "FcwMemSens_D_Actl",
|
||||
"FcwMsgTxt_D_Rq", "AccWarn_D_Dsply", "FcwVisblWarn_B_Rq", "FcwAudioWarn_B_Rq",
|
||||
"AccTGap_D_Dsply", "AccMemEnbl_B_RqDrv", "FdaMem_B_Stat",
|
||||
], 0)
|
||||
|
||||
regular = fordcan.create_acc_ui_msg(
|
||||
packer, CAN, CP, True, True, False, False, False, hud, stock_values)
|
||||
hands_free = fordcan.create_acc_ui_msg(
|
||||
packer, CAN, CP, True, True, False, False, False, hud, stock_values, True)
|
||||
expected_regular = packer.make_can_msg("ACCDATA_3", 0, {"Tja_D_Stat": 2})
|
||||
expected_hands_free = packer.make_can_msg("ACCDATA_3", 0, {"Tja_D_Stat": 7})
|
||||
|
||||
assert regular == expected_regular
|
||||
assert hands_free == expected_hands_free
|
||||
|
||||
@@ -9,10 +9,12 @@ from opendbc.car.common.conversions import Conversions as CV
|
||||
from opendbc.car.hyundai import hyundaicanfd, hyundaican
|
||||
from opendbc.car.hyundai.hyundaicanfd import CanBus
|
||||
from opendbc.car.hyundai.values import HyundaiFlags, Buttons, CarControllerParams, CAR, CANFD_ANGLE_LONGITUDINAL_CAR, \
|
||||
CANFD_RADAR_LIVE_LONGITUDINAL_CAR, kia_ev6_gt_line_longitudinal_tuning
|
||||
CANFD_RADAR_LIVE_LONGITUDINAL_CAR, kia_ev6_gt_line_longitudinal_tuning, \
|
||||
KIA_EV6_GT_LINE_LONG_TUNING_TESTING_GROUND_ID
|
||||
from opendbc.car.interfaces import CarControllerBase
|
||||
from opendbc.car.vehicle_model import VehicleModel
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.starpilot.common.testing_grounds import testing_ground
|
||||
|
||||
VisualAlert = structs.CarControl.HUDControl.VisualAlert
|
||||
LongCtrlState = structs.CarControl.Actuators.LongControlState
|
||||
@@ -79,7 +81,10 @@ BLINDSPOT_WARNING_SOUND_SAMPLES = 36
|
||||
|
||||
def egmp_dynamic_longitudinal_tuning(CP) -> bool:
|
||||
return CP.carFingerprint in (CAR.HYUNDAI_IONIQ_6, CAR.KIA_EV9, CAR.HYUNDAI_IONIQ_5_PE) or \
|
||||
kia_ev6_gt_line_longitudinal_tuning(CP.carFingerprint, getattr(CP, "carVin", ""))
|
||||
kia_ev6_gt_line_longitudinal_tuning(
|
||||
CP.carFingerprint, getattr(CP, "carVin", ""),
|
||||
testing_ground.use(KIA_EV6_GT_LINE_LONG_TUNING_TESTING_GROUND_ID),
|
||||
)
|
||||
|
||||
|
||||
def get_canfd_scc_decel_step(CP) -> float:
|
||||
@@ -87,7 +92,10 @@ def get_canfd_scc_decel_step(CP) -> float:
|
||||
|
||||
|
||||
def should_reset_ev6_gt_line_longitudinal_tuning(CP, long_control_state: LongCtrlState) -> bool:
|
||||
return kia_ev6_gt_line_longitudinal_tuning(CP.carFingerprint, getattr(CP, "carVin", "")) and \
|
||||
return kia_ev6_gt_line_longitudinal_tuning(
|
||||
CP.carFingerprint, getattr(CP, "carVin", ""),
|
||||
testing_ground.use(KIA_EV6_GT_LINE_LONG_TUNING_TESTING_GROUND_ID),
|
||||
) and \
|
||||
long_control_state == LongCtrlState.off
|
||||
|
||||
|
||||
@@ -631,7 +639,10 @@ class CarController(CarControllerBase):
|
||||
|
||||
use_egmp_dynamic_long_tuning = egmp_dynamic_longitudinal_tuning(self.CP) and self.long_active_ecu and \
|
||||
actuators.longControlState in (LongCtrlState.starting, LongCtrlState.pid, LongCtrlState.stopping)
|
||||
is_ev6_gt_line = kia_ev6_gt_line_longitudinal_tuning(self.CP.carFingerprint, getattr(self.CP, "carVin", ""))
|
||||
is_ev6_gt_line = kia_ev6_gt_line_longitudinal_tuning(
|
||||
self.CP.carFingerprint, getattr(self.CP, "carVin", ""),
|
||||
testing_ground.use(KIA_EV6_GT_LINE_LONG_TUNING_TESTING_GROUND_ID),
|
||||
)
|
||||
is_ccnc_angle_long = self.CP.carFingerprint in CANFD_ANGLE_LONGITUDINAL_CAR
|
||||
if is_ccnc_angle_long and (self._ev9_long_tuning.stop_request or not CC.enabled or CC.cruiseControl.override):
|
||||
self._ioniq_6_long_tuning = reset_egmp_longitudinal_tuning(self._ioniq_6_long_tuning)
|
||||
|
||||
@@ -12,13 +12,15 @@ from opendbc.car.hyundai.values import HyundaiFlags, CAR, CarControllerParams, \
|
||||
CAN_CANFD_BLENDED_HDA2_LONGITUDINAL_CAR, \
|
||||
HyundaiStarPilotSafetyFlags, \
|
||||
hyundai_cancel_button_enables_cruise, \
|
||||
kia_ev6_gt_line_longitudinal_tuning
|
||||
kia_ev6_gt_line_longitudinal_tuning, \
|
||||
KIA_EV6_GT_LINE_LONG_TUNING_TESTING_GROUND_ID
|
||||
from opendbc.car.hyundai.radar_interface import get_radar_track_config, radar_tracks_available
|
||||
from opendbc.car.interfaces import CarInterfaceBase, ACCEL_MIN
|
||||
from opendbc.car.disable_ecu import disable_ecu, ecu_log
|
||||
from opendbc.car.hyundai.carcontroller import CarController
|
||||
from opendbc.car.hyundai.carstate import CarState
|
||||
from opendbc.car.hyundai.radar_interface import RadarInterface
|
||||
from openpilot.starpilot.common.testing_grounds import testing_ground
|
||||
|
||||
ButtonType = structs.CarState.ButtonEvent.Type
|
||||
Ecu = structs.CarParams.Ecu
|
||||
@@ -106,7 +108,8 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
@staticmethod
|
||||
def apply_post_fingerprint_params(CP: structs.CarParams, candidate, fingerprint, car_fw) -> None:
|
||||
if kia_ev6_gt_line_longitudinal_tuning(CP.carFingerprint, CP.carVin):
|
||||
gt_line_testing_ground = testing_ground.use(KIA_EV6_GT_LINE_LONG_TUNING_TESTING_GROUND_ID)
|
||||
if kia_ev6_gt_line_longitudinal_tuning(CP.carFingerprint, CP.carVin, gt_line_testing_ground):
|
||||
apply_kia_ev6_gt_line_longitudinal_params(CP)
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -988,6 +988,45 @@ class TestHyundaiFingerprint:
|
||||
assert long_xceed.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.HYBRID_GAS
|
||||
assert long_xceed.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.LONG
|
||||
|
||||
def test_g80_alpha_long_preserves_legacy_safety(self):
|
||||
toggles = get_test_toggles()
|
||||
|
||||
stock_g80 = CarInterface.get_params(CAR.GENESIS_G80, gen_empty_fingerprint(), [], False, False, False, toggles)
|
||||
assert CAR.GENESIS_G80 in LEGACY_LONGITUDINAL_CAR
|
||||
assert stock_g80.alphaLongitudinalAvailable
|
||||
assert not stock_g80.openpilotLongitudinalControl
|
||||
assert stock_g80.pcmCruise
|
||||
assert stock_g80.safetyConfigs[-1].safetyModel == CarParams.SafetyModel.hyundaiLegacy
|
||||
assert not (stock_g80.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.LONG)
|
||||
|
||||
long_g80 = CarInterface.get_params(CAR.GENESIS_G80, gen_empty_fingerprint(), [], True, False, False, toggles)
|
||||
assert long_g80.alphaLongitudinalAvailable
|
||||
assert long_g80.openpilotLongitudinalControl
|
||||
assert not long_g80.pcmCruise
|
||||
assert long_g80.safetyConfigs[-1].safetyModel == CarParams.SafetyModel.hyundaiLegacy
|
||||
assert long_g80.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.LONG
|
||||
|
||||
@pytest.mark.parametrize("ecu_disabled", (True, False))
|
||||
def test_g80_alpha_long_disables_stock_scc(self, monkeypatch, ecu_disabled):
|
||||
toggles = get_test_toggles()
|
||||
CP = CarInterface.get_params(CAR.GENESIS_G80, gen_empty_fingerprint(), [], True, False, False, toggles)
|
||||
|
||||
called = {}
|
||||
|
||||
def fake_disable_ecu(*args, **kwargs):
|
||||
called.update(kwargs)
|
||||
return ecu_disabled
|
||||
|
||||
monkeypatch.setattr("opendbc.car.hyundai.interface.disable_ecu", fake_disable_ecu)
|
||||
CarInterface.init(CP, None, None)
|
||||
|
||||
assert called["addr"] == 0x7d0
|
||||
assert called["bus"] == 0
|
||||
assert called["reset"] is False
|
||||
assert CP.openpilotLongitudinalControl == ecu_disabled
|
||||
assert CP.pcmCruise != ecu_disabled
|
||||
assert bool(CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.LONG) == ecu_disabled
|
||||
|
||||
def test_xceed_phev_disable_failure_falls_back_to_stock_acc(self, monkeypatch):
|
||||
toggles = get_test_toggles()
|
||||
CP = CarInterface.get_params(CAR.KIA_XCEED_PHEV, gen_empty_fingerprint(), [], True, False, False, toggles)
|
||||
@@ -1043,6 +1082,24 @@ class TestHyundaiFingerprint:
|
||||
assert reset_state.accel_last == pytest.approx(0.0)
|
||||
assert reset_state.long_control_state_last == LongCtrlState.off
|
||||
|
||||
def test_kia_ev6_gt_line_testing_ground_longitudinal_params(self, monkeypatch):
|
||||
toggles = get_test_toggles()
|
||||
CP = CarInterface.get_params(CAR.KIA_EV6, gen_empty_fingerprint(), [], True, False, False, toggles)
|
||||
CP.carVin = "00000000000000000"
|
||||
|
||||
monkeypatch.setattr(
|
||||
"opendbc.car.hyundai.interface.testing_ground",
|
||||
SimpleNamespace(use=lambda slot_id: slot_id == "5"),
|
||||
)
|
||||
CarInterface.apply_post_fingerprint_params(CP, CAR.KIA_EV6, gen_empty_fingerprint(), [])
|
||||
|
||||
assert CP.startAccel == pytest.approx(1.4)
|
||||
assert CP.vEgoStarting == pytest.approx(0.5)
|
||||
assert CP.longitudinalActuatorDelay == pytest.approx(0.35)
|
||||
|
||||
assert kia_ev6_gt_line_longitudinal_tuning(CP.carFingerprint, CP.carVin, testing_ground_active=True)
|
||||
assert not kia_ev6_gt_line_longitudinal_tuning(CAR.KIA_EV6_2025, CP.carVin, testing_ground_active=True)
|
||||
|
||||
def test_kia_ev6_non_gt_line_keeps_family_longitudinal_params(self):
|
||||
toggles = get_test_toggles()
|
||||
CP = CarInterface.get_params(CAR.KIA_EV6, gen_empty_fingerprint(), [], True, False, False, toggles)
|
||||
|
||||
@@ -111,6 +111,7 @@ class HyundaiSafetyFlags(IntFlag):
|
||||
|
||||
|
||||
class HyundaiStarPilotSafetyFlags(IntFlag):
|
||||
AOL_MAIN_LKAS_SYNC = 32
|
||||
HAS_LDA_BUTTON = 1024
|
||||
AOL_LKAS_ON_ENGAGE = 2048
|
||||
|
||||
@@ -974,6 +975,7 @@ CAN_CANFD_BLENDED_HDA2_LONGITUDINAL_CAR = frozenset({
|
||||
KIA_EV6_GT_LINE_LONG_TUNING_VDS_PREFIXES = frozenset({
|
||||
"C4DLC",
|
||||
})
|
||||
KIA_EV6_GT_LINE_LONG_TUNING_TESTING_GROUND_ID = "5"
|
||||
|
||||
|
||||
ALT_BUS_LDA_BUTTON_CARS = frozenset()
|
||||
@@ -984,9 +986,9 @@ def hyundai_cancel_button_enables_cruise(car_fingerprint) -> bool:
|
||||
return car_fingerprint in CANCEL_BUTTON_ENABLE_CARS
|
||||
|
||||
|
||||
def kia_ev6_gt_line_longitudinal_tuning(car_fingerprint, vin: str) -> bool:
|
||||
return car_fingerprint == CAR.KIA_EV6 and isinstance(vin, str) and \
|
||||
len(vin) == 17 and vin[3:8] in KIA_EV6_GT_LINE_LONG_TUNING_VDS_PREFIXES
|
||||
def kia_ev6_gt_line_longitudinal_tuning(car_fingerprint, vin: str, testing_ground_active: bool = False) -> bool:
|
||||
vin_match = isinstance(vin, str) and len(vin) == 17 and vin[3:8] in KIA_EV6_GT_LINE_LONG_TUNING_VDS_PREFIXES
|
||||
return car_fingerprint == CAR.KIA_EV6 and (vin_match or testing_ground_active)
|
||||
|
||||
|
||||
def get_platform_codes(fw_versions: list[bytes]) -> set[tuple[bytes, bytes | None]]:
|
||||
@@ -1211,6 +1213,9 @@ NON_SCC_CAR = CAR.with_flags(HyundaiFlags.NON_SCC)
|
||||
# HyundaiFlags.CANFD_RADAR_SCC | HyundaiFlags.CANFD_NO_RADAR_DISABLE | )
|
||||
UNSUPPORTED_LONGITUDINAL_CAR = CAR.with_flags(HyundaiFlags.LEGACY) | CAR.with_flags(HyundaiFlags.UNSUPPORTED_LONGITUDINAL)
|
||||
|
||||
LEGACY_LONGITUDINAL_CAR = {CAR.KIA_XCEED_PHEV}
|
||||
LEGACY_LONGITUDINAL_CAR = {
|
||||
CAR.GENESIS_G80,
|
||||
CAR.KIA_XCEED_PHEV,
|
||||
}
|
||||
|
||||
DBC = CAR.create_dbc_map()
|
||||
|
||||
@@ -261,6 +261,10 @@ 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
|
||||
|
||||
@@ -15,19 +15,19 @@ LEAF_ADAS_ECU_BUS = 0
|
||||
LEAF_ADAS_COMMAND_BUS = 1
|
||||
LEAF_ADAS_COMMAND_ADDRS = frozenset((0x1C3, 0x2B0))
|
||||
LEAF_2025_SV_PLUS_CAMERA_FW = b'6WK2CDB\x04\x18\x00\x00\x00\x00\x00R=1\x18\x99\x10\x00\x00\x00\x80'
|
||||
LEAF_2025_SV_PLUS_ALPHA_LONG_ENABLED = False
|
||||
|
||||
# This Leaf camera uses KWP2000 rather than UDS for session management.
|
||||
LEAF_KWP_DATA_MONITOR_REQUEST = b"\x10\xF0"
|
||||
LEAF_KWP_DATA_MONITOR_RESPONSE = b"\x50\xF0"
|
||||
LEAF_KWP_DISABLE_NORMAL_TX = b"\x28\x01"
|
||||
LEAF_KWP_EXTENDED_REQUEST = b"\x10\xC0"
|
||||
LEAF_KWP_EXTENDED_RESPONSE = b"\x50\xC0"
|
||||
LEAF_KWP_DISABLE_NORMAL_TX_NO_RESPONSE = b"\x28\x02"
|
||||
|
||||
LEAF_KWP_TAKEOVER_SESSIONS = (
|
||||
(LEAF_KWP_DATA_MONITOR_REQUEST, LEAF_KWP_DATA_MONITOR_RESPONSE),
|
||||
(LEAF_KWP_EXTENDED_REQUEST, LEAF_KWP_EXTENDED_RESPONSE),
|
||||
)
|
||||
|
||||
|
||||
def is_leaf_2025_sv_plus_longitudinal(candidate, car_fw):
|
||||
return candidate == CAR.NISSAN_LEAF and any(
|
||||
return LEAF_2025_SV_PLUS_ALPHA_LONG_ENABLED and candidate == CAR.NISSAN_LEAF and any(
|
||||
fw.address == LEAF_ADAS_ECU_ADDR and bytes(fw.fwVersion) == LEAF_2025_SV_PLUS_CAMERA_FW
|
||||
for fw in car_fw
|
||||
)
|
||||
@@ -161,7 +161,7 @@ class CarInterface(CarInterfaceBase):
|
||||
for diag_request, diag_response in LEAF_KWP_TAKEOVER_SESSIONS:
|
||||
ecu_log(f"Nissan Leaf ADAS takeover using KWP session {diag_request.hex()}")
|
||||
ecu_disabled = disable_ecu(can_recv, can_send, bus=LEAF_ADAS_ECU_BUS, addr=LEAF_ADAS_ECU_ADDR,
|
||||
com_cont_req=LEAF_KWP_DISABLE_NORMAL_TX, require_response=True, retry=1,
|
||||
com_cont_req=LEAF_KWP_DISABLE_NORMAL_TX_NO_RESPONSE, require_response=False, retry=1,
|
||||
diag_request=diag_request, diag_response=diag_response, response_offset=NISSAN_RX_OFFSET)
|
||||
if ecu_disabled:
|
||||
break
|
||||
|
||||
@@ -4,6 +4,7 @@ import pytest
|
||||
|
||||
from opendbc.car import Bus, ButtonType, gen_empty_fingerprint, structs
|
||||
from opendbc.car.can_definitions import CanData
|
||||
from opendbc.car.nissan import interface as nissan_interface
|
||||
from opendbc.car.nissan.carstate import CarState
|
||||
from opendbc.car.nissan.interface import CarInterface, LEAF_2025_SV_PLUS_CAMERA_FW, leaf_adas_commands_present, \
|
||||
leaf_adas_commands_silent, restore_leaf_adas_tx
|
||||
@@ -18,6 +19,12 @@ SUPPORTED_LEAF_FW = [structs.CarParams.CarFw(
|
||||
)]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def experimental_leaf_long(monkeypatch):
|
||||
"""Exercise the dormant implementation without making it available in production."""
|
||||
monkeypatch.setattr(nissan_interface, "LEAF_2025_SV_PLUS_ALPHA_LONG_ENABLED", True)
|
||||
|
||||
|
||||
def run_controller(alpha_long, accel=0.0, long_active=True, long_state=structs.CarControl.Actuators.LongControlState.pid):
|
||||
CP = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, alpha_long, False, False, TEST_TOGGLES)
|
||||
FPCP = CarInterface.get_starpilot_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, CP, TEST_TOGGLES)
|
||||
@@ -33,7 +40,28 @@ def run_controller(alpha_long, accel=0.0, long_active=True, long_state=structs.C
|
||||
return {msg[0]: msg for msg in can_sends}
|
||||
|
||||
|
||||
def test_leaf_2025_sv_plus_alpha_long_params():
|
||||
def test_leaf_2025_sv_plus_alpha_long_is_disabled(monkeypatch):
|
||||
stock = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, False, False, False, None)
|
||||
alpha_long = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, None)
|
||||
|
||||
assert not stock.alphaLongitudinalAvailable
|
||||
assert not stock.openpilotLongitudinalControl
|
||||
assert stock.pcmCruise
|
||||
assert not (stock.safetyConfigs[-1].safetyParam & NissanSafetyFlags.LONG_CONTROL)
|
||||
|
||||
assert not alpha_long.alphaLongitudinalAvailable
|
||||
assert not alpha_long.openpilotLongitudinalControl
|
||||
assert alpha_long.pcmCruise
|
||||
assert not alpha_long.autoResumeSng
|
||||
assert not (alpha_long.safetyConfigs[-1].safetyParam & NissanSafetyFlags.LONG_CONTROL)
|
||||
|
||||
disable_calls = []
|
||||
monkeypatch.setattr("opendbc.car.nissan.interface.disable_ecu", lambda *args, **kwargs: disable_calls.append((args, kwargs)))
|
||||
CarInterface.init(alpha_long, None, None)
|
||||
assert not disable_calls
|
||||
|
||||
|
||||
def test_dormant_leaf_2025_sv_plus_alpha_long_params(experimental_leaf_long):
|
||||
stock = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, False, False, False, None)
|
||||
alpha_long = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, None)
|
||||
|
||||
@@ -79,7 +107,13 @@ def test_stock_controller_does_not_send_longitudinal_messages():
|
||||
assert not ({0x2B0, 0x1C3, 0x707} & can_sends.keys())
|
||||
|
||||
|
||||
def test_alpha_long_controller_sends_stock_shaped_commands_and_keepalive():
|
||||
def test_disabled_alpha_long_controller_does_not_send_longitudinal_messages():
|
||||
can_sends = run_controller(True)
|
||||
|
||||
assert not ({0x2B0, 0x1C3, 0x707} & can_sends.keys())
|
||||
|
||||
|
||||
def test_alpha_long_controller_sends_stock_shaped_commands_and_keepalive(experimental_leaf_long):
|
||||
can_sends = run_controller(True)
|
||||
|
||||
assert can_sends[0x2B0][1].hex() == "ff6090ac5b000e03"
|
||||
@@ -89,13 +123,13 @@ def test_alpha_long_controller_sends_stock_shaped_commands_and_keepalive():
|
||||
assert can_sends[0x707][2] == 0
|
||||
|
||||
|
||||
def test_alpha_long_controller_clamps_to_panda_accel_limit():
|
||||
def test_alpha_long_controller_clamps_to_panda_accel_limit(experimental_leaf_long):
|
||||
can_sends = run_controller(True, accel=5.0)
|
||||
|
||||
assert can_sends[0x2B0][1].hex() == "007f8fac5b000e0c"
|
||||
|
||||
|
||||
def test_alpha_long_controller_blends_friction_brake_below_regen_limit():
|
||||
def test_alpha_long_controller_blends_friction_brake_below_regen_limit(experimental_leaf_long):
|
||||
can_sends = run_controller(True, accel=-2.0)
|
||||
|
||||
assert can_sends[0x2B0][1].hex() == "a827d5ac5b000e09"
|
||||
@@ -104,7 +138,7 @@ def test_alpha_long_controller_blends_friction_brake_below_regen_limit():
|
||||
assert brake[5] & 0x84 == 0x84
|
||||
|
||||
|
||||
def test_alpha_long_controller_sends_inactive_commands_when_disengaged():
|
||||
def test_alpha_long_controller_sends_inactive_commands_when_disengaged(experimental_leaf_long):
|
||||
can_sends = run_controller(True, accel=1.0, long_active=False)
|
||||
|
||||
assert can_sends[0x2B0][1].hex() == "dc53a2ac1b000e03"
|
||||
@@ -113,7 +147,7 @@ def test_alpha_long_controller_sends_inactive_commands_when_disengaged():
|
||||
|
||||
@pytest.mark.parametrize(("signal", "button_type"), [("SET_BUTTON", ButtonType.decelCruise),
|
||||
("RES_BUTTON", ButtonType.accelCruise)])
|
||||
def test_leaf_set_resume_release_enables_alpha_long(signal, button_type):
|
||||
def test_leaf_set_resume_release_enables_alpha_long(signal, button_type, experimental_leaf_long):
|
||||
CP = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, TEST_TOGGLES)
|
||||
FPCP = CarInterface.get_starpilot_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, CP, TEST_TOGGLES)
|
||||
CS = CarState(CP, FPCP)
|
||||
@@ -130,7 +164,7 @@ def test_leaf_set_resume_release_enables_alpha_long(signal, button_type):
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ecu_disabled", [False, True])
|
||||
def test_leaf_ecu_disable_is_strict_and_falls_back(monkeypatch, ecu_disabled):
|
||||
def test_leaf_ecu_disable_is_strict_and_falls_back(monkeypatch, ecu_disabled, experimental_leaf_long):
|
||||
CP = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, None)
|
||||
calls = []
|
||||
|
||||
@@ -148,17 +182,17 @@ def test_leaf_ecu_disable_is_strict_and_falls_back(monkeypatch, ecu_disabled):
|
||||
assert calls[0]["addr"] == 0x707
|
||||
assert calls[0]["bus"] == 0
|
||||
assert calls[0]["response_offset"] == 0x20
|
||||
assert calls[0]["require_response"] is True
|
||||
assert calls[0]["diag_request"] == b"\x10\xf0"
|
||||
assert calls[0]["diag_response"] == b"\x50\xf0"
|
||||
assert calls[0]["com_cont_req"] == b"\x28\x01"
|
||||
assert calls[0]["require_response"] is False
|
||||
assert calls[0]["diag_request"] == b"\x10\xc0"
|
||||
assert calls[0]["diag_response"] == b"\x50\xc0"
|
||||
assert calls[0]["com_cont_req"] == b"\x28\x02"
|
||||
assert calls[0]["retry"] == 1
|
||||
assert CP.openpilotLongitudinalControl is ecu_disabled
|
||||
assert CP.pcmCruise is not ecu_disabled
|
||||
assert bool(CP.safetyConfigs[-1].safetyParam & NissanSafetyFlags.LONG_CONTROL) is ecu_disabled
|
||||
|
||||
|
||||
def test_leaf_kwp_data_monitor_session_can_confirm_ecu_disable(monkeypatch):
|
||||
def test_leaf_kwp_no_response_disable_can_confirm_ecu_silence(monkeypatch, experimental_leaf_long):
|
||||
CP = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, None)
|
||||
|
||||
monkeypatch.setattr("opendbc.car.nissan.interface.disable_ecu", lambda *args, **kwargs: True)
|
||||
@@ -171,7 +205,7 @@ def test_leaf_kwp_data_monitor_session_can_confirm_ecu_disable(monkeypatch):
|
||||
assert CP.safetyConfigs[-1].safetyParam & NissanSafetyFlags.LONG_CONTROL
|
||||
|
||||
|
||||
def test_leaf_positive_disable_response_without_command_silence_falls_back(monkeypatch):
|
||||
def test_leaf_positive_disable_response_without_command_silence_falls_back(monkeypatch, experimental_leaf_long):
|
||||
CP = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, None)
|
||||
restore_calls = []
|
||||
|
||||
|
||||
@@ -22,14 +22,14 @@ _LEGACY_2025_REENGAGE_MAX_STEER_RATE = 2.0
|
||||
_LEGACY_2025_REENGAGE_MAX_ANGLE_DELTA = 1.0
|
||||
_LEGACY_2025_RECLAIM_FRAMES = 36
|
||||
_LEGACY_2025_RECLAIM_EXPONENT = 2.5
|
||||
_ASCENT_OVERRIDE_HOLD_FRAMES = 10
|
||||
_ASCENT_REENGAGE_SETTLE_FRAMES = 8
|
||||
_ASCENT_REENGAGE_MAX_STEER_RATE = 2.0
|
||||
_ASCENT_REENGAGE_MAX_ANGLE_DELTA = 1.0
|
||||
_ASCENT_RECLAIM_FRAMES = 36
|
||||
_ASCENT_RECLAIM_EXPONENT = 2.5
|
||||
_ASCENT_MADS_MIN_SPEED = 0.44704
|
||||
_ASCENT_MADS_MAX_STEER_ANGLE = 120.0
|
||||
_ANGLE_OVERRIDE_HOLD_FRAMES = 10
|
||||
_ANGLE_REENGAGE_SETTLE_FRAMES = 8
|
||||
_ANGLE_REENGAGE_MAX_STEER_RATE = 2.0
|
||||
_ANGLE_REENGAGE_MAX_ANGLE_DELTA = 1.0
|
||||
_ANGLE_RECLAIM_FRAMES = 36
|
||||
_ANGLE_RECLAIM_EXPONENT = 2.5
|
||||
_ANGLE_MADS_MIN_SPEED = 0.44704
|
||||
_ANGLE_MADS_MAX_STEER_ANGLE = 120.0
|
||||
|
||||
|
||||
def get_safety_CP():
|
||||
@@ -50,13 +50,13 @@ class CarController(CarControllerBase):
|
||||
self.legacy_2025_reengage_reference_angle = 0.0
|
||||
self.legacy_2025_reclaim_frames = 0
|
||||
self.legacy_2025_reclaim_start_angle = 0.0
|
||||
self.ascent_lkas_active = False
|
||||
self.ascent_handoff_active = False
|
||||
self.ascent_override_hold_frames = 0
|
||||
self.ascent_reengage_settle_frames = 0
|
||||
self.ascent_reengage_reference_angle = 0.0
|
||||
self.ascent_reclaim_frames = 0
|
||||
self.ascent_reclaim_start_angle = 0.0
|
||||
self.angle_lkas_active = False
|
||||
self.angle_handoff_active = False
|
||||
self.angle_override_hold_frames = 0
|
||||
self.angle_reengage_settle_frames = 0
|
||||
self.angle_reengage_reference_angle = 0.0
|
||||
self.angle_reclaim_frames = 0
|
||||
self.angle_reclaim_start_angle = 0.0
|
||||
|
||||
self.cruise_button_prev = 0
|
||||
self.steer_rate_counter = 0
|
||||
@@ -137,67 +137,67 @@ class CarController(CarControllerBase):
|
||||
self.legacy_2025_reclaim_frames -= 1
|
||||
return target_angle
|
||||
|
||||
def _reset_ascent_handoff(self):
|
||||
self.ascent_handoff_active = False
|
||||
self.ascent_override_hold_frames = 0
|
||||
self.ascent_reengage_settle_frames = 0
|
||||
self.ascent_reengage_reference_angle = 0.0
|
||||
self.ascent_reclaim_frames = 0
|
||||
self.ascent_reclaim_start_angle = 0.0
|
||||
def _reset_angle_handoff(self):
|
||||
self.angle_handoff_active = False
|
||||
self.angle_override_hold_frames = 0
|
||||
self.angle_reengage_settle_frames = 0
|
||||
self.angle_reengage_reference_angle = 0.0
|
||||
self.angle_reclaim_frames = 0
|
||||
self.angle_reclaim_start_angle = 0.0
|
||||
|
||||
def _ascent_manual_handoff(self, CS, lat_active):
|
||||
def _angle_manual_handoff(self, CS, lat_active):
|
||||
if not lat_active:
|
||||
self._reset_ascent_handoff()
|
||||
self._reset_angle_handoff()
|
||||
return False
|
||||
|
||||
if CS.out.steeringPressed:
|
||||
self.ascent_handoff_active = True
|
||||
self.ascent_override_hold_frames = _ASCENT_OVERRIDE_HOLD_FRAMES
|
||||
self.ascent_reengage_settle_frames = 0
|
||||
self.ascent_reengage_reference_angle = CS.out.steeringAngleDeg
|
||||
self.ascent_reclaim_frames = 0
|
||||
self.angle_handoff_active = True
|
||||
self.angle_override_hold_frames = _ANGLE_OVERRIDE_HOLD_FRAMES
|
||||
self.angle_reengage_settle_frames = 0
|
||||
self.angle_reengage_reference_angle = CS.out.steeringAngleDeg
|
||||
self.angle_reclaim_frames = 0
|
||||
return True
|
||||
|
||||
if not self.ascent_handoff_active and not self.ascent_lkas_active and \
|
||||
abs(CS.out.steeringRateDeg) > _ASCENT_REENGAGE_MAX_STEER_RATE:
|
||||
self.ascent_handoff_active = True
|
||||
self.ascent_reengage_reference_angle = CS.out.steeringAngleDeg
|
||||
if not self.angle_handoff_active and not self.angle_lkas_active and \
|
||||
abs(CS.out.steeringRateDeg) > _ANGLE_REENGAGE_MAX_STEER_RATE:
|
||||
self.angle_handoff_active = True
|
||||
self.angle_reengage_reference_angle = CS.out.steeringAngleDeg
|
||||
|
||||
if not self.ascent_handoff_active:
|
||||
if not self.angle_handoff_active:
|
||||
return False
|
||||
|
||||
if self.ascent_override_hold_frames > 0:
|
||||
self.ascent_override_hold_frames -= 1
|
||||
if self.ascent_override_hold_frames == 0:
|
||||
self.ascent_reengage_reference_angle = CS.out.steeringAngleDeg
|
||||
if self.angle_override_hold_frames > 0:
|
||||
self.angle_override_hold_frames -= 1
|
||||
if self.angle_override_hold_frames == 0:
|
||||
self.angle_reengage_reference_angle = CS.out.steeringAngleDeg
|
||||
return True
|
||||
|
||||
wheel_stable = abs(CS.out.steeringRateDeg) <= _ASCENT_REENGAGE_MAX_STEER_RATE and \
|
||||
abs(CS.out.steeringAngleDeg - self.ascent_reengage_reference_angle) <= _ASCENT_REENGAGE_MAX_ANGLE_DELTA
|
||||
wheel_stable = abs(CS.out.steeringRateDeg) <= _ANGLE_REENGAGE_MAX_STEER_RATE and \
|
||||
abs(CS.out.steeringAngleDeg - self.angle_reengage_reference_angle) <= _ANGLE_REENGAGE_MAX_ANGLE_DELTA
|
||||
if wheel_stable:
|
||||
self.ascent_reengage_settle_frames += 1
|
||||
self.angle_reengage_settle_frames += 1
|
||||
else:
|
||||
self.ascent_reengage_settle_frames = 0
|
||||
self.ascent_reengage_reference_angle = CS.out.steeringAngleDeg
|
||||
self.angle_reengage_settle_frames = 0
|
||||
self.angle_reengage_reference_angle = CS.out.steeringAngleDeg
|
||||
|
||||
if self.ascent_reengage_settle_frames < _ASCENT_REENGAGE_SETTLE_FRAMES:
|
||||
if self.angle_reengage_settle_frames < _ANGLE_REENGAGE_SETTLE_FRAMES:
|
||||
return True
|
||||
|
||||
self.ascent_handoff_active = False
|
||||
self.ascent_reengage_settle_frames = 0
|
||||
self.ascent_reclaim_frames = _ASCENT_RECLAIM_FRAMES
|
||||
self.ascent_reclaim_start_angle = CS.out.steeringAngleDeg
|
||||
self.angle_handoff_active = False
|
||||
self.angle_reengage_settle_frames = 0
|
||||
self.angle_reclaim_frames = _ANGLE_RECLAIM_FRAMES
|
||||
self.angle_reclaim_start_angle = CS.out.steeringAngleDeg
|
||||
return True
|
||||
|
||||
def _ascent_reclaim_target(self, target_angle):
|
||||
if self.ascent_reclaim_frames <= 0:
|
||||
def _angle_reclaim_target(self, target_angle):
|
||||
if self.angle_reclaim_frames <= 0:
|
||||
return target_angle
|
||||
|
||||
progress = (_ASCENT_RECLAIM_FRAMES - self.ascent_reclaim_frames + 1) / _ASCENT_RECLAIM_FRAMES
|
||||
eased_progress = progress ** _ASCENT_RECLAIM_EXPONENT
|
||||
target_angle = self.ascent_reclaim_start_angle + eased_progress * \
|
||||
(target_angle - self.ascent_reclaim_start_angle)
|
||||
self.ascent_reclaim_frames -= 1
|
||||
progress = (_ANGLE_RECLAIM_FRAMES - self.angle_reclaim_frames + 1) / _ANGLE_RECLAIM_FRAMES
|
||||
eased_progress = progress ** _ANGLE_RECLAIM_EXPONENT
|
||||
target_angle = self.angle_reclaim_start_angle + eased_progress * \
|
||||
(target_angle - self.angle_reclaim_start_angle)
|
||||
self.angle_reclaim_frames -= 1
|
||||
return target_angle
|
||||
|
||||
def lateral_angle(self, CC, CS):
|
||||
@@ -224,30 +224,41 @@ class CarController(CarControllerBase):
|
||||
self.legacy_2025_lkas_active = lkas_active
|
||||
return subarucan.create_steering_control_angle(self.packer, apply_steer, lkas_active, self.angle_bus)
|
||||
|
||||
if self.CP.carFingerprint == CAR.SUBARU_ASCENT_2023:
|
||||
if self.CP.carFingerprint in (CAR.SUBARU_ASCENT_2023, CAR.SUBARU_OUTBACK_2023):
|
||||
mads_only = CC.latActive and not CC.enabled
|
||||
mads_only_ok = CS.out.vEgoRaw > _ASCENT_MADS_MIN_SPEED and \
|
||||
abs(CS.out.steeringAngleDeg) < _ASCENT_MADS_MAX_STEER_ANGLE
|
||||
mads_only_ok = CS.out.vEgoRaw > _ANGLE_MADS_MIN_SPEED and \
|
||||
abs(CS.out.steeringAngleDeg) < _ANGLE_MADS_MAX_STEER_ANGLE
|
||||
lkas_available = CC.latActive and (not mads_only or mads_only_ok) and \
|
||||
CS.out.gearShifter == structs.CarState.GearShifter.drive and not CS.out.standstill
|
||||
|
||||
manual_handoff = self._ascent_manual_handoff(CS, lkas_available)
|
||||
manual_handoff = self._angle_manual_handoff(CS, lkas_available)
|
||||
lkas_active = lkas_available and not manual_handoff
|
||||
|
||||
if lkas_active and not self.ascent_lkas_active:
|
||||
if lkas_active and not self.angle_lkas_active:
|
||||
self.apply_steer_last = CS.out.steeringAngleDeg
|
||||
|
||||
steer_target = self._ascent_reclaim_target(CC.actuators.steeringAngleDeg) if lkas_active else CC.actuators.steeringAngleDeg
|
||||
apply_steer = apply_std_steer_angle_limits(
|
||||
steer_target,
|
||||
self.apply_steer_last,
|
||||
CS.out.vEgoRaw,
|
||||
CS.out.steeringAngleDeg,
|
||||
lkas_active,
|
||||
self.p.FIXED_ANGLE_LIMITS,
|
||||
)
|
||||
steer_target = self._angle_reclaim_target(CC.actuators.steeringAngleDeg) if lkas_active else CC.actuators.steeringAngleDeg
|
||||
if self.CP.carFingerprint == CAR.SUBARU_ASCENT_2023:
|
||||
apply_steer = apply_std_steer_angle_limits(
|
||||
steer_target,
|
||||
self.apply_steer_last,
|
||||
CS.out.vEgoRaw,
|
||||
CS.out.steeringAngleDeg,
|
||||
lkas_active,
|
||||
self.p.FIXED_ANGLE_LIMITS,
|
||||
)
|
||||
else:
|
||||
apply_steer = apply_steer_angle_limits_vm(
|
||||
steer_target,
|
||||
self.apply_steer_last,
|
||||
CS.out.vEgoRaw,
|
||||
CS.out.steeringAngleDeg,
|
||||
lkas_active,
|
||||
self.p,
|
||||
self.VM,
|
||||
)
|
||||
self.apply_steer_last = apply_steer
|
||||
self.ascent_lkas_active = lkas_active
|
||||
self.angle_lkas_active = lkas_active
|
||||
return subarucan.create_steering_control_angle(self.packer, apply_steer, lkas_active, self.angle_bus)
|
||||
|
||||
abs_torque = abs(CS.out.steeringTorque)
|
||||
|
||||
@@ -51,6 +51,8 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
if ret.flags & SubaruFlags.LKAS_ANGLE:
|
||||
ret.steerControlType = structs.CarParams.SteerControlType.angle
|
||||
if candidate == CAR.SUBARU_OUTBACK_2023:
|
||||
ret.lateralSmoothSeconds = 0.4
|
||||
|
||||
elif candidate in (CAR.SUBARU_ASCENT, CAR.SUBARU_ASCENT_2023):
|
||||
ret.steerActuatorDelay = 0.3 # end-to-end angle controller
|
||||
|
||||
@@ -202,6 +202,7 @@ def test_outback_2023_uses_d_platform_bus_layout():
|
||||
assert parsers[Bus.main].bus == CanBus.main
|
||||
assert controller.angle_bus == CanBus.main
|
||||
assert controller.status_bus == CanBus.main
|
||||
assert CP.lateralSmoothSeconds == pytest.approx(0.4)
|
||||
|
||||
|
||||
def test_legacy_2025_uses_gen2_angle_bus_layout():
|
||||
@@ -458,8 +459,9 @@ def test_ascent_angle_controller_uses_fixed_angle_rate_limits():
|
||||
assert CS.out.steeringAngleDeg < parser.vl["ES_LKAS_ANGLE"]["LKAS_Output"] < -25.0
|
||||
|
||||
|
||||
def test_ascent_angle_controller_yields_until_manual_steering_settles():
|
||||
CP = CarInterface.get_non_essential_params(CAR.SUBARU_ASCENT_2023)
|
||||
@pytest.mark.parametrize("platform", (CAR.SUBARU_ASCENT_2023, CAR.SUBARU_OUTBACK_2023))
|
||||
def test_angle_controller_yields_until_manual_steering_settles(platform):
|
||||
CP = CarInterface.get_non_essential_params(platform)
|
||||
controller = CarController({}, CP)
|
||||
CC = SimpleNamespace(enabled=True, latActive=True, actuators=SimpleNamespace(steeringAngleDeg=-10.0))
|
||||
CS = SimpleNamespace(out=SimpleNamespace(
|
||||
|
||||
@@ -165,13 +165,18 @@ class TestCarInterfaces:
|
||||
"Center_Stack_2": {"LKAS_Button": 1},
|
||||
}, is_ram=True)
|
||||
|
||||
def test_chrysler_wd_mod_enables_steer_to_zero(self):
|
||||
@pytest.mark.parametrize("candidate", (
|
||||
CHRYSLER_CAR.CHRYSLER_PACIFICA_2020,
|
||||
CHRYSLER_CAR.JEEP_GRAND_CHEROKEE,
|
||||
CHRYSLER_CAR.JEEP_GRAND_CHEROKEE_2019,
|
||||
))
|
||||
def test_chrysler_steer_to_zero_module(self, candidate):
|
||||
fingerprint = {bus: {} for bus in range(8)}
|
||||
fingerprint[0][0x4FF] = 8
|
||||
toggles = get_test_starpilot_toggles()
|
||||
|
||||
car_params = ChryslerCarInterface.get_params(
|
||||
CHRYSLER_CAR.CHRYSLER_PACIFICA_2020,
|
||||
candidate,
|
||||
fingerprint,
|
||||
[],
|
||||
alpha_long=False,
|
||||
@@ -182,7 +187,7 @@ class TestCarInterfaces:
|
||||
assert car_params.minSteerSpeed > 0.
|
||||
|
||||
fp_car_params = ChryslerCarInterface.get_starpilot_params(
|
||||
CHRYSLER_CAR.CHRYSLER_PACIFICA_2020,
|
||||
candidate,
|
||||
fingerprint,
|
||||
[],
|
||||
car_params,
|
||||
@@ -206,11 +211,14 @@ class TestCarInterfaces:
|
||||
button_message="CRUISE_BUTTONS",
|
||||
auto_high_beam=0,
|
||||
)
|
||||
controller.update(CC, CS, 0, toggles)
|
||||
controller.update(CC, CS, 0, toggles)
|
||||
_, can_sends = controller.update(CC, CS, 0, toggles)
|
||||
|
||||
lkas_parser = CANParser(CHRYSLER_DBC[car_params.carFingerprint][Bus.pt], [("LKAS_COMMAND", 50)], 0)
|
||||
lkas_parser.update([0, can_sends])
|
||||
assert lkas_parser.vl["LKAS_COMMAND"]["LKAS_CONTROL_BIT"] == 1
|
||||
assert lkas_parser.vl["LKAS_COMMAND"]["STEERING_TORQUE"] != 0
|
||||
|
||||
@pytest.mark.parametrize("candidate", (CHRYSLER_CAR.JEEP_GRAND_CHEROKEE, CHRYSLER_CAR.JEEP_GRAND_CHEROKEE_2019))
|
||||
def test_jeep_brake_hold_safety_capability_is_provisioned(self, candidate):
|
||||
|
||||
@@ -437,6 +437,11 @@ static safety_config ford_init(uint16_t param) {
|
||||
{FORD_LateralMotionControl2, 0, 8, .check_relay = true},
|
||||
};
|
||||
|
||||
static const CanMsg FORD_STOCK_TX_MSGS[] = {
|
||||
FORD_COMMON_TX_MSGS
|
||||
{FORD_LateralMotionControl, 0, 8, .check_relay = true},
|
||||
};
|
||||
|
||||
static const CanMsg FORD_LONG_TX_MSGS[] = {
|
||||
FORD_COMMON_TX_MSGS
|
||||
{FORD_ACCDATA, 0, 8, .check_relay = true},
|
||||
@@ -459,15 +464,13 @@ static safety_config ford_init(uint16_t param) {
|
||||
ford_longitudinal = GET_FLAG(param, FORD_PARAM_LONGITUDINAL);
|
||||
#endif
|
||||
|
||||
// Longitudinal is the default for CAN, and optional for CAN FD w/ ALLOW_DEBUG
|
||||
ford_longitudinal = !ford_canfd || ford_longitudinal;
|
||||
|
||||
safety_config ret;
|
||||
if (ford_canfd) {
|
||||
ret = ford_longitudinal ? BUILD_SAFETY_CFG(ford_rx_checks, FORD_CANFD_LONG_TX_MSGS) : \
|
||||
BUILD_SAFETY_CFG(ford_rx_checks, FORD_CANFD_STOCK_TX_MSGS);
|
||||
} else {
|
||||
ret = BUILD_SAFETY_CFG(ford_rx_checks, FORD_LONG_TX_MSGS);
|
||||
ret = ford_longitudinal ? BUILD_SAFETY_CFG(ford_rx_checks, FORD_LONG_TX_MSGS) : \
|
||||
BUILD_SAFETY_CFG(ford_rx_checks, FORD_STOCK_TX_MSGS);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ 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}, \
|
||||
@@ -193,7 +194,12 @@ static void hyundai_rx_hook(const CANPacket_t *msg) {
|
||||
if (msg->addr == 0x420U) {
|
||||
if (msg->bus == scc_bus) {
|
||||
if (!hyundai_longitudinal) {
|
||||
acc_main_on = GET_BIT(msg, hyundai_can_canfd_blended ? 27U : 0U);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -442,6 +448,8 @@ 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,6 +60,9 @@ 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;
|
||||
@@ -95,6 +98,7 @@ 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;
|
||||
@@ -160,7 +164,9 @@ void hyundai_common_cruise_buttons_check(const int cruise_button, const bool mai
|
||||
}
|
||||
|
||||
if (main_button && !main_button_prev) {
|
||||
acc_main_on = !acc_main_on;
|
||||
if (!hyundai_aol_main_lkas_sync) {
|
||||
acc_main_on = !acc_main_on;
|
||||
}
|
||||
}
|
||||
main_button_prev = main_button;
|
||||
}
|
||||
|
||||
@@ -1103,6 +1103,7 @@ class SafetyTest(SafetyTestBase):
|
||||
'TestHyundaiSafetyFCEVLong', 'TestHyundaiLongitudinalAolLkasOnEngageSafety',
|
||||
'TestHyundaiSafetyCanRefreshLong', 'TestHyundaiSafetyCanRefreshLongCameraSCC',
|
||||
'TestHyundaiCanCanfdBlendedLongitudinalSafety',
|
||||
'TestHyundaiLegacyLongitudinalSafety',
|
||||
'TestHyundaiLegacyLongitudinalSafetyHEV'}):
|
||||
continue
|
||||
volkswagen_shared = ('TestVolkswagenMqb', 'TestVolkswagenMlb', 'TestVolkswagenMeb')
|
||||
@@ -1156,6 +1157,7 @@ class SafetyTest(SafetyTestBase):
|
||||
if attr.startswith('TestHyundaiLongitudinal') or attr in ('TestHyundaiSafetyFCEVLong',
|
||||
'TestHyundaiLongitudinalAolLkasOnEngageSafety',
|
||||
'TestHyundaiCanCanfdBlendedLongitudinalSafety',
|
||||
'TestHyundaiLegacyLongitudinalSafety',
|
||||
'TestHyundaiLegacyLongitudinalSafetyHEV'):
|
||||
# exceptions for common msgs across different Hyundai CAN platforms
|
||||
tx = list(filter(lambda m: m[0] not in [0x420, 0x50A, 0x389, 0x4A2], tx))
|
||||
|
||||
@@ -61,6 +61,7 @@ class Buttons:
|
||||
|
||||
|
||||
# Ford safety has four different configurations tested here:
|
||||
# * CAN with stock longitudinal
|
||||
# * CAN with openpilot longitudinal
|
||||
# * CAN FD with stock longitudinal
|
||||
# * CAN FD with openpilot longitudinal
|
||||
@@ -443,6 +444,30 @@ class TestFordCANFDStockSafety(TestFordSafetyBase):
|
||||
self.assertFalse(self._tx(self._lat_ctl_msg(True, 0.0, 0.01, 0.0, 0.0)))
|
||||
|
||||
|
||||
class TestFordStockSafety(TestFordSafetyBase):
|
||||
STEER_MESSAGE = MSG_LateralMotionControl
|
||||
|
||||
TX_MSGS = [
|
||||
[MSG_Steering_Data_FD1, 0], [MSG_Steering_Data_FD1, 2], [MSG_ACCDATA_3, 0], [MSG_Lane_Assist_Data1, 0],
|
||||
[MSG_LateralMotionControl, 0], [MSG_IPMA_Data, 0],
|
||||
]
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl,
|
||||
MSG_IPMA_Data)}
|
||||
|
||||
FWD_BLACKLISTED_ADDRS = {2: [MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl,
|
||||
MSG_IPMA_Data]}
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("ford_lincoln_base_pt")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.ford, 0)
|
||||
self.safety.init_tests()
|
||||
|
||||
def test_max_lateral_acceleration(self):
|
||||
# CAN does not limit curvature from lateral acceleration
|
||||
pass
|
||||
|
||||
|
||||
class TestFordLongitudinalSafetyBase(TestFordSafetyBase):
|
||||
MAX_ACCEL = 2.0 # accel is used for brakes, but openpilot can set positive values
|
||||
MIN_ACCEL = -3.5
|
||||
@@ -509,8 +534,7 @@ class TestFordLongitudinalSafety(TestFordLongitudinalSafetyBase):
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("ford_lincoln_base_pt")
|
||||
self.safety = libsafety_py.libsafety
|
||||
# Make sure we enforce long safety even without long flag for CAN
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.ford, 0)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.ford, FordSafetyFlags.LONG_CONTROL)
|
||||
self.safety.init_tests()
|
||||
|
||||
def test_max_lateral_acceleration(self):
|
||||
@@ -524,7 +548,7 @@ class TestFordLKASteeringSafety(TestFordLongitudinalSafety):
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("ford_lincoln_base_pt")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.ford, FordSafetyFlags.LKA_STEERING)
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.ford, FordSafetyFlags.LONG_CONTROL | FordSafetyFlags.LKA_STEERING)
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ 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
|
||||
@@ -596,6 +597,14 @@ class TestHyundaiSafetyFCEVLong(TestHyundaiLongitudinalSafety, TestHyundaiSafety
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
class TestHyundaiLegacyLongitudinalSafety(TestHyundaiLongitudinalSafety, TestHyundaiLegacySafety):
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiLegacy, HyundaiSafetyFlags.LONG)
|
||||
self.safety.init_tests()
|
||||
|
||||
|
||||
class TestHyundaiLegacyLongitudinalSafetyHEV(TestHyundaiLongitudinalSafety, TestHyundaiLegacySafetyHEV):
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("hyundai_kia_generic")
|
||||
@@ -621,5 +630,65 @@ 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.
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-459d7c40-DEBUG";
|
||||
const uint8_t gitversion[19] = "DEV-284dbddd-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.
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.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user