Skip to content

Commit

Permalink
Merge branch 'master' of ssh://github.com/commaai/opendbc into 2019-y…
Browse files Browse the repository at this point in the history
…ukon-port
  • Loading branch information
jyoung8607 committed Dec 11, 2024
2 parents 2ca5175 + f3855a7 commit 1257ae6
Show file tree
Hide file tree
Showing 17 changed files with 92 additions and 120 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ on:
workflow_dispatch:

env:
DAYS_BEFORE_PR_CLOSE: 2
DAYS_BEFORE_PR_STALE: 9
DAYS_BEFORE_PR_CLOSE: 7
DAYS_BEFORE_PR_STALE: 60

jobs:
stale:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ The entirery of a car port lives in `opendbc/car/<brand>/`:

### Reverse Engineer CAN messages

Start off by recording a route with lots of interesting events: enable LKAS and ACC, turn the steering weel both extremes, etc. Then, load up that route in [cabana](https://github.com/commaai/openpilot/tree/master/tools/cabana).
Start off by recording a route with lots of interesting events: enable LKAS and ACC, turn the steering wheel both extremes, etc. Then, load up that route in [cabana](https://github.com/commaai/openpilot/tree/master/tools/cabana).

### Tuning

Expand Down
3 changes: 3 additions & 0 deletions opendbc/car/chrysler/fingerprints.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@
b'68320950AL',
b'68320950AM',
b'68454268AB',
b'68454268AC',
b'68475160AE',
b'68475160AF',
b'68475160AG',
Expand Down Expand Up @@ -577,6 +578,7 @@
b'68448165AK',
b'68455111AC ',
b'68455119AC ',
b'68455137AC ',
b'68455145AC ',
b'68455145AE ',
b'68455146AC ',
Expand Down Expand Up @@ -631,6 +633,7 @@
b'68384328AD',
b'68384332AD',
b'68445531AC',
b'68445532AB',
b'68445533AB',
b'68445536AB',
b'68445537AB',
Expand Down
4 changes: 4 additions & 0 deletions opendbc/car/honda/fingerprints.py
Original file line number Diff line number Diff line change
Expand Up @@ -800,22 +800,26 @@
(Ecu.srs, 0x18da53f1, None): [
b'77959-3M0-K840\x00\x00',
b'77959-3V0-A820\x00\x00',
b'77959-3V0-A910\x00\x00',
],
(Ecu.fwdRadar, 0x18dab0f1, None): [
b'8S102-3M6-P030\x00\x00',
b'8S102-3W0-A060\x00\x00',
b'8S102-3W0-AB10\x00\x00',
b'8S102-3W0-AB20\x00\x00',
],
(Ecu.vsa, 0x18da28f1, None): [
b'57114-3M6-M010\x00\x00',
b'57114-3W0-A040\x00\x00',
],
(Ecu.transmission, 0x18da1ef1, None): [
b'28101-6EH-A010\x00\x00',
b'28101-6EH-A110\x00\x00',
b'28101-6JC-M310\x00\x00',
],
(Ecu.electricBrakeBooster, 0x18da2bf1, None): [
b'46114-3W0-A020\x00\x00',
b'46114-3W0-A050\x00\x00',
],
},
CAR.ACURA_ILX: {
Expand Down
6 changes: 3 additions & 3 deletions opendbc/car/hyundai/carcontroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def update(self, CC, CS, now_nanos):
# *** common hyundai stuff ***

# tester present - w/ no response (keeps relevant ECU disabled)
if self.frame % 100 == 0 and not (self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC.value) and self.CP.openpilotLongitudinalControl:
if self.frame % 100 == 0 and not (self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC) and self.CP.openpilotLongitudinalControl:
# for longitudinal control, either radar or ADAS driving ECU
addr, bus = 0x7d0, 0
if self.CP.flags & HyundaiFlags.CANFD_HDA2.value:
Expand Down Expand Up @@ -147,15 +147,15 @@ def update(self, CC, CS, now_nanos):
use_fca = self.CP.flags & HyundaiFlags.USE_FCA.value
can_sends.extend(hyundaican.create_acc_commands(self.packer, CC.enabled, accel, jerk, int(self.frame / 2),
hud_control, set_speed_in_units, stopping,
CC.cruiseControl.override, use_fca))
CC.cruiseControl.override, use_fca, self.CP))

