Skip to content

Commit 0eb15e8

Browse files
committed
Merge branch 'xt4'
2 parents bf5a45e + 6872063 commit 0eb15e8

File tree

7 files changed

+110
-33
lines changed

7 files changed

+110
-33
lines changed

.gitmodules

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
[submodule "panda"]
2-
path = panda
3-
url = ../../commaai/panda.git
41
[submodule "opendbc"]
52
path = opendbc
63
url = ../../commaai/opendbc.git
@@ -19,3 +16,6 @@
1916
[submodule "tinygrad"]
2017
path = tinygrad_repo
2118
url = https://github.com/geohot/tinygrad.git
19+
[submodule "panda"]
20+
path = panda
21+
url = https://github.com/garrettpall/panda.git

selfdrive/car/gm/carcontroller.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from opendbc.can.packer import CANPacker
66
from openpilot.selfdrive.car import apply_driver_steer_torque_limits
77
from openpilot.selfdrive.car.gm import gmcan
8-
from openpilot.selfdrive.car.gm.values import DBC, CanBus, CarControllerParams, CruiseButtons
8+
from openpilot.selfdrive.car.gm.values import DBC, CanBus, CarControllerParams, CruiseButtons, SDGM_CAR
99

1010
VisualAlert = car.CarControl.HUDControl.VisualAlert
1111
NetworkLocation = car.CarParams.NetworkLocation
@@ -147,7 +147,11 @@ def update(self, CC, CS, now_nanos):
147147
if (self.frame - self.last_button_frame) * DT_CTRL > 0.04:
148148
if self.cancel_counter > CAMERA_CANCEL_DELAY_FRAMES:
149149
self.last_button_frame = self.frame
150-
can_sends.append(gmcan.create_buttons(self.packer_pt, CanBus.CAMERA, CS.buttons_counter, CruiseButtons.CANCEL))
150+
if self.CP.carFingerprint in SDGM_CAR:
151+
can_sends.append(gmcan.create_buttons(self.packer_pt, CanBus.POWERTRAIN, CS.buttons_counter, CruiseButtons.CANCEL))
152+
else:
153+
can_sends.append(gmcan.create_buttons(self.packer_pt, CanBus.CAMERA, CS.buttons_counter, CruiseButtons.CANCEL))
154+
151155

152156
if self.CP.networkLocation == NetworkLocation.fwdCamera:
153157
# Silence "Take Steering" alert sent by camera, forward PSCMStatus with HandsOffSWlDetectionStatus=1

selfdrive/car/gm/carstate.py

+66-25
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from opendbc.can.can_define import CANDefine
66
from opendbc.can.parser import CANParser
77
from openpilot.selfdrive.car.interfaces import CarStateBase
8-
from openpilot.selfdrive.car.gm.values import DBC, AccState, CanBus, STEER_THRESHOLD
8+
from openpilot.selfdrive.car.gm.values import DBC, AccState, CanBus, STEER_THRESHOLD, SDGM_CAR
99

1010
TransmissionType = car.CarParams.TransmissionType
1111
NetworkLocation = car.CarParams.NetworkLocation
@@ -30,8 +30,12 @@ def update(self, pt_cp, cam_cp, loopback_cp):
3030
ret = car.CarState.new_message()
3131

3232
self.prev_cruise_buttons = self.cruise_buttons
33-
self.cruise_buttons = pt_cp.vl["ASCMSteeringButton"]["ACCButtons"]
34-
self.buttons_counter = pt_cp.vl["ASCMSteeringButton"]["RollingCounter"]
33+
if self.CP.carFingerprint not in SDGM_CAR:
34+
self.cruise_buttons = pt_cp.vl["ASCMSteeringButton"]["ACCButtons"]
35+
self.buttons_counter = pt_cp.vl["ASCMSteeringButton"]["RollingCounter"]
36+
else:
37+
self.cruise_buttons = cam_cp.vl["ASCMSteeringButton"]["ACCButtons"]
38+
self.buttons_counter = cam_cp.vl["ASCMSteeringButton"]["RollingCounter"]
3539
self.pscm_status = copy.copy(pt_cp.vl["PSCMStatus"])
3640
self.moving_backward = pt_cp.vl["EBCMWheelSpdRear"]["MovingBackward"] != 0
3741

