mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-10-28 00:53:45 +08:00
Chrysler
Update Chrysler vehicle parameters and controller behavior with focused platform tests.
This commit is contained in:
@@ -2,7 +2,8 @@ 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 CUSW_CARS, RAM_CARS, CarControllerParams, ChryslerFlags
|
||||
from opendbc.car.chrysler.values import CUSW_CARS, RAM_CARS, RAM_DT, CarControllerParams, ChryslerFlags
|
||||
from opendbc.car.structs import CarState
|
||||
from opendbc.car.interfaces import CarControllerBase
|
||||
|
||||
|
||||
@@ -50,7 +51,15 @@ class CarController(CarControllerBase):
|
||||
|
||||
# TODO: can we make this more sane? why is it different for all the cars?
|
||||
lkas_control_bit = self.lkas_control_bit_prev
|
||||
if CS.out.vEgo > self.CP.minSteerSpeed:
|
||||
if self.CP.flags & ChryslerFlags.STEERING_SPEED_BYPASS:
|
||||
lkas_control_bit = CC.latActive
|
||||
elif self.CP.carFingerprint in RAM_DT:
|
||||
# Arm in the EPS speed window, then keep the request through lower speeds.
|
||||
if self.CP.minEnableSpeed <= CS.out.vEgo <= self.CP.minEnableSpeed + 0.5:
|
||||
lkas_control_bit = True
|
||||
if self.CP.minEnableSpeed >= 14.5 and CS.out.gearShifter != CarState.GearShifter.drive:
|
||||
lkas_control_bit = False
|
||||
elif CS.out.vEgo > self.CP.minSteerSpeed:
|
||||
lkas_control_bit = True
|
||||
elif self.CP.flags & ChryslerFlags.HIGHER_MIN_STEERING_SPEED:
|
||||
if CS.out.vEgo < (self.CP.minSteerSpeed - 3.0):
|
||||
|
||||
@@ -66,9 +66,8 @@ class CarInterface(CarInterfaceBase):
|
||||
# Ram
|
||||
elif candidate == CAR.RAM_1500_5TH_GEN:
|
||||
ret.steerActuatorDelay = 0.2
|
||||
# Older EPS FW allow steer to zero
|
||||
if any(fw.ecu == 'eps' and b"68" < fw.fwVersion[:4] <= b"6831" for fw in car_fw):
|
||||
ret.minSteerSpeed = 0.
|
||||
ret.minEnableSpeed = 14.5
|
||||
ret.minSteerSpeed = 0.5
|
||||
|
||||
elif candidate == CAR.RAM_HD_5TH_GEN:
|
||||
ret.steerActuatorDelay = 0.2
|
||||
@@ -81,6 +80,10 @@ class CarInterface(CarInterfaceBase):
|
||||
# TODO: Durango 2020 may be able to steer to zero once above 38 kph
|
||||
ret.minSteerSpeed = 17.5 # m/s 17 on the way up, 13 on the way down once engaged.
|
||||
|
||||
if candidate not in CUSW_CARS and 0x4FF in fingerprint[0]:
|
||||
ret.flags |= ChryslerFlags.STEERING_SPEED_BYPASS.value
|
||||
ret.minSteerSpeed = 0.
|
||||
|
||||
ret.centerToFront = ret.wheelbase * 0.44
|
||||
if (0x62cc033 if candidate in CUSW_CARS else 0x2d0) in fingerprint[0]:
|
||||
ret.flags |= ChryslerFlags.HAS_BSM.value
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import unittest
|
||||
|
||||
from opendbc.can import CANParser
|
||||
from opendbc.car import Bus, gen_empty_fingerprint, structs
|
||||
from opendbc.car.chrysler.interface import CarInterface
|
||||
from opendbc.car.chrysler.values import CAR, DBC
|
||||
|
||||
|
||||
def params(alpha=False, release=False, firmware=b"68410000"):
|
||||
fw = structs.CarParams.CarFw(ecu=structs.CarParams.Ecu.eps, fwVersion=firmware)
|
||||
return CarInterface.get_params(CAR.RAM_1500_5TH_GEN, gen_empty_fingerprint(), [fw], alpha, release, False)
|
||||
|
||||
|
||||
class TestRamSteering(unittest.TestCase):
|
||||
def test_enable_window_is_separate_from_steering_minimum(self):
|
||||
for firmware in (b"68310000", b"68410000"):
|
||||
for alpha in (False, True):
|
||||
for release in (False, True):
|
||||
with self.subTest(firmware=firmware, alpha=alpha, release=release):
|
||||
cp = params(alpha, release, firmware)
|
||||
self.assertEqual(cp.minEnableSpeed, 14.5)
|
||||
self.assertEqual(cp.minSteerSpeed, 0.5)
|
||||
self.assertEqual(cp.safetyConfigs[0].safetyParam, 1)
|
||||
self.assertTrue(cp.pcmCruise)
|
||||
self.assertFalse(cp.openpilotLongitudinalControl)
|
||||
|
||||
def test_window_latches_but_gear_change_and_cooldown_block_reentry(self):
|
||||
ci = CarInterface(params())
|
||||
ci.update([])
|
||||
command = structs.CarControl(latActive=True)
|
||||
command.actuators.torque = 0.1
|
||||
gear = structs.CarState.GearShifter
|
||||
parser = CANParser(DBC[CAR.RAM_1500_5TH_GEN][Bus.pt], [("LKAS_COMMAND", 0)], 0)
|
||||
cases = (
|
||||
(202, 15.1, gear.drive, False),
|
||||
(204, 14.5, gear.drive, True),
|
||||
(206, 25, gear.drive, True),
|
||||
(208, 2, gear.drive, True),
|
||||
(210, 14.75, gear.reverse, False),
|
||||
(212, 14.75, gear.drive, False),
|
||||
(410, 14.75, gear.drive, False),
|
||||
(412, 14.75, gear.drive, True),
|
||||
(414, 14.75, gear.neutral, False),
|
||||
(616, 15, gear.drive, True),
|
||||
)
|
||||
for frame, speed, selected_gear, expected in cases:
|
||||
with self.subTest(frame=frame):
|
||||
ci.CC.frame = frame
|
||||
ci.CS.out.vEgo = speed
|
||||
ci.CS.out.gearShifter = selected_gear
|
||||
_, messages = ci.CC.update(command.as_reader(), ci.CS, frame * 10_000_000)
|
||||
parser.update((frame * 10_000_000, messages))
|
||||
self.assertEqual(ci.CC.lkas_control_bit_prev, expected)
|
||||
if not expected:
|
||||
self.assertEqual(parser.vl["LKAS_COMMAND"]["STEERING_TORQUE"], 0)
|
||||
|
||||
def test_full_host_torque_ramp_passes_existing_native_limits(self):
|
||||
from opendbc.safety.tests.libsafety import libsafety_py
|
||||
from opendbc.safety.tests.libsafety.libsafety_py import make_CANPacket
|
||||
|
||||
native = libsafety_py.libsafety
|
||||
self.assertEqual(native.set_safety_hooks(9, 1), 0)
|
||||
native.init_tests()
|
||||
native.set_controls_allowed(True)
|
||||
ci = CarInterface(params())
|
||||
ci.update([])
|
||||
ci.CS.out.vEgo = 14.75
|
||||
ci.CS.out.gearShifter = structs.CarState.GearShifter.drive
|
||||
command = structs.CarControl(latActive=True)
|
||||
command.actuators.torque = 1
|
||||
for frame in range(202, 342, 2):
|
||||
ci.CC.frame = frame
|
||||
ci.CS.out.steeringTorqueEps = ci.CC.apply_torque_last
|
||||
native.set_torque_meas(ci.CC.apply_torque_last, ci.CC.apply_torque_last)
|
||||
native.set_timer(frame * 10_000)
|
||||
actuators, messages = ci.CC.update(command.as_reader(), ci.CS, frame * 10_000_000)
|
||||
for address, data, bus in messages:
|
||||
self.assertTrue(native.safety_tx_hook(make_CANPacket(address, bus, data)), (frame, address, data))
|
||||
self.assertEqual(actuators.torqueOutputCan, 350)
|
||||
self.assertEqual(actuators.torque, 1)
|
||||
command.latActive = False
|
||||
ci.CC.frame = 344
|
||||
actuators, _ = ci.CC.update(command.as_reader(), ci.CS, 3_440_000_000)
|
||||
self.assertEqual(actuators.torqueOutputCan, 0)
|
||||
@@ -0,0 +1,82 @@
|
||||
import unittest
|
||||
|
||||
from opendbc.can import CANParser
|
||||
from opendbc.car import Bus, gen_empty_fingerprint, structs
|
||||
from opendbc.car.chrysler.interface import CarInterface
|
||||
from opendbc.car.chrysler.values import CAR, CUSW_CARS, DBC, ChryslerFlags
|
||||
|
||||
|
||||
def params(car, bus=None):
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
if bus is not None:
|
||||
fingerprint[bus][0x4FF] = 8
|
||||
return CarInterface.get_params(car, fingerprint, [], False, False, False)
|
||||
|
||||
|
||||
class TestSteeringSpeedBypass(unittest.TestCase):
|
||||
def test_blind_spot_detection_does_not_enable_speed_bypass(self):
|
||||
car = CAR.CHRYSLER_PACIFICA_2020
|
||||
baseline = params(car)
|
||||
for blind_spot in (False, True):
|
||||
for bypass in (False, True):
|
||||
for bus in (0, 1, 2):
|
||||
with self.subTest(blind_spot=blind_spot, bypass=bypass, bus=bus):
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
if blind_spot:
|
||||
fingerprint[bus][0x2d0] = 8
|
||||
if bypass:
|
||||
fingerprint[bus][0x4ff] = 8
|
||||
cp = CarInterface.get_params(car, fingerprint, [], False, False, False)
|
||||
self.assertEqual(bool(cp.flags & ChryslerFlags.HAS_BSM), blind_spot and bus == 0)
|
||||
self.assertEqual(bool(cp.flags & ChryslerFlags.STEERING_SPEED_BYPASS), bypass and bus == 0)
|
||||
self.assertEqual(cp.minSteerSpeed, 0 if bypass and bus == 0 else baseline.minSteerSpeed)
|
||||
self.assertEqual([(str(c.safetyModel), c.safetyParam) for c in cp.safetyConfigs],
|
||||
[(str(c.safetyModel), c.safetyParam) for c in baseline.safetyConfigs])
|
||||
|
||||
def test_hardware_is_scoped_to_original_platforms_and_bus(self):
|
||||
for car in CAR:
|
||||
baseline = params(car)
|
||||
for bus in (0, 1, 2):
|
||||
with self.subTest(car=car, bus=bus):
|
||||
cp = params(car, bus)
|
||||
supported = bus == 0 and car not in CUSW_CARS
|
||||
self.assertEqual(bool(cp.flags & ChryslerFlags.STEERING_SPEED_BYPASS), supported)
|
||||
self.assertEqual(cp.minSteerSpeed, 0 if supported else baseline.minSteerSpeed)
|
||||
self.assertEqual([(str(c.safetyModel), c.safetyParam) for c in cp.safetyConfigs],
|
||||
[(str(c.safetyModel), c.safetyParam) for c in baseline.safetyConfigs])
|
||||
self.assertEqual(cp.dashcamOnly, baseline.dashcamOnly)
|
||||
self.assertEqual(cp.pcmCruise, baseline.pcmCruise)
|
||||
self.assertFalse(cp.openpilotLongitudinalControl)
|
||||
|
||||
def test_standstill_engagement_and_reentry_keep_eps_cooldown(self):
|
||||
for car in set(CAR) - CUSW_CARS:
|
||||
with self.subTest(car=car):
|
||||
ci = CarInterface(params(car, 0))
|
||||
ci.update([])
|
||||
ci.CS.out.vEgo = 0
|
||||
command = structs.CarControl()
|
||||
command.actuators.torque = 0.1
|
||||
parser = CANParser(DBC[car][Bus.pt], [('LKAS_COMMAND', 0)], 0)
|
||||
for frame, active, expected in ((200, True, False), (202, True, True), (204, True, True),
|
||||
(206, False, False), (208, True, False),
|
||||
(406, True, False), (408, True, True)):
|
||||
ci.CC.frame = frame
|
||||
command.latActive = active
|
||||
_, sends = ci.CC.update(command.as_reader(), ci.CS, frame * 10_000_000)
|
||||
parser.update((frame * 10_000_000, sends))
|
||||
self.assertEqual(ci.CC.lkas_control_bit_prev, expected)
|
||||
if not expected:
|
||||
self.assertEqual(parser.vl['LKAS_COMMAND']['STEERING_TORQUE'], 0)
|
||||
|
||||
def test_without_hardware_standstill_does_not_enable_steering(self):
|
||||
for car in set(CAR) - CUSW_CARS:
|
||||
with self.subTest(car=car):
|
||||
ci = CarInterface(params(car))
|
||||
ci.update([])
|
||||
ci.CC.frame = 202
|
||||
command = structs.CarControl()
|
||||
command.latActive = True
|
||||
command.actuators.torque = 0.1
|
||||
actuators, _ = ci.CC.update(command.as_reader(), ci.CS, 2_020_000_000)
|
||||
self.assertFalse(ci.CC.lkas_control_bit_prev)
|
||||
self.assertEqual(actuators.torqueOutputCan, 0)
|
||||
@@ -18,6 +18,7 @@ class ChryslerFlags(IntFlag):
|
||||
# Detected flags
|
||||
HIGHER_MIN_STEERING_SPEED = 1
|
||||
HAS_BSM = 2 # blind spot monitoring
|
||||
STEERING_SPEED_BYPASS = 4
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -110,7 +111,7 @@ class CarControllerParams:
|
||||
elif CP.carFingerprint in RAM_DT:
|
||||
self.STEER_DELTA_UP = 6
|
||||
self.STEER_DELTA_DOWN = 6
|
||||
self.STEER_MAX = 261 # EPS allows more, up to 350?
|
||||
self.STEER_MAX = 350
|
||||
elif CP.carFingerprint in CUSW_CARS:
|
||||
self.STEER_STEP = 1 # 100 Hz
|
||||
self.STEER_DELTA_UP = 4
|
||||
|
||||
Reference in New Issue
Block a user