# 20 Hz LFA MFA message
if self.frame % 5 == 0 and self.CP.flags & HyundaiFlags.SEND_LFA.value:
can_sends.append(hyundaican.create_lfahda_mfc(self.packer, CC.enabled))

# 5 Hz ACC options
if self.frame % 20 == 0 and self.CP.openpilotLongitudinalControl:
can_sends.extend(hyundaican.create_acc_opt(self.packer))
can_sends.extend(hyundaican.create_acc_opt(self.packer, self.CP))

# 2 Hz front radar options
if self.frame % 50 == 0 and self.CP.openpilotLongitudinalControl:
Expand Down
4 changes: 2 additions & 2 deletions opendbc/car/hyundai/carstate.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def update(self, can_parsers) -> structs.CarState:

ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(gear))

if not self.CP.openpilotLongitudinalControl:
if not self.CP.openpilotLongitudinalControl or self.CP.flags & HyundaiFlags.CAMERA_SCC:
aeb_src = "FCA11" if self.CP.flags & HyundaiFlags.USE_FCA.value else "SCC12"
aeb_sig = "FCA_CmdAct" if self.CP.flags & HyundaiFlags.USE_FCA.value else "AEB_CmdAct"
aeb_warning = cp_cruise.vl[aeb_src]["CF_VSM_Warn"] != 0
Expand Down Expand Up @@ -372,7 +372,7 @@ def get_can_parsers(self, CP):
("LKAS11", 100)
]

if not CP.openpilotLongitudinalControl and CP.flags & HyundaiFlags.CAMERA_SCC:
if CP.flags & HyundaiFlags.CAMERA_SCC:
cam_messages += [
("SCC11", 50),
("SCC12", 50),
Expand Down
4 changes: 4 additions & 0 deletions opendbc/car/hyundai/fingerprints.py
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@
(Ecu.eps, 0x7d4, None): [
b'\xf1\x00DL3 MDPS C 1.00 1.01 56310-L3110 4DLAC101',
b'\xf1\x00DL3 MDPS C 1.00 1.01 56310-L3220 4DLAC101',
b'\xf1\x00DL3 MDPS C 1.00 1.01 56310L3220\x00 4DLAC101',
b'\xf1\x00DL3 MDPS C 1.00 1.02 56310-L2220 4DLDC102',
b'\xf1\x00DL3 MDPS C 1.00 1.02 56310L3220\x00 4DLAC102',
b'\xf1\x00DL3 MDPS R 1.00 1.02 57700-L3000 4DLAP102',
Expand Down Expand Up @@ -637,6 +638,7 @@
b'\xf1\x00OS MDPS C 1.00 1.04 56310/K4550 4OEDC104',
b'\xf1\x00OS MDPS C 1.00 1.04 56310K4000\x00 4OEDC104',
b'\xf1\x00OS MDPS C 1.00 1.04 56310K4050\x00 4OEDC104',
b'\xf1\x00OS MDPS C 1.00 1.05 56310K4000\x00 4OEDC105',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00OSev SCC F-CUP 1.00 1.00 99110-K4000 ',
Expand Down Expand Up @@ -1004,12 +1006,14 @@
CAR.HYUNDAI_IONIQ_6: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00CE__ RDR ----- 1.00 1.01 99110-KL000 ',
b'\xf1\x00CE__ RDR ----- 1.00 1.02 99110-KL000 ',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00CE MFC AT CAN LHD 1.00 1.04 99211-KL000 221213',
b'\xf1\x00CE MFC AT EUR LHD 1.00 1.03 99211-KL000 221011',
b'\xf1\x00CE MFC AT EUR LHD 1.00 1.04 99211-KL000 221213',
b'\xf1\x00CE MFC AT USA LHD 1.00 1.04 99211-KL000 221213',
b'\xf1\x00CE MFC AT USA LHD 1.00 1.06 99211-KL000 230915',
],
},
CAR.HYUNDAI_TUCSON_4TH_GEN: {
Expand Down
19 changes: 11 additions & 8 deletions opendbc/car/hyundai/hyundaican.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def create_lfahda_mfc(packer, enabled):
}
return packer.make_can_msg("LFAHDA_MFC", 0, values)