@@ -87,18 +91,32 @@ def update(self, pt_cp, cam_cp, loopback_cp):
8791
ret.steerFaultTemporary = self.lkas_status == 2
8892
ret.steerFaultPermanent = self.lkas_status == 3
8993

90-
# 1 - open, 0 - closed
91-
ret.doorOpen = (pt_cp.vl["BCMDoorBeltStatus"]["FrontLeftDoor"] == 1 or
92-
pt_cp.vl["BCMDoorBeltStatus"]["FrontRightDoor"] == 1 or
93-
pt_cp.vl["BCMDoorBeltStatus"]["RearLeftDoor"] == 1 or
94-
pt_cp.vl["BCMDoorBeltStatus"]["RearRightDoor"] == 1)
94+
if self.CP.carFingerprint not in SDGM_CAR:
95+
# 1 - open, 0 - closed
96+
ret.doorOpen = (pt_cp.vl["BCMDoorBeltStatus"]["FrontLeftDoor"] == 1 or
97+
pt_cp.vl["BCMDoorBeltStatus"]["FrontRightDoor"] == 1 or
98+
pt_cp.vl["BCMDoorBeltStatus"]["RearLeftDoor"] == 1 or
99+
pt_cp.vl["BCMDoorBeltStatus"]["RearRightDoor"] == 1)
95100

96-
# 1 - latched
97-
ret.seatbeltUnlatched = pt_cp.vl["BCMDoorBeltStatus"]["LeftSeatBelt"] == 0
98-
ret.leftBlinker = pt_cp.vl["BCMTurnSignals"]["TurnSignals"] == 1
99-
ret.rightBlinker = pt_cp.vl["BCMTurnSignals"]["TurnSignals"] == 2
101+
# 1 - latched
102+
ret.seatbeltUnlatched = pt_cp.vl["BCMDoorBeltStatus"]["LeftSeatBelt"] == 0
103+
ret.leftBlinker = pt_cp.vl["BCMTurnSignals"]["TurnSignals"] == 1
104+
ret.rightBlinker = pt_cp.vl["BCMTurnSignals"]["TurnSignals"] == 2
100105

101-
ret.parkingBrake = pt_cp.vl["BCMGeneralPlatformStatus"]["ParkBrakeSwActive"] == 1
106+
ret.parkingBrake = pt_cp.vl["BCMGeneralPlatformStatus"]["ParkBrakeSwActive"] == 1
107+
else:
108+
# 1 - open, 0 - closed
109+
ret.doorOpen = (cam_cp.vl["BCMDoorBeltStatus"]["FrontLeftDoor"] == 1 or
110+
cam_cp.vl["BCMDoorBeltStatus"]["FrontRightDoor"] == 1 or
111+
cam_cp.vl["BCMDoorBeltStatus"]["RearLeftDoor"] == 1 or
112+
cam_cp.vl["BCMDoorBeltStatus"]["RearRightDoor"] == 1)
113+
114+
# 1 - latched
115+
ret.seatbeltUnlatched = cam_cp.vl["BCMDoorBeltStatus"]["LeftSeatBelt"] == 0
116+
ret.leftBlinker = cam_cp.vl["BCMTurnSignals"]["TurnSignals"] == 1
117+
ret.rightBlinker = cam_cp.vl["BCMTurnSignals"]["TurnSignals"] == 2
118+
119+
ret.parkingBrake = cam_cp.vl["BCMGeneralPlatformStatus"]["ParkBrakeSwActive"] == 1
102120
ret.cruiseState.available = pt_cp.vl["ECMEngineStatus"]["CruiseMainOn"] != 0
103121
ret.espDisabled = pt_cp.vl["ESPStatus"]["TractionControlOn"] != 1
104122
ret.accFaulted = (pt_cp.vl["AcceleratorPedal2"]["CruiseState"] == AccState.FAULTED or
@@ -108,7 +126,10 @@ def update(self, pt_cp, cam_cp, loopback_cp):
108126
ret.cruiseState.standstill = pt_cp.vl["AcceleratorPedal2"]["CruiseState"] == AccState.STANDSTILL
109127
if self.CP.networkLocation == NetworkLocation.fwdCamera:
110128
ret.cruiseState.speed = cam_cp.vl["ASCMActiveCruiseControlStatus"]["ACCSpeedSetpoint"] * CV.KPH_TO_MS
111-
ret.stockAeb = cam_cp.vl["AEBCmd"]["AEBCmdActive"] != 0
129+
if self.CP.carFingerprint not in SDGM_CAR:
130+
ret.stockAeb = cam_cp.vl["AEBCmd"]["AEBCmdActive"] != 0
131+
else:
132+
ret.stockAeb = False
112133
# openpilot controls nonAdaptive when not pcmCruise
113134
if self.CP.pcmCruise:
114135
ret.cruiseState.nonAdaptive = cam_cp.vl["ASCMActiveCruiseControlStatus"]["ACCCruiseState"] not in (2, 3)
@@ -120,32 +141,52 @@ def get_cam_can_parser(CP):
120141
messages = []
121142
if CP.networkLocation == NetworkLocation.fwdCamera:
122143
messages += [
123-
("AEBCmd", 10),
124-
("ASCMLKASteeringCmd", 10),
125-
("ASCMActiveCruiseControlStatus", 25),
126-
]
144+
("ASCMLKASteeringCmd", 10),
145+
("ASCMActiveCruiseControlStatus", 25),
146+
]
147+
if CP.carFingerprint in SDGM_CAR:
148+
messages += [
149+
("BCMTurnSignals", 1),
150+
("BCMDoorBeltStatus", 10),
151+
("BCMGeneralPlatformStatus", 10),
152+
("ASCMSteeringButton", 33),
153+
]
154+
else:
155+
messages += [
156+
("AEBCmd", 10),
157+
]
127158

