mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-07 22:52:06 +08:00
Auracast
This commit is contained in:
@@ -640,6 +640,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"VeryLongModeButtonControl", {PERSISTENT, INT, "0", "0", 2}},
|
||||
{"VeryLongStarButtonControl", {PERSISTENT, INT, "0", "0", 2}},
|
||||
{"VoltSNG", {PERSISTENT, BOOL, "0", "0", 2}},
|
||||
{"JeepBrakeHold", {PERSISTENT, BOOL, "0", "0", 2}},
|
||||
{"GMAutoHold", {PERSISTENT, BOOL, "0", "0", 2}},
|
||||
{"VoltOnePedalMode", {PERSISTENT, BOOL, "0", "0", 2}},
|
||||
{"ToyotaAutoHold", {PERSISTENT, BOOL, "0", "0", 2}},
|
||||
|
||||
@@ -2,9 +2,28 @@ from opendbc.can import CANPacker
|
||||
from opendbc.car import Bus, DT_CTRL
|
||||
from opendbc.car.lateral import apply_meas_steer_torque_limits
|
||||
from opendbc.car.chrysler import chryslercan
|
||||
from opendbc.car.chrysler.values import RAM_CARS, RAM_DT, CarControllerParams, ChryslerFlags, ChryslerStarPilotFlags
|
||||
from opendbc.car.chrysler.values import JEEPS, RAM_CARS, RAM_DT, CarControllerParams, ChryslerFlags, ChryslerSafetyFlags, ChryslerStarPilotFlags
|
||||
from opendbc.car.interfaces import CarControllerBase
|
||||
|
||||
JEEP_BRAKE_HOLD_DEFAULT_DECEL = -2.0
|
||||
JEEP_BRAKE_HOLD_MIN_DECEL = -0.5
|
||||
JEEP_BRAKE_HOLD_MAX_DECEL = -3.0
|
||||
|
||||
|
||||
def clip_jeep_brake_hold_decel(decel: float) -> float:
|
||||
return max(JEEP_BRAKE_HOLD_MAX_DECEL, min(JEEP_BRAKE_HOLD_MIN_DECEL, float(decel)))
|
||||
|
||||
|
||||
def supports_jeep_brake_hold(CP, brake_hold_enabled: bool) -> bool:
|
||||
safety_cfg = getattr(CP, "safetyConfigs", ())
|
||||
safety_param = safety_cfg[0].safetyParam if safety_cfg else 0
|
||||
return (
|
||||
brake_hold_enabled and
|
||||
getattr(CP, "pcmCruise", False) and
|
||||
CP.carFingerprint in JEEPS and
|
||||
bool(safety_param & ChryslerSafetyFlags.JEEP_BRAKE_HOLD.value)
|
||||
)
|
||||
|
||||
|
||||
class CarController(CarControllerBase):
|
||||
def __init__(self, dbc_names, CP):
|
||||
@@ -18,6 +37,8 @@ class CarController(CarControllerBase):
|
||||
|
||||
self.packer = CANPacker(dbc_names[Bus.pt])
|
||||
self.params = CarControllerParams(CP)
|
||||
self.jeep_brake_hold_decel = JEEP_BRAKE_HOLD_DEFAULT_DECEL
|
||||
self.last_das_3_counter = -1
|
||||
|
||||
def update(self, CC, CS, now_nanos, starpilot_toggles):
|
||||
can_sends = []
|
||||
@@ -82,6 +103,11 @@ class CarController(CarControllerBase):
|
||||
|
||||
can_sends.append(chryslercan.create_lkas_command(self.packer, self.CP, int(apply_torque), lkas_control_bit))
|
||||
|
||||
if supports_jeep_brake_hold(self.CP, getattr(starpilot_toggles, "jeep_brake_hold", False)):
|
||||
self.update_jeep_brake_hold(CC, CS, can_sends)
|
||||
elif getattr(CS, "brake_hold", False):
|
||||
CS.brake_hold = False
|
||||
|
||||
self.frame += 1
|
||||
|
||||
new_actuators = CC.actuators.as_builder()
|
||||
@@ -89,3 +115,43 @@ class CarController(CarControllerBase):
|
||||
new_actuators.torqueOutputCan = self.apply_torque_last
|
||||
|
||||
return new_actuators, can_sends
|
||||
|
||||
def update_jeep_brake_hold(self, CC, CS, can_sends):
|
||||
if not getattr(CS, "das_3", None):
|
||||
CS.brake_hold = False
|
||||
return
|
||||
|
||||
counter_changed = CS.das_3.get("COUNTER") != self.last_das_3_counter
|
||||
self.last_das_3_counter = CS.das_3.get("COUNTER")
|
||||
|
||||
if not CS.brake_hold and CS.cruise_active_actual and CS.acc_decelerating and CS.out.standstill:
|
||||
CS.brake_hold = True
|
||||
self.jeep_brake_hold_decel = JEEP_BRAKE_HOLD_DEFAULT_DECEL
|
||||
|
||||
driver_intervened = (
|
||||
CC.cruiseControl.cancel or
|
||||
CS.out.gasPressed or
|
||||
CS.out.brakePressed or
|
||||
not CS.forward_gear or
|
||||
not CS.out.standstill
|
||||
)
|
||||
if CS.brake_hold and driver_intervened:
|
||||
CS.brake_hold = False
|
||||
return
|
||||
|
||||
if not CS.brake_hold:
|
||||
return
|
||||
|
||||
if CS.cruise_active_actual:
|
||||
self.jeep_brake_hold_decel = clip_jeep_brake_hold_decel(
|
||||
min(self.jeep_brake_hold_decel, CS.das_3.get("ACC_DECEL", JEEP_BRAKE_HOLD_DEFAULT_DECEL))
|
||||
)
|
||||
return
|
||||
|
||||
counter_offset = 2 if counter_changed else 3
|
||||
can_sends.append(chryslercan.create_das_3_command(self.packer, counter_offset, self.jeep_brake_hold_decel, CS.das_3))
|
||||
|
||||
if self.frame % 10 == 0:
|
||||
can_sends.append(chryslercan.create_cruise_buttons(
|
||||
self.packer, CS.button_counter + 1, 0, CS.button_message, resume=True
|
||||
))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from cereal import custom
|
||||
from opendbc.can import CANDefine, CANParser
|
||||
from opendbc.car import Bus, create_button_events, structs
|
||||
from opendbc.car.chrysler.values import DBC, STEER_THRESHOLD, RAM_CARS, ChryslerStarPilotFlags
|
||||
from opendbc.car.chrysler.values import DBC, JEEPS, STEER_THRESHOLD, RAM_CARS, ChryslerStarPilotFlags
|
||||
from opendbc.car.common.conversions import Conversions as CV
|
||||
from opendbc.car.interfaces import CarStateBase
|
||||
|
||||
@@ -29,6 +29,11 @@ class CarState(CarStateBase):
|
||||
self.button_message = "CRUISE_BUTTONS_ALT" if FPCP.flags & ChryslerStarPilotFlags.RAM_HD_ALT_BUTTONS else "CRUISE_BUTTONS"
|
||||
|
||||
self.lkas_button = 0
|
||||
self.brake_hold = False
|
||||
self.cruise_active_actual = False
|
||||
self.forward_gear = False
|
||||
self.acc_decelerating = False
|
||||
self.das_3 = {}
|
||||
|
||||
@staticmethod
|
||||
def get_lkas_button(pt_signals, is_ram: bool) -> bool:
|
||||
@@ -93,6 +98,13 @@ class CarState(CarStateBase):
|
||||
ret.cruiseState.standstill = cp_cruise.vl["DAS_3"]["ACC_STANDSTILL"] == 1
|
||||
ret.accFaulted = cp_cruise.vl["DAS_3"]["ACC_FAULTED"] != 0
|
||||
|
||||
if self.CP.carFingerprint in JEEPS:
|
||||
self.forward_gear = ret.gearShifter == structs.CarState.GearShifter.drive
|
||||
self.cruise_active_actual = ret.cruiseState.enabled
|
||||
self.acc_decelerating = cp_cruise.vl["DAS_3"]["ACC_DECEL"] < -0.5
|
||||
self.das_3 = dict(cp_cruise.vl["DAS_3"])
|
||||
ret.brakeHoldActive = self.brake_hold
|
||||
|
||||
if self.CP.carFingerprint in RAM_CARS:
|
||||
# Auto High Beam isn't Located in this message on chrysler or jeep currently located in 729 message
|
||||
self.auto_high_beam = cp_cam.vl["DAS_6"]['AUTO_HIGH_BEAM_ON']
|
||||
|
||||
@@ -73,6 +73,21 @@ def create_cruise_buttons(packer, frame, bus, button_message, cancel=False, resu
|
||||
return packer.make_can_msg(button_message, bus, values)
|
||||
|
||||
|
||||
def create_das_3_command(packer, counter_offset, brake_decel, das_3):
|
||||
values = das_3.copy()
|
||||
values["ACC_AVAILABLE"] = 1
|
||||
values["ACC_ACTIVE"] = 1
|
||||
values["ACC_GO"] = 0
|
||||
values["ACC_STANDSTILL"] = 0
|
||||
values["ACC_DECEL_REQ"] = 1
|
||||
values["ACC_DECEL"] = brake_decel
|
||||
values["ACC_BRK_PREP"] = 0
|
||||
values["ENGINE_TORQUE_REQUEST_MAX"] = 0
|
||||
values["GR_MAX_REQ"] = 2
|
||||
values["COUNTER"] = (das_3["COUNTER"] + counter_offset) % 0x10
|
||||
return packer.make_can_msg("DAS_3", 0, values)
|
||||
|
||||
|
||||
def chrysler_checksum(address: int, sig, d: bytearray) -> int:
|
||||
checksum = 0xFF
|
||||
for j in range(len(d) - 1):
|
||||
|
||||
@@ -3,8 +3,9 @@ from opendbc.car import get_safety_config, structs
|
||||
from opendbc.car.chrysler.carcontroller import CarController
|
||||
from opendbc.car.chrysler.carstate import CarState
|
||||
from opendbc.car.chrysler.radar_interface import RadarInterface
|
||||
from opendbc.car.chrysler.values import CAR, RAM_HD, RAM_DT, RAM_CARS, ChryslerFlags, ChryslerSafetyFlags
|
||||
from opendbc.car.chrysler.values import CAR, JEEPS, RAM_HD, RAM_DT, RAM_CARS, ChryslerFlags, ChryslerSafetyFlags
|
||||
from opendbc.car.interfaces import CarInterfaceBase
|
||||
from openpilot.common.params import Params, UnknownKeyName
|
||||
|
||||
|
||||
class CarInterface(CarInterfaceBase):
|
||||
@@ -14,6 +15,12 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
params = Params()
|
||||
try:
|
||||
jeep_brake_hold = params.get_bool("JeepBrakeHold")
|
||||
except UnknownKeyName:
|
||||
jeep_brake_hold = False
|
||||
|
||||
ret.brand = "chrysler"
|
||||
ret.dashcamOnly = candidate in RAM_HD
|
||||
|
||||
@@ -28,6 +35,8 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.safetyConfigs[0].safetyParam |= ChryslerSafetyFlags.RAM_HD.value
|
||||
elif candidate in RAM_DT:
|
||||
ret.safetyConfigs[0].safetyParam |= ChryslerSafetyFlags.RAM_DT.value
|
||||
elif candidate in JEEPS and jeep_brake_hold:
|
||||
ret.safetyConfigs[0].safetyParam |= ChryslerSafetyFlags.JEEP_BRAKE_HOLD.value
|
||||
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
if candidate not in RAM_CARS:
|
||||
|
||||
@@ -12,6 +12,7 @@ Ecu = CarParams.Ecu
|
||||
class ChryslerSafetyFlags(IntFlag):
|
||||
RAM_DT = 1
|
||||
RAM_HD = 2
|
||||
JEEP_BRAKE_HOLD = 4
|
||||
|
||||
|
||||
class ChryslerFlags(IntFlag):
|
||||
@@ -140,6 +141,7 @@ STEER_THRESHOLD = 120
|
||||
RAM_DT = {CAR.RAM_1500_5TH_GEN, }
|
||||
RAM_HD = {CAR.RAM_HD_5TH_GEN, }
|
||||
RAM_CARS = RAM_DT | RAM_HD
|
||||
JEEPS = {CAR.JEEP_GRAND_CHEROKEE, CAR.JEEP_GRAND_CHEROKEE_2019}
|
||||
|
||||
|
||||
CHRYSLER_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \
|
||||
|
||||
@@ -652,6 +652,8 @@ class CarController(CarControllerBase):
|
||||
|
||||
# prevent LFA from activating on LKA steering cars by sending "no lane lines detected" to ADAS ECU
|
||||
suppress_lfa = bool(lka_steering)
|
||||
if self.CP.carFingerprint == CAR.KIA_EV9 and self.CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING:
|
||||
suppress_lfa = bool(lka_steering and CC.latActive)
|
||||
if self.frame % 5 == 0 and suppress_lfa:
|
||||
can_sends.append(hyundaicanfd.create_suppress_lfa(self.packer, self.CAN, CS.lfa_block_msg,
|
||||
self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT))
|
||||
|
||||
@@ -1460,7 +1460,28 @@ class TestHyundaiFingerprint:
|
||||
assert parser.vl["LKAS_ALT"]["STEER_MODE"] == 2
|
||||
assert parser.vl["LKAS_ALT"]["NEW_SIGNAL_2"] == 3
|
||||
|
||||
def test_ev9_inactive_angle_steering_still_suppresses_stock_lfa(self):
|
||||
def test_ev9_inactive_angle_steering_does_not_suppress_stock_lfa(self):
|
||||
CP = CarParams.new_message()
|
||||
CP.carFingerprint = CAR.KIA_EV9
|
||||
CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.EV | HyundaiFlags.CANFD_ANGLE_STEERING |
|
||||
HyundaiFlags.CANFD_LKA_STEERING | HyundaiFlags.CANFD_LKA_STEERING_ALT)
|
||||
CP.openpilotLongitudinalControl = False
|
||||
|
||||
controller = CarController(DBC[CP.carFingerprint], CP)
|
||||
controller.frame = 5
|
||||
cc = SimpleNamespace(enabled=False, latActive=False, actuators=SimpleNamespace(longControlState=LongCtrlState.off),
|
||||
leftBlinker=False, rightBlinker=False, hudControl=SimpleNamespace())
|
||||
lfa_block_msg = {f"BYTE{i}": 0 for i in range(3, 32) if i != 7}
|
||||
lfa_block_msg["COUNTER"] = 0
|
||||
cs = SimpleNamespace(stock_lfa_msg=None, stock_lkas_msg={}, lfa_block_msg=lfa_block_msg,
|
||||
out=SimpleNamespace(steeringAngleDeg=0.0))
|
||||
|
||||
msgs = controller.create_canfd_msgs(0, False, 0.0, 0.0, 0.0, 0.0, False, cc.hudControl, cs, cc,
|
||||
get_test_toggles(), lka_icon=1, lfa_icon=1)
|
||||
suppress_msgs = [msg for msg in msgs if msg[0] == 0x362]
|
||||
assert not suppress_msgs
|
||||
|
||||
def test_ev9_active_angle_steering_still_suppresses_stock_lfa(self):
|
||||
CP = CarParams.new_message()
|
||||
CP.carFingerprint = CAR.KIA_EV9
|
||||
CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.EV | HyundaiFlags.CANFD_ANGLE_STEERING |
|
||||
@@ -1471,7 +1492,7 @@ class TestHyundaiFingerprint:
|
||||
controller.frame = 5
|
||||
can_bus = CanBus(CP)
|
||||
parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("CAM_0x362", 0)], can_bus.ECAN)
|
||||
cc = SimpleNamespace(enabled=False, latActive=False, actuators=SimpleNamespace(longControlState=LongCtrlState.off),
|
||||
cc = SimpleNamespace(enabled=False, latActive=True, actuators=SimpleNamespace(longControlState=LongCtrlState.off),
|
||||
leftBlinker=False, rightBlinker=False, hudControl=SimpleNamespace())
|
||||
lfa_block_msg = {f"BYTE{i}": 0 for i in range(3, 32) if i != 7}
|
||||
lfa_block_msg["COUNTER"] = 0
|
||||
@@ -1479,7 +1500,7 @@ class TestHyundaiFingerprint:
|
||||
out=SimpleNamespace(steeringAngleDeg=0.0))
|
||||
|
||||
msgs = controller.create_canfd_msgs(0, False, 0.0, 0.0, 0.0, 0.0, False, cc.hudControl, cs, cc,
|
||||
get_test_toggles(), lka_icon=1, lfa_icon=1)
|
||||
get_test_toggles(), lka_icon=2, lfa_icon=2)
|
||||
suppress_msgs = [msg for msg in msgs if msg[0] == 0x362]
|
||||
assert len(suppress_msgs) == 1
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
from opendbc.car.chrysler.carcontroller import (
|
||||
JEEP_BRAKE_HOLD_DEFAULT_DECEL,
|
||||
clip_jeep_brake_hold_decel,
|
||||
supports_jeep_brake_hold,
|
||||
)
|
||||
from opendbc.car.chrysler.values import CAR, ChryslerSafetyFlags, JEEPS
|
||||
|
||||
|
||||
def test_jeep_group_is_grand_cherokee_only():
|
||||
assert JEEPS == {CAR.JEEP_GRAND_CHEROKEE, CAR.JEEP_GRAND_CHEROKEE_2019}
|
||||
|
||||
|
||||
def test_jeep_brake_hold_support_requires_toggle_jeep_pcm_and_safety_flag():
|
||||
safety = [SimpleNamespace(safetyParam=ChryslerSafetyFlags.JEEP_BRAKE_HOLD.value)]
|
||||
no_safety = [SimpleNamespace(safetyParam=0)]
|
||||
|
||||
assert supports_jeep_brake_hold(SimpleNamespace(
|
||||
carFingerprint=CAR.JEEP_GRAND_CHEROKEE,
|
||||
pcmCruise=True,
|
||||
safetyConfigs=safety,
|
||||
), True)
|
||||
assert not supports_jeep_brake_hold(SimpleNamespace(
|
||||
carFingerprint=CAR.JEEP_GRAND_CHEROKEE,
|
||||
pcmCruise=True,
|
||||
safetyConfigs=no_safety,
|
||||
), True)
|
||||
assert not supports_jeep_brake_hold(SimpleNamespace(
|
||||
carFingerprint=CAR.JEEP_GRAND_CHEROKEE,
|
||||
pcmCruise=False,
|
||||
safetyConfigs=safety,
|
||||
), True)
|
||||
assert not supports_jeep_brake_hold(SimpleNamespace(
|
||||
carFingerprint=CAR.CHRYSLER_PACIFICA_2018,
|
||||
pcmCruise=True,
|
||||
safetyConfigs=safety,
|
||||
), True)
|
||||
assert not supports_jeep_brake_hold(SimpleNamespace(
|
||||
carFingerprint=CAR.JEEP_GRAND_CHEROKEE,
|
||||
pcmCruise=True,
|
||||
safetyConfigs=safety,
|
||||
), False)
|
||||
|
||||
|
||||
def test_jeep_brake_hold_decel_is_bounded():
|
||||
assert clip_jeep_brake_hold_decel(JEEP_BRAKE_HOLD_DEFAULT_DECEL) == JEEP_BRAKE_HOLD_DEFAULT_DECEL
|
||||
assert clip_jeep_brake_hold_decel(-8.0) == -3.0
|
||||
assert clip_jeep_brake_hold_decel(0.5) == -0.5
|
||||
@@ -23,6 +23,7 @@ typedef enum {
|
||||
} ChryslerPlatform;
|
||||
static ChryslerPlatform chrysler_platform;
|
||||
static const ChryslerAddrs *chrysler_addrs;
|
||||
static bool chrysler_jeep_brake_hold;
|
||||
|
||||
static uint32_t chrysler_get_checksum(const CANPacket_t *msg) {
|
||||
int checksum_byte = GET_LEN(msg) - 1U;
|
||||
@@ -153,18 +154,27 @@ static bool chrysler_tx_hook(const CANPacket_t *msg) {
|
||||
if (msg->addr == chrysler_addrs->CRUISE_BUTTONS || msg->addr == chrysler_addrs->CRUISE_BUTTONS_ALT) {
|
||||
const bool is_cancel = msg->data[0] == 1U;
|
||||
const bool is_resume = msg->data[0] == 0x10U;
|
||||
const bool allowed = is_cancel || (is_resume && controls_allowed);
|
||||
const bool allow_resume_standstill = chrysler_jeep_brake_hold && is_resume && acc_main_on &&
|
||||
!vehicle_moving && !gas_pressed && !brake_pressed;
|
||||
const bool allowed = is_cancel || (is_resume && (controls_allowed || allow_resume_standstill));
|
||||
if (!allowed) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->addr == chrysler_addrs->DAS_3) {
|
||||
if (!chrysler_jeep_brake_hold || !acc_main_on || vehicle_moving || gas_pressed || brake_pressed) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
static safety_config chrysler_init(uint16_t param) {
|
||||
|
||||
const uint32_t CHRYSLER_PARAM_RAM_DT = 1U; // set for Ram DT platform
|
||||
const uint32_t CHRYSLER_PARAM_JEEP_BRAKE_HOLD = 4U;
|
||||
|
||||
// CAN messages for Chrysler/Jeep platforms
|
||||
static const ChryslerAddrs CHRYSLER_ADDRS = {
|
||||
@@ -217,6 +227,7 @@ static safety_config chrysler_init(uint16_t param) {
|
||||
{CHRYSLER_ADDRS.CRUISE_BUTTONS, 0, 3, .check_relay = false},
|
||||
{CHRYSLER_ADDRS.LKAS_COMMAND, 0, 6, .check_relay = true},
|
||||
{CHRYSLER_ADDRS.DAS_6, 0, 8, .check_relay = true},
|
||||
{CHRYSLER_ADDRS.DAS_3, 0, 8, .check_relay = false},
|
||||
|
||||
// RealFast variables
|
||||
{CHRYSLER_ADDRS.CRUISE_BUTTONS_ALT, 2, 3, .check_relay = false},
|
||||
@@ -287,6 +298,7 @@ static safety_config chrysler_init(uint16_t param) {
|
||||
chrysler_addrs = &CHRYSLER_ADDRS;
|
||||
ret = BUILD_SAFETY_CFG(chrysler_rx_checks, CHRYSLER_TX_MSGS);
|
||||
}
|
||||
chrysler_jeep_brake_hold = GET_FLAG(param, CHRYSLER_PARAM_JEEP_BRAKE_HOLD) && (chrysler_platform == CHRYSLER_PACIFICA);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from opendbc.safety.tests.common import CANPackerSafety
|
||||
|
||||
|
||||
class TestChryslerSafety(common.CarSafetyTest, common.MotorTorqueSteeringSafetyTest):
|
||||
TX_MSGS = [[0x23B, 0], [0x292, 0], [0x2A6, 0]]
|
||||
TX_MSGS = [[0x23B, 0], [0x292, 0], [0x2A6, 0], [0x1F4, 0]]
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0x292, 0x2A6)}
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0x292, 0x2A6]}
|
||||
|
||||
@@ -37,6 +37,14 @@ class TestChryslerSafety(common.CarSafetyTest, common.MotorTorqueSteeringSafetyT
|
||||
values = {"ACC_ACTIVE": enable}
|
||||
return self.packer.make_can_msg_safety("DAS_3", self.DAS_BUS, values)
|
||||
|
||||
def _main_on_msg(self, available=True, active=False):
|
||||
values = {"ACC_AVAILABLE": available, "ACC_ACTIVE": active}
|
||||
return self.packer.make_can_msg_panda("DAS_3", self.DAS_BUS, values)
|
||||
|
||||
def _das_3_msg(self):
|
||||
values = {"ACC_AVAILABLE": 1, "ACC_ACTIVE": 1, "ACC_DECEL_REQ": 1, "ACC_DECEL": -2.0}
|
||||
return self.packer.make_can_msg_safety("DAS_3", self.DAS_BUS, values)
|
||||
|
||||
def _speed_msg(self, speed):
|
||||
values = {"SPEED_LEFT": speed, "SPEED_RIGHT": speed}
|
||||
return self.packer.make_can_msg_safety("SPEED_1", 0, values)
|
||||
@@ -71,6 +79,58 @@ class TestChryslerSafety(common.CarSafetyTest, common.MotorTorqueSteeringSafetyT
|
||||
self.assertFalse(self._tx(self._button_msg(cancel=True, resume=True)))
|
||||
self.assertFalse(self._tx(self._button_msg(cancel=False, resume=False)))
|
||||
|
||||
def test_jeep_brake_hold_resume_at_standstill_requires_safety_flag_and_main_on(self):
|
||||
if self.__class__ is not TestChryslerSafety:
|
||||
self.skipTest("Jeep brake hold applies to base Chrysler/Jeep safety only")
|
||||
|
||||
self._rx(self._speed_msg(0))
|
||||
self._rx(self._main_on_msg(True))
|
||||
self.safety.set_controls_allowed(False)
|
||||
|
||||
self.assertFalse(self._tx(self._button_msg(resume=True)))
|
||||
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.chrysler, ChryslerSafetyFlags.JEEP_BRAKE_HOLD)
|
||||
self.safety.init_tests()
|
||||
self._rx(self._speed_msg(0))
|
||||
self._rx(self._main_on_msg(True))
|
||||
self.assertTrue(self._tx(self._button_msg(resume=True)))
|
||||
|
||||
self._rx(self._user_gas_msg(1))
|
||||
self.assertFalse(self._tx(self._button_msg(resume=True)))
|
||||
self._rx(self._user_gas_msg(0))
|
||||
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self.assertFalse(self._tx(self._button_msg(resume=True)))
|
||||
self._rx(self._user_brake_msg(False))
|
||||
|
||||
self._rx(self._speed_msg(1))
|
||||
self.assertFalse(self._tx(self._button_msg(resume=True)))
|
||||
|
||||
def test_jeep_brake_hold_das_3_requires_safety_flag_main_on_and_standstill(self):
|
||||
if self.__class__ is not TestChryslerSafety:
|
||||
self.skipTest("Jeep brake hold applies to base Chrysler/Jeep safety only")
|
||||
|
||||
self.assertFalse(self._tx(self._das_3_msg()))
|
||||
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.chrysler, ChryslerSafetyFlags.JEEP_BRAKE_HOLD)
|
||||
self.safety.init_tests()
|
||||
self._rx(self._speed_msg(0))
|
||||
self.assertFalse(self._tx(self._das_3_msg()))
|
||||
|
||||
self._rx(self._main_on_msg(True))
|
||||
self.assertTrue(self._tx(self._das_3_msg()))
|
||||
|
||||
self._rx(self._user_gas_msg(1))
|
||||
self.assertFalse(self._tx(self._das_3_msg()))
|
||||
self._rx(self._user_gas_msg(0))
|
||||
|
||||
self._rx(self._user_brake_msg(True))
|
||||
self.assertFalse(self._tx(self._das_3_msg()))
|
||||
self._rx(self._user_brake_msg(False))
|
||||
|
||||
self._rx(self._speed_msg(1))
|
||||
self.assertFalse(self._tx(self._das_3_msg()))
|
||||
|
||||
def _toggle_aol(self, toggle_on):
|
||||
# DAS_3, bit 20 is ACC_AVAILABLE
|
||||
values = {"ACC_AVAILABLE": 1 if toggle_on else 0}
|
||||
|
||||
@@ -589,8 +589,9 @@ class SelfdriveD:
|
||||
self.CP.openpilotLongitudinalControl and not self.CP.pcmCruise
|
||||
)
|
||||
effective_pcm_cruise = self.CP.pcmCruise or preap_software_cruise
|
||||
jeep_brake_hold = self.CP.brand == "chrysler" and getattr(CS, "brakeHoldActive", False)
|
||||
cruise_mismatch = should_flag_cruise_mismatch(self.CP, CS.cruiseState.enabled, self.enabled,
|
||||
effective_pcm_cruise) and not pacifica_hybrid_aol
|
||||
effective_pcm_cruise) and not pacifica_hybrid_aol and not jeep_brake_hold
|
||||
self.cruise_mismatch_counter = self.cruise_mismatch_counter + 1 if cruise_mismatch else 0
|
||||
if self.cruise_mismatch_counter > int(6. / DT_CTRL):
|
||||
self.events.add(EventName.cruiseMismatch)
|
||||
|
||||
@@ -162,6 +162,13 @@ class VehicleSettingsManagerView(PanelManagerView):
|
||||
"get_state": lambda: self._controller._params.get_bool("VoltSNG"),
|
||||
"set_state": lambda s: self._controller._on_toggle("VoltSNG"),
|
||||
})
|
||||
if cs.isJeep:
|
||||
toggles.append({
|
||||
"title": tr("Jeep Brake Hold"),
|
||||
"subtitle": tr("Hold after ACC times out at a stop and resume when traffic moves."),
|
||||
"get_state": lambda: self._controller._params.get_bool("JeepBrakeHold"),
|
||||
"set_state": lambda s: self._controller._on_toggle("JeepBrakeHold"),
|
||||
})
|
||||
|
||||
if cs.isSubaru:
|
||||
toggles.append({
|
||||
|
||||
@@ -14,6 +14,7 @@ class StarPilotCarState:
|
||||
# ========== Car Type Detection ==========
|
||||
isGM: bool = False
|
||||
isHKG: bool = False
|
||||
isJeep: bool = False
|
||||
isToyota: bool = False
|
||||
isSubaru: bool = False
|
||||
isVolt: bool = False
|
||||
@@ -86,8 +87,10 @@ class StarPilotState:
|
||||
from openpilot.selfdrive.ui.lib.fingerprint_catalog import FINGERPRINT_MAKE_TO_VALUES_DIR
|
||||
fallback_make_lower = fallback_make.lower()
|
||||
brand = FINGERPRINT_MAKE_TO_VALUES_DIR.get(fallback_make_lower, fallback_make_lower)
|
||||
fallback_model_str = fallback_model or ""
|
||||
self.car_state.isGM = brand == "gm"
|
||||
self.car_state.isHKG = brand == "hyundai"
|
||||
self.car_state.isJeep = brand == "chrysler" and fallback_model_str.startswith("JEEP_")
|
||||
self.car_state.isSubaru = brand == "subaru"
|
||||
self.car_state.isToyota = brand == "toyota"
|
||||
self.car_state.isHKGCanFd = False
|
||||
@@ -98,6 +101,7 @@ class StarPilotState:
|
||||
|
||||
if fallback_model:
|
||||
self.params.put("CarModel", fallback_model)
|
||||
self.car_state.isJeep = fallback_model.startswith("JEEP_")
|
||||
|
||||
if not starpilot_toggles:
|
||||
self.car_state.hasOpenpilotLongitudinal = True
|
||||
@@ -161,6 +165,7 @@ class StarPilotState:
|
||||
self.car_state.isGM = car_make == "gm"
|
||||
self.car_state.isHKG = car_make == "hyundai"
|
||||
self.car_state.isHKGCanFd = self.car_state.isHKG and safety_model == car.CarParams.SafetyModel.hyundaiCanfd
|
||||
self.car_state.isJeep = car_make == "chrysler" and car_fingerprint.startswith("JEEP_")
|
||||
self.car_state.isSubaru = car_make == "subaru"
|
||||
self.car_state.isToyota = car_make == "toyota"
|
||||
self.car_state.isTSK = bool(self._safe_get(CP, "secOcRequired", False))
|
||||
|
||||
@@ -185,6 +185,7 @@ SAFE_MODE_MANAGED_KEYS = (
|
||||
"SubaruSNG",
|
||||
"SubaruSNGManualParkingBrake",
|
||||
"VoltSNG",
|
||||
"JeepBrakeHold",
|
||||
"GMAutoHold",
|
||||
"VoltOnePedalMode",
|
||||
"GMPedalLongitudinal",
|
||||
|
||||
@@ -15,6 +15,7 @@ import numpy as np
|
||||
from cereal import car, custom, log
|
||||
from opendbc.car import gen_empty_fingerprint
|
||||
from opendbc.car.car_helpers import interfaces
|
||||
from opendbc.car.chrysler.values import JEEPS as CHRYSLER_JEEPS
|
||||
from opendbc.car.gm.values import CAR as GM_CAR, EV_CAR as GM_EV_CAR, GMFlags
|
||||
from opendbc.car.hyundai.values import CAR as HYUNDAI_CAR, EV_CAR as HYUNDAI_EV_CAR, HyundaiFlags, HyundaiStarPilotSafetyFlags
|
||||
from opendbc.car.interfaces import TORQUE_SUBSTITUTE_PATH, CarInterfaceBase, GearShifter
|
||||
@@ -1412,6 +1413,7 @@ class StarPilotVariables:
|
||||
toggle.volt_one_pedal_mode = self.get_value("VoltOnePedalMode", condition=gm_auto_hold_supported)
|
||||
|
||||
toggle.volt_sng = self.get_value("VoltSNG", condition=toggle.car_model in LEGACY_VOLT_STOCK_ACC_CARS)
|
||||
toggle.jeep_brake_hold = self.get_value("JeepBrakeHold", condition=toggle.car_model in CHRYSLER_JEEPS)
|
||||
|
||||
process_starpilot_toggles.cache_clear()
|
||||
self.params_memory.remove("StarPilotTogglesUpdated")
|
||||
|
||||
@@ -4,6 +4,7 @@ import json
|
||||
import platform
|
||||
import shutil
|
||||
import signal
|
||||
import socket
|
||||
import subprocess
|
||||
import tarfile
|
||||
import time
|
||||
@@ -23,6 +24,8 @@ else:
|
||||
FRPC_VERSION = "0.67.0"
|
||||
FRPC_LOG = GALAXY_DIR / "frpc.log"
|
||||
AUTH_PORT = 8083
|
||||
GALAXY_WEB_HOST = "127.0.0.1"
|
||||
GALAXY_WEB_PORT = 8082
|
||||
BUNDLED_FRPC_DIR = Path(__file__).resolve().parent / "bin"
|
||||
|
||||
process = None
|
||||
@@ -92,6 +95,11 @@ def cleanup_frpc(*_):
|
||||
process = None
|
||||
|
||||
|
||||
def shutdown(*_):
|
||||
cleanup_frpc()
|
||||
raise SystemExit
|
||||
|
||||
|
||||
def get_arch_url():
|
||||
arch = platform.machine()
|
||||
system = platform.system()
|
||||
@@ -135,6 +143,14 @@ def get_param_str(params, key):
|
||||
return str(value or "")
|
||||
|
||||
|
||||
def local_galaxy_ready():
|
||||
try:
|
||||
with socket.create_connection((GALAXY_WEB_HOST, GALAXY_WEB_PORT), timeout=1.0):
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
|
||||
def setup_frpc():
|
||||
GALAXY_DIR.mkdir(parents=True, exist_ok=True)
|
||||
frpc_bin = GALAXY_DIR / "frpc"
|
||||
@@ -182,8 +198,8 @@ def main():
|
||||
global process
|
||||
params = Params()
|
||||
|
||||
signal.signal(signal.SIGTERM, cleanup_frpc)
|
||||
signal.signal(signal.SIGINT, cleanup_frpc)
|
||||
signal.signal(signal.SIGTERM, shutdown)
|
||||
signal.signal(signal.SIGINT, shutdown)
|
||||
|
||||
dongle_id = get_param_str(params, "DongleId")
|
||||
while not dongle_id:
|
||||
@@ -205,11 +221,21 @@ def main():
|
||||
is_paired = galaxy_password_hash and len(galaxy_password_hash) == 64 and slug
|
||||
|
||||
if is_paired:
|
||||
if process is not None and process.poll() is None and not local_galaxy_ready():
|
||||
print(f"Galaxy: Web app is not ready on {GALAXY_WEB_HOST}:{GALAXY_WEB_PORT}. Stopping frpc tunnel until it recovers...")
|
||||
cleanup_frpc()
|
||||
last_slug = None
|
||||
|
||||
if process is None or process.poll() is not None or slug != last_slug:
|
||||
cleanup_frpc()
|
||||
if process is not None and slug == last_slug:
|
||||
print(f"Galaxy: frpc exited with code {process.returncode}. Restarting...")
|
||||
|
||||
if not local_galaxy_ready():
|
||||
print(f"Galaxy: Waiting for web app on {GALAXY_WEB_HOST}:{GALAXY_WEB_PORT} before starting frpc tunnel...")
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
print("Galaxy: Password set. Preparing frpc tunnel...")
|
||||
if not setup_frpc():
|
||||
print("Galaxy: FRPC setup failed. Retrying later...")
|
||||
|
||||
@@ -344,6 +344,7 @@ void StarPilotSettingsWindow::updateVariables() {
|
||||
isGM = carMake == "gm";
|
||||
isHKG = carMake == "hyundai";
|
||||
isHKGCanFd = isHKG && hasModeStarButtons;
|
||||
isJeep = fallbackFingerprint.rfind("JEEP_", 0) == 0;
|
||||
isSubaru = carMake == "subaru";
|
||||
isToyota = carMake == "toyota";
|
||||
isVolt = fallbackFingerprint.rfind("CHEVROLET_VOLT", 0) == 0;
|
||||
@@ -380,6 +381,7 @@ void StarPilotSettingsWindow::updateVariables() {
|
||||
isGM = carMake == "gm";
|
||||
isHKG = carMake == "hyundai";
|
||||
isHKGCanFd = isHKG && safetyModel == cereal::CarParams::SafetyModel::HYUNDAI_CANFD;
|
||||
isJeep = carMake == "chrysler" && carFingerprint.rfind("JEEP_", 0) == 0;
|
||||
isSubaru = carMake == "subaru";
|
||||
isTorqueCar = CP.getLateralTuning().which() == cereal::CarParams::LateralTuning::TORQUE;
|
||||
isToyota = carMake == "toyota";
|
||||
|
||||
@@ -39,6 +39,7 @@ public:
|
||||
bool isGM = true;
|
||||
bool isHKG = true;
|
||||
bool isHKGCanFd = true;
|
||||
bool isJeep = false;
|
||||
bool isSubaru = false;
|
||||
bool isTorqueCar = false;
|
||||
bool isToyota = true;
|
||||
|
||||
@@ -154,18 +154,21 @@ StarPilotVehiclesPanel::StarPilotVehiclesPanel(StarPilotSettingsWindow *parent,
|
||||
});
|
||||
settingsList->addItem(disableOpenpilotLong);
|
||||
|
||||
StarPilotListWidget *chryslerList = new StarPilotListWidget(this);
|
||||
StarPilotListWidget *gmList = new StarPilotListWidget(this);
|
||||
StarPilotListWidget *hkgList = new StarPilotListWidget(this);
|
||||
StarPilotListWidget *subaruList = new StarPilotListWidget(this);
|
||||
StarPilotListWidget *toyotaList = new StarPilotListWidget(this);
|
||||
StarPilotListWidget *vehicleInfoList = new StarPilotListWidget(this);
|
||||
|
||||
ScrollView *chryslerPanel = new ScrollView(chryslerList, this);
|
||||
ScrollView *gmPanel = new ScrollView(gmList, this);
|
||||
ScrollView *hkgPanel = new ScrollView(hkgList, this);
|
||||
ScrollView *subaruPanel = new ScrollView(subaruList, this);
|
||||
ScrollView *toyotaPanel = new ScrollView(toyotaList, this);
|
||||
ScrollView *vehicleInfoPanel = new ScrollView(vehicleInfoList, this);
|
||||
|
||||
vehiclesLayout->addWidget(chryslerPanel);
|
||||
vehiclesLayout->addWidget(gmPanel);
|
||||
vehiclesLayout->addWidget(hkgPanel);
|
||||
vehiclesLayout->addWidget(subaruPanel);
|
||||
@@ -173,6 +176,9 @@ StarPilotVehiclesPanel::StarPilotVehiclesPanel(StarPilotSettingsWindow *parent,
|
||||
vehiclesLayout->addWidget(vehicleInfoPanel);
|
||||
|
||||
std::vector<std::tuple<QString, QString, QString, QString>> vehicleToggles {
|
||||
{"ChryslerToggles", tr("Chrysler/Jeep Settings"), tr("<b>StarPilot features for Chrysler and Jeep vehicles.</b>"), ""},
|
||||
{"JeepBrakeHold", tr("Brake Hold"), tr("<b>Hold the brakes after Jeep ACC times out at a stop</b>, then send resume when traffic moves again."), ""},
|
||||
|
||||
{"GMToggles", tr("General Motors Settings"), tr("<b>StarPilot features for General Motors vehicles.</b>"), ""},
|
||||
{"GMPedalLongitudinal", tr("Use Pedal For Longitudinal"), tr("<b>Use the pedal interceptor for full longitudinal control</b> on supported GM vehicles."), ""},
|
||||
{"GMDashSpoofOffsets", tr("Apply Offsets To Dash Spoof"), tr("<b>On GM pedal-long cars, add the configured set-speed offset</b> to the spoofed dash set speed so it matches the on-screen set speed."), ""},
|
||||
@@ -209,7 +215,15 @@ StarPilotVehiclesPanel::StarPilotVehiclesPanel(StarPilotSettingsWindow *parent,
|
||||
for (const auto &[param, title, desc, icon] : vehicleToggles) {
|
||||
AbstractControl *vehicleToggle;
|
||||
|
||||
if (param == "GMToggles") {
|
||||
if (param == "ChryslerToggles") {
|
||||
ButtonControl *chryslerButton = new ButtonControl(title, tr("MANAGE"), desc);
|
||||
QObject::connect(chryslerButton, &ButtonControl::clicked, [vehiclesLayout, chryslerPanel, this]() {
|
||||
openDescriptions(forceOpenDescriptions, toggles);
|
||||
vehiclesLayout->setCurrentWidget(chryslerPanel);
|
||||
});
|
||||
vehicleToggle = chryslerButton;
|
||||
|
||||
} else if (param == "GMToggles") {
|
||||
ButtonControl *gmButton = new ButtonControl(title, tr("MANAGE"), desc);
|
||||
QObject::connect(gmButton, &ButtonControl::clicked, [vehiclesLayout, gmPanel, this]() {
|
||||
openDescriptions(forceOpenDescriptions, toggles);
|
||||
@@ -275,7 +289,9 @@ StarPilotVehiclesPanel::StarPilotVehiclesPanel(StarPilotSettingsWindow *parent,
|
||||
|
||||
toggles[param] = vehicleToggle;
|
||||
|
||||
if (gmKeys.contains(param)) {
|
||||
if (chryslerKeys.contains(param)) {
|
||||
chryslerList->addItem(vehicleToggle);
|
||||
} else if (gmKeys.contains(param)) {
|
||||
gmList->addItem(vehicleToggle);
|
||||
} else if (hkgKeys.contains(param)) {
|
||||
hkgList->addItem(vehicleToggle);
|
||||
@@ -407,7 +423,9 @@ void StarPilotVehiclesPanel::updateToggles() {
|
||||
bool setVisible = showAllToggles || parent->tuningLevel >= parent->starpilotToggleLevels[key].toDouble();
|
||||
|
||||
if (!showAllToggles) {
|
||||
if (gmKeys.contains(key)) {
|
||||
if (chryslerKeys.contains(key)) {
|
||||
setVisible &= parent->isJeep;
|
||||
} else if (gmKeys.contains(key)) {
|
||||
setVisible &= parent->isGM;
|
||||
} else if (hkgKeys.contains(key)) {
|
||||
setVisible &= parent->isHKGCanFd && parent->hasOpenpilotLongitudinal;
|
||||
@@ -455,7 +473,9 @@ void StarPilotVehiclesPanel::updateToggles() {
|
||||
toggle->setVisible(setVisible);
|
||||
|
||||
if (setVisible) {
|
||||
if (gmKeys.contains(key)) {
|
||||
if (chryslerKeys.contains(key)) {
|
||||
toggles["ChryslerToggles"]->setVisible(true);
|
||||
} else if (gmKeys.contains(key)) {
|
||||
toggles["GMToggles"]->setVisible(true);
|
||||
} else if (hkgKeys.contains(key)) {
|
||||
toggles["HKGToggles"]->setVisible(true);
|
||||
|
||||
@@ -23,6 +23,7 @@ private:
|
||||
|
||||
std::map<QString, AbstractControl*> toggles;
|
||||
|
||||
QSet<QString> chryslerKeys = {"JeepBrakeHold"};
|
||||
QSet<QString> gmKeys = {"GMPedalLongitudinal", "GMDashSpoofOffsets", "IgnoreIgnitionLine", "LongPitch", "RemoteStartBootsComma", "RemapCancelToDistance", "VoltSNG"};
|
||||
QSet<QString> hkgKeys = {"HKGRemoteStartBootsComma"};
|
||||
QSet<QString> longitudinalKeys = {"FrogsGoMoosTweak", "GMDashSpoofOffsets", "LongPitch", "RemapCancelToDistance", "SNGHack", "VoltSNG"};
|
||||
|
||||
Reference in New Issue
Block a user