def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, set_speed, stopping, long_override, use_fca):
def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, set_speed, stopping, long_override, use_fca, CP):
commands = []

scc11_values = {
Expand Down Expand Up @@ -169,7 +169,8 @@ def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, se
commands.append(packer.make_can_msg("SCC14", 0, scc14_values))

# Only send FCA11 on cars where it exists on the bus
if use_fca:
# On Camera SCC cars, FCA11 is not disabled, so we forward stock FCA11 back to the car forward hooks
if use_fca and not (CP.flags & HyundaiFlags.CAMERA_SCC):
# note that some vehicles most likely have an alternate checksum/counter definition
# https://github.com/commaai/opendbc/commit/9ddcdb22c4929baf310295e832668e6e7fcfa602
fca11_values = {
Expand All @@ -184,7 +185,7 @@ def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, se

return commands

def create_acc_opt(packer):
def create_acc_opt(packer, CP):
commands = []

scc13_values = {
Expand All @@ -195,11 +196,13 @@ def create_acc_opt(packer):
commands.append(packer.make_can_msg("SCC13", 0, scc13_values))

# TODO: this needs to be detected and conditionally sent on unsupported long cars
fca12_values = {
"FCA_DrvSetState": 2,
"FCA_USM": 1, # AEB disabled
}
commands.append(packer.make_can_msg("FCA12", 0, fca12_values))
# On Camera SCC cars, FCA12 is not disabled, so we forward stock FCA12 back to the car forward hooks
if not (CP.flags & HyundaiFlags.CAMERA_SCC):
fca12_values = {
"FCA_DrvSetState": 2,
"FCA_USM": 1, # AEB disabled
}
commands.append(packer.make_can_msg("FCA12", 0, fca12_values))

return commands

Expand Down
6 changes: 3 additions & 3 deletions opendbc/car/hyundai/interface.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from panda import Panda
from opendbc.car import Bus, get_safety_config, structs
from opendbc.car.hyundai.hyundaicanfd import CanBus
from opendbc.car.hyundai.values import HyundaiFlags, CAR, DBC, CAMERA_SCC_CAR, CANFD_RADAR_SCC_CAR, \
from opendbc.car.hyundai.values import HyundaiFlags, CAR, DBC, CANFD_RADAR_SCC_CAR, \
CANFD_UNSUPPORTED_LONGITUDINAL_CAR, \
UNSUPPORTED_LONGITUDINAL_CAR
from opendbc.car.hyundai.radar_interface import RADAR_START_ADDR
Expand Down Expand Up @@ -68,7 +68,7 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, experime

else:
# Shared configuration for non CAN-FD cars
ret.experimentalLongitudinalAvailable = candidate not in (UNSUPPORTED_LONGITUDINAL_CAR | CAMERA_SCC_CAR)
ret.experimentalLongitudinalAvailable = candidate not in UNSUPPORTED_LONGITUDINAL_CAR
ret.enableBsm = 0x58b in fingerprint[0]

# Send LFA message on cars with HDA
Expand Down Expand Up @@ -128,7 +128,7 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, experime

@staticmethod
def init(CP, can_recv, can_send):
if CP.openpilotLongitudinalControl and not (CP.flags & HyundaiFlags.CANFD_CAMERA_SCC.value):
if CP.openpilotLongitudinalControl and not (CP.flags & (HyundaiFlags.CANFD_CAMERA_SCC | HyundaiFlags.CAMERA_SCC)):
addr, bus = 0x7d0, 0
if CP.flags & HyundaiFlags.CANFD_HDA2.value:
addr, bus = 0x730, CanBus(CP).ECAN
Expand Down
2 changes: 1 addition & 1 deletion opendbc/car/mazda/values.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class CAR(Platforms):
MAZDA_CX9.specs
)
MAZDA_CX5_2022 = MazdaPlatformConfig(
[MazdaCarDocs("Mazda CX-5 2022-24")],
[MazdaCarDocs("Mazda CX-5 2022-25")],
MAZDA_CX5.specs,
)

Expand Down
113 changes: 35 additions & 78 deletions opendbc/car/toyota/carcontroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

# The up limit allows the brakes/gas to unwind quickly leaving a stop,
# the down limit roughly matches the rate of ACCEL_NET, reducing PCM compensation windup
ACCEL_WINDUP_LIMIT = 6.0 * DT_CTRL * 3 # m/s^2 / frame
ACCEL_WINDUP_LIMIT = 4.0 * DT_CTRL * 3 # m/s^2 / frame
ACCEL_WINDDOWN_LIMIT = -4.0 * DT_CTRL * 3 # m/s^2 / frame

# LKA limits
Expand All @@ -42,12 +42,9 @@ def get_long_tune(CP, params):
kdBP = [0.]
kdV = [0.]
if CP.carFingerprint in TSS2_CAR:
kiV = [0.5]
kiV = [0.25]
kdV = [0.25 / 4]

# Since we compensate for imprecise acceleration in carcontroller and error correct on aEgo, we can avoid using gains
if CP.flags & ToyotaFlags.RAISED_ACCEL_LIMIT:
kiV = [0.0]
else:
kiBP = [0., 5., 35.]
kiV = [3.6, 2.4, 1.5]
Expand All @@ -70,34 +67,21 @@ def __init__(self, dbc_names, CP):
self.steer_rate_counter = 0
self.distance_button = 0

# *** start long control state ***
self.long_pid = get_long_tune(self.CP, self.params)

self.error_rate = FirstOrderFilter(0.0, 0.5, DT_CTRL * 3)
self.prev_error = 0.0

# *** start PCM compensation state ***
self.pitch = FirstOrderFilter(0, 0.5, DT_CTRL)

# FIXME: rate isn't set properly
self.pcm_pid = PIDController(2.0, 0.5, 1 / (DT_CTRL * 3))
self.pcm_accel_compensation = FirstOrderFilter(0, 0.5, DT_CTRL * 3)
self.aego = FirstOrderFilter(0.0, 0.25, DT_CTRL * 3)

# the PCM's reported acceleration request can sometimes mismatch aEgo, close the loop
self.pcm_accel_net_offset = FirstOrderFilter(0, 1.0, DT_CTRL * 3)

# aEgo also often lags behind the PCM request due to physical brake lag which varies by car,
# so we error correct on the filtered PCM acceleration request using the actuator delay.
# TODO: move the delay into the interface
self.pcm_accel_net = FirstOrderFilter(0, self.CP.longitudinalActuatorDelay, DT_CTRL * 3)
self.net_acceleration_request = FirstOrderFilter(0, 0.15, DT_CTRL * 3)
if not any(fw.ecu == Ecu.hybrid for fw in self.CP.carFw):
self.pcm_accel_net.update_alpha(self.CP.longitudinalActuatorDelay + 0.2)
self.net_acceleration_request.update_alpha(self.CP.longitudinalActuatorDelay + 0.2)
# *** end PCM compensation state ***
self.pitch = FirstOrderFilter(0, 0.5, DT_CTRL)

self.packer = CANPacker(dbc_names[Bus.pt])
self.accel = 0
self.prev_accel = 0
# *** end long control state ***

self.packer = CANPacker(dbc_names[Bus.pt])

self.secoc_lka_message_counter = 0
self.secoc_lta_message_counter = 0
Expand Down Expand Up @@ -230,68 +214,41 @@ def update(self, CC, CS, now_nanos):

# calculate amount of acceleration PCM should apply to reach target, given pitch
accel_due_to_pitch = math.sin(self.pitch.x) * ACCELERATION_DUE_TO_GRAVITY
# TODO: on uphills this sometimes sets PERMIT_BRAKING low not considering the creep force
net_acceleration_request = pcm_accel_cmd + accel_due_to_pitch
self.net_acceleration_request.update(net_acceleration_request)

# For cars where we allow a higher max acceleration of 2.0 m/s^2, compensate for PCM request overshoot and imprecise braking
if self.CP.flags & ToyotaFlags.RAISED_ACCEL_LIMIT and CC.longActive and not CS.out.cruiseState.standstill:
# filter ACCEL_NET so it more closely matches aEgo delay for error correction
self.pcm_accel_net.update(CS.pcm_accel_net)

# Our model of the PCM's acceleration request isn't perfect, so we learn the offset when moving
new_pcm_accel_net = CS.pcm_accel_net
if stopping or CS.out.standstill:
# TODO: check if maintaining the offset from before stopping is beneficial
self.pcm_accel_net_offset.x = 0.0
else:
new_pcm_accel_net -= self.pcm_accel_net_offset.update((self.pcm_accel_net.x - accel_due_to_pitch) - CS.out.aEgo)

# let PCM handle stopping for now, error correct on a delayed acceleration request
pcm_accel_compensation = 0.0
if not stopping:
# prevent compensation windup
self.pcm_pid.neg_limit = pcm_accel_cmd - self.params.ACCEL_MAX
self.pcm_pid.pos_limit = pcm_accel_cmd - self.params.ACCEL_MIN
pcm_accel_compensation = self.pcm_pid.update(new_pcm_accel_net - self.net_acceleration_request.x)
else:
self.pcm_pid.reset()

pcm_accel_cmd = pcm_accel_cmd - self.pcm_accel_compensation.update(pcm_accel_compensation)

# GVC does not overshoot ego acceleration when starting from stop, but still has a similar delay
if not self.CP.flags & ToyotaFlags.SECOC.value:
a_ego_blended = interp(CS.out.vEgo, [1.0, 2.0], [CS.gvc, CS.out.aEgo])
else:
self.pcm_accel_compensation.x = 0.0
self.pcm_accel_net_offset.x = 0.0
self.net_acceleration_request.x = 0.0
self.pcm_accel_net.x = CS.pcm_accel_net
self.pcm_pid.reset()
self.permit_braking = True

if not (self.CP.flags & ToyotaFlags.RAISED_ACCEL_LIMIT):
if actuators.longControlState == LongCtrlState.pid:
# GVC does not overshoot ego acceleration when starting from stop, but still has a similar delay
if not self.CP.flags & ToyotaFlags.SECOC.value:
a_ego_blended = interp(CS.out.vEgo, [1.0, 2.0], [CS.gvc, CS.out.aEgo])
else:
a_ego_blended = CS.out.aEgo

error = pcm_accel_cmd - a_ego_blended
self.error_rate.update((error - self.prev_error) / (DT_CTRL * 3))
self.prev_error = error

pcm_accel_cmd = self.long_pid.update(error, error_rate=self.error_rate.x,
speed=CS.out.vEgo,
feedforward=pcm_accel_cmd)
else:
self.long_pid.reset()
self.error_rate.x = 0.0
self.prev_error = 0.0
a_ego_blended = CS.out.aEgo

# wind down integral when approaching target for step changes and smooth ramps to reduce overshoot
prev_aego = self.aego.x
self.aego.update(a_ego_blended)
j_ego = (self.aego.x - prev_aego) / (DT_CTRL * 3)
a_ego_future = a_ego_blended + j_ego * 0.5

if actuators.longControlState == LongCtrlState.pid:
error = pcm_accel_cmd - a_ego_blended
self.error_rate.update((error - self.prev_error) / (DT_CTRL * 3))
self.prev_error = error

error_future = pcm_accel_cmd - a_ego_future
pcm_accel_cmd = self.long_pid.update(error_future, error_rate=self.error_rate.x,
speed=CS.out.vEgo,
feedforward=pcm_accel_cmd)
else:
self.long_pid.reset()
self.error_rate.x = 0.0
self.prev_error = 0.0

# Along with rate limiting positive jerk above, this greatly improves gas response time
# Consider the net acceleration request that the PCM should be applying (pitch included)
net_acceleration_request_min = min(actuators.accel + accel_due_to_pitch, net_acceleration_request)
if net_acceleration_request_min < 0.1 or stopping or not CC.longActive:
if net_acceleration_request_min < 0.2 or stopping or not CC.longActive:
self.permit_braking = True
elif net_acceleration_request_min > 0.2:
elif net_acceleration_request_min > 0.3:
self.permit_braking = False

pcm_accel_cmd = clip(pcm_accel_cmd, self.params.ACCEL_MIN, self.params.ACCEL_MAX)
Expand Down
Loading

0 comments on commit 1257ae6

Please sign in to comment.