128159
return CANParser(DBC[CP.carFingerprint]["pt"], messages, CanBus.CAMERA)
129160

130161
@staticmethod
131162
def get_can_parser(CP):
132163
messages = [
133-
("BCMTurnSignals", 1),
134-
("ECMPRDNL2", 10),
135164
("PSCMStatus", 10),
136165
("ESPStatus", 10),
137-
("BCMDoorBeltStatus", 10),
138-
("BCMGeneralPlatformStatus", 10),
139166
("EBCMWheelSpdFront", 20),
140167
("EBCMWheelSpdRear", 20),
141168
("EBCMFrictionBrakeStatus", 20),
142-
("AcceleratorPedal2", 33),
143-
("ASCMSteeringButton", 33),
144-
("ECMEngineStatus", 100),
145169
("PSCMSteeringAngle", 100),
146170
("ECMAcceleratorPos", 80),
147171
]
148172

173+
if CP.carFingerprint in SDGM_CAR:
174+
messages += [
175+
("ECMPRDNL2", 40),
176+
("AcceleratorPedal2", 40),
177+
("ECMEngineStatus", 80),
178+
]
179+
else:
180+
messages += [
181+
("ECMPRDNL2", 10),
182+
("AcceleratorPedal2", 33),
183+
("ECMEngineStatus", 100),
184+
("BCMTurnSignals", 1),
185+
("BCMDoorBeltStatus", 10),
186+
("BCMGeneralPlatformStatus", 10),
187+
("ASCMSteeringButton", 33),
188+
]
189+
149190
# Used to read back last counter sent to PT by camera
150191
if CP.networkLocation == NetworkLocation.fwdCamera:
151192
messages += [

selfdrive/car/gm/interface.py

+17-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from openpilot.common.conversions import Conversions as CV
77
from openpilot.selfdrive.car import create_button_events, get_safety_config
88
from openpilot.selfdrive.car.gm.radar_interface import RADAR_HEADER_MSG
9-
from openpilot.selfdrive.car.gm.values import CAR, CruiseButtons, CarControllerParams, EV_CAR, CAMERA_ACC_CAR, CanBus
9+
from openpilot.selfdrive.car.gm.values import CAR, CruiseButtons, CarControllerParams, EV_CAR, CAMERA_ACC_CAR, SDGM_CAR, CanBus
1010
from openpilot.selfdrive.car.interfaces import CarInterfaceBase, TorqueFromLateralAccelCallbackType, FRICTION_THRESHOLD
1111
from openpilot.selfdrive.controls.lib.drive_helpers import get_friction
1212

@@ -105,6 +105,15 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs):
105105
ret.openpilotLongitudinalControl = True
106106
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG
107107

