This commit is contained in:
firestar5683
2026-07-01 15:02:27 -05:00
parent 5c9888a0d7
commit 23b354d47e
21 changed files with 330 additions and 15 deletions
+1
View File
@@ -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
))
+13 -1
View File
@@ -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):
+10 -1
View File
@@ -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
+13 -1
View File
@@ -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}
+2 -1
View File
@@ -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({
+5
View File
@@ -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))
+1
View File
@@ -185,6 +185,7 @@ SAFE_MODE_MANAGED_KEYS = (
"SubaruSNG",
"SubaruSNGManualParkingBrake",
"VoltSNG",
"JeepBrakeHold",
"GMAutoHold",
"VoltOnePedalMode",
"GMPedalLongitudinal",
+2
View File
@@ -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")
+28 -2
View File
@@ -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;
+24 -4
View File
@@ -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"};