108+
elif candidate in SDGM_CAR:
109+
ret.experimentalLongitudinalAvailable = False
110+
ret.networkLocation = NetworkLocation.fwdCamera
111+
ret.pcmCruise = True
112+
ret.radarUnavailable = True
113+
ret.minEnableSpeed = 31 * CV.MPH_TO_MS
114+
ret.minSteerSpeed = 29 * CV.MPH_TO_MS
115+
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_SDGM
116+
108117
else: # ASCM, OBD-II harness
109118
ret.openpilotLongitudinalControl = True
110119
ret.networkLocation = NetworkLocation.gateway
@@ -252,6 +261,12 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs):
252261
ret.steerActuatorDelay = 0.2
253262
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
254263

264+
elif candidate == CAR.XT4:
265+
ret.mass = 3660. * CV.LB_TO_KG
266+
ret.wheelbase = 2.78
267+
ret.steerRatio = 14.4
268+
ret.centerToFront = ret.wheelbase * 0.4
269+
255270
return ret
256271

257272
# returns a car.CarState
@@ -275,7 +290,7 @@ def _update(self, c):
275290
# TODO: verify 17 Volt can enable for the first time at a stop and allow for all GMs
276291
below_min_enable_speed = ret.vEgo < self.CP.minEnableSpeed or self.CS.moving_backward
277292
if below_min_enable_speed and not (ret.standstill and ret.brake >= 20 and
278-
self.CP.networkLocation == NetworkLocation.fwdCamera):
293+
(self.CP.networkLocation == NetworkLocation.fwdCamera and not self.CP.carFingerprint in SDGM_CAR)):
279294
events.add(EventName.belowEngageSpeed)
280295
if ret.cruiseState.standstill:
281296
events.add(EventName.resumeRequired)

selfdrive/car/gm/values.py

+16
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ def __init__(self, CP):
4646
# Camera transitions to MAX_ACC_REGEN from ZERO_GAS and uses friction brakes instantly
4747
max_regen_acceleration = 0.
4848

49+
elif CP.carFingerprint in SDGM_CAR:
50+
self.MAX_GAS = 3400
51+
self.MAX_ACC_REGEN = 1514
52+
self.INACTIVE_REGEN = 1554
53+
max_regen_acceleration = 0.
54+
4955
else:
5056
self.MAX_GAS = 3072 # Safety limit, not ACC max. Stock ACC >4096 from standstill.
5157
self.MAX_ACC_REGEN = 1404 # Max ACC regen is slightly less than max paddle regen
@@ -76,6 +82,7 @@ class CAR(StrEnum):
7682
SILVERADO = "CHEVROLET SILVERADO 1500 2020"
7783
EQUINOX = "CHEVROLET EQUINOX 2019"
7884
TRAILBLAZER = "CHEVROLET TRAILBLAZER 2021"
85+
XT4 = "CADILLAC XT4 2023"
7986

8087

8188
class Footnote(Enum):
@@ -118,6 +125,7 @@ def init_make(self, CP: car.CarParams):
118125
],
119126
CAR.EQUINOX: GMCarInfo("Chevrolet Equinox 2019-22"),
120127
CAR.TRAILBLAZER: GMCarInfo("Chevrolet Trailblazer 2021-22"),
128+
CAR.XT4: GMCarInfo("Cadillac XT4 2023", "Driver Assist Package"),
121129
}
122130

123131

@@ -222,6 +230,11 @@ class CanBus:
222230
# {
223231
# 190: 6, 193: 8, 197: 8, 201: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 289: 8, 298: 8, 304: 3, 309: 8, 311: 8, 313: 8, 320: 4, 328: 1, 352: 5, 381: 8, 384: 4, 386: 8, 388: 8, 413: 8, 451: 8, 452: 8, 453: 6, 455: 7, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 500: 6, 501: 8, 532: 6, 560: 8, 562: 8, 563: 5, 565: 5, 587: 8, 707: 8, 715: 8, 717: 5, 761: 7, 789: 5, 800: 6, 810: 8, 840: 5, 842: 5, 844: 8, 869: 4, 880: 6, 977: 8, 1001: 8, 1011: 6, 1017: 8, 1020: 8, 1217: 8, 1221: 5, 1233: 8, 1249: 8, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1271: 8, 1280: 4, 1296: 4, 1300: 8, 1609: 8, 1611: 8, 1613: 8, 1649: 8, 1792: 8, 1798: 8, 1824: 8, 1825: 8, 1840: 8, 1842: 8, 1858: 8, 1860: 8, 1863: 8, 1872: 8, 1875: 8, 1882: 8, 1888: 8, 1889: 8, 1892: 8, 1930: 7, 1937: 8, 1953: 8, 1968: 8, 2001: 8, 2017: 8, 2018: 8, 2020: 8
224232
# }],
233+
CAR.XT4: [
234+
# Cadillac XT4 w/ ACC 2023
235+
{
236+
190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 289: 8, 292: 2, 298: 8, 304: 3, 309: 8, 313: 8, 320: 4, 322: 7, 328: 1, 331: 3, 352: 5, 353: 3, 368: 3, 381: 8, 384: 4, 386: 8, 388: 8, 393: 7, 398: 8, 401: 8, 407: 7, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 455: 7, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 499: 3, 500: 6, 501: 8, 503: 2, 508: 8, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 567: 5, 573: 1, 577: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 719: 5, 761: 7, 806: 1, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 872: 1, 880: 6, 961: 8, 969: 8, 975: 2, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1011: 6, 1013: 5, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1037: 5, 1105: 5, 1187: 5, 1195: 3, 1217: 8, 1221: 5, 1223: 2, 1225: 7, 1233: 8, 1236: 8, 1249: 8, 1257: 6, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1268: 2, 1271: 8, 1273: 3, 1276: 2, 1277: 7, 1278: 4, 1279: 4, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1601: 8, 1609: 8, 1613: 8, 1649: 8, 1792: 8, 1793: 8, 1798: 8, 1824: 8, 1825: 8, 1840: 8, 1842: 8, 1858: 8, 1860: 8, 1863: 8, 1872: 8, 1875: 8, 1882: 8, 1888: 8, 1889: 8, 1892: 8, 1906: 7, 1907: 7, 1912: 7, 1919: 7, 1920: 8, 1924: 8, 1930: 7, 1937: 8, 1953: 8, 1968: 8, 1969: 8, 1971: 8, 1975: 8, 1984: 8, 1988: 8, 2000: 8, 2001: 8, 2002: 8, 2017: 8, 2018: 8, 2020: 8, 2026: 8
237+
}],
225238
}
226239

227240
GM_RX_OFFSET = 0x400
@@ -233,4 +246,7 @@ class CanBus:
233246
# We're integrated at the camera with VOACC on these cars (instead of ASCM w/ OBD-II harness)
234247
CAMERA_ACC_CAR = {CAR.BOLT_EUV, CAR.SILVERADO, CAR.EQUINOX, CAR.TRAILBLAZER}
235248

249+
# We're integrated at the Saftey Data Gateway Module on these cars
250+
SDGM_CAR = {CAR.XT4}
251+
236252
STEER_THRESHOLD = 1.0

selfdrive/car/torque_data/substitute.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ CADILLAC ESCALADE ESV 2016: CHEVROLET VOLT PREMIER 2017
5252
CADILLAC ATS Premium Performance 2018: CHEVROLET VOLT PREMIER 2017
5353
CHEVROLET MALIBU PREMIER 2017: CHEVROLET VOLT PREMIER 2017
5454
HOLDEN ASTRA RS-V BK 2017: CHEVROLET VOLT PREMIER 2017
55+
CADILLAC XT4 2023: CHEVROLET VOLT PREMIER 2017
5556

5657
SKODA FABIA 4TH GEN: VOLKSWAGEN GOLF 7TH GEN
5758
SKODA OCTAVIA 3RD GEN: SKODA SUPERB 3RD GEN

0 commit comments

Comments
 (0)