mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-08-04 15:46:54 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 66bdc1665d |
Binary file not shown.
@@ -130,6 +130,7 @@ class CarHarness(EnumBase):
|
|||||||
hyundai_p = BaseCarHarness("Hyundai P connector")
|
hyundai_p = BaseCarHarness("Hyundai P connector")
|
||||||
hyundai_q = BaseCarHarness("Hyundai Q connector")
|
hyundai_q = BaseCarHarness("Hyundai Q connector")
|
||||||
hyundai_r = BaseCarHarness("Hyundai R connector")
|
hyundai_r = BaseCarHarness("Hyundai R connector")
|
||||||
|
hyundai_s = BaseCarHarness("Hyundai S connector")
|
||||||
custom = BaseCarHarness("Developer connector")
|
custom = BaseCarHarness("Developer connector")
|
||||||
obd_ii = BaseCarHarness("OBD-II connector", parts=[Cable.long_obdc_cable], has_connector=False)
|
obd_ii = BaseCarHarness("OBD-II connector", parts=[Cable.long_obdc_cable], has_connector=False)
|
||||||
gm = BaseCarHarness("GM connector", parts=[Accessory.harness_box])
|
gm = BaseCarHarness("GM connector", parts=[Accessory.harness_box])
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
|
|||||||
|
|
||||||
lka_steering = self.CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG
|
lka_steering = self.CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG
|
||||||
lka_steering_long = lka_steering and self.CP.openpilotLongitudinalControl
|
lka_steering_long = lka_steering and self.CP.openpilotLongitudinalControl
|
||||||
|
ccnc_non_hda2 = self.CP.flags & HyundaiFlags.CCNC and not lka_steering
|
||||||
|
|
||||||
# steering control
|
# steering control
|
||||||
can_sends.extend(hyundaicanfd.create_steering_messages(self.packer, self.CP, self.CAN, CC.enabled, apply_steer_req, apply_torque, self.lkas_icon))
|
can_sends.extend(hyundaicanfd.create_steering_messages(self.packer, self.CP, self.CAN, CC.enabled, apply_steer_req, apply_torque, self.lkas_icon))
|
||||||
@@ -211,7 +212,12 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
|
|||||||
|
|
||||||
# LFA and HDA icons
|
# LFA and HDA icons
|
||||||
if self.frame % 5 == 0 and (not lka_steering or lka_steering_long):
|
if self.frame % 5 == 0 and (not lka_steering or lka_steering_long):
|
||||||
can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, CC.enabled, self.lfa_icon))
|
if ccnc_non_hda2:
|
||||||
|
can_sends.extend(hyundaicanfd.create_ccnc(self.packer, self.CAN, self.CP.openpilotLongitudinalControl, CC.enabled, CC.hudControl, CC.leftBlinker,
|
||||||
|
CC.rightBlinker, CS.msg_161, CS.msg_162, CS.msg_1b5, CS.is_metric, CS.out, CS.main_cruise_enabled,
|
||||||
|
self.lfa_icon))
|
||||||
|
else:
|
||||||
|
can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, CC.enabled, self.lfa_icon))
|
||||||
|
|
||||||
# blinkers
|
# blinkers
|
||||||
if lka_steering and self.CP.flags & HyundaiFlags.CANFD_ENABLE_BLINKERS:
|
if lka_steering and self.CP.flags & HyundaiFlags.CANFD_ENABLE_BLINKERS:
|
||||||
@@ -220,11 +226,12 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
|
|||||||
if self.CP.openpilotLongitudinalControl:
|
if self.CP.openpilotLongitudinalControl:
|
||||||
if lka_steering:
|
if lka_steering:
|
||||||
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
|
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
|
||||||
else:
|
elif not ccnc_non_hda2:
|
||||||
can_sends.extend(hyundaicanfd.create_fca_warning_light(self.packer, self.CAN, self.frame))
|
can_sends.extend(hyundaicanfd.create_fca_warning_light(self.packer, self.CAN, self.frame))
|
||||||
if self.frame % 2 == 0:
|
if self.frame % 2 == 0:
|
||||||
can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CAN, CC.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
|
can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CAN, CC.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
|
||||||
set_speed_in_units, hud_control, self.lead_data, CS.main_cruise_enabled, self.tuning))
|
set_speed_in_units, hud_control, self.lead_data, CS.main_cruise_enabled, self.tuning,
|
||||||
|
CS.cruise_info if ccnc_non_hda2 else None))
|
||||||
self.accel_last = accel
|
self.accel_last = accel
|
||||||
else:
|
else:
|
||||||
# button presses
|
# button presses
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ class CarState(CarStateBase, EsccCarStateBase, MadsCarState, CarStateExt):
|
|||||||
self.buttons_counter = 0
|
self.buttons_counter = 0
|
||||||
|
|
||||||
self.cruise_info = {}
|
self.cruise_info = {}
|
||||||
|
self.msg_161, self.msg_162, self.msg_1b5 = {}, {}, {}
|
||||||
|
|
||||||
# On some cars, CLU15->CF_Clu_VehicleSpeed can oscillate faster than the dash updates. Sample at 5 Hz
|
# On some cars, CLU15->CF_Clu_VehicleSpeed can oscillate faster than the dash updates. Sample at 5 Hz
|
||||||
self.cluster_speed = 0
|
self.cluster_speed = 0
|
||||||
@@ -256,12 +257,14 @@ class CarState(CarStateBase, EsccCarStateBase, MadsCarState, CarStateExt):
|
|||||||
ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > self.params.STEER_THRESHOLD, 5)
|
ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > self.params.STEER_THRESHOLD, 5)
|
||||||
ret.steerFaultTemporary = cp.vl["MDPS"]["MDPS_LkaFailSta"] != 0
|
ret.steerFaultTemporary = cp.vl["MDPS"]["MDPS_LkaFailSta"] != 0
|
||||||
|
|
||||||
# TODO: alt signal usage may be described by cp.vl['BLINKERS']['USE_ALT_LAMP']
|
alt = ""
|
||||||
left_blinker_sig, right_blinker_sig = "LEFT_LAMP", "RIGHT_LAMP"
|
if self.CP.flags & HyundaiFlags.CCNC:
|
||||||
if self.CP.carFingerprint == CAR.HYUNDAI_KONA_EV_2ND_GEN:
|
alt = "_ALT"
|
||||||
left_blinker_sig, right_blinker_sig = "LEFT_LAMP_ALT", "RIGHT_LAMP_ALT"
|
if not self.CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG:
|
||||||
ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, cp.vl["BLINKERS"][left_blinker_sig],
|
self.msg_161, self.msg_162, self.msg_1b5 = map(copy.copy, (cp_cam.vl["CCNC_0x161"], cp_cam.vl["CCNC_0x162"], cp_cam.vl["FR_CMR_03_50ms"]))
|
||||||
cp.vl["BLINKERS"][right_blinker_sig])
|
self.cruise_info = copy.copy((cp_cam if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else cp).vl["SCC_CONTROL"])
|
||||||
|
ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, cp.vl["BLINKERS"][f"LEFT_LAMP{alt}"],
|
||||||
|
cp.vl["BLINKERS"][f"RIGHT_LAMP{alt}"])
|
||||||
if self.CP.enableBsm:
|
if self.CP.enableBsm:
|
||||||
ret.leftBlindspot = bool(cp.vl["ADAS_CMD_50_50ms"]["BCW_LtIndSta"])
|
ret.leftBlindspot = bool(cp.vl["ADAS_CMD_50_50ms"]["BCW_LtIndSta"])
|
||||||
ret.rightBlindspot = bool(cp.vl["ADAS_CMD_50_50ms"]["BCW_RtIndSta"])
|
ret.rightBlindspot = bool(cp.vl["ADAS_CMD_50_50ms"]["BCW_RtIndSta"])
|
||||||
|
|||||||
@@ -220,6 +220,16 @@ FW_VERSIONS = {
|
|||||||
b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.07 99211-L1000 211223',
|
b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.07 99211-L1000 211223',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
CAR.HYUNDAI_SONATA_2024: {
|
||||||
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
|
b'\xf1\x00DN8 MFC AT KOR LHD 1.00 1.01 99211-L1800 230512',
|
||||||
|
b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.01 99211-L1800 230512',
|
||||||
|
b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.02 99211-L1800 250613',
|
||||||
|
],
|
||||||
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
|
b'\xf1\x00DN8_ RDR ----- 1.00 1.00 99110-L1800 ',
|
||||||
|
],
|
||||||
|
},
|
||||||
CAR.HYUNDAI_SONATA_LF: {
|
CAR.HYUNDAI_SONATA_LF: {
|
||||||
(Ecu.fwdRadar, 0x7d0, None): [
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
b'\xf1\x00LF__ SCC F-CUP 1.00 1.00 96401-C2200 ',
|
b'\xf1\x00LF__ SCC F-CUP 1.00 1.00 96401-C2200 ',
|
||||||
@@ -570,6 +580,16 @@ FW_VERSIONS = {
|
|||||||
b'\xf1\x00OS9 LKAS AT USA LHD 1.00 1.00 95740-J9300 g21',
|
b'\xf1\x00OS9 LKAS AT USA LHD 1.00 1.00 95740-J9300 g21',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
CAR.HYUNDAI_KONA_2ND_GEN: {
|
||||||
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
|
b'\xf1\x00SX2 MFC AT USA LHD 1.00 1.03 99211-BE000 230517',
|
||||||
|
b'\xf1\x00SX2 MFC AT USA LHD 1.00 1.07 99211-BE000 240611',
|
||||||
|
],
|
||||||
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
|
b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE000 ',
|
||||||
|
b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE500 ',
|
||||||
|
],
|
||||||
|
},
|
||||||
CAR.KIA_CEED: {
|
CAR.KIA_CEED: {
|
||||||
(Ecu.fwdRadar, 0x7d0, None): [
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
b'\xf1\x00CD__ SCC F-CUP 1.00 1.00 99110-J7500 ',
|
b'\xf1\x00CD__ SCC F-CUP 1.00 1.00 99110-J7500 ',
|
||||||
@@ -605,6 +625,17 @@ FW_VERSIONS = {
|
|||||||
b'\xf1\x00BD__ SCC H-CUP 1.00 1.02 99110-M6000 ',
|
b'\xf1\x00BD__ SCC H-CUP 1.00 1.02 99110-M6000 ',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
CAR.KIA_K4_2025: {
|
||||||
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
|
b'\xf1\x00CL4 MFC AT CAN LHD 1.00 1.02 99210-GG000 240708',
|
||||||
|
b'\xf1\x00CL4 MFC AT USA LHD 1.00 1.02 99210-GG000 240708',
|
||||||
|
b'\xf1\x00CL4 MFC AT USA LHD 1.00 1.04 99210-GG100 251205',
|
||||||
|
],
|
||||||
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
|
b'\xf1\x00CL4_ RDR ----- 1.00 1.01 99110-GG000 ',
|
||||||
|
b'\xf1\x00CL4_ RDR ----- 1.00 1.01 99110-GG100 ',
|
||||||
|
],
|
||||||
|
},
|
||||||
CAR.KIA_K5_2021: {
|
CAR.KIA_K5_2021: {
|
||||||
(Ecu.fwdRadar, 0x7d0, None): [
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
b'\xf1\x00DL3_ SCC F-CUP 1.00 1.03 99110-L2100 ',
|
b'\xf1\x00DL3_ SCC F-CUP 1.00 1.03 99110-L2100 ',
|
||||||
@@ -637,6 +668,14 @@ FW_VERSIONS = {
|
|||||||
b'\xf1\x00DL ESC \t 102"\x08\x10 58910-L3800',
|
b'\xf1\x00DL ESC \t 102"\x08\x10 58910-L3800',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
CAR.KIA_K5_2025: {
|
||||||
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
|
b'\xf1\x00DL3 MFC AT USA LHD 1.00 1.04 99210-L2500 240117',
|
||||||
|
],
|
||||||
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
|
b'\xf1\x00DL3_ RDR ----- 1.00 1.01 99110-L2500 ',
|
||||||
|
],
|
||||||
|
},
|
||||||
CAR.KIA_K5_HEV_2020: {
|
CAR.KIA_K5_HEV_2020: {
|
||||||
(Ecu.fwdRadar, 0x7d0, None): [
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
b'\xf1\x00DLhe SCC FHCUP 1.00 1.02 99110-L7000 ',
|
b'\xf1\x00DLhe SCC FHCUP 1.00 1.02 99110-L7000 ',
|
||||||
@@ -723,6 +762,7 @@ FW_VERSIONS = {
|
|||||||
],
|
],
|
||||||
(Ecu.fwdCamera, 0x7c4, None): [
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
b'\xf1\x00SX2EMFC AT KOR LHD 1.00 1.00 99211-BF000 230410',
|
b'\xf1\x00SX2EMFC AT KOR LHD 1.00 1.00 99211-BF000 230410',
|
||||||
|
b'\xf1\x00SX2EMFC AT USA LHD 1.00 1.02 99211-BF000 230823',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
CAR.KIA_NIRO_EV: {
|
CAR.KIA_NIRO_EV: {
|
||||||
@@ -981,6 +1021,17 @@ FW_VERSIONS = {
|
|||||||
b'\xf1\x00OSH LKAS AT KOR LHD 1.00 1.01 95740-CM000 l31',
|
b'\xf1\x00OSH LKAS AT KOR LHD 1.00 1.01 95740-CM000 l31',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
CAR.HYUNDAI_KONA_HEV_2ND_GEN: {
|
||||||
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
|
b'\xf1\x00SX2HMFC AT AUS RHD 1.00 1.00 99211-BE001 241015',
|
||||||
|
b'\xf1\x00SX2HMFC AT EUR LHD 1.00 1.01 99211-BE001 250117',
|
||||||
|
b'\xf1\x00SX2HMFC AT EUR RHD 1.00 1.04 99211-BE000 231010',
|
||||||
|
],
|
||||||
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
|
b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE000 ',
|
||||||
|
b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE500 ',
|
||||||
|
],
|
||||||
|
},
|
||||||
CAR.HYUNDAI_SONATA_HYBRID: {
|
CAR.HYUNDAI_SONATA_HYBRID: {
|
||||||
(Ecu.fwdRadar, 0x7d0, None): [
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
b'\xf1\x00DNhe SCC F-CUP 1.00 1.02 99110-L5000 ',
|
b'\xf1\x00DNhe SCC F-CUP 1.00 1.02 99110-L5000 ',
|
||||||
@@ -1002,6 +1053,15 @@ FW_VERSIONS = {
|
|||||||
b'\xf1\x00DN8HMFC AT USA LHD 1.00 1.07 99211-L1000 211223',
|
b'\xf1\x00DN8HMFC AT USA LHD 1.00 1.07 99211-L1000 211223',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
CAR.HYUNDAI_SONATA_HEV_2024: {
|
||||||
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
|
b'\xf1\x00DN8HMFC AT KOR LHD 1.00 1.01 99211-L1800 230512',
|
||||||
|
b'\xf1\x00DN8HMFC AT USA LHD 1.00 1.01 99211-L1800 230512',
|
||||||
|
],
|
||||||
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
|
b'\xf1\x00DN8_ RDR ----- 1.00 1.00 99110-L1800 ',
|
||||||
|
],
|
||||||
|
},
|
||||||
CAR.KIA_SORENTO: {
|
CAR.KIA_SORENTO: {
|
||||||
(Ecu.fwdCamera, 0x7c4, None): [
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
b'\xf1\x00UMP LKAS AT AUS RHD 1.00 1.00 96400-C6550 S30',
|
b'\xf1\x00UMP LKAS AT AUS RHD 1.00 1.00 96400-C6550 S30',
|
||||||
@@ -1069,6 +1129,16 @@ FW_VERSIONS = {
|
|||||||
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.06 99211-GI010 230110',
|
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.06 99211-GI010 230110',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
CAR.HYUNDAI_IONIQ_5_N: {
|
||||||
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
|
b'\xf1\x00NE1N RDR ----- 1.00 1.00 99110-NI000 ',
|
||||||
|
],
|
||||||
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
|
b'\xf1\x00NE1NMFC AT KOR LHD 1.00 1.04 99211-NI000 231219',
|
||||||
|
b'\xf1\x00NE1NMFC AT KOR LHD 1.00 1.00 99211-NI010 240712',
|
||||||
|
b'\xf1\x00NE1NMFC AT USA LHD 1.00 1.04 99211-NI000 231219',
|
||||||
|
],
|
||||||
|
},
|
||||||
CAR.HYUNDAI_IONIQ_6: {
|
CAR.HYUNDAI_IONIQ_6: {
|
||||||
(Ecu.fwdRadar, 0x7d0, None): [
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
b'\xf1\x00CE__ RDR ----- 1.00 1.01 99110-KL000 ',
|
b'\xf1\x00CE__ RDR ----- 1.00 1.01 99110-KL000 ',
|
||||||
@@ -1107,6 +1177,37 @@ FW_VERSIONS = {
|
|||||||
b'\xf1\x00NX4__ 1.01 1.02 99110-N9000 ',
|
b'\xf1\x00NX4__ 1.01 1.02 99110-N9000 ',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
CAR.HYUNDAI_TUCSON_2025: {
|
||||||
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
|
b'\xf1\x00NX4 FR_CMR AT GEN LHD 1.00 1.00 99211-N7030 C55',
|
||||||
|
b'\xf1\x00NX4 FR_CMR AT GEN LHD 1.00 1.00 99211-N7035 C5C',
|
||||||
|
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.01 99211-N7050 C5A',
|
||||||
|
],
|
||||||
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
|
b'\xf1\x00NX4__ 1.00 1.02 99110N7000 ',
|
||||||
|
b'\xf1\x00NX4__ 1.00 1.03 99110N7100 ',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
CAR.HYUNDAI_TUCSON_HEV_2025: {
|
||||||
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
|
b'\xf1\x00NX4 FR_CMR AT EUR LHD 1.00 1.00 99211-N7030 C55',
|
||||||
|
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N7030 C55',
|
||||||
|
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N7035 C5C',
|
||||||
|
],
|
||||||
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
|
b'\xf1\x00NX4__ 1.00 1.02 99110N7000 ',
|
||||||
|
b'\xf1\x00NX4__ 1.00 1.02 99110N7100 ',
|
||||||
|
b'\xf1\x00NX4__ 1.00 1.03 99110N7100 ',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
CAR.HYUNDAI_TUCSON_PHEV_2025: {
|
||||||
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
|
b'\xf1\x00NX4 FR_CMR AT CAN LHD 1.00 1.00 99211-N7030 C55',
|
||||||
|
],
|
||||||
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
|
b'\xf1\x00NX4__ 1.00 1.02 99110N7100 ',
|
||||||
|
],
|
||||||
|
},
|
||||||
CAR.HYUNDAI_SANTA_CRUZ_1ST_GEN: {
|
CAR.HYUNDAI_SANTA_CRUZ_1ST_GEN: {
|
||||||
(Ecu.fwdCamera, 0x7c4, None): [
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-CW000 14M',
|
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-CW000 14M',
|
||||||
@@ -1118,6 +1219,14 @@ FW_VERSIONS = {
|
|||||||
b'\xf1\x00NX4__ 1.01 1.00 99110-K5000 ',
|
b'\xf1\x00NX4__ 1.01 1.00 99110-K5000 ',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
CAR.HYUNDAI_SANTA_CRUZ_2025: {
|
||||||
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
|
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N7030 C55',
|
||||||
|
],
|
||||||
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
|
b'\xf1\x00NX4__ 1.00 1.00 99110K5500 ',
|
||||||
|
],
|
||||||
|
},
|
||||||
CAR.KIA_SPORTAGE_5TH_GEN: {
|
CAR.KIA_SPORTAGE_5TH_GEN: {
|
||||||
(Ecu.fwdCamera, 0x7c4, None): [
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
b'\xf1\x00NQ5 FR_CMR AT AUS RHD 1.00 1.00 99211-P1040 663',
|
b'\xf1\x00NQ5 FR_CMR AT AUS RHD 1.00 1.00 99211-P1040 663',
|
||||||
@@ -1190,6 +1299,16 @@ FW_VERSIONS = {
|
|||||||
b'\xf1\x00MQ4_ SCC FHCUP 1.00 1.08 99110-P2000 ',
|
b'\xf1\x00MQ4_ SCC FHCUP 1.00 1.08 99110-P2000 ',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
CAR.KIA_SORENTO_2024: {
|
||||||
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
|
b'\xf1\x00MQ4 MFC AT AUS RHD 1.01 1.04 99210-P2550 231127',
|
||||||
|
b'\xf1\x00MQ4 MFC AT USA LHD 1.01 1.04 99210-R5500 231127',
|
||||||
|
],
|
||||||
|
(Ecu.fwdRadar, 0x7d0, None): [
|
||||||
|
b'\xf1\x00MQ4_ RDR ----- 1.00 1.01 99110-P2500 ',
|
||||||
|
b'\xf1\x00MQ4_ RDR ----- 1.00 1.01 99110-R5500 ',
|
||||||
|
],
|
||||||
|
},
|
||||||
CAR.KIA_SORENTO_HEV_4TH_GEN: {
|
CAR.KIA_SORENTO_HEV_4TH_GEN: {
|
||||||
(Ecu.fwdCamera, 0x7c4, None): [
|
(Ecu.fwdCamera, 0x7c4, None): [
|
||||||
b'\xf1\x00MQ4HMFC AT KOR LHD 1.00 1.04 99210-P2000 200330',
|
b'\xf1\x00MQ4HMFC AT KOR LHD 1.00 1.04 99210-P2000 200330',
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from opendbc.car import CanBusBase
|
from opendbc.car import CanBusBase
|
||||||
|
from opendbc.car.common.conversions import Conversions as CV
|
||||||
from opendbc.car.crc import CRC16_XMODEM
|
from opendbc.car.crc import CRC16_XMODEM
|
||||||
from opendbc.car.hyundai.values import HyundaiFlags
|
from opendbc.car.hyundai.values import HyundaiFlags
|
||||||
from opendbc.sunnypilot.car.hyundai.lead_data_ext import CanFdLeadData
|
from opendbc.sunnypilot.car.hyundai.lead_data_ext import CanFdLeadData
|
||||||
@@ -125,8 +126,106 @@ def create_lfahda_cluster(packer, CAN, enabled, lfa_icon):
|
|||||||
return packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values)
|
return packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values)
|
||||||
|
|
||||||
|
|
||||||
|
def create_ccnc(packer, CAN, openpilotLongitudinalControl, enabled, hud, leftBlinker, rightBlinker, msg_161, msg_162, msg_1b5,
|
||||||
|
is_metric, out, main_cruise_enabled, lfa_icon):
|
||||||
|
for f in {"FAULT_LSS", "FAULT_HDA", "FAULT_DAS", "FAULT_LFA", "FAULT_DAW", "FAULT_ESS"}:
|
||||||
|
msg_162[f] = 0
|
||||||
|
if msg_161["ALERTS_2"] == 5:
|
||||||
|
msg_161.update({"ALERTS_2": 0, "SOUNDS_2": 0})
|
||||||
|
if msg_161["ALERTS_3"] == 17:
|
||||||
|
msg_161["ALERTS_3"] = 0
|
||||||
|
if msg_161["ALERTS_5"] in (2, 5):
|
||||||
|
msg_161["ALERTS_5"] = 0
|
||||||
|
if msg_161["SOUNDS_4"] == 2 and msg_161["LFA_ICON"] in (3, 0,):
|
||||||
|
msg_161["SOUNDS_4"] = 0
|
||||||
|
|
||||||
|
LANE_CHANGE_SPEED_MIN = 8.9408
|
||||||
|
anyBlinker = leftBlinker or rightBlinker
|
||||||
|
curvature = {i: (31 if i == -1 else 13 - abs(i + 15)) if i < 0 else 15 + i for i in range(-15, 16)}
|
||||||
|
|
||||||
|
msg_161.update({
|
||||||
|
"DAW_ICON": 0,
|
||||||
|
"LKA_ICON": 0,
|
||||||
|
"LFA_ICON": 2 if lfa_icon else 0,
|
||||||
|
"CENTERLINE": 1 if lfa_icon else 0,
|
||||||
|
"LANELINE_CURVATURE": curvature.get(max(-15, min(int(out.steeringAngleDeg / 4.5), 15)), 14) if lfa_icon and not anyBlinker else 15,
|
||||||
|
"LANELINE_LEFT": (0 if not lfa_icon else 1 if not hud.leftLaneVisible else 4 if hud.leftLaneDepart else 6 if anyBlinker else 2),
|
||||||
|
"LANELINE_RIGHT": (0 if not lfa_icon else 1 if not hud.rightLaneVisible else 4 if hud.rightLaneDepart else 6 if anyBlinker else 2),
|
||||||
|
"LCA_LEFT_ICON": (0 if not lfa_icon or out.vEgo < LANE_CHANGE_SPEED_MIN else 1 if out.leftBlindspot else 2 if anyBlinker else 4),
|
||||||
|
"LCA_RIGHT_ICON": (0 if not lfa_icon or out.vEgo < LANE_CHANGE_SPEED_MIN else 1 if out.rightBlindspot else 2 if anyBlinker else 4),
|
||||||
|
"LCA_LEFT_ARROW": 2 if leftBlinker else 0,
|
||||||
|
"LCA_RIGHT_ARROW": 2 if rightBlinker else 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
if lfa_icon and (leftBlinker or rightBlinker):
|
||||||
|
leftlaneraw, rightlaneraw = msg_1b5["Info_LftLnPosVal"], msg_1b5["Info_RtLnPosVal"]
|
||||||
|
|
||||||
|
scale_per_m = 15 / 1.7
|
||||||
|
leftlane = abs(int(round(15 + (leftlaneraw - 1.7) * scale_per_m)))
|
||||||
|
rightlane = abs(int(round(15 + (rightlaneraw - 1.7) * scale_per_m)))
|
||||||
|
|
||||||
|
if msg_1b5["Info_LftLnQualSta"] not in (2, 3):
|
||||||
|
leftlane = 0
|
||||||
|
if msg_1b5["Info_RtLnQualSta"] not in (2, 3):
|
||||||
|
rightlane = 0
|
||||||
|
|
||||||
|
if leftlaneraw == -2.0248375:
|
||||||
|
leftlane = 30 - rightlane
|
||||||
|
if rightlaneraw == 2.0248375:
|
||||||
|
rightlane = 30 - leftlane
|
||||||
|
|
||||||
|
if leftlaneraw == rightlaneraw == 0:
|
||||||
|
leftlane = rightlane = 15
|
||||||
|
elif leftlaneraw == 0:
|
||||||
|
leftlane = 30 - rightlane
|
||||||
|
elif rightlaneraw == 0:
|
||||||
|
rightlane = 30 - leftlane
|
||||||
|
|
||||||
|
total = leftlane + rightlane
|
||||||
|
if total == 0:
|
||||||
|
leftlane = rightlane = 15
|
||||||
|
else:
|
||||||
|
leftlane = round((leftlane / total) * 30)
|
||||||
|
rightlane = 30 - leftlane
|
||||||
|
|
||||||
|
msg_161["LANELINE_LEFT_POSITION"] = leftlane
|
||||||
|
msg_161["LANELINE_RIGHT_POSITION"] = rightlane
|
||||||
|
|
||||||
|
if hud.leftLaneDepart or hud.rightLaneDepart:
|
||||||
|
msg_162["VIBRATE"] = 1
|
||||||
|
|
||||||
|
if openpilotLongitudinalControl:
|
||||||
|
if msg_161["ALERTS_3"] in (1, 2, 3, 4, 7, 8, 9, 10):
|
||||||
|
msg_161["ALERTS_3"] = 0
|
||||||
|
if msg_161["ALERTS_5"] == 4:
|
||||||
|
msg_161["ALERTS_5"] = 0
|
||||||
|
if msg_161["SOUNDS_3"] == 5:
|
||||||
|
msg_161["SOUNDS_3"] = 0
|
||||||
|
|
||||||
|
msg_161.update({
|
||||||
|
"SETSPEED": 3 if enabled else 1,
|
||||||
|
"SETSPEED_HUD": 0 if not main_cruise_enabled else 2 if enabled else 1,
|
||||||
|
"SETSPEED_SPEED": (
|
||||||
|
255 if not main_cruise_enabled else
|
||||||
|
(40 if is_metric else 25) if (s := round(out.vCruiseCluster * (1 if is_metric else CV.KPH_TO_MPH))) > (145 if is_metric else 90) else s
|
||||||
|
),
|
||||||
|
"DISTANCE": hud.leadDistanceBars,
|
||||||
|
"DISTANCE_SPACING": 0 if not main_cruise_enabled else 1 if enabled else 3,
|
||||||
|
"DISTANCE_LEAD": 0 if not main_cruise_enabled else 2 if enabled and hud.leadVisible else 1 if hud.leadVisible else 0,
|
||||||
|
"DISTANCE_CAR": 0 if not main_cruise_enabled else 2 if enabled else 1,
|
||||||
|
"SLA_ICON": 0,
|
||||||
|
"NAV_ICON": 0,
|
||||||
|
"TARGET": 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
msg_162["LEAD"] = 0 if not main_cruise_enabled else 2 if enabled else 1
|
||||||
|
msg_162["LEAD_DISTANCE"] = msg_1b5["Longitudinal_Distance"]
|
||||||
|
|
||||||
|
return [packer.make_can_msg(msg, CAN.ECAN, data) for msg, data in [("CCNC_0x161", msg_161), ("CCNC_0x162", msg_162)]]
|
||||||
|
|
||||||
|
|
||||||
def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control,
|
def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control,
|
||||||
lead_data: CanFdLeadData, main_cruise_enabled, tuning):
|
lead_data: CanFdLeadData, main_cruise_enabled, tuning, cruise_info=None):
|
||||||
jerk = 5
|
jerk = 5
|
||||||
jn = jerk / 50
|
jn = jerk / 50
|
||||||
if not enabled or gas_override:
|
if not enabled or gas_override:
|
||||||
@@ -154,6 +253,8 @@ def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_ov
|
|||||||
"SET_ME_TMP_64": 0x64,
|
"SET_ME_TMP_64": 0x64,
|
||||||
"DISTANCE_SETTING": hud_control.leadDistanceBars,
|
"DISTANCE_SETTING": hud_control.leadDistanceBars,
|
||||||
}
|
}
|
||||||
|
if cruise_info:
|
||||||
|
values.update({s: cruise_info[s] for s in ["ACC_ObjDist", "ACC_ObjRelSpd"]})
|
||||||
|
|
||||||
return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values)
|
return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values)
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ class CarInterface(CarInterfaceBase):
|
|||||||
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_ALT_BUTTONS.value
|
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_ALT_BUTTONS.value
|
||||||
if ret.flags & HyundaiFlags.CANFD_CAMERA_SCC:
|
if ret.flags & HyundaiFlags.CANFD_CAMERA_SCC:
|
||||||
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CAMERA_SCC.value
|
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CAMERA_SCC.value
|
||||||
|
if ret.flags & HyundaiFlags.CCNC and not ret.flags & HyundaiFlags.CANFD_LKA_STEER_MSG:
|
||||||
|
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CCNC.value
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Shared configuration for non CAN-FD cars
|
# Shared configuration for non CAN-FD cars
|
||||||
|
|||||||
@@ -23,7 +23,11 @@ NO_DATES_PLATFORMS = {
|
|||||||
# CAN FD
|
# CAN FD
|
||||||
CAR.KIA_SPORTAGE_5TH_GEN,
|
CAR.KIA_SPORTAGE_5TH_GEN,
|
||||||
CAR.HYUNDAI_SANTA_CRUZ_1ST_GEN,
|
CAR.HYUNDAI_SANTA_CRUZ_1ST_GEN,
|
||||||
|
CAR.HYUNDAI_SANTA_CRUZ_2025,
|
||||||
CAR.HYUNDAI_TUCSON_4TH_GEN,
|
CAR.HYUNDAI_TUCSON_4TH_GEN,
|
||||||
|
CAR.HYUNDAI_TUCSON_2025,
|
||||||
|
CAR.HYUNDAI_TUCSON_HEV_2025,
|
||||||
|
CAR.HYUNDAI_TUCSON_PHEV_2025,
|
||||||
# CAN
|
# CAN
|
||||||
CAR.HYUNDAI_ELANTRA,
|
CAR.HYUNDAI_ELANTRA,
|
||||||
CAR.HYUNDAI_ELANTRA_GT_I30,
|
CAR.HYUNDAI_ELANTRA_GT_I30,
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ class HyundaiSafetyFlags(IntFlag):
|
|||||||
CANFD_LKA_STEER_MSG_ALT = 128
|
CANFD_LKA_STEER_MSG_ALT = 128
|
||||||
FCEV_GAS = 256
|
FCEV_GAS = 256
|
||||||
ALT_LIMITS_2 = 512
|
ALT_LIMITS_2 = 512
|
||||||
|
CCNC = 1024
|
||||||
|
|
||||||
|
|
||||||
# Hyundai/Kia/Genesis SCC (Smart Cruise Control) and steering architecture:
|
# Hyundai/Kia/Genesis SCC (Smart Cruise Control) and steering architecture:
|
||||||
@@ -149,6 +150,8 @@ class HyundaiFlags(IntFlag):
|
|||||||
|
|
||||||
ALT_LIMITS_2 = 2 ** 26
|
ALT_LIMITS_2 = 2 ** 26
|
||||||
|
|
||||||
|
CCNC = 2 ** 27
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class HyundaiCarDocs(CarDocs):
|
class HyundaiCarDocs(CarDocs):
|
||||||
@@ -285,6 +288,16 @@ class CAR(Platforms):
|
|||||||
CarSpecs(mass=1491, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385),
|
CarSpecs(mass=1491, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385),
|
||||||
flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.ALT_LIMITS_2,
|
flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.ALT_LIMITS_2,
|
||||||
)
|
)
|
||||||
|
HYUNDAI_KONA_2ND_GEN = HyundaiCanFDPlatformConfig(
|
||||||
|
[HyundaiCarDocs("Hyundai Kona (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_l]))],
|
||||||
|
CarSpecs(mass=1590, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385),
|
||||||
|
flags=HyundaiFlags.CCNC,
|
||||||
|
)
|
||||||
|
HYUNDAI_KONA_HEV_2ND_GEN = HyundaiCanFDPlatformConfig(
|
||||||
|
[HyundaiCarDocs("Hyundai Kona Hybrid (without HDA II) 2024", car_parts=CarParts.common([CarHarness.hyundai_l]))],
|
||||||
|
CarSpecs(mass=1590, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385),
|
||||||
|
flags=HyundaiFlags.CCNC,
|
||||||
|
)
|
||||||
HYUNDAI_KONA_EV = HyundaiPlatformConfig(
|
HYUNDAI_KONA_EV = HyundaiPlatformConfig(
|
||||||
[HyundaiCarDocs("Hyundai Kona Electric 2018-21", car_parts=CarParts.common([CarHarness.hyundai_g]))],
|
[HyundaiCarDocs("Hyundai Kona Electric 2018-21", car_parts=CarParts.common([CarHarness.hyundai_g]))],
|
||||||
CarSpecs(mass=1685, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385),
|
CarSpecs(mass=1685, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385),
|
||||||
@@ -296,10 +309,13 @@ class CAR(Platforms):
|
|||||||
flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.EV | HyundaiFlags.ALT_LIMITS,
|
flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.EV | HyundaiFlags.ALT_LIMITS,
|
||||||
)
|
)
|
||||||
HYUNDAI_KONA_EV_2ND_GEN = HyundaiCanFDPlatformConfig(
|
HYUNDAI_KONA_EV_2ND_GEN = HyundaiCanFDPlatformConfig(
|
||||||
[HyundaiCarDocs("Hyundai Kona Electric (with HDA II, Korea only) 2023", video="https://www.youtube.com/watch?v=U2fOCmcQ8hw",
|
[
|
||||||
car_parts=CarParts.common([CarHarness.hyundai_r]))],
|
HyundaiCarDocs("Hyundai Kona Electric (with HDA II, Korea only) 2023", video="https://www.youtube.com/watch?v=U2fOCmcQ8hw",
|
||||||
|
car_parts=CarParts.common([CarHarness.hyundai_r])),
|
||||||
|
HyundaiCarDocs("Hyundai Kona Electric (without HDA II) 2024", car_parts=CarParts.common([CarHarness.hyundai_a])),
|
||||||
|
],
|
||||||
CarSpecs(mass=1740, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385),
|
CarSpecs(mass=1740, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385),
|
||||||
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE,
|
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE | HyundaiFlags.CCNC,
|
||||||
)
|
)
|
||||||
HYUNDAI_KONA_HEV = HyundaiPlatformConfig(
|
HYUNDAI_KONA_HEV = HyundaiPlatformConfig(
|
||||||
[HyundaiCarDocs("Hyundai Kona Hybrid 2020", car_parts=CarParts.common([CarHarness.hyundai_i]))], # TODO: check packages,
|
[HyundaiCarDocs("Hyundai Kona Hybrid 2020", car_parts=CarParts.common([CarHarness.hyundai_i]))], # TODO: check packages,
|
||||||
@@ -339,6 +355,11 @@ class CAR(Platforms):
|
|||||||
CarSpecs(mass=1513, wheelbase=2.84, steerRatio=13.27 * 1.15, tireStiffnessFactor=0.65), # 15% higher at the center seems reasonable
|
CarSpecs(mass=1513, wheelbase=2.84, steerRatio=13.27 * 1.15, tireStiffnessFactor=0.65), # 15% higher at the center seems reasonable
|
||||||
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8,
|
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8,
|
||||||
)
|
)
|
||||||
|
HYUNDAI_SONATA_2024 = HyundaiCanFDPlatformConfig(
|
||||||
|
[HyundaiCarDocs("Hyundai Sonata (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||||
|
CarSpecs(mass=1556, wheelbase=2.84, steerRatio=12.81),
|
||||||
|
flags=HyundaiFlags.CCNC,
|
||||||
|
)
|
||||||
HYUNDAI_SONATA_LF = HyundaiPlatformConfig(
|
HYUNDAI_SONATA_LF = HyundaiPlatformConfig(
|
||||||
[HyundaiCarDocs("Hyundai Sonata 2018-19", car_parts=CarParts.common([CarHarness.hyundai_e]))],
|
[HyundaiCarDocs("Hyundai Sonata 2018-19", car_parts=CarParts.common([CarHarness.hyundai_e]))],
|
||||||
CarSpecs(mass=1536, wheelbase=2.804, steerRatio=13.27 * 1.15), # 15% higher at the center seems reasonable
|
CarSpecs(mass=1536, wheelbase=2.804, steerRatio=13.27 * 1.15), # 15% higher at the center seems reasonable
|
||||||
@@ -374,6 +395,11 @@ class CAR(Platforms):
|
|||||||
HYUNDAI_SONATA.specs,
|
HYUNDAI_SONATA.specs,
|
||||||
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID,
|
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID,
|
||||||
)
|
)
|
||||||
|
HYUNDAI_SONATA_HEV_2024 = HyundaiCanFDPlatformConfig(
|
||||||
|
[HyundaiCarDocs("Hyundai Sonata Hybrid (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||||
|
CarSpecs(mass=1616, wheelbase=2.84, steerRatio=13.27),
|
||||||
|
flags=HyundaiFlags.CCNC,
|
||||||
|
)
|
||||||
HYUNDAI_IONIQ_5 = HyundaiCanFDPlatformConfig(
|
HYUNDAI_IONIQ_5 = HyundaiCanFDPlatformConfig(
|
||||||
[
|
[
|
||||||
HyundaiCarDocs("Hyundai Ioniq 5 (Southeast Asia and Europe only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_q])),
|
HyundaiCarDocs("Hyundai Ioniq 5 (Southeast Asia and Europe only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_q])),
|
||||||
@@ -383,6 +409,11 @@ class CAR(Platforms):
|
|||||||
CarSpecs(mass=1948, wheelbase=2.97, steerRatio=14.26, tireStiffnessFactor=0.65),
|
CarSpecs(mass=1948, wheelbase=2.97, steerRatio=14.26, tireStiffnessFactor=0.65),
|
||||||
flags=HyundaiFlags.EV,
|
flags=HyundaiFlags.EV,
|
||||||
)
|
)
|
||||||
|
HYUNDAI_IONIQ_5_N = HyundaiCanFDPlatformConfig(
|
||||||
|
[HyundaiCarDocs("Hyundai Ioniq 5 N (with HDA II) 2024", car_parts=CarParts.common([CarHarness.hyundai_s]))],
|
||||||
|
CarSpecs(mass=2205, wheelbase=3.00, steerRatio=14.26, tireStiffnessFactor=1.3),
|
||||||
|
flags=HyundaiFlags.EV | HyundaiFlags.CCNC,
|
||||||
|
)
|
||||||
HYUNDAI_IONIQ_6 = HyundaiCanFDPlatformConfig(
|
HYUNDAI_IONIQ_6 = HyundaiCanFDPlatformConfig(
|
||||||
[
|
[
|
||||||
HyundaiCarDocs("Hyundai Ioniq 6 (without HDA II) 2023-24", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_l])),
|
HyundaiCarDocs("Hyundai Ioniq 6 (without HDA II) 2023-24", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_l])),
|
||||||
@@ -400,11 +431,31 @@ class CAR(Platforms):
|
|||||||
],
|
],
|
||||||
CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385),
|
CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385),
|
||||||
)
|
)
|
||||||
|
HYUNDAI_TUCSON_2025 = HyundaiCanFDPlatformConfig(
|
||||||
|
[HyundaiCarDocs("Hyundai Tucson (without HDA II) 2025-26", car_parts=CarParts.common([CarHarness.hyundai_n]))],
|
||||||
|
CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385),
|
||||||
|
flags=HyundaiFlags.CCNC,
|
||||||
|
)
|
||||||
|
HYUNDAI_TUCSON_HEV_2025 = HyundaiCanFDPlatformConfig(
|
||||||
|
[HyundaiCarDocs("Hyundai Tucson Hybrid (without HDA II) 2025-26", car_parts=CarParts.common([CarHarness.hyundai_n]))],
|
||||||
|
CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385),
|
||||||
|
flags=HyundaiFlags.CCNC,
|
||||||
|
)
|
||||||
|
HYUNDAI_TUCSON_PHEV_2025 = HyundaiCanFDPlatformConfig(
|
||||||
|
[HyundaiCarDocs("Hyundai Tucson Plug-in Hybrid (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_n]))],
|
||||||
|
CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385),
|
||||||
|
flags=HyundaiFlags.CCNC,
|
||||||
|
)
|
||||||
HYUNDAI_SANTA_CRUZ_1ST_GEN = HyundaiCanFDPlatformConfig(
|
HYUNDAI_SANTA_CRUZ_1ST_GEN = HyundaiCanFDPlatformConfig(
|
||||||
[HyundaiCarDocs("Hyundai Santa Cruz 2022-24", car_parts=CarParts.common([CarHarness.hyundai_n]))],
|
[HyundaiCarDocs("Hyundai Santa Cruz 2022-24", car_parts=CarParts.common([CarHarness.hyundai_n]))],
|
||||||
# weight from Limited trim - the only supported trim, steering ratio according to Hyundai News https://www.hyundainews.com/assets/documents/original/48035-2022SantaCruzProductGuideSpecsv2081521.pdf
|
# weight from Limited trim - the only supported trim, steering ratio according to Hyundai News https://www.hyundainews.com/assets/documents/original/48035-2022SantaCruzProductGuideSpecsv2081521.pdf
|
||||||
CarSpecs(mass=1870, wheelbase=3, steerRatio=14.2),
|
CarSpecs(mass=1870, wheelbase=3, steerRatio=14.2),
|
||||||
)
|
)
|
||||||
|
HYUNDAI_SANTA_CRUZ_2025 = HyundaiCanFDPlatformConfig(
|
||||||
|
[HyundaiCarDocs("Hyundai Santa Cruz (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_n]))],
|
||||||
|
CarSpecs(mass=1920, wheelbase=3, steerRatio=14.2),
|
||||||
|
flags=HyundaiFlags.CCNC,
|
||||||
|
)
|
||||||
HYUNDAI_CUSTIN_1ST_GEN = HyundaiPlatformConfig(
|
HYUNDAI_CUSTIN_1ST_GEN = HyundaiPlatformConfig(
|
||||||
[HyundaiCarDocs("Hyundai Custin 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))],
|
[HyundaiCarDocs("Hyundai Custin 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))],
|
||||||
CarSpecs(mass=1690, wheelbase=3.055, steerRatio=17), # mass: from https://www.hyundai-motor.com.tw/clicktobuy/custin#spec_0, steerRatio: from learner
|
CarSpecs(mass=1690, wheelbase=3.055, steerRatio=17), # mass: from https://www.hyundai-motor.com.tw/clicktobuy/custin#spec_0, steerRatio: from learner
|
||||||
@@ -419,11 +470,24 @@ class CAR(Platforms):
|
|||||||
],
|
],
|
||||||
CarSpecs(mass=2878 * CV.LB_TO_KG, wheelbase=2.8, steerRatio=13.75, tireStiffnessFactor=0.5)
|
CarSpecs(mass=2878 * CV.LB_TO_KG, wheelbase=2.8, steerRatio=13.75, tireStiffnessFactor=0.5)
|
||||||
)
|
)
|
||||||
|
KIA_K4_2025 = HyundaiCanFDPlatformConfig(
|
||||||
|
[
|
||||||
|
HyundaiCarDocs("Kia K4 (without HDA II) 2025-26", car_parts=CarParts.common([CarHarness.hyundai_a])),
|
||||||
|
HyundaiCarDocs("Kia K4 (with HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_r])),
|
||||||
|
],
|
||||||
|
CarSpecs(mass=2987 * CV.LB_TO_KG, wheelbase=2.72, steerRatio=13.4),
|
||||||
|
flags=HyundaiFlags.CCNC,
|
||||||
|
)
|
||||||
KIA_K5_2021 = HyundaiPlatformConfig(
|
KIA_K5_2021 = HyundaiPlatformConfig(
|
||||||
[HyundaiCarDocs("Kia K5 2021-24", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
[HyundaiCarDocs("Kia K5 2021-24", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||||
CarSpecs(mass=3381 * CV.LB_TO_KG, wheelbase=2.85, steerRatio=13.27, tireStiffnessFactor=0.5), # 2021 Kia K5 Steering Ratio (all trims)
|
CarSpecs(mass=3381 * CV.LB_TO_KG, wheelbase=2.85, steerRatio=13.27, tireStiffnessFactor=0.5), # 2021 Kia K5 Steering Ratio (all trims)
|
||||||
flags=HyundaiFlags.CHECKSUM_CRC8,
|
flags=HyundaiFlags.CHECKSUM_CRC8,
|
||||||
)
|
)
|
||||||
|
KIA_K5_2025 = HyundaiCanFDPlatformConfig(
|
||||||
|
[HyundaiCarDocs("Kia K5 (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_m]))],
|
||||||
|
CarSpecs(mass=3230 * CV.LB_TO_KG, wheelbase=2.85, steerRatio=13.27),
|
||||||
|
flags=HyundaiFlags.CCNC,
|
||||||
|
)
|
||||||
KIA_K5_HEV_2020 = HyundaiPlatformConfig(
|
KIA_K5_HEV_2020 = HyundaiPlatformConfig(
|
||||||
[HyundaiCarDocs("Kia K5 Hybrid 2020-22", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
[HyundaiCarDocs("Kia K5 Hybrid 2020-22", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||||
KIA_K5_2021.specs,
|
KIA_K5_2021.specs,
|
||||||
@@ -534,6 +598,11 @@ class CAR(Platforms):
|
|||||||
CarSpecs(mass=3957 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5), # average of the platforms
|
CarSpecs(mass=3957 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5), # average of the platforms
|
||||||
flags=HyundaiFlags.CANFD_RADAR_SCC,
|
flags=HyundaiFlags.CANFD_RADAR_SCC,
|
||||||
)
|
)
|
||||||
|
KIA_SORENTO_2024 = HyundaiCanFDPlatformConfig(
|
||||||
|
[HyundaiCarDocs("Kia Sorento (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_a]))],
|
||||||
|
CarSpecs(mass=3957 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5),
|
||||||
|
flags=HyundaiFlags.CCNC,
|
||||||
|
)
|
||||||
KIA_SORENTO_HEV_4TH_GEN = HyundaiCanFDPlatformConfig(
|
KIA_SORENTO_HEV_4TH_GEN = HyundaiCanFDPlatformConfig(
|
||||||
[
|
[
|
||||||
HyundaiCarDocs("Kia Sorento Hybrid 2021-23", "All", car_parts=CarParts.common([CarHarness.hyundai_a])),
|
HyundaiCarDocs("Kia Sorento Hybrid 2021-23", "All", car_parts=CarParts.common([CarHarness.hyundai_a])),
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ non_tested_cars = [
|
|||||||
SUBARU.SUBARU_FORESTER_HYBRID,
|
SUBARU.SUBARU_FORESTER_HYBRID,
|
||||||
VOLKSWAGEN.PORSCHE_MACAN_MK1,
|
VOLKSWAGEN.PORSCHE_MACAN_MK1,
|
||||||
HONDA.ACURA_TLX_2G,
|
HONDA.ACURA_TLX_2G,
|
||||||
|
HYUNDAI.KIA_SORENTO_2024,
|
||||||
|
HYUNDAI.HYUNDAI_IONIQ_5_N,
|
||||||
|
HYUNDAI.HYUNDAI_TUCSON_PHEV_2025,
|
||||||
|
|
||||||
# These had their DSUs unplugged, need new routes
|
# These had their DSUs unplugged, need new routes
|
||||||
# TOYOTA.LEXUS_ES # hybrid
|
# TOYOTA.LEXUS_ES # hybrid
|
||||||
@@ -166,6 +169,7 @@ routes = [
|
|||||||
CarTestRoute("66eaa6c3b6b2afc6/00000009--3a5199aabe", HYUNDAI.GENESIS_G80_2ND_GEN_FL), # LKA steering
|
CarTestRoute("66eaa6c3b6b2afc6/00000009--3a5199aabe", HYUNDAI.GENESIS_G80_2ND_GEN_FL), # LKA steering
|
||||||
CarTestRoute("0bbe367c98fa1538/2023-09-16--00-16-49", HYUNDAI.HYUNDAI_CUSTIN_1ST_GEN),
|
CarTestRoute("0bbe367c98fa1538/2023-09-16--00-16-49", HYUNDAI.HYUNDAI_CUSTIN_1ST_GEN),
|
||||||
CarTestRoute("f0709d2bc6ca451f/2022-10-15--08-13-54", HYUNDAI.HYUNDAI_SANTA_CRUZ_1ST_GEN),
|
CarTestRoute("f0709d2bc6ca451f/2022-10-15--08-13-54", HYUNDAI.HYUNDAI_SANTA_CRUZ_1ST_GEN),
|
||||||
|
CarTestRoute("6e7904b03a4aafc2/00000010--31034184b6", HYUNDAI.HYUNDAI_SANTA_CRUZ_2025),
|
||||||
CarTestRoute("4dbd55df87507948/2022-03-01--09-45-38", HYUNDAI.HYUNDAI_SANTA_FE),
|
CarTestRoute("4dbd55df87507948/2022-03-01--09-45-38", HYUNDAI.HYUNDAI_SANTA_FE),
|
||||||
CarTestRoute("bf43d9df2b660eb0/2021-09-23--14-16-37", HYUNDAI.HYUNDAI_SANTA_FE_2022),
|
CarTestRoute("bf43d9df2b660eb0/2021-09-23--14-16-37", HYUNDAI.HYUNDAI_SANTA_FE_2022),
|
||||||
CarTestRoute("37398f32561a23ad/2021-11-18--00-11-35", HYUNDAI.HYUNDAI_SANTA_FE_HEV_2022),
|
CarTestRoute("37398f32561a23ad/2021-11-18--00-11-35", HYUNDAI.HYUNDAI_SANTA_FE_HEV_2022),
|
||||||
@@ -179,11 +183,14 @@ routes = [
|
|||||||
CarTestRoute("6a42c1197b2a8179/2023-09-21--10-23-44", HYUNDAI.KIA_OPTIMA_H_G4_FL),
|
CarTestRoute("6a42c1197b2a8179/2023-09-21--10-23-44", HYUNDAI.KIA_OPTIMA_H_G4_FL),
|
||||||
CarTestRoute("c75a59efa0ecd502/2021-03-11--20-52-55", HYUNDAI.KIA_SELTOS),
|
CarTestRoute("c75a59efa0ecd502/2021-03-11--20-52-55", HYUNDAI.KIA_SELTOS),
|
||||||
CarTestRoute("5b7c365c50084530/2020-04-15--16-13-24", HYUNDAI.HYUNDAI_SONATA),
|
CarTestRoute("5b7c365c50084530/2020-04-15--16-13-24", HYUNDAI.HYUNDAI_SONATA),
|
||||||
|
CarTestRoute("4267ea8a353cdb36/00000262--8a427003c7", HYUNDAI.HYUNDAI_SONATA_2024, segment=34),
|
||||||
CarTestRoute("b2a38c712dcf90bd/2020-05-18--18-12-48", HYUNDAI.HYUNDAI_SONATA_LF),
|
CarTestRoute("b2a38c712dcf90bd/2020-05-18--18-12-48", HYUNDAI.HYUNDAI_SONATA_LF),
|
||||||
CarTestRoute("c344fd2492c7a9d2/2023-12-11--09-03-23", HYUNDAI.HYUNDAI_STARIA_4TH_GEN),
|
CarTestRoute("c344fd2492c7a9d2/2023-12-11--09-03-23", HYUNDAI.HYUNDAI_STARIA_4TH_GEN),
|
||||||
CarTestRoute("fb3fd42f0baaa2f8/2022-03-30--15-25-05", HYUNDAI.HYUNDAI_TUCSON),
|
CarTestRoute("fb3fd42f0baaa2f8/2022-03-30--15-25-05", HYUNDAI.HYUNDAI_TUCSON),
|
||||||
CarTestRoute("db68bbe12250812c/2022-12-05--00-54-12", HYUNDAI.HYUNDAI_TUCSON_4TH_GEN), # 2023
|
CarTestRoute("db68bbe12250812c/2022-12-05--00-54-12", HYUNDAI.HYUNDAI_TUCSON_4TH_GEN), # 2023
|
||||||
CarTestRoute("36e10531feea61a4/2022-07-25--13-37-42", HYUNDAI.HYUNDAI_TUCSON_4TH_GEN), # hybrid
|
CarTestRoute("36e10531feea61a4/2022-07-25--13-37-42", HYUNDAI.HYUNDAI_TUCSON_4TH_GEN), # hybrid
|
||||||
|
CarTestRoute("a01ca5d4f394c812/00000000--e98b7e4414", HYUNDAI.HYUNDAI_TUCSON_2025),
|
||||||
|
CarTestRoute("22f9090014364a87/00000002--4cc739c0b2", HYUNDAI.HYUNDAI_TUCSON_HEV_2025),
|
||||||
CarTestRoute("5875672fc1d4bf57/2020-07-23--21-33-28", HYUNDAI.KIA_SORENTO),
|
CarTestRoute("5875672fc1d4bf57/2020-07-23--21-33-28", HYUNDAI.KIA_SORENTO),
|
||||||
CarTestRoute("1d0d000db3370fd0/2023-01-04--22-28-42", HYUNDAI.KIA_SORENTO_4TH_GEN, segment=5),
|
CarTestRoute("1d0d000db3370fd0/2023-01-04--22-28-42", HYUNDAI.KIA_SORENTO_4TH_GEN, segment=5),
|
||||||
CarTestRoute("fc19648042eb6896/2023-08-16--11-43-27", HYUNDAI.KIA_SORENTO_HEV_4TH_GEN, segment=14),
|
CarTestRoute("fc19648042eb6896/2023-08-16--11-43-27", HYUNDAI.KIA_SORENTO_HEV_4TH_GEN, segment=14),
|
||||||
@@ -201,6 +208,8 @@ routes = [
|
|||||||
CarTestRoute("ab59fe909f626921/2021-10-18--18-34-28", HYUNDAI.HYUNDAI_IONIQ_HEV_2022),
|
CarTestRoute("ab59fe909f626921/2021-10-18--18-34-28", HYUNDAI.HYUNDAI_IONIQ_HEV_2022),
|
||||||
CarTestRoute("22d955b2cd499c22/2020-08-10--19-58-21", HYUNDAI.HYUNDAI_KONA),
|
CarTestRoute("22d955b2cd499c22/2020-08-10--19-58-21", HYUNDAI.HYUNDAI_KONA),
|
||||||
CarTestRoute("0099bdb24d82951b/00000005--c38d940b04", HYUNDAI.HYUNDAI_KONA_2022),
|
CarTestRoute("0099bdb24d82951b/00000005--c38d940b04", HYUNDAI.HYUNDAI_KONA_2022),
|
||||||
|
CarTestRoute("32025f26789d8fab/00000022--a499e8ffa3", HYUNDAI.HYUNDAI_KONA_2ND_GEN),
|
||||||
|
CarTestRoute("97ca61196eb73e0d/00000052--4555329470", HYUNDAI.HYUNDAI_KONA_HEV_2ND_GEN),
|
||||||
CarTestRoute("efc48acf44b1e64d/2021-05-28--21-05-04", HYUNDAI.HYUNDAI_KONA_EV),
|
CarTestRoute("efc48acf44b1e64d/2021-05-28--21-05-04", HYUNDAI.HYUNDAI_KONA_EV),
|
||||||
CarTestRoute("f90d3cd06caeb6fa/2023-09-06--17-15-47", HYUNDAI.HYUNDAI_KONA_EV), # openpilot longitudinal enabled
|
CarTestRoute("f90d3cd06caeb6fa/2023-09-06--17-15-47", HYUNDAI.HYUNDAI_KONA_EV), # openpilot longitudinal enabled
|
||||||
CarTestRoute("ff973b941a69366f/2022-07-28--22-01-19", HYUNDAI.HYUNDAI_KONA_EV_2022, segment=11),
|
CarTestRoute("ff973b941a69366f/2022-07-28--22-01-19", HYUNDAI.HYUNDAI_KONA_EV_2022, segment=11),
|
||||||
@@ -214,7 +223,9 @@ routes = [
|
|||||||
CarTestRoute("d545129f3ca90f28/2022-10-19--09-22-54", HYUNDAI.KIA_EV6), # LKA steering
|
CarTestRoute("d545129f3ca90f28/2022-10-19--09-22-54", HYUNDAI.KIA_EV6), # LKA steering
|
||||||
CarTestRoute("68d6a96e703c00c9/2022-09-10--16-09-39", HYUNDAI.KIA_EV6), # LFA steering
|
CarTestRoute("68d6a96e703c00c9/2022-09-10--16-09-39", HYUNDAI.KIA_EV6), # LFA steering
|
||||||
CarTestRoute("9b25e8c1484a1b67/2023-04-13--10-41-45", HYUNDAI.KIA_EV6),
|
CarTestRoute("9b25e8c1484a1b67/2023-04-13--10-41-45", HYUNDAI.KIA_EV6),
|
||||||
|
CarTestRoute("baf39eeaba1217ca/00000002--b36e3fa031", HYUNDAI.KIA_K4_2025),
|
||||||
CarTestRoute("007d5e4ad9f86d13/2021-09-30--15-09-23", HYUNDAI.KIA_K5_2021),
|
CarTestRoute("007d5e4ad9f86d13/2021-09-30--15-09-23", HYUNDAI.KIA_K5_2021),
|
||||||
|
CarTestRoute("c4a804b067623789/0000007c--163f831540", HYUNDAI.KIA_K5_2025),
|
||||||
CarTestRoute("c58dfc9fc16590e0/2023-01-14--13-51-48", HYUNDAI.KIA_K5_HEV_2020),
|
CarTestRoute("c58dfc9fc16590e0/2023-01-14--13-51-48", HYUNDAI.KIA_K5_HEV_2020),
|
||||||
CarTestRoute("74fbff45aa20fe9e/00000010--6f173d5799", HYUNDAI.KIA_K7_2017),
|
CarTestRoute("74fbff45aa20fe9e/00000010--6f173d5799", HYUNDAI.KIA_K7_2017),
|
||||||
CarTestRoute("78ad5150de133637/2023-09-13--16-15-57", HYUNDAI.KIA_K8_HEV_1ST_GEN),
|
CarTestRoute("78ad5150de133637/2023-09-13--16-15-57", HYUNDAI.KIA_K8_HEV_1ST_GEN),
|
||||||
@@ -233,6 +244,7 @@ routes = [
|
|||||||
CarTestRoute("82e9cdd3f43bf83e/2021-05-15--02-42-51", HYUNDAI.HYUNDAI_ELANTRA_2021),
|
CarTestRoute("82e9cdd3f43bf83e/2021-05-15--02-42-51", HYUNDAI.HYUNDAI_ELANTRA_2021),
|
||||||
CarTestRoute("715ac05b594e9c59/2021-06-20--16-21-07", HYUNDAI.HYUNDAI_ELANTRA_HEV_2021),
|
CarTestRoute("715ac05b594e9c59/2021-06-20--16-21-07", HYUNDAI.HYUNDAI_ELANTRA_HEV_2021),
|
||||||
CarTestRoute("7120aa90bbc3add7/2021-08-02--07-12-31", HYUNDAI.HYUNDAI_SONATA_HYBRID),
|
CarTestRoute("7120aa90bbc3add7/2021-08-02--07-12-31", HYUNDAI.HYUNDAI_SONATA_HYBRID),
|
||||||
|
CarTestRoute("bc40c72b728178f2/00000006--ee76ae8c42", HYUNDAI.HYUNDAI_SONATA_HEV_2024),
|
||||||
CarTestRoute("715ac05b594e9c59/2021-10-27--23-24-56", HYUNDAI.GENESIS_G70_2020),
|
CarTestRoute("715ac05b594e9c59/2021-10-27--23-24-56", HYUNDAI.GENESIS_G70_2020),
|
||||||
CarTestRoute("6b0d44d22df18134/2023-05-06--10-36-55", HYUNDAI.GENESIS_GV80),
|
CarTestRoute("6b0d44d22df18134/2023-05-06--10-36-55", HYUNDAI.GENESIS_GV80),
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,13 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
|||||||
"JEEP_CHEROKEE_5TH_GEN" = [1.5, 1.5, 0.15]
|
"JEEP_CHEROKEE_5TH_GEN" = [1.5, 1.5, 0.15]
|
||||||
"ACURA_MDX_4G" = [1.4, 1.4, 0.17]
|
"ACURA_MDX_4G" = [1.4, 1.4, 0.17]
|
||||||
"ACURA_RDX_3G_MMR" = [1.5, 1.5, 0.16]
|
"ACURA_RDX_3G_MMR" = [1.5, 1.5, 0.16]
|
||||||
|
"HYUNDAI_KONA_2ND_GEN" = [2.5, 2.5, 0.1]
|
||||||
|
"HYUNDAI_KONA_HEV_2ND_GEN" = [2.5, 2.5, 0.1]
|
||||||
|
"KIA_SORENTO_2024" = [2.5, 2.5, 0.1]
|
||||||
|
"KIA_K5_2025" = [2.5, 2.5, 0.1]
|
||||||
|
"KIA_K4_2025" = [2.5, 2.5, 0.1]
|
||||||
|
"HYUNDAI_SANTA_CRUZ_2025" = [2.5, 2.5, 0.1]
|
||||||
|
"HYUNDAI_IONIQ_5_N" = [2.5, 2.5, 0.005]
|
||||||
|
|
||||||
# Dashcam or fallback configured as ideal car
|
# Dashcam or fallback configured as ideal car
|
||||||
"MOCK" = [10.0, 10, 0.0]
|
"MOCK" = [10.0, 10, 0.0]
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
|||||||
"GENESIS_G90" = "GENESIS_G70"
|
"GENESIS_G90" = "GENESIS_G70"
|
||||||
"GENESIS_G80" = "GENESIS_G70"
|
"GENESIS_G80" = "GENESIS_G70"
|
||||||
"GENESIS_G70_2020" = "HYUNDAI_SONATA"
|
"GENESIS_G70_2020" = "HYUNDAI_SONATA"
|
||||||
|
"HYUNDAI_SONATA_2024" = "HYUNDAI_SONATA"
|
||||||
|
"HYUNDAI_SONATA_HEV_2024" = "HYUNDAI_SONATA_HYBRID"
|
||||||
|
"HYUNDAI_TUCSON_2025" = "HYUNDAI_TUCSON_4TH_GEN"
|
||||||
|
"HYUNDAI_TUCSON_HEV_2025" = "HYUNDAI_TUCSON_4TH_GEN"
|
||||||
|
"HYUNDAI_TUCSON_PHEV_2025" = "HYUNDAI_TUCSON_4TH_GEN"
|
||||||
|
|
||||||
"HONDA_FREED" = "HONDA_ODYSSEY"
|
"HONDA_FREED" = "HONDA_ODYSSEY"
|
||||||
"HONDA_CRV_EU" = "HONDA_CRV"
|
"HONDA_CRV_EU" = "HONDA_CRV"
|
||||||
|
|||||||
@@ -951,7 +951,7 @@ CM_ SG_ 1041 COUNTER_ALT "only increments on change";
|
|||||||
CM_ BO_ 1043 "Lamp signals do not seem universal on cars that use LKAS_ALT, but stalk signals do.";
|
CM_ BO_ 1043 "Lamp signals do not seem universal on cars that use LKAS_ALT, but stalk signals do.";
|
||||||
CM_ SG_ 1043 COUNTER_ALT "only increments on change";
|
CM_ SG_ 1043 COUNTER_ALT "only increments on change";
|
||||||
CM_ SG_ 1043 USE_ALT_LAMP "likely 1 on cars that use alt lamp signals";
|
CM_ SG_ 1043 USE_ALT_LAMP "likely 1 on cars that use alt lamp signals";
|
||||||
VAL_ 53 GEAR 0 "P" 5 "D" 6 "N" 7 "R";
|
VAL_ 53 GEAR 0 "P" 4 "S" 5 "D" 6 "N" 7 "R";
|
||||||
VAL_ 64 GEAR 0 "P" 5 "D" 6 "N" 7 "R";
|
VAL_ 64 GEAR 0 "P" 5 "D" 6 "N" 7 "R";
|
||||||
VAL_ 69 GEAR 0 "P" 5 "D" 6 "N" 7 "R";
|
VAL_ 69 GEAR 0 "P" 5 "D" 6 "N" 7 "R";
|
||||||
VAL_ 96 TRACTION_AND_STABILITY_CONTROL 0 "On" 5 "Limited" 1 "Off";
|
VAL_ 96 TRACTION_AND_STABILITY_CONTROL 0 "On" 5 "Limited" 1 "Off";
|
||||||
|
|||||||
@@ -47,6 +47,11 @@
|
|||||||
|
|
||||||
static bool hyundai_canfd_alt_buttons = false;
|
static bool hyundai_canfd_alt_buttons = false;
|
||||||
static bool hyundai_canfd_lka_steer_msg_alt = false;
|
static bool hyundai_canfd_lka_steer_msg_alt = false;
|
||||||
|
static bool hyundai_ccnc = false;
|
||||||
|
|
||||||
|
static bool get_hyundai_ccnc(void) {
|
||||||
|
return hyundai_ccnc;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int hyundai_canfd_get_lka_addr(void) {
|
static unsigned int hyundai_canfd_get_lka_addr(void) {
|
||||||
return hyundai_canfd_lka_steer_msg_alt ? 0x110U : 0x50U;
|
return hyundai_canfd_lka_steer_msg_alt ? 0x110U : 0x50U;
|
||||||
@@ -227,6 +232,7 @@ static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) {
|
|||||||
static safety_config hyundai_canfd_init(uint16_t param) {
|
static safety_config hyundai_canfd_init(uint16_t param) {
|
||||||
const uint16_t HYUNDAI_PARAM_CANFD_LKA_STEER_MSG_ALT = 128;
|
const uint16_t HYUNDAI_PARAM_CANFD_LKA_STEER_MSG_ALT = 128;
|
||||||
const uint16_t HYUNDAI_PARAM_CANFD_ALT_BUTTONS = 32;
|
const uint16_t HYUNDAI_PARAM_CANFD_ALT_BUTTONS = 32;
|
||||||
|
const uint16_t HYUNDAI_PARAM_CCNC = 1024;
|
||||||
|
|
||||||
static const CanMsg HYUNDAI_CANFD_LKA_STEER_MSG_TX_MSGS[] = {
|
static const CanMsg HYUNDAI_CANFD_LKA_STEER_MSG_TX_MSGS[] = {
|
||||||
HYUNDAI_CANFD_LKA_STEER_MSG_COMMON_TX_MSGS(0, 1)
|
HYUNDAI_CANFD_LKA_STEER_MSG_COMMON_TX_MSGS(0, 1)
|
||||||
@@ -271,11 +277,21 @@ static safety_config hyundai_canfd_init(uint16_t param) {
|
|||||||
HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, (longitudinal)) \
|
HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, (longitudinal)) \
|
||||||
{0x160, 0, 16, .check_relay = (longitudinal)}, /* ADRV_0x160 */ \
|
{0x160, 0, 16, .check_relay = (longitudinal)}, /* ADRV_0x160 */ \
|
||||||
|
|
||||||
|
#define HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_CCNC_TX_MSGS(longitudinal) \
|
||||||
|
HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(2) \
|
||||||
|
HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(0) \
|
||||||
|
HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, (longitudinal)) \
|
||||||
|
{0x161, 0, 32, .check_relay = true}, /* CCNC_0x161 */ \
|
||||||
|
{0x162, 0, 32, .check_relay = true}, /* CCNC_0x162 */ \
|
||||||
|
{0x7C4, 2, 8, .check_relay = true}, /* 0x7C4 */ \
|
||||||
|
{0xEA, 2, 24, .check_relay = true}, /* MDPS */ \
|
||||||
|
|
||||||
hyundai_common_init(param);
|
hyundai_common_init(param);
|
||||||
|
|
||||||
gen_crc_lookup_table_16(0x1021, hyundai_canfd_crc_lut);
|
gen_crc_lookup_table_16(0x1021, hyundai_canfd_crc_lut);
|
||||||
hyundai_canfd_alt_buttons = GET_FLAG(param, HYUNDAI_PARAM_CANFD_ALT_BUTTONS);
|
hyundai_canfd_alt_buttons = GET_FLAG(param, HYUNDAI_PARAM_CANFD_ALT_BUTTONS);
|
||||||
hyundai_canfd_lka_steer_msg_alt = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEER_MSG_ALT);
|
hyundai_canfd_lka_steer_msg_alt = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEER_MSG_ALT);
|
||||||
|
hyundai_ccnc = GET_FLAG(param, HYUNDAI_PARAM_CCNC);
|
||||||
|
|
||||||
safety_config ret;
|
safety_config ret;
|
||||||
if (hyundai_longitudinal) {
|
if (hyundai_longitudinal) {
|
||||||
@@ -300,6 +316,10 @@ static safety_config hyundai_canfd_init(uint16_t param) {
|
|||||||
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_TX_MSGS(true)
|
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_TX_MSGS(true)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static CanMsg hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs[] = {
|
||||||
|
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_CCNC_TX_MSGS(true)
|
||||||
|
};
|
||||||
|
|
||||||
if (hyundai_canfd_alt_buttons) {
|
if (hyundai_canfd_alt_buttons) {
|
||||||
SET_RX_CHECKS(hyundai_canfd_alt_buttons_long_rx_checks, ret);
|
SET_RX_CHECKS(hyundai_canfd_alt_buttons_long_rx_checks, ret);
|
||||||
} else {
|
} else {
|
||||||
@@ -307,7 +327,11 @@ static safety_config hyundai_canfd_init(uint16_t param) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hyundai_camera_scc) {
|
if (hyundai_camera_scc) {
|
||||||
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret);
|
if (get_hyundai_ccnc()) {
|
||||||
|
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs, ret);
|
||||||
|
} else {
|
||||||
|
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
SET_TX_MSGS(HYUNDAI_CANFD_LFA_STEERING_LONG_TX_MSGS, ret);
|
SET_TX_MSGS(HYUNDAI_CANFD_LFA_STEERING_LONG_TX_MSGS, ret);
|
||||||
}
|
}
|
||||||
@@ -368,7 +392,15 @@ static safety_config hyundai_canfd_init(uint16_t param) {
|
|||||||
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_TX_MSGS(false)
|
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_TX_MSGS(false)
|
||||||
};
|
};
|
||||||
|
|
||||||
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret);
|
static CanMsg hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs[] = {
|
||||||
|
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_CCNC_TX_MSGS(false)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (get_hyundai_ccnc()) {
|
||||||
|
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs, ret);
|
||||||
|
} else {
|
||||||
|
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret);
|
||||||
|
}
|
||||||
|
|
||||||
if (hyundai_canfd_alt_buttons) {
|
if (hyundai_canfd_alt_buttons) {
|
||||||
SET_RX_CHECKS(hyundai_canfd_alt_buttons_rx_checks, ret);
|
SET_RX_CHECKS(hyundai_canfd_alt_buttons_rx_checks, ret);
|
||||||
|
|||||||
@@ -21,6 +21,13 @@ ALL_GAS_EV_HYBRID_COMBOS = [
|
|||||||
{"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS | HyundaiSafetyFlags.CAMERA_SCC},
|
{"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS | HyundaiSafetyFlags.CAMERA_SCC},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
ALL_GAS_EV_HYBRID_COMBOS_CCNC = [
|
||||||
|
# Camera SCC
|
||||||
|
{"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.CAMERA_SCC},
|
||||||
|
{"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS | HyundaiSafetyFlags.CAMERA_SCC},
|
||||||
|
{"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS | HyundaiSafetyFlags.CAMERA_SCC},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class TestHyundaiCanfdBase(HyundaiButtonBase, common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest):
|
class TestHyundaiCanfdBase(HyundaiButtonBase, common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest):
|
||||||
|
|
||||||
@@ -308,5 +315,73 @@ class TestHyundaiCanfdLFASteeringLongAltButtons(TestHyundaiCanfdLFASteeringLongB
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS_CCNC)
|
||||||
|
class TestHyundaiCanfdLFASteeringCCNC(TestHyundaiCanfdLFASteeringBase):
|
||||||
|
|
||||||
|
TX_MSGS = [[0x12A, 0], [0x1E0, 0], [0x1CF, 2], [0x7C4, 2]]
|
||||||
|
RELAY_MALFUNCTION_ADDRS = {0: (0x12A, 0x1E0, 0x161, 0x162), 2: (0x7C4, 0xEA)}
|
||||||
|
FWD_BLACKLISTED_ADDRS = {2: [0x12A, 0x1E0, 0x161, 0x162], 0: [0x7C4, 0xEA]}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
if cls.__name__ == "TestHyundaiCanfdLFASteeringCCNC":
|
||||||
|
cls.safety = None
|
||||||
|
raise unittest.SkipTest
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.packer = CANPackerSafety("hyundai_canfd_generated")
|
||||||
|
self.safety = libsafety_py.libsafety
|
||||||
|
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CCNC | self.SAFETY_PARAM)
|
||||||
|
self.safety.init_tests()
|
||||||
|
|
||||||
|
def test_ccnc(self):
|
||||||
|
self.assertTrue(self._tx(self.packer.make_can_msg_safety("CCNC_0x161", self.STEER_BUS, {})))
|
||||||
|
self.assertTrue(self._tx(self.packer.make_can_msg_safety("CCNC_0x162", self.STEER_BUS, {})))
|
||||||
|
|
||||||
|
def test_tx_hook_on_wrong_safety_mode(self):
|
||||||
|
from opendbc.safety.tests.common import make_msg
|
||||||
|
import importlib
|
||||||
|
for test_name in ["TestElm327"]:
|
||||||
|
mod = importlib.import_module("opendbc.safety.tests.test_" + test_name.replace("Test", "").lower())
|
||||||
|
tx_list = [m for m in getattr(mod, test_name).TX_MSGS if m[0] != 0x7C4] # skip overlapping 0x7C4 from Elm327
|
||||||
|
for addr, bus in tx_list:
|
||||||
|
if [addr, bus] not in self.TX_MSGS:
|
||||||
|
self.assertFalse(self._tx(make_msg(bus, addr)), f"allowed TX {addr=:#x} {bus=}")
|
||||||
|
|
||||||
|
|
||||||
|
@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS_CCNC)
|
||||||
|
class TestHyundaiCanfdLFASteeringLongCCNC(TestHyundaiCanfdLFASteeringLongBase):
|
||||||
|
|
||||||
|
TX_MSGS = [[0x12A, 0], [0x1E0, 0], [0x1CF, 2], [0x7C4, 2], [0x1A0, 0]]
|
||||||
|
RELAY_MALFUNCTION_ADDRS = {0: (0x12A, 0x1E0, 0x161, 0x162, 0x1A0), 2: (0x7C4, 0xEA)}
|
||||||
|
FWD_BLACKLISTED_ADDRS = {2: [0x12A, 0x1E0, 0x161, 0x162, 0x1A0], 0: [0x7C4, 0xEA]}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
if cls.__name__ == "TestHyundaiCanfdLFASteeringLongCCNC":
|
||||||
|
cls.safety = None
|
||||||
|
raise unittest.SkipTest
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.packer = CANPackerSafety("hyundai_canfd_generated")
|
||||||
|
self.safety = libsafety_py.libsafety
|
||||||
|
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CCNC | HyundaiSafetyFlags.LONG | self.SAFETY_PARAM)
|
||||||
|
self.safety.init_tests()
|
||||||
|
|
||||||
|
def test_ccnc(self):
|
||||||
|
self.assertTrue(self._tx(self.packer.make_can_msg_safety("CCNC_0x161", self.STEER_BUS, {})))
|
||||||
|
self.assertTrue(self._tx(self.packer.make_can_msg_safety("CCNC_0x162", self.STEER_BUS, {})))
|
||||||
|
|
||||||
|
def test_tx_hook_on_wrong_safety_mode(self):
|
||||||
|
from opendbc.safety.tests.common import make_msg
|
||||||
|
import importlib
|
||||||
|
for test_name in ["TestElm327"]:
|
||||||
|
mod = importlib.import_module("opendbc.safety.tests.test_" + test_name.replace("Test", "").lower())
|
||||||
|
tx_list = [m for m in getattr(mod, test_name).TX_MSGS if m[0] != 0x7C4] # skip overlapping 0x7C4 from Elm327
|
||||||
|
for addr, bus in tx_list:
|
||||||
|
if [addr, bus] not in self.TX_MSGS:
|
||||||
|
self.assertFalse(self._tx(make_msg(bus, addr)), f"allowed TX {addr=:#x} {bus=}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -1604,6 +1604,16 @@
|
|||||||
],
|
],
|
||||||
"package": "Highway Driving Assist"
|
"package": "Highway Driving Assist"
|
||||||
},
|
},
|
||||||
|
"Hyundai Ioniq 5 N (with HDA II) 2024": {
|
||||||
|
"platform": "HYUNDAI_IONIQ_5_N",
|
||||||
|
"make": "Hyundai",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "Ioniq 5 N (with HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2024"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
"Hyundai Ioniq 6 (with HDA II) 2023-24": {
|
"Hyundai Ioniq 6 (with HDA II) 2023-24": {
|
||||||
"platform": "HYUNDAI_IONIQ_6",
|
"platform": "HYUNDAI_IONIQ_6",
|
||||||
"make": "Hyundai",
|
"make": "Hyundai",
|
||||||
@@ -1713,6 +1723,17 @@
|
|||||||
],
|
],
|
||||||
"package": "Smart Cruise Control (SCC)"
|
"package": "Smart Cruise Control (SCC)"
|
||||||
},
|
},
|
||||||
|
"Hyundai Kona (without HDA II) 2024-25": {
|
||||||
|
"platform": "HYUNDAI_KONA_2ND_GEN",
|
||||||
|
"make": "Hyundai",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "Kona (without HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2024",
|
||||||
|
"2025"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
"Hyundai Kona Electric 2018-21": {
|
"Hyundai Kona Electric 2018-21": {
|
||||||
"platform": "HYUNDAI_KONA_EV",
|
"platform": "HYUNDAI_KONA_EV",
|
||||||
"make": "Hyundai",
|
"make": "Hyundai",
|
||||||
@@ -1747,6 +1768,16 @@
|
|||||||
],
|
],
|
||||||
"package": "Smart Cruise Control (SCC)"
|
"package": "Smart Cruise Control (SCC)"
|
||||||
},
|
},
|
||||||
|
"Hyundai Kona Electric (without HDA II) 2024": {
|
||||||
|
"platform": "HYUNDAI_KONA_EV_2ND_GEN",
|
||||||
|
"make": "Hyundai",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "Kona Electric (without HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2024"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
"Hyundai Kona Electric Non-SCC 2019": {
|
"Hyundai Kona Electric Non-SCC 2019": {
|
||||||
"platform": "HYUNDAI_KONA_EV_NON_SCC",
|
"platform": "HYUNDAI_KONA_EV_NON_SCC",
|
||||||
"make": "Hyundai",
|
"make": "Hyundai",
|
||||||
@@ -1767,6 +1798,16 @@
|
|||||||
],
|
],
|
||||||
"package": "Smart Cruise Control (SCC)"
|
"package": "Smart Cruise Control (SCC)"
|
||||||
},
|
},
|
||||||
|
"Hyundai Kona Hybrid (without HDA II) 2024": {
|
||||||
|
"platform": "HYUNDAI_KONA_HEV_2ND_GEN",
|
||||||
|
"make": "Hyundai",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "Kona Hybrid (without HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2024"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
"Hyundai Kona Non-SCC 2019": {
|
"Hyundai Kona Non-SCC 2019": {
|
||||||
"platform": "HYUNDAI_KONA_NON_SCC",
|
"platform": "HYUNDAI_KONA_NON_SCC",
|
||||||
"make": "Hyundai",
|
"make": "Hyundai",
|
||||||
@@ -1811,6 +1852,16 @@
|
|||||||
],
|
],
|
||||||
"package": "Smart Cruise Control (SCC)"
|
"package": "Smart Cruise Control (SCC)"
|
||||||
},
|
},
|
||||||
|
"Hyundai Santa Cruz (without HDA II) 2025": {
|
||||||
|
"platform": "HYUNDAI_SANTA_CRUZ_2025",
|
||||||
|
"make": "Hyundai",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "Santa Cruz (without HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2025"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
"Hyundai Santa Fe 2019-20": {
|
"Hyundai Santa Fe 2019-20": {
|
||||||
"platform": "HYUNDAI_SANTA_FE",
|
"platform": "HYUNDAI_SANTA_FE",
|
||||||
"make": "Hyundai",
|
"make": "Hyundai",
|
||||||
@@ -1880,6 +1931,17 @@
|
|||||||
],
|
],
|
||||||
"package": "All"
|
"package": "All"
|
||||||
},
|
},
|
||||||
|
"Hyundai Sonata (without HDA II) 2024-25": {
|
||||||
|
"platform": "HYUNDAI_SONATA_2024",
|
||||||
|
"make": "Hyundai",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "Sonata (without HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2024",
|
||||||
|
"2025"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
"Hyundai Sonata Hybrid 2020-23": {
|
"Hyundai Sonata Hybrid 2020-23": {
|
||||||
"platform": "HYUNDAI_SONATA_HYBRID",
|
"platform": "HYUNDAI_SONATA_HYBRID",
|
||||||
"make": "Hyundai",
|
"make": "Hyundai",
|
||||||
@@ -1893,6 +1955,17 @@
|
|||||||
],
|
],
|
||||||
"package": "All"
|
"package": "All"
|
||||||
},
|
},
|
||||||
|
"Hyundai Sonata Hybrid (without HDA II) 2024-25": {
|
||||||
|
"platform": "HYUNDAI_SONATA_HEV_2024",
|
||||||
|
"make": "Hyundai",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "Sonata Hybrid (without HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2024",
|
||||||
|
"2025"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
"Hyundai Staria 2023": {
|
"Hyundai Staria 2023": {
|
||||||
"platform": "HYUNDAI_STARIA_4TH_GEN",
|
"platform": "HYUNDAI_STARIA_4TH_GEN",
|
||||||
"make": "Hyundai",
|
"make": "Hyundai",
|
||||||
@@ -1934,6 +2007,17 @@
|
|||||||
],
|
],
|
||||||
"package": "All"
|
"package": "All"
|
||||||
},
|
},
|
||||||
|
"Hyundai Tucson (without HDA II) 2025-26": {
|
||||||
|
"platform": "HYUNDAI_TUCSON_2025",
|
||||||
|
"make": "Hyundai",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "Tucson (without HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2025",
|
||||||
|
"2026"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
"Hyundai Tucson Diesel 2019": {
|
"Hyundai Tucson Diesel 2019": {
|
||||||
"platform": "HYUNDAI_TUCSON",
|
"platform": "HYUNDAI_TUCSON",
|
||||||
"make": "Hyundai",
|
"make": "Hyundai",
|
||||||
@@ -1956,6 +2040,17 @@
|
|||||||
],
|
],
|
||||||
"package": "All"
|
"package": "All"
|
||||||
},
|
},
|
||||||
|
"Hyundai Tucson Hybrid (without HDA II) 2025-26": {
|
||||||
|
"platform": "HYUNDAI_TUCSON_HEV_2025",
|
||||||
|
"make": "Hyundai",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "Tucson Hybrid (without HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2025",
|
||||||
|
"2026"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
"Hyundai Tucson Plug-in Hybrid 2024": {
|
"Hyundai Tucson Plug-in Hybrid 2024": {
|
||||||
"platform": "HYUNDAI_TUCSON_4TH_GEN",
|
"platform": "HYUNDAI_TUCSON_4TH_GEN",
|
||||||
"make": "Hyundai",
|
"make": "Hyundai",
|
||||||
@@ -1966,6 +2061,16 @@
|
|||||||
],
|
],
|
||||||
"package": "All"
|
"package": "All"
|
||||||
},
|
},
|
||||||
|
"Hyundai Tucson Plug-in Hybrid (without HDA II) 2025": {
|
||||||
|
"platform": "HYUNDAI_TUCSON_PHEV_2025",
|
||||||
|
"make": "Hyundai",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "Tucson Plug-in Hybrid (without HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2025"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
"Hyundai Veloster 2019-20": {
|
"Hyundai Veloster 2019-20": {
|
||||||
"platform": "HYUNDAI_VELOSTER",
|
"platform": "HYUNDAI_VELOSTER",
|
||||||
"make": "Hyundai",
|
"make": "Hyundai",
|
||||||
@@ -2114,6 +2219,27 @@
|
|||||||
],
|
],
|
||||||
"package": "No Smart Cruise Control (Non-SCC)"
|
"package": "No Smart Cruise Control (Non-SCC)"
|
||||||
},
|
},
|
||||||
|
"Kia K4 (with HDA II) 2025": {
|
||||||
|
"platform": "KIA_K4_2025",
|
||||||
|
"make": "Kia",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "K4 (with HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2025"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
|
"Kia K4 (without HDA II) 2025-26": {
|
||||||
|
"platform": "KIA_K4_2025",
|
||||||
|
"make": "Kia",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "K4 (without HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2025",
|
||||||
|
"2026"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
"Kia K5 2021-24": {
|
"Kia K5 2021-24": {
|
||||||
"platform": "KIA_K5_2021",
|
"platform": "KIA_K5_2021",
|
||||||
"make": "Kia",
|
"make": "Kia",
|
||||||
@@ -2127,6 +2253,16 @@
|
|||||||
],
|
],
|
||||||
"package": "Smart Cruise Control (SCC)"
|
"package": "Smart Cruise Control (SCC)"
|
||||||
},
|
},
|
||||||
|
"Kia K5 (without HDA II) 2025": {
|
||||||
|
"platform": "KIA_K5_2025",
|
||||||
|
"make": "Kia",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "K5 (without HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2025"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
"Kia K5 Hybrid 2020-22": {
|
"Kia K5 Hybrid 2020-22": {
|
||||||
"platform": "KIA_K5_HEV_2020",
|
"platform": "KIA_K5_HEV_2020",
|
||||||
"make": "Kia",
|
"make": "Kia",
|
||||||
@@ -2377,6 +2513,17 @@
|
|||||||
],
|
],
|
||||||
"package": "Smart Cruise Control (SCC)"
|
"package": "Smart Cruise Control (SCC)"
|
||||||
},
|
},
|
||||||
|
"Kia Sorento (without HDA II) 2024-25": {
|
||||||
|
"platform": "KIA_SORENTO_2024",
|
||||||
|
"make": "Kia",
|
||||||
|
"brand": "hyundai",
|
||||||
|
"model": "Sorento (without HDA II)",
|
||||||
|
"year": [
|
||||||
|
"2024",
|
||||||
|
"2025"
|
||||||
|
],
|
||||||
|
"package": "Smart Cruise Control (SCC)"
|
||||||
|
},
|
||||||
"Kia Sorento Hybrid 2021-23": {
|
"Kia Sorento Hybrid 2021-23": {
|
||||||
"platform": "KIA_SORENTO_HEV_4TH_GEN",
|
"platform": "KIA_SORENTO_HEV_4TH_GEN",
|
||||||
"make": "Kia",
|
"make": "Kia",
|
||||||
|
|||||||
@@ -69,8 +69,6 @@ struct LeadData {
|
|||||||
struct SelfdriveStateSP @0x81c2f05a394cf4af {
|
struct SelfdriveStateSP @0x81c2f05a394cf4af {
|
||||||
mads @0 :ModularAssistiveDrivingSystem;
|
mads @0 :ModularAssistiveDrivingSystem;
|
||||||
intelligentCruiseButtonManagement @1 :IntelligentCruiseButtonManagement;
|
intelligentCruiseButtonManagement @1 :IntelligentCruiseButtonManagement;
|
||||||
buttonsPressed @2 :UInt16;
|
|
||||||
buttonsReleaseToggle @3 :UInt16;
|
|
||||||
|
|
||||||
enum AudibleAlert {
|
enum AudibleAlert {
|
||||||
none @0;
|
none @0;
|
||||||
@@ -139,16 +137,10 @@ struct ModelManagerSP @0xaedffd8f31e7b55d {
|
|||||||
eta @2 :UInt32;
|
eta @2 :UInt32;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Chunk {
|
|
||||||
fileName @0 :Text;
|
|
||||||
sha256 @1 :Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Artifact {
|
struct Artifact {
|
||||||
fileName @0 :Text;
|
fileName @0 :Text;
|
||||||
downloadUri @1 :DownloadUri;
|
downloadUri @1 :DownloadUri;
|
||||||
downloadProgress @2 :DownloadProgress;
|
downloadProgress @2 :DownloadProgress;
|
||||||
chunks @3 :List(Chunk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Model {
|
struct Model {
|
||||||
@@ -163,7 +155,6 @@ struct ModelManagerSP @0xaedffd8f31e7b55d {
|
|||||||
policy @3;
|
policy @3;
|
||||||
offPolicy @4;
|
offPolicy @4;
|
||||||
onPolicy @5;
|
onPolicy @5;
|
||||||
chunked @6;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -636,17 +636,17 @@ const ::capnp::_::RawSchema s_f488e435979fe1ff = {
|
|||||||
0, 16, i_f488e435979fe1ff, nullptr, nullptr, { &s_f488e435979fe1ff, nullptr, nullptr, 0, 0, nullptr }, false
|
0, 16, i_f488e435979fe1ff, nullptr, nullptr, { &s_f488e435979fe1ff, nullptr, nullptr, 0, 0, nullptr }, false
|
||||||
};
|
};
|
||||||
#endif // !CAPNP_LITE
|
#endif // !CAPNP_LITE
|
||||||
static const ::capnp::_::AlignedData<89> b_81c2f05a394cf4af = {
|
static const ::capnp::_::AlignedData<56> b_81c2f05a394cf4af = {
|
||||||
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
||||||
175, 244, 76, 57, 90, 240, 194, 129,
|
175, 244, 76, 57, 90, 240, 194, 129,
|
||||||
13, 0, 0, 0, 1, 0, 1, 0,
|
13, 0, 0, 0, 1, 0, 0, 0,
|
||||||
89, 10, 85, 29, 102, 186, 38, 181,
|
89, 10, 85, 29, 102, 186, 38, 181,
|
||||||
2, 0, 7, 0, 0, 0, 0, 0,
|
2, 0, 7, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
21, 0, 0, 0, 242, 0, 0, 0,
|
21, 0, 0, 0, 242, 0, 0, 0,
|
||||||
33, 0, 0, 0, 23, 0, 0, 0,
|
33, 0, 0, 0, 23, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
45, 0, 0, 0, 231, 0, 0, 0,
|
45, 0, 0, 0, 119, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
99, 117, 115, 116, 111, 109, 46, 99,
|
99, 117, 115, 116, 111, 109, 46, 99,
|
||||||
@@ -658,35 +658,21 @@ static const ::capnp::_::AlignedData<89> b_81c2f05a394cf4af = {
|
|||||||
1, 0, 0, 0, 106, 0, 0, 0,
|
1, 0, 0, 0, 106, 0, 0, 0,
|
||||||
65, 117, 100, 105, 98, 108, 101, 65,
|
65, 117, 100, 105, 98, 108, 101, 65,
|
||||||
108, 101, 114, 116, 0, 0, 0, 0,
|
108, 101, 114, 116, 0, 0, 0, 0,
|
||||||
16, 0, 0, 0, 3, 0, 4, 0,
|
8, 0, 0, 0, 3, 0, 4, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 1, 0, 0, 0, 0, 0,
|
0, 0, 1, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
97, 0, 0, 0, 42, 0, 0, 0,
|
41, 0, 0, 0, 42, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
92, 0, 0, 0, 3, 0, 1, 0,
|
36, 0, 0, 0, 3, 0, 1, 0,
|
||||||
104, 0, 0, 0, 2, 0, 1, 0,
|
48, 0, 0, 0, 2, 0, 1, 0,
|
||||||
1, 0, 0, 0, 1, 0, 0, 0,
|
1, 0, 0, 0, 1, 0, 0, 0,
|
||||||
0, 0, 1, 0, 1, 0, 0, 0,
|
0, 0, 1, 0, 1, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
101, 0, 0, 0, 18, 1, 0, 0,
|
45, 0, 0, 0, 18, 1, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
112, 0, 0, 0, 3, 0, 1, 0,
|
56, 0, 0, 0, 3, 0, 1, 0,
|
||||||
124, 0, 0, 0, 2, 0, 1, 0,
|
68, 0, 0, 0, 2, 0, 1, 0,
|
||||||
2, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 1, 0, 2, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
121, 0, 0, 0, 122, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
120, 0, 0, 0, 3, 0, 1, 0,
|
|
||||||
132, 0, 0, 0, 2, 0, 1, 0,
|
|
||||||
3, 0, 0, 0, 1, 0, 0, 0,
|
|
||||||
0, 0, 1, 0, 3, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
129, 0, 0, 0, 170, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
132, 0, 0, 0, 3, 0, 1, 0,
|
|
||||||
144, 0, 0, 0, 2, 0, 1, 0,
|
|
||||||
109, 97, 100, 115, 0, 0, 0, 0,
|
109, 97, 100, 115, 0, 0, 0, 0,
|
||||||
16, 0, 0, 0, 0, 0, 0, 0,
|
16, 0, 0, 0, 0, 0, 0, 0,
|
||||||
143, 147, 68, 238, 187, 112, 77, 205,
|
143, 147, 68, 238, 187, 112, 77, 205,
|
||||||
@@ -705,25 +691,6 @@ static const ::capnp::_::AlignedData<89> b_81c2f05a394cf4af = {
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
16, 0, 0, 0, 0, 0, 0, 0,
|
16, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
98, 117, 116, 116, 111, 110, 115, 80,
|
|
||||||
114, 101, 115, 115, 101, 100, 0, 0,
|
|
||||||
7, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
7, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
98, 117, 116, 116, 111, 110, 115, 82,
|
|
||||||
101, 108, 101, 97, 115, 101, 84, 111,
|
|
||||||
103, 103, 108, 101, 0, 0, 0, 0,
|
|
||||||
7, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
7, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, }
|
0, 0, 0, 0, 0, 0, 0, 0, }
|
||||||
};
|
};
|
||||||
@@ -733,11 +700,11 @@ static const ::capnp::_::RawSchema* const d_81c2f05a394cf4af[] = {
|
|||||||
&s_90a324fe70479956,
|
&s_90a324fe70479956,
|
||||||
&s_cd4d70bbee44938f,
|
&s_cd4d70bbee44938f,
|
||||||
};
|
};
|
||||||
static const uint16_t m_81c2f05a394cf4af[] = {2, 3, 1, 0};
|
static const uint16_t m_81c2f05a394cf4af[] = {1, 0};
|
||||||
static const uint16_t i_81c2f05a394cf4af[] = {0, 1, 2, 3};
|
static const uint16_t i_81c2f05a394cf4af[] = {0, 1};
|
||||||
const ::capnp::_::RawSchema s_81c2f05a394cf4af = {
|
const ::capnp::_::RawSchema s_81c2f05a394cf4af = {
|
||||||
0x81c2f05a394cf4af, b_81c2f05a394cf4af.words, 89, d_81c2f05a394cf4af, m_81c2f05a394cf4af,
|
0x81c2f05a394cf4af, b_81c2f05a394cf4af.words, 56, d_81c2f05a394cf4af, m_81c2f05a394cf4af,
|
||||||
2, 4, i_81c2f05a394cf4af, nullptr, nullptr, { &s_81c2f05a394cf4af, nullptr, nullptr, 0, 0, nullptr }, false
|
2, 2, i_81c2f05a394cf4af, nullptr, nullptr, { &s_81c2f05a394cf4af, nullptr, nullptr, 0, 0, nullptr }, false
|
||||||
};
|
};
|
||||||
#endif // !CAPNP_LITE
|
#endif // !CAPNP_LITE
|
||||||
static const ::capnp::_::AlignedData<184> b_878e32a6bc486e3f = {
|
static const ::capnp::_::AlignedData<184> b_878e32a6bc486e3f = {
|
||||||
@@ -935,7 +902,7 @@ const ::capnp::_::RawSchema s_878e32a6bc486e3f = {
|
|||||||
};
|
};
|
||||||
#endif // !CAPNP_LITE
|
#endif // !CAPNP_LITE
|
||||||
CAPNP_DEFINE_ENUM(AudibleAlert_878e32a6bc486e3f, 878e32a6bc486e3f);
|
CAPNP_DEFINE_ENUM(AudibleAlert_878e32a6bc486e3f, 878e32a6bc486e3f);
|
||||||
static const ::capnp::_::AlignedData<105> b_aedffd8f31e7b55d = {
|
static const ::capnp::_::AlignedData<102> b_aedffd8f31e7b55d = {
|
||||||
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
||||||
93, 181, 231, 49, 143, 253, 223, 174,
|
93, 181, 231, 49, 143, 253, 223, 174,
|
||||||
13, 0, 0, 0, 1, 0, 0, 0,
|
13, 0, 0, 0, 1, 0, 0, 0,
|
||||||
@@ -943,34 +910,32 @@ static const ::capnp::_::AlignedData<105> b_aedffd8f31e7b55d = {
|
|||||||
3, 0, 7, 0, 0, 0, 0, 0,
|
3, 0, 7, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
21, 0, 0, 0, 226, 0, 0, 0,
|
21, 0, 0, 0, 226, 0, 0, 0,
|
||||||
33, 0, 0, 0, 151, 0, 0, 0,
|
33, 0, 0, 0, 135, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
165, 0, 0, 0, 175, 0, 0, 0,
|
153, 0, 0, 0, 175, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
99, 117, 115, 116, 111, 109, 46, 99,
|
99, 117, 115, 116, 111, 109, 46, 99,
|
||||||
97, 112, 110, 112, 58, 77, 111, 100,
|
97, 112, 110, 112, 58, 77, 111, 100,
|
||||||
101, 108, 77, 97, 110, 97, 103, 101,
|
101, 108, 77, 97, 110, 97, 103, 101,
|
||||||
114, 83, 80, 0, 0, 0, 0, 0,
|
114, 83, 80, 0, 0, 0, 0, 0,
|
||||||
36, 0, 0, 0, 1, 0, 1, 0,
|
32, 0, 0, 0, 1, 0, 1, 0,
|
||||||
134, 226, 223, 233, 138, 174, 203, 216,
|
134, 226, 223, 233, 138, 174, 203, 216,
|
||||||
65, 0, 0, 0, 98, 0, 0, 0,
|
|
||||||
185, 72, 32, 230, 83, 77, 131, 218,
|
|
||||||
65, 0, 0, 0, 122, 0, 0, 0,
|
|
||||||
115, 76, 214, 20, 81, 178, 119, 166,
|
|
||||||
65, 0, 0, 0, 138, 0, 0, 0,
|
|
||||||
65, 138, 151, 169, 170, 42, 110, 141,
|
|
||||||
69, 0, 0, 0, 50, 0, 0, 0,
|
|
||||||
209, 147, 70, 166, 116, 206, 65, 228,
|
|
||||||
65, 0, 0, 0, 74, 0, 0, 0,
|
|
||||||
177, 18, 161, 254, 101, 110, 195, 231,
|
|
||||||
65, 0, 0, 0, 50, 0, 0, 0,
|
|
||||||
5, 123, 36, 126, 138, 18, 156, 201,
|
|
||||||
61, 0, 0, 0, 58, 0, 0, 0,
|
|
||||||
124, 232, 26, 54, 13, 0, 109, 215,
|
|
||||||
57, 0, 0, 0, 74, 0, 0, 0,
|
|
||||||
115, 212, 90, 80, 192, 33, 8, 230,
|
|
||||||
57, 0, 0, 0, 98, 0, 0, 0,
|
57, 0, 0, 0, 98, 0, 0, 0,
|
||||||
|
185, 72, 32, 230, 83, 77, 131, 218,
|
||||||
|
57, 0, 0, 0, 122, 0, 0, 0,
|
||||||
|
115, 76, 214, 20, 81, 178, 119, 166,
|
||||||
|
57, 0, 0, 0, 138, 0, 0, 0,
|
||||||
|
209, 147, 70, 166, 116, 206, 65, 228,
|
||||||
|
61, 0, 0, 0, 74, 0, 0, 0,
|
||||||
|
177, 18, 161, 254, 101, 110, 195, 231,
|
||||||
|
61, 0, 0, 0, 50, 0, 0, 0,
|
||||||
|
5, 123, 36, 126, 138, 18, 156, 201,
|
||||||
|
57, 0, 0, 0, 58, 0, 0, 0,
|
||||||
|
124, 232, 26, 54, 13, 0, 109, 215,
|
||||||
|
53, 0, 0, 0, 74, 0, 0, 0,
|
||||||
|
115, 212, 90, 80, 192, 33, 8, 230,
|
||||||
|
53, 0, 0, 0, 98, 0, 0, 0,
|
||||||
68, 111, 119, 110, 108, 111, 97, 100,
|
68, 111, 119, 110, 108, 111, 97, 100,
|
||||||
85, 114, 105, 0, 0, 0, 0, 0,
|
85, 114, 105, 0, 0, 0, 0, 0,
|
||||||
68, 111, 119, 110, 108, 111, 97, 100,
|
68, 111, 119, 110, 108, 111, 97, 100,
|
||||||
@@ -978,7 +943,6 @@ static const ::capnp::_::AlignedData<105> b_aedffd8f31e7b55d = {
|
|||||||
68, 111, 119, 110, 108, 111, 97, 100,
|
68, 111, 119, 110, 108, 111, 97, 100,
|
||||||
80, 114, 111, 103, 114, 101, 115, 115,
|
80, 114, 111, 103, 114, 101, 115, 115,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
67, 104, 117, 110, 107, 0, 0, 0,
|
|
||||||
65, 114, 116, 105, 102, 97, 99, 116,
|
65, 114, 116, 105, 102, 97, 99, 116,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
77, 111, 100, 101, 108, 0, 0, 0,
|
77, 111, 100, 101, 108, 0, 0, 0,
|
||||||
@@ -1050,7 +1014,7 @@ static const ::capnp::_::RawSchema* const d_aedffd8f31e7b55d[] = {
|
|||||||
static const uint16_t m_aedffd8f31e7b55d[] = {0, 2, 1};
|
static const uint16_t m_aedffd8f31e7b55d[] = {0, 2, 1};
|
||||||
static const uint16_t i_aedffd8f31e7b55d[] = {0, 1, 2};
|
static const uint16_t i_aedffd8f31e7b55d[] = {0, 1, 2};
|
||||||
const ::capnp::_::RawSchema s_aedffd8f31e7b55d = {
|
const ::capnp::_::RawSchema s_aedffd8f31e7b55d = {
|
||||||
0xaedffd8f31e7b55d, b_aedffd8f31e7b55d.words, 105, d_aedffd8f31e7b55d, m_aedffd8f31e7b55d,
|
0xaedffd8f31e7b55d, b_aedffd8f31e7b55d.words, 102, d_aedffd8f31e7b55d, m_aedffd8f31e7b55d,
|
||||||
1, 3, i_aedffd8f31e7b55d, nullptr, nullptr, { &s_aedffd8f31e7b55d, nullptr, nullptr, 0, 0, nullptr }, false
|
1, 3, i_aedffd8f31e7b55d, nullptr, nullptr, { &s_aedffd8f31e7b55d, nullptr, nullptr, 0, 0, nullptr }, false
|
||||||
};
|
};
|
||||||
#endif // !CAPNP_LITE
|
#endif // !CAPNP_LITE
|
||||||
@@ -1248,78 +1212,17 @@ const ::capnp::_::RawSchema s_a677b25114d64c73 = {
|
|||||||
1, 3, i_a677b25114d64c73, nullptr, nullptr, { &s_a677b25114d64c73, nullptr, nullptr, 0, 0, nullptr }, false
|
1, 3, i_a677b25114d64c73, nullptr, nullptr, { &s_a677b25114d64c73, nullptr, nullptr, 0, 0, nullptr }, false
|
||||||
};
|
};
|
||||||
#endif // !CAPNP_LITE
|
#endif // !CAPNP_LITE
|
||||||
static const ::capnp::_::AlignedData<50> b_8d6e2aaaa9978a41 = {
|
static const ::capnp::_::AlignedData<68> b_e441ce74a64693d1 = {
|
||||||
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
|
||||||
65, 138, 151, 169, 170, 42, 110, 141,
|
|
||||||
28, 0, 0, 0, 1, 0, 0, 0,
|
|
||||||
93, 181, 231, 49, 143, 253, 223, 174,
|
|
||||||
2, 0, 7, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
21, 0, 0, 0, 18, 1, 0, 0,
|
|
||||||
37, 0, 0, 0, 7, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
33, 0, 0, 0, 119, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
99, 117, 115, 116, 111, 109, 46, 99,
|
|
||||||
97, 112, 110, 112, 58, 77, 111, 100,
|
|
||||||
101, 108, 77, 97, 110, 97, 103, 101,
|
|
||||||
114, 83, 80, 46, 67, 104, 117, 110,
|
|
||||||
107, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 1, 0, 1, 0,
|
|
||||||
8, 0, 0, 0, 3, 0, 4, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 1, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
41, 0, 0, 0, 74, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
40, 0, 0, 0, 3, 0, 1, 0,
|
|
||||||
52, 0, 0, 0, 2, 0, 1, 0,
|
|
||||||
1, 0, 0, 0, 1, 0, 0, 0,
|
|
||||||
0, 0, 1, 0, 1, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
49, 0, 0, 0, 58, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
44, 0, 0, 0, 3, 0, 1, 0,
|
|
||||||
56, 0, 0, 0, 2, 0, 1, 0,
|
|
||||||
102, 105, 108, 101, 78, 97, 109, 101,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
12, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
12, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
115, 104, 97, 50, 53, 54, 0, 0,
|
|
||||||
12, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
12, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, }
|
|
||||||
};
|
|
||||||
::capnp::word const* const bp_8d6e2aaaa9978a41 = b_8d6e2aaaa9978a41.words;
|
|
||||||
#if !CAPNP_LITE
|
|
||||||
static const uint16_t m_8d6e2aaaa9978a41[] = {0, 1};
|
|
||||||
static const uint16_t i_8d6e2aaaa9978a41[] = {0, 1};
|
|
||||||
const ::capnp::_::RawSchema s_8d6e2aaaa9978a41 = {
|
|
||||||
0x8d6e2aaaa9978a41, b_8d6e2aaaa9978a41.words, 50, nullptr, m_8d6e2aaaa9978a41,
|
|
||||||
0, 2, i_8d6e2aaaa9978a41, nullptr, nullptr, { &s_8d6e2aaaa9978a41, nullptr, nullptr, 0, 0, nullptr }, false
|
|
||||||
};
|
|
||||||
#endif // !CAPNP_LITE
|
|
||||||
static const ::capnp::_::AlignedData<87> b_e441ce74a64693d1 = {
|
|
||||||
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
||||||
209, 147, 70, 166, 116, 206, 65, 228,
|
209, 147, 70, 166, 116, 206, 65, 228,
|
||||||
28, 0, 0, 0, 1, 0, 0, 0,
|
28, 0, 0, 0, 1, 0, 0, 0,
|
||||||
93, 181, 231, 49, 143, 253, 223, 174,
|
93, 181, 231, 49, 143, 253, 223, 174,
|
||||||
4, 0, 7, 0, 0, 0, 0, 0,
|
3, 0, 7, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
21, 0, 0, 0, 42, 1, 0, 0,
|
21, 0, 0, 0, 42, 1, 0, 0,
|
||||||
37, 0, 0, 0, 7, 0, 0, 0,
|
37, 0, 0, 0, 7, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
33, 0, 0, 0, 231, 0, 0, 0,
|
33, 0, 0, 0, 175, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
99, 117, 115, 116, 111, 109, 46, 99,
|
99, 117, 115, 116, 111, 109, 46, 99,
|
||||||
@@ -1328,35 +1231,28 @@ static const ::capnp::_::AlignedData<87> b_e441ce74a64693d1 = {
|
|||||||
114, 83, 80, 46, 65, 114, 116, 105,
|
114, 83, 80, 46, 65, 114, 116, 105,
|
||||||
102, 97, 99, 116, 0, 0, 0, 0,
|
102, 97, 99, 116, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 1, 0, 1, 0,
|
0, 0, 0, 0, 1, 0, 1, 0,
|
||||||
16, 0, 0, 0, 3, 0, 4, 0,
|
12, 0, 0, 0, 3, 0, 4, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 1, 0, 0, 0, 0, 0,
|
0, 0, 1, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
97, 0, 0, 0, 74, 0, 0, 0,
|
69, 0, 0, 0, 74, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
96, 0, 0, 0, 3, 0, 1, 0,
|
68, 0, 0, 0, 3, 0, 1, 0,
|
||||||
108, 0, 0, 0, 2, 0, 1, 0,
|
80, 0, 0, 0, 2, 0, 1, 0,
|
||||||
1, 0, 0, 0, 1, 0, 0, 0,
|
1, 0, 0, 0, 1, 0, 0, 0,
|
||||||
0, 0, 1, 0, 1, 0, 0, 0,
|
0, 0, 1, 0, 1, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
105, 0, 0, 0, 98, 0, 0, 0,
|
77, 0, 0, 0, 98, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
104, 0, 0, 0, 3, 0, 1, 0,
|
76, 0, 0, 0, 3, 0, 1, 0,
|
||||||
116, 0, 0, 0, 2, 0, 1, 0,
|
88, 0, 0, 0, 2, 0, 1, 0,
|
||||||
2, 0, 0, 0, 2, 0, 0, 0,
|
2, 0, 0, 0, 2, 0, 0, 0,
|
||||||
0, 0, 1, 0, 2, 0, 0, 0,
|
0, 0, 1, 0, 2, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
113, 0, 0, 0, 138, 0, 0, 0,
|
85, 0, 0, 0, 138, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
116, 0, 0, 0, 3, 0, 1, 0,
|
88, 0, 0, 0, 3, 0, 1, 0,
|
||||||
128, 0, 0, 0, 2, 0, 1, 0,
|
100, 0, 0, 0, 2, 0, 1, 0,
|
||||||
3, 0, 0, 0, 3, 0, 0, 0,
|
|
||||||
0, 0, 1, 0, 3, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
125, 0, 0, 0, 58, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
120, 0, 0, 0, 3, 0, 1, 0,
|
|
||||||
148, 0, 0, 0, 2, 0, 1, 0,
|
|
||||||
102, 105, 108, 101, 78, 97, 109, 101,
|
102, 105, 108, 101, 78, 97, 109, 101,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
12, 0, 0, 0, 0, 0, 0, 0,
|
12, 0, 0, 0, 0, 0, 0, 0,
|
||||||
@@ -1383,33 +1279,20 @@ static const ::capnp::_::AlignedData<87> b_e441ce74a64693d1 = {
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
16, 0, 0, 0, 0, 0, 0, 0,
|
16, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
99, 104, 117, 110, 107, 115, 0, 0,
|
|
||||||
14, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 3, 0, 1, 0,
|
|
||||||
16, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
65, 138, 151, 169, 170, 42, 110, 141,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
14, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, }
|
0, 0, 0, 0, 0, 0, 0, 0, }
|
||||||
};
|
};
|
||||||
::capnp::word const* const bp_e441ce74a64693d1 = b_e441ce74a64693d1.words;
|
::capnp::word const* const bp_e441ce74a64693d1 = b_e441ce74a64693d1.words;
|
||||||
#if !CAPNP_LITE
|
#if !CAPNP_LITE
|
||||||
static const ::capnp::_::RawSchema* const d_e441ce74a64693d1[] = {
|
static const ::capnp::_::RawSchema* const d_e441ce74a64693d1[] = {
|
||||||
&s_8d6e2aaaa9978a41,
|
|
||||||
&s_a677b25114d64c73,
|
&s_a677b25114d64c73,
|
||||||
&s_d8cbae8ae9dfe286,
|
&s_d8cbae8ae9dfe286,
|
||||||
};
|
};
|
||||||
static const uint16_t m_e441ce74a64693d1[] = {3, 2, 1, 0};
|
static const uint16_t m_e441ce74a64693d1[] = {2, 1, 0};
|
||||||
static const uint16_t i_e441ce74a64693d1[] = {0, 1, 2, 3};
|
static const uint16_t i_e441ce74a64693d1[] = {0, 1, 2};
|
||||||
const ::capnp::_::RawSchema s_e441ce74a64693d1 = {
|
const ::capnp::_::RawSchema s_e441ce74a64693d1 = {
|
||||||
0xe441ce74a64693d1, b_e441ce74a64693d1.words, 87, d_e441ce74a64693d1, m_e441ce74a64693d1,
|
0xe441ce74a64693d1, b_e441ce74a64693d1.words, 68, d_e441ce74a64693d1, m_e441ce74a64693d1,
|
||||||
3, 4, i_e441ce74a64693d1, nullptr, nullptr, { &s_e441ce74a64693d1, nullptr, nullptr, 0, 0, nullptr }, false
|
2, 3, i_e441ce74a64693d1, nullptr, nullptr, { &s_e441ce74a64693d1, nullptr, nullptr, 0, 0, nullptr }, false
|
||||||
};
|
};
|
||||||
#endif // !CAPNP_LITE
|
#endif // !CAPNP_LITE
|
||||||
static const ::capnp::_::AlignedData<69> b_e7c36e65fea112b1 = {
|
static const ::capnp::_::AlignedData<69> b_e7c36e65fea112b1 = {
|
||||||
@@ -1496,7 +1379,7 @@ const ::capnp::_::RawSchema s_e7c36e65fea112b1 = {
|
|||||||
2, 3, i_e7c36e65fea112b1, nullptr, nullptr, { &s_e7c36e65fea112b1, nullptr, nullptr, 0, 0, nullptr }, false
|
2, 3, i_e7c36e65fea112b1, nullptr, nullptr, { &s_e7c36e65fea112b1, nullptr, nullptr, 0, 0, nullptr }, false
|
||||||
};
|
};
|
||||||
#endif // !CAPNP_LITE
|
#endif // !CAPNP_LITE
|
||||||
static const ::capnp::_::AlignedData<51> b_af23faeb2c26a5b2 = {
|
static const ::capnp::_::AlignedData<47> b_af23faeb2c26a5b2 = {
|
||||||
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
||||||
178, 165, 38, 44, 235, 250, 35, 175,
|
178, 165, 38, 44, 235, 250, 35, 175,
|
||||||
34, 0, 0, 0, 2, 0, 0, 0,
|
34, 0, 0, 0, 2, 0, 0, 0,
|
||||||
@@ -1506,7 +1389,7 @@ static const ::capnp::_::AlignedData<51> b_af23faeb2c26a5b2 = {
|
|||||||
21, 0, 0, 0, 58, 1, 0, 0,
|
21, 0, 0, 0, 58, 1, 0, 0,
|
||||||
37, 0, 0, 0, 7, 0, 0, 0,
|
37, 0, 0, 0, 7, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
33, 0, 0, 0, 175, 0, 0, 0,
|
33, 0, 0, 0, 151, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
99, 117, 115, 116, 111, 109, 46, 99,
|
99, 117, 115, 116, 111, 109, 46, 99,
|
||||||
@@ -1515,27 +1398,24 @@ static const ::capnp::_::AlignedData<51> b_af23faeb2c26a5b2 = {
|
|||||||
114, 83, 80, 46, 77, 111, 100, 101,
|
114, 83, 80, 46, 77, 111, 100, 101,
|
||||||
108, 46, 84, 121, 112, 101, 0, 0,
|
108, 46, 84, 121, 112, 101, 0, 0,
|
||||||
0, 0, 0, 0, 1, 0, 1, 0,
|
0, 0, 0, 0, 1, 0, 1, 0,
|
||||||
28, 0, 0, 0, 1, 0, 2, 0,
|
24, 0, 0, 0, 1, 0, 2, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
77, 0, 0, 0, 90, 0, 0, 0,
|
65, 0, 0, 0, 90, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
1, 0, 0, 0, 0, 0, 0, 0,
|
1, 0, 0, 0, 0, 0, 0, 0,
|
||||||
73, 0, 0, 0, 90, 0, 0, 0,
|
61, 0, 0, 0, 90, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
2, 0, 0, 0, 0, 0, 0, 0,
|
2, 0, 0, 0, 0, 0, 0, 0,
|
||||||
69, 0, 0, 0, 58, 0, 0, 0,
|
57, 0, 0, 0, 58, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
3, 0, 0, 0, 0, 0, 0, 0,
|
3, 0, 0, 0, 0, 0, 0, 0,
|
||||||
61, 0, 0, 0, 58, 0, 0, 0,
|
49, 0, 0, 0, 58, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
4, 0, 0, 0, 0, 0, 0, 0,
|
4, 0, 0, 0, 0, 0, 0, 0,
|
||||||
53, 0, 0, 0, 82, 0, 0, 0,
|
41, 0, 0, 0, 82, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
5, 0, 0, 0, 0, 0, 0, 0,
|
5, 0, 0, 0, 0, 0, 0, 0,
|
||||||
49, 0, 0, 0, 74, 0, 0, 0,
|
37, 0, 0, 0, 74, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
6, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
45, 0, 0, 0, 66, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
115, 117, 112, 101, 114, 99, 111, 109,
|
115, 117, 112, 101, 114, 99, 111, 109,
|
||||||
98, 111, 0, 0, 0, 0, 0, 0,
|
98, 111, 0, 0, 0, 0, 0, 0,
|
||||||
@@ -1546,15 +1426,14 @@ static const ::capnp::_::AlignedData<51> b_af23faeb2c26a5b2 = {
|
|||||||
111, 102, 102, 80, 111, 108, 105, 99,
|
111, 102, 102, 80, 111, 108, 105, 99,
|
||||||
121, 0, 0, 0, 0, 0, 0, 0,
|
121, 0, 0, 0, 0, 0, 0, 0,
|
||||||
111, 110, 80, 111, 108, 105, 99, 121,
|
111, 110, 80, 111, 108, 105, 99, 121,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, }
|
||||||
99, 104, 117, 110, 107, 101, 100, 0, }
|
|
||||||
};
|
};
|
||||||
::capnp::word const* const bp_af23faeb2c26a5b2 = b_af23faeb2c26a5b2.words;
|
::capnp::word const* const bp_af23faeb2c26a5b2 = b_af23faeb2c26a5b2.words;
|
||||||
#if !CAPNP_LITE
|
#if !CAPNP_LITE
|
||||||
static const uint16_t m_af23faeb2c26a5b2[] = {6, 1, 4, 5, 3, 0, 2};
|
static const uint16_t m_af23faeb2c26a5b2[] = {1, 4, 5, 3, 0, 2};
|
||||||
const ::capnp::_::RawSchema s_af23faeb2c26a5b2 = {
|
const ::capnp::_::RawSchema s_af23faeb2c26a5b2 = {
|
||||||
0xaf23faeb2c26a5b2, b_af23faeb2c26a5b2.words, 51, nullptr, m_af23faeb2c26a5b2,
|
0xaf23faeb2c26a5b2, b_af23faeb2c26a5b2.words, 47, nullptr, m_af23faeb2c26a5b2,
|
||||||
0, 7, nullptr, nullptr, nullptr, { &s_af23faeb2c26a5b2, nullptr, nullptr, 0, 0, nullptr }, false
|
0, 6, nullptr, nullptr, nullptr, { &s_af23faeb2c26a5b2, nullptr, nullptr, 0, 0, nullptr }, false
|
||||||
};
|
};
|
||||||
#endif // !CAPNP_LITE
|
#endif // !CAPNP_LITE
|
||||||
CAPNP_DEFINE_ENUM(Type_af23faeb2c26a5b2, af23faeb2c26a5b2);
|
CAPNP_DEFINE_ENUM(Type_af23faeb2c26a5b2, af23faeb2c26a5b2);
|
||||||
@@ -5416,18 +5295,6 @@ constexpr ::capnp::_::RawSchema const* ModelManagerSP::DownloadProgress::_capnpP
|
|||||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||||
#endif // !CAPNP_LITE
|
#endif // !CAPNP_LITE
|
||||||
|
|
||||||
// ModelManagerSP::Chunk
|
|
||||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
|
||||||
constexpr uint16_t ModelManagerSP::Chunk::_capnpPrivate::dataWordSize;
|
|
||||||
constexpr uint16_t ModelManagerSP::Chunk::_capnpPrivate::pointerCount;
|
|
||||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
|
||||||
#if !CAPNP_LITE
|
|
||||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
|
||||||
constexpr ::capnp::Kind ModelManagerSP::Chunk::_capnpPrivate::kind;
|
|
||||||
constexpr ::capnp::_::RawSchema const* ModelManagerSP::Chunk::_capnpPrivate::schema;
|
|
||||||
#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
|
||||||
#endif // !CAPNP_LITE
|
|
||||||
|
|
||||||
// ModelManagerSP::Artifact
|
// ModelManagerSP::Artifact
|
||||||
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||||
constexpr uint16_t ModelManagerSP::Artifact::_capnpPrivate::dataWordSize;
|
constexpr uint16_t ModelManagerSP::Artifact::_capnpPrivate::dataWordSize;
|
||||||
|
|||||||
@@ -96,7 +96,6 @@ enum class DownloadStatus_da834d53e62048b9: uint16_t {
|
|||||||
};
|
};
|
||||||
CAPNP_DECLARE_ENUM(DownloadStatus, da834d53e62048b9);
|
CAPNP_DECLARE_ENUM(DownloadStatus, da834d53e62048b9);
|
||||||
CAPNP_DECLARE_SCHEMA(a677b25114d64c73);
|
CAPNP_DECLARE_SCHEMA(a677b25114d64c73);
|
||||||
CAPNP_DECLARE_SCHEMA(8d6e2aaaa9978a41);
|
|
||||||
CAPNP_DECLARE_SCHEMA(e441ce74a64693d1);
|
CAPNP_DECLARE_SCHEMA(e441ce74a64693d1);
|
||||||
CAPNP_DECLARE_SCHEMA(e7c36e65fea112b1);
|
CAPNP_DECLARE_SCHEMA(e7c36e65fea112b1);
|
||||||
CAPNP_DECLARE_SCHEMA(af23faeb2c26a5b2);
|
CAPNP_DECLARE_SCHEMA(af23faeb2c26a5b2);
|
||||||
@@ -107,7 +106,6 @@ enum class Type_af23faeb2c26a5b2: uint16_t {
|
|||||||
POLICY,
|
POLICY,
|
||||||
OFF_POLICY,
|
OFF_POLICY,
|
||||||
ON_POLICY,
|
ON_POLICY,
|
||||||
CHUNKED,
|
|
||||||
};
|
};
|
||||||
CAPNP_DECLARE_ENUM(Type, af23faeb2c26a5b2);
|
CAPNP_DECLARE_ENUM(Type, af23faeb2c26a5b2);
|
||||||
CAPNP_DECLARE_SCHEMA(c99c128a7e247b05);
|
CAPNP_DECLARE_SCHEMA(c99c128a7e247b05);
|
||||||
@@ -322,7 +320,7 @@ struct SelfdriveStateSP {
|
|||||||
|
|
||||||
|
|
||||||
struct _capnpPrivate {
|
struct _capnpPrivate {
|
||||||
CAPNP_DECLARE_STRUCT_HEADER(81c2f05a394cf4af, 1, 2)
|
CAPNP_DECLARE_STRUCT_HEADER(81c2f05a394cf4af, 0, 2)
|
||||||
#if !CAPNP_LITE
|
#if !CAPNP_LITE
|
||||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||||
#endif // !CAPNP_LITE
|
#endif // !CAPNP_LITE
|
||||||
@@ -339,7 +337,6 @@ struct ModelManagerSP {
|
|||||||
typedef ::capnp::schemas::DownloadStatus_da834d53e62048b9 DownloadStatus;
|
typedef ::capnp::schemas::DownloadStatus_da834d53e62048b9 DownloadStatus;
|
||||||
|
|
||||||
struct DownloadProgress;
|
struct DownloadProgress;
|
||||||
struct Chunk;
|
|
||||||
struct Artifact;
|
struct Artifact;
|
||||||
struct Model;
|
struct Model;
|
||||||
typedef ::capnp::schemas::Runner_c99c128a7e247b05 Runner;
|
typedef ::capnp::schemas::Runner_c99c128a7e247b05 Runner;
|
||||||
@@ -385,21 +382,6 @@ struct ModelManagerSP::DownloadProgress {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ModelManagerSP::Chunk {
|
|
||||||
Chunk() = delete;
|
|
||||||
|
|
||||||
class Reader;
|
|
||||||
class Builder;
|
|
||||||
class Pipeline;
|
|
||||||
|
|
||||||
struct _capnpPrivate {
|
|
||||||
CAPNP_DECLARE_STRUCT_HEADER(8d6e2aaaa9978a41, 0, 2)
|
|
||||||
#if !CAPNP_LITE
|
|
||||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
|
||||||
#endif // !CAPNP_LITE
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModelManagerSP::Artifact {
|
struct ModelManagerSP::Artifact {
|
||||||
Artifact() = delete;
|
Artifact() = delete;
|
||||||
|
|
||||||
@@ -408,7 +390,7 @@ struct ModelManagerSP::Artifact {
|
|||||||
class Pipeline;
|
class Pipeline;
|
||||||
|
|
||||||
struct _capnpPrivate {
|
struct _capnpPrivate {
|
||||||
CAPNP_DECLARE_STRUCT_HEADER(e441ce74a64693d1, 0, 4)
|
CAPNP_DECLARE_STRUCT_HEADER(e441ce74a64693d1, 0, 3)
|
||||||
#if !CAPNP_LITE
|
#if !CAPNP_LITE
|
||||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||||
#endif // !CAPNP_LITE
|
#endif // !CAPNP_LITE
|
||||||
@@ -1345,10 +1327,6 @@ public:
|
|||||||
inline bool hasIntelligentCruiseButtonManagement() const;
|
inline bool hasIntelligentCruiseButtonManagement() const;
|
||||||
inline ::cereal::IntelligentCruiseButtonManagement::Reader getIntelligentCruiseButtonManagement() const;
|
inline ::cereal::IntelligentCruiseButtonManagement::Reader getIntelligentCruiseButtonManagement() const;
|
||||||
|
|
||||||
inline ::uint16_t getButtonsPressed() const;
|
|
||||||
|
|
||||||
inline ::uint16_t getButtonsReleaseToggle() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::capnp::_::StructReader _reader;
|
::capnp::_::StructReader _reader;
|
||||||
template <typename, ::capnp::Kind>
|
template <typename, ::capnp::Kind>
|
||||||
@@ -1391,12 +1369,6 @@ public:
|
|||||||
inline void adoptIntelligentCruiseButtonManagement(::capnp::Orphan< ::cereal::IntelligentCruiseButtonManagement>&& value);
|
inline void adoptIntelligentCruiseButtonManagement(::capnp::Orphan< ::cereal::IntelligentCruiseButtonManagement>&& value);
|
||||||
inline ::capnp::Orphan< ::cereal::IntelligentCruiseButtonManagement> disownIntelligentCruiseButtonManagement();
|
inline ::capnp::Orphan< ::cereal::IntelligentCruiseButtonManagement> disownIntelligentCruiseButtonManagement();
|
||||||
|
|
||||||
inline ::uint16_t getButtonsPressed();
|
|
||||||
inline void setButtonsPressed( ::uint16_t value);
|
|
||||||
|
|
||||||
inline ::uint16_t getButtonsReleaseToggle();
|
|
||||||
inline void setButtonsReleaseToggle( ::uint16_t value);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::capnp::_::StructBuilder _builder;
|
::capnp::_::StructBuilder _builder;
|
||||||
template <typename, ::capnp::Kind>
|
template <typename, ::capnp::Kind>
|
||||||
@@ -1705,97 +1677,6 @@ private:
|
|||||||
};
|
};
|
||||||
#endif // !CAPNP_LITE
|
#endif // !CAPNP_LITE
|
||||||
|
|
||||||
class ModelManagerSP::Chunk::Reader {
|
|
||||||
public:
|
|
||||||
typedef Chunk Reads;
|
|
||||||
|
|
||||||
Reader() = default;
|
|
||||||
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
|
|
||||||
|
|
||||||
inline ::capnp::MessageSize totalSize() const {
|
|
||||||
return _reader.totalSize().asPublic();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !CAPNP_LITE
|
|
||||||
inline ::kj::StringTree toString() const {
|
|
||||||
return ::capnp::_::structString(_reader, *_capnpPrivate::brand());
|
|
||||||
}
|
|
||||||
#endif // !CAPNP_LITE
|
|
||||||
|
|
||||||
inline bool hasFileName() const;
|
|
||||||
inline ::capnp::Text::Reader getFileName() const;
|
|
||||||
|
|
||||||
inline bool hasSha256() const;
|
|
||||||
inline ::capnp::Text::Reader getSha256() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
::capnp::_::StructReader _reader;
|
|
||||||
template <typename, ::capnp::Kind>
|
|
||||||
friend struct ::capnp::ToDynamic_;
|
|
||||||
template <typename, ::capnp::Kind>
|
|
||||||
friend struct ::capnp::_::PointerHelpers;
|
|
||||||
template <typename, ::capnp::Kind>
|
|
||||||
friend struct ::capnp::List;
|
|
||||||
friend class ::capnp::MessageBuilder;
|
|
||||||
friend class ::capnp::Orphanage;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ModelManagerSP::Chunk::Builder {
|
|
||||||
public:
|
|
||||||
typedef Chunk Builds;
|
|
||||||
|
|
||||||
Builder() = delete; // Deleted to discourage incorrect usage.
|
|
||||||
// You can explicitly initialize to nullptr instead.
|
|
||||||
inline Builder(decltype(nullptr)) {}
|
|
||||||
inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {}
|
|
||||||
inline operator Reader() const { return Reader(_builder.asReader()); }
|
|
||||||
inline Reader asReader() const { return *this; }
|
|
||||||
|
|
||||||
inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }
|
|
||||||
#if !CAPNP_LITE
|
|
||||||
inline ::kj::StringTree toString() const { return asReader().toString(); }
|
|
||||||
#endif // !CAPNP_LITE
|
|
||||||
|
|
||||||
inline bool hasFileName();
|
|
||||||
inline ::capnp::Text::Builder getFileName();
|
|
||||||
inline void setFileName( ::capnp::Text::Reader value);
|
|
||||||
inline ::capnp::Text::Builder initFileName(unsigned int size);
|
|
||||||
inline void adoptFileName(::capnp::Orphan< ::capnp::Text>&& value);
|
|
||||||
inline ::capnp::Orphan< ::capnp::Text> disownFileName();
|
|
||||||
|
|
||||||
inline bool hasSha256();
|
|
||||||
inline ::capnp::Text::Builder getSha256();
|
|
||||||
inline void setSha256( ::capnp::Text::Reader value);
|
|
||||||
inline ::capnp::Text::Builder initSha256(unsigned int size);
|
|
||||||
inline void adoptSha256(::capnp::Orphan< ::capnp::Text>&& value);
|
|
||||||
inline ::capnp::Orphan< ::capnp::Text> disownSha256();
|
|
||||||
|
|
||||||
private:
|
|
||||||
::capnp::_::StructBuilder _builder;
|
|
||||||
template <typename, ::capnp::Kind>
|
|
||||||
friend struct ::capnp::ToDynamic_;
|
|
||||||
friend class ::capnp::Orphanage;
|
|
||||||
template <typename, ::capnp::Kind>
|
|
||||||
friend struct ::capnp::_::PointerHelpers;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if !CAPNP_LITE
|
|
||||||
class ModelManagerSP::Chunk::Pipeline {
|
|
||||||
public:
|
|
||||||
typedef Chunk Pipelines;
|
|
||||||
|
|
||||||
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
|
|
||||||
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
|
|
||||||
: _typeless(kj::mv(typeless)) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
::capnp::AnyPointer::Pipeline _typeless;
|
|
||||||
friend class ::capnp::PipelineHook;
|
|
||||||
template <typename, ::capnp::Kind>
|
|
||||||
friend struct ::capnp::ToDynamic_;
|
|
||||||
};
|
|
||||||
#endif // !CAPNP_LITE
|
|
||||||
|
|
||||||
class ModelManagerSP::Artifact::Reader {
|
class ModelManagerSP::Artifact::Reader {
|
||||||
public:
|
public:
|
||||||
typedef Artifact Reads;
|
typedef Artifact Reads;
|
||||||
@@ -1822,9 +1703,6 @@ public:
|
|||||||
inline bool hasDownloadProgress() const;
|
inline bool hasDownloadProgress() const;
|
||||||
inline ::cereal::ModelManagerSP::DownloadProgress::Reader getDownloadProgress() const;
|
inline ::cereal::ModelManagerSP::DownloadProgress::Reader getDownloadProgress() const;
|
||||||
|
|
||||||
inline bool hasChunks() const;
|
|
||||||
inline ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Reader getChunks() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::capnp::_::StructReader _reader;
|
::capnp::_::StructReader _reader;
|
||||||
template <typename, ::capnp::Kind>
|
template <typename, ::capnp::Kind>
|
||||||
@@ -1874,13 +1752,6 @@ public:
|
|||||||
inline void adoptDownloadProgress(::capnp::Orphan< ::cereal::ModelManagerSP::DownloadProgress>&& value);
|
inline void adoptDownloadProgress(::capnp::Orphan< ::cereal::ModelManagerSP::DownloadProgress>&& value);
|
||||||
inline ::capnp::Orphan< ::cereal::ModelManagerSP::DownloadProgress> disownDownloadProgress();
|
inline ::capnp::Orphan< ::cereal::ModelManagerSP::DownloadProgress> disownDownloadProgress();
|
||||||
|
|
||||||
inline bool hasChunks();
|
|
||||||
inline ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Builder getChunks();
|
|
||||||
inline void setChunks( ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Reader value);
|
|
||||||
inline ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Builder initChunks(unsigned int size);
|
|
||||||
inline void adoptChunks(::capnp::Orphan< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>&& value);
|
|
||||||
inline ::capnp::Orphan< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>> disownChunks();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::capnp::_::StructBuilder _builder;
|
::capnp::_::StructBuilder _builder;
|
||||||
template <typename, ::capnp::Kind>
|
template <typename, ::capnp::Kind>
|
||||||
@@ -5726,34 +5597,6 @@ inline ::capnp::Orphan< ::cereal::IntelligentCruiseButtonManagement> SelfdriveSt
|
|||||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
::capnp::bounded<1>() * ::capnp::POINTERS));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ::uint16_t SelfdriveStateSP::Reader::getButtonsPressed() const {
|
|
||||||
return _reader.getDataField< ::uint16_t>(
|
|
||||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ::uint16_t SelfdriveStateSP::Builder::getButtonsPressed() {
|
|
||||||
return _builder.getDataField< ::uint16_t>(
|
|
||||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
|
||||||
}
|
|
||||||
inline void SelfdriveStateSP::Builder::setButtonsPressed( ::uint16_t value) {
|
|
||||||
_builder.setDataField< ::uint16_t>(
|
|
||||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ::uint16_t SelfdriveStateSP::Reader::getButtonsReleaseToggle() const {
|
|
||||||
return _reader.getDataField< ::uint16_t>(
|
|
||||||
::capnp::bounded<1>() * ::capnp::ELEMENTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ::uint16_t SelfdriveStateSP::Builder::getButtonsReleaseToggle() {
|
|
||||||
return _builder.getDataField< ::uint16_t>(
|
|
||||||
::capnp::bounded<1>() * ::capnp::ELEMENTS);
|
|
||||||
}
|
|
||||||
inline void SelfdriveStateSP::Builder::setButtonsReleaseToggle( ::uint16_t value) {
|
|
||||||
_builder.setDataField< ::uint16_t>(
|
|
||||||
::capnp::bounded<1>() * ::capnp::ELEMENTS, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool ModelManagerSP::Reader::hasActiveBundle() const {
|
inline bool ModelManagerSP::Reader::hasActiveBundle() const {
|
||||||
return !_reader.getPointerField(
|
return !_reader.getPointerField(
|
||||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||||
@@ -5976,74 +5819,6 @@ inline void ModelManagerSP::DownloadProgress::Builder::setEta( ::uint32_t value)
|
|||||||
::capnp::bounded<2>() * ::capnp::ELEMENTS, value);
|
::capnp::bounded<2>() * ::capnp::ELEMENTS, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool ModelManagerSP::Chunk::Reader::hasFileName() const {
|
|
||||||
return !_reader.getPointerField(
|
|
||||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
|
||||||
}
|
|
||||||
inline bool ModelManagerSP::Chunk::Builder::hasFileName() {
|
|
||||||
return !_builder.getPointerField(
|
|
||||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
|
||||||
}
|
|
||||||
inline ::capnp::Text::Reader ModelManagerSP::Chunk::Reader::getFileName() const {
|
|
||||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField(
|
|
||||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
|
||||||
}
|
|
||||||
inline ::capnp::Text::Builder ModelManagerSP::Chunk::Builder::getFileName() {
|
|
||||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField(
|
|
||||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
|
||||||
}
|
|
||||||
inline void ModelManagerSP::Chunk::Builder::setFileName( ::capnp::Text::Reader value) {
|
|
||||||
::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField(
|
|
||||||
::capnp::bounded<0>() * ::capnp::POINTERS), value);
|
|
||||||
}
|
|
||||||
inline ::capnp::Text::Builder ModelManagerSP::Chunk::Builder::initFileName(unsigned int size) {
|
|
||||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField(
|
|
||||||
::capnp::bounded<0>() * ::capnp::POINTERS), size);
|
|
||||||
}
|
|
||||||
inline void ModelManagerSP::Chunk::Builder::adoptFileName(
|
|
||||||
::capnp::Orphan< ::capnp::Text>&& value) {
|
|
||||||
::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField(
|
|
||||||
::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value));
|
|
||||||
}
|
|
||||||
inline ::capnp::Orphan< ::capnp::Text> ModelManagerSP::Chunk::Builder::disownFileName() {
|
|
||||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField(
|
|
||||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool ModelManagerSP::Chunk::Reader::hasSha256() const {
|
|
||||||
return !_reader.getPointerField(
|
|
||||||
::capnp::bounded<1>() * ::capnp::POINTERS).isNull();
|
|
||||||
}
|
|
||||||
inline bool ModelManagerSP::Chunk::Builder::hasSha256() {
|
|
||||||
return !_builder.getPointerField(
|
|
||||||
::capnp::bounded<1>() * ::capnp::POINTERS).isNull();
|
|
||||||
}
|
|
||||||
inline ::capnp::Text::Reader ModelManagerSP::Chunk::Reader::getSha256() const {
|
|
||||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField(
|
|
||||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
|
||||||
}
|
|
||||||
inline ::capnp::Text::Builder ModelManagerSP::Chunk::Builder::getSha256() {
|
|
||||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField(
|
|
||||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
|
||||||
}
|
|
||||||
inline void ModelManagerSP::Chunk::Builder::setSha256( ::capnp::Text::Reader value) {
|
|
||||||
::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField(
|
|
||||||
::capnp::bounded<1>() * ::capnp::POINTERS), value);
|
|
||||||
}
|
|
||||||
inline ::capnp::Text::Builder ModelManagerSP::Chunk::Builder::initSha256(unsigned int size) {
|
|
||||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField(
|
|
||||||
::capnp::bounded<1>() * ::capnp::POINTERS), size);
|
|
||||||
}
|
|
||||||
inline void ModelManagerSP::Chunk::Builder::adoptSha256(
|
|
||||||
::capnp::Orphan< ::capnp::Text>&& value) {
|
|
||||||
::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField(
|
|
||||||
::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value));
|
|
||||||
}
|
|
||||||
inline ::capnp::Orphan< ::capnp::Text> ModelManagerSP::Chunk::Builder::disownSha256() {
|
|
||||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField(
|
|
||||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool ModelManagerSP::Artifact::Reader::hasFileName() const {
|
inline bool ModelManagerSP::Artifact::Reader::hasFileName() const {
|
||||||
return !_reader.getPointerField(
|
return !_reader.getPointerField(
|
||||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||||
@@ -6156,40 +5931,6 @@ inline ::capnp::Orphan< ::cereal::ModelManagerSP::DownloadProgress> ModelManager
|
|||||||
::capnp::bounded<2>() * ::capnp::POINTERS));
|
::capnp::bounded<2>() * ::capnp::POINTERS));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool ModelManagerSP::Artifact::Reader::hasChunks() const {
|
|
||||||
return !_reader.getPointerField(
|
|
||||||
::capnp::bounded<3>() * ::capnp::POINTERS).isNull();
|
|
||||||
}
|
|
||||||
inline bool ModelManagerSP::Artifact::Builder::hasChunks() {
|
|
||||||
return !_builder.getPointerField(
|
|
||||||
::capnp::bounded<3>() * ::capnp::POINTERS).isNull();
|
|
||||||
}
|
|
||||||
inline ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Reader ModelManagerSP::Artifact::Reader::getChunks() const {
|
|
||||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField(
|
|
||||||
::capnp::bounded<3>() * ::capnp::POINTERS));
|
|
||||||
}
|
|
||||||
inline ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Builder ModelManagerSP::Artifact::Builder::getChunks() {
|
|
||||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField(
|
|
||||||
::capnp::bounded<3>() * ::capnp::POINTERS));
|
|
||||||
}
|
|
||||||
inline void ModelManagerSP::Artifact::Builder::setChunks( ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Reader value) {
|
|
||||||
::capnp::_::PointerHelpers< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField(
|
|
||||||
::capnp::bounded<3>() * ::capnp::POINTERS), value);
|
|
||||||
}
|
|
||||||
inline ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>::Builder ModelManagerSP::Artifact::Builder::initChunks(unsigned int size) {
|
|
||||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField(
|
|
||||||
::capnp::bounded<3>() * ::capnp::POINTERS), size);
|
|
||||||
}
|
|
||||||
inline void ModelManagerSP::Artifact::Builder::adoptChunks(
|
|
||||||
::capnp::Orphan< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>&& value) {
|
|
||||||
::capnp::_::PointerHelpers< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField(
|
|
||||||
::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value));
|
|
||||||
}
|
|
||||||
inline ::capnp::Orphan< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>> ModelManagerSP::Artifact::Builder::disownChunks() {
|
|
||||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::cereal::ModelManagerSP::Chunk, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField(
|
|
||||||
::capnp::bounded<3>() * ::capnp::POINTERS));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ::cereal::ModelManagerSP::Model::Type ModelManagerSP::Model::Reader::getType() const {
|
inline ::cereal::ModelManagerSP::Model::Type ModelManagerSP::Model::Reader::getType() const {
|
||||||
return _reader.getDataField< ::cereal::ModelManagerSP::Model::Type>(
|
return _reader.getDataField< ::cereal::ModelManagerSP::Model::Type>(
|
||||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||||
|
|||||||
@@ -222,7 +222,6 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"SubaruStopAndGo", {PERSISTENT | BACKUP, BOOL, "0"}},
|
{"SubaruStopAndGo", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"SubaruStopAndGoManualParkingBrake", {PERSISTENT | BACKUP, BOOL, "0"}},
|
{"SubaruStopAndGoManualParkingBrake", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"TeslaCoopSteering", {PERSISTENT | BACKUP, BOOL, "0"}},
|
{"TeslaCoopSteering", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"TeslaMadsScreenButton", {PERSISTENT | BACKUP, INT, "0"}},
|
|
||||||
{"ToyotaEnforceStockLongitudinal", {PERSISTENT | BACKUP, BOOL, "0"}},
|
{"ToyotaEnforceStockLongitudinal", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"ToyotaStopAndGoHack", {PERSISTENT | BACKUP, BOOL, "0"}},
|
{"ToyotaStopAndGoHack", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -1,524 +0,0 @@
|
|||||||
{
|
|
||||||
"acados_include_path": "/usr/local/venv/lib/python3.12/site-packages/acados/install/include",
|
|
||||||
"acados_lib_path": "/usr/local/venv/lib/python3.12/site-packages/acados/install/lib",
|
|
||||||
"code_export_directory": "/data/openpilot/openpilot/selfdrive/controls/lib/longitudinal_mpc_lib/c_generated_code",
|
|
||||||
"constraints": {
|
|
||||||
"C": [],
|
|
||||||
"C_e": [],
|
|
||||||
"D": [],
|
|
||||||
"constr_type": "BGH",
|
|
||||||
"constr_type_e": "BGH",
|
|
||||||
"idxbu": [],
|
|
||||||
"idxbx": [],
|
|
||||||
"idxbx_0": [
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
"idxbx_e": [],
|
|
||||||
"idxbxe_0": [
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
"idxsbu": [],
|
|
||||||
"idxsbx": [],
|
|
||||||
"idxsbx_e": [],
|
|
||||||
"idxsg": [],
|
|
||||||
"idxsg_e": [],
|
|
||||||
"idxsh": [
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3
|
|
||||||
],
|
|
||||||
"idxsh_e": [],
|
|
||||||
"idxsphi": [],
|
|
||||||
"idxsphi_e": [],
|
|
||||||
"lbu": [],
|
|
||||||
"lbx": [],
|
|
||||||
"lbx_0": [
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
"lbx_e": [],
|
|
||||||
"lg": [],
|
|
||||||
"lg_e": [],
|
|
||||||
"lh": [
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
"lh_e": [],
|
|
||||||
"lphi": [],
|
|
||||||
"lphi_e": [],
|
|
||||||
"lsbu": [],
|
|
||||||
"lsbx": [],
|
|
||||||
"lsbx_e": [],
|
|
||||||
"lsg": [],
|
|
||||||
"lsg_e": [],
|
|
||||||
"lsh": [
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
"lsh_e": [],
|
|
||||||
"lsphi": [],
|
|
||||||
"lsphi_e": [],
|
|
||||||
"ubu": [],
|
|
||||||
"ubx": [],
|
|
||||||
"ubx_0": [
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
"ubx_e": [],
|
|
||||||
"ug": [],
|
|
||||||
"ug_e": [],
|
|
||||||
"uh": [
|
|
||||||
10000.0,
|
|
||||||
10000.0,
|
|
||||||
10000.0,
|
|
||||||
10000.0
|
|
||||||
],
|
|
||||||
"uh_e": [],
|
|
||||||
"uphi": [],
|
|
||||||
"uphi_e": [],
|
|
||||||
"usbu": [],
|
|
||||||
"usbx": [],
|
|
||||||
"usbx_e": [],
|
|
||||||
"usg": [],
|
|
||||||
"usg_e": [],
|
|
||||||
"ush": [
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
"ush_e": [],
|
|
||||||
"usphi": [],
|
|
||||||
"usphi_e": []
|
|
||||||
},
|
|
||||||
"cost": {
|
|
||||||
"Vu": [],
|
|
||||||
"Vu_0": [],
|
|
||||||
"Vx": [],
|
|
||||||
"Vx_0": [],
|
|
||||||
"Vx_e": [],
|
|
||||||
"Vz": [],
|
|
||||||
"Vz_0": [],
|
|
||||||
"W": [
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"W_0": [
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"W_e": [
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"Zl": [
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
"Zl_e": [],
|
|
||||||
"Zu": [
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
"Zu_e": [],
|
|
||||||
"cost_ext_fun_type": "casadi",
|
|
||||||
"cost_ext_fun_type_0": "casadi",
|
|
||||||
"cost_ext_fun_type_e": "casadi",
|
|
||||||
"cost_type": "NONLINEAR_LS",
|
|
||||||
"cost_type_0": "NONLINEAR_LS",
|
|
||||||
"cost_type_e": "NONLINEAR_LS",
|
|
||||||
"yref": [
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
"yref_0": [
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
"yref_e": [
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
"zl": [
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
"zl_e": [],
|
|
||||||
"zu": [
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0
|
|
||||||
],
|
|
||||||
"zu_e": []
|
|
||||||
},
|
|
||||||
"cython_include_dirs": [
|
|
||||||
"/usr/local/venv/lib/python3.12/site-packages/numpy/_core/include",
|
|
||||||
"/usr/include/python3.12"
|
|
||||||
],
|
|
||||||
"dims": {
|
|
||||||
"N": 12,
|
|
||||||
"nbu": 0,
|
|
||||||
"nbx": 0,
|
|
||||||
"nbx_0": 3,
|
|
||||||
"nbx_e": 0,
|
|
||||||
"nbxe_0": 3,
|
|
||||||
"ng": 0,
|
|
||||||
"ng_e": 0,
|
|
||||||
"nh": 4,
|
|
||||||
"nh_e": 0,
|
|
||||||
"np": 6,
|
|
||||||
"nphi": 0,
|
|
||||||
"nphi_e": 0,
|
|
||||||
"nr": 0,
|
|
||||||
"nr_e": 0,
|
|
||||||
"ns": 4,
|
|
||||||
"ns_e": 0,
|
|
||||||
"nsbu": 0,
|
|
||||||
"nsbx": 0,
|
|
||||||
"nsbx_e": 0,
|
|
||||||
"nsg": 0,
|
|
||||||
"nsg_e": 0,
|
|
||||||
"nsh": 4,
|
|
||||||
"nsh_e": 0,
|
|
||||||
"nsphi": 0,
|
|
||||||
"nsphi_e": 0,
|
|
||||||
"nu": 1,
|
|
||||||
"nx": 3,
|
|
||||||
"ny": 6,
|
|
||||||
"ny_0": 6,
|
|
||||||
"ny_e": 5,
|
|
||||||
"nz": 0
|
|
||||||
},
|
|
||||||
"json_file": "/data/openpilot/openpilot/selfdrive/controls/lib/longitudinal_mpc_lib/acados_ocp_long.json",
|
|
||||||
"model": {
|
|
||||||
"con_h_expr": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegiaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpgegpcaaaaaaaaaaaaaafaaaaaaabgpfngjgogegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaabgpfngbgihchcaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaakaaaaaaaihpfpgcgdhehbgdgmgfgegpcaaaaaaaaaaaaaafaaaaaaaihpffghgpgegdaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaacbaaaaaamgfgbgegpfegbgoghgfgchpfggbgdgehpgchegbaaaaaaaaaaaaaaaegbaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaeglaaaaaaaaaaaaaaachbaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajgfaaaaaaaegdaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaanaaaaaaamgfgbgegpfehpfggpgmgmgpghhchbaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajggaaaaaaaegbaaaaaaaaaaaaaaachbaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajgkaaaaaaa",
|
|
||||||
"con_h_expr_e": null,
|
|
||||||
"con_phi_expr": null,
|
|
||||||
"con_phi_expr_e": null,
|
|
||||||
"con_r_expr": null,
|
|
||||||
"con_r_expr_e": null,
|
|
||||||
"con_r_in_phi": null,
|
|
||||||
"con_r_in_phi_e": null,
|
|
||||||
"cost_conl_custom_outer_hess": null,
|
|
||||||
"cost_conl_custom_outer_hess_0": null,
|
|
||||||
"cost_conl_custom_outer_hess_e": null,
|
|
||||||
"cost_expr_ext_cost": null,
|
|
||||||
"cost_expr_ext_cost_0": null,
|
|
||||||
"cost_expr_ext_cost_custom_hess": null,
|
|
||||||
"cost_expr_ext_cost_custom_hess_0": null,
|
|
||||||
"cost_expr_ext_cost_custom_hess_e": null,
|
|
||||||
"cost_expr_ext_cost_e": null,
|
|
||||||
"cost_psi_expr": null,
|
|
||||||
"cost_psi_expr_0": null,
|
|
||||||
"cost_psi_expr_e": null,
|
|
||||||
"cost_r_in_psi_expr": null,
|
|
||||||
"cost_r_in_psi_expr_0": null,
|
|
||||||
"cost_r_in_psi_expr_e": null,
|
|
||||||
"cost_y_expr": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegkaaaaaaaaaaaaaaagaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaafaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaakaaaaaaaihpfpgcgdhehbgdgmgfgegpcaaaaaaaaaaaaaafaaaaaaaihpffghgpgegbaaaaaaaaaaaaaaaegbaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaeglaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegmcaaaaaaaaaaaaaajgfaaaaaaaegdaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaanaaaaaaamgfgbgegpfehpfggpgmgmgpghhcheaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajggaaaaaaaegbaaaaaaaaaaaaaaacheaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajgkaaaaaaachcaaaaaaaaaaaaaaacheaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpgegcaaaaaaaaaaaaaaachbbaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaagaaaaaaabgpfahchfgghegpcaaaaaaaaaaaaaafaaaaaaakgpffghgpg",
|
|
||||||
"cost_y_expr_0": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegkaaaaaaaaaaaaaaagaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaafaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaakaaaaaaaihpfpgcgdhehbgdgmgfgegpcaaaaaaaaaaaaaafaaaaaaaihpffghgpgegbaaaaaaaaaaaaaaaegbaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaeglaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegmcaaaaaaaaaaaaaajgfaaaaaaaegdaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaanaaaaaaamgfgbgegpfehpfggpgmgmgpghhcheaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajggaaaaaaaegbaaaaaaaaaaaaaaacheaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajgkaaaaaaachcaaaaaaaaaaaaaaacheaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpgegcaaaaaaaaaaaaaaachbbaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaagaaaaaaabgpfahchfgghegpcaaaaaaaaaaaaaafaaaaaaakgpffghgpg",
|
|
||||||
"cost_y_expr_e": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegjaaaaaaaaaaaaaaafaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaakaaaaaaaihpfpgcgdhehbgdgmgfgegpcaaaaaaaaaaaaaafaaaaaaaihpffghgpgegbaaaaaaaaaaaaaaaegbaaaaaaaaaaaaaaaegeaaaaaaaaaaaaaaaeglaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegmcaaaaaaaaaaaaaajgfaaaaaaaegdaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaanaaaaaaamgfgbgegpfehpfggpgmgmgpghhcheaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajggaaaaaaaegbaaaaaaaaaaaaaaacheaaaaaaaaaaaaaaaegmcaaaaaaaaaaaaaajgkaaaaaaachcaaaaaaaaaaaaaaacheaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpgegcaaaaaaaaaaaaaaachbbaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaagaaaaaaabgpfahchfggh",
|
|
||||||
"disc_dyn_expr": null,
|
|
||||||
"dyn_disc_fun": null,
|
|
||||||
"dyn_disc_fun_jac": null,
|
|
||||||
"dyn_disc_fun_jac_hess": null,
|
|
||||||
"dyn_ext_fun_type": "casadi",
|
|
||||||
"dyn_generic_source": null,
|
|
||||||
"f_expl_expr": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaeghaaaaaaaaaaaaaaadaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpgegpcaaaaaaaaaaaaaafaaaaaaakgpffghgpg",
|
|
||||||
"f_impl_expr": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaeghaaaaaaaaaaaaaaadaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaajaaaaaaaihpffghgpgpfegpgehegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaajaaaaaaaghpffghgpgpfegpgehegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpgegcaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaajaaaaaaabgpffghgpgpfegpgehegpcaaaaaaaaaaaaaafaaaaaaakgpffghgpg",
|
|
||||||
"gnsf": {
|
|
||||||
"nontrivial_f_LO": 1,
|
|
||||||
"purely_linear": 0
|
|
||||||
},
|
|
||||||
"name": "long",
|
|
||||||
"p": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegkaaaaaaaaaaaaaaagaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaeaaaaaaaaaaaaaaafaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaabgpfngjgogegpcaaaaaaaaaaaaaafaaaaaaabgpfngbgihegpcaaaaaaaaaaaaaakaaaaaaaihpfpgcgdhehbgdgmgfgegpcaaaaaaaaaaaaaagaaaaaaabgpfahchfgghegpcaaaaaaaaaaaaaanaaaaaaamgfgbgegpfehpfggpgmgmgpghhegpcaaaaaaaaaaaaaacbaaaaaamgfgbgegpfegbgoghgfgchpfggbgdgehpgch",
|
|
||||||
"u": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegfaaaaaaaaaaaaaaabaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaakgpffghgpg",
|
|
||||||
"x": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaeghaaaaaaaaaaaaaaadaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaafaaaaaaaihpffghgpgegpcaaaaaaaaaaaaaafaaaaaaaghpffghgpgegpcaaaaaaaaaaaaaafaaaaaaabgpffghgpg",
|
|
||||||
"xdot": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaeghaaaaaaaaaaaaaaadaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaacaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaegpcaaaaaaaaaaaaaajaaaaaaaihpffghgpgpfegpgehegpcaaaaaaaaaaaaaajaaaaaaaghpffghgpgpfegpgehegpcaaaaaaaaaaaaaajaaaaaaabgpffghgpgpfegpgeh",
|
|
||||||
"z": "jhpnnagiieahaaaadaaaaaaaaaaaaaaaaaegdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
||||||
},
|
|
||||||
"parameter_values": [
|
|
||||||
-1.2,
|
|
||||||
1.2,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
1.45,
|
|
||||||
0.75
|
|
||||||
],
|
|
||||||
"problem_class": "OCP",
|
|
||||||
"shared_lib_ext": ".so",
|
|
||||||
"solver_options": {
|
|
||||||
"Tsim": 0.06944444444444445,
|
|
||||||
"alpha_min": 0.05,
|
|
||||||
"alpha_reduction": 0.7,
|
|
||||||
"collocation_type": "GAUSS_LEGENDRE",
|
|
||||||
"custom_templates": [],
|
|
||||||
"custom_update_copy": true,
|
|
||||||
"custom_update_filename": "",
|
|
||||||
"custom_update_header_filename": "",
|
|
||||||
"eps_sufficient_descent": 0.0001,
|
|
||||||
"exact_hess_constr": 1,
|
|
||||||
"exact_hess_cost": 1,
|
|
||||||
"exact_hess_dyn": 1,
|
|
||||||
"ext_cost_num_hess": 0,
|
|
||||||
"ext_fun_compile_flags": "-O2",
|
|
||||||
"full_step_dual": 0,
|
|
||||||
"globalization": "FIXED_STEP",
|
|
||||||
"globalization_use_SOC": 0,
|
|
||||||
"hessian_approx": "GAUSS_NEWTON",
|
|
||||||
"hpipm_mode": "BALANCE",
|
|
||||||
"initialize_t_slacks": 0,
|
|
||||||
"integrator_type": "ERK",
|
|
||||||
"levenberg_marquardt": 0.0,
|
|
||||||
"line_search_use_sufficient_descent": 0,
|
|
||||||
"model_external_shared_lib_dir": null,
|
|
||||||
"model_external_shared_lib_name": null,
|
|
||||||
"nlp_solver_ext_qp_res": 0,
|
|
||||||
"nlp_solver_max_iter": 100,
|
|
||||||
"nlp_solver_step_length": 1.0,
|
|
||||||
"nlp_solver_tol_comp": 1e-06,
|
|
||||||
"nlp_solver_tol_eq": 1e-06,
|
|
||||||
"nlp_solver_tol_ineq": 1e-06,
|
|
||||||
"nlp_solver_tol_stat": 1e-06,
|
|
||||||
"nlp_solver_type": "SQP_RTI",
|
|
||||||
"print_level": 0,
|
|
||||||
"qp_solver": "PARTIAL_CONDENSING_HPIPM",
|
|
||||||
"qp_solver_cond_N": 1,
|
|
||||||
"qp_solver_cond_ric_alg": 1,
|
|
||||||
"qp_solver_iter_max": 10,
|
|
||||||
"qp_solver_ric_alg": 1,
|
|
||||||
"qp_solver_tol_comp": 0.001,
|
|
||||||
"qp_solver_tol_eq": 0.001,
|
|
||||||
"qp_solver_tol_ineq": 0.001,
|
|
||||||
"qp_solver_tol_stat": 0.001,
|
|
||||||
"qp_solver_warm_start": 0,
|
|
||||||
"regularize_method": null,
|
|
||||||
"shooting_nodes": [
|
|
||||||
0.0,
|
|
||||||
0.06944444444444445,
|
|
||||||
0.2777777777777778,
|
|
||||||
0.625,
|
|
||||||
1.1111111111111112,
|
|
||||||
1.7361111111111114,
|
|
||||||
2.5,
|
|
||||||
3.4027777777777786,
|
|
||||||
4.444444444444445,
|
|
||||||
5.625,
|
|
||||||
6.9444444444444455,
|
|
||||||
8.402777777777777,
|
|
||||||
10.0
|
|
||||||
],
|
|
||||||
"sim_method_jac_reuse": [
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
],
|
|
||||||
"sim_method_newton_iter": 3,
|
|
||||||
"sim_method_newton_tol": 0.0,
|
|
||||||
"sim_method_num_stages": [
|
|
||||||
4,
|
|
||||||
4,
|
|
||||||
4,
|
|
||||||
4,
|
|
||||||
4,
|
|
||||||
4,
|
|
||||||
4,
|
|
||||||
4,
|
|
||||||
4,
|
|
||||||
4,
|
|
||||||
4,
|
|
||||||
4
|
|
||||||
],
|
|
||||||
"sim_method_num_steps": [
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
],
|
|
||||||
"tf": 10.0,
|
|
||||||
"time_steps": [
|
|
||||||
0.06944444444444445,
|
|
||||||
0.20833333333333334,
|
|
||||||
0.3472222222222222,
|
|
||||||
0.48611111111111116,
|
|
||||||
0.6250000000000002,
|
|
||||||
0.7638888888888886,
|
|
||||||
0.9027777777777786,
|
|
||||||
1.041666666666666,
|
|
||||||
1.1805555555555554,
|
|
||||||
1.3194444444444455,
|
|
||||||
1.4583333333333313,
|
|
||||||
1.5972222222222232
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -158,7 +158,7 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
|
|||||||
def publish(self, sm, pm):
|
def publish(self, sm, pm):
|
||||||
plan_send = messaging.new_message('longitudinalPlan')
|
plan_send = messaging.new_message('longitudinalPlan')
|
||||||
|
|
||||||
plan_send.valid = sm.all_checks()
|
plan_send.valid = sm.all_checks(service_list=['carState', 'controlsState', 'selfdriveState', 'radarState'])
|
||||||
|
|
||||||
longitudinalPlan = plan_send.longitudinalPlan
|
longitudinalPlan = plan_send.longitudinalPlan
|
||||||
longitudinalPlan.modelMonoTime = sm.logMonoTime['modelV2']
|
longitudinalPlan.modelMonoTime = sm.logMonoTime['modelV2']
|
||||||
|
|||||||
@@ -29,19 +29,19 @@ def main():
|
|||||||
longitudinal_planner = LongitudinalPlanner(CP, CP_SP)
|
longitudinal_planner = LongitudinalPlanner(CP, CP_SP)
|
||||||
pm = messaging.PubMaster(['longitudinalPlan', 'driverAssistance', 'longitudinalPlanSP'])
|
pm = messaging.PubMaster(['longitudinalPlan', 'driverAssistance', 'longitudinalPlanSP'])
|
||||||
sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'liveParameters', 'radarState', 'modelV2', 'selfdriveState',
|
sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'liveParameters', 'radarState', 'modelV2', 'selfdriveState',
|
||||||
'liveMapDataSP', 'carStateSP', 'selfdriveStateSP', gps_location_service],
|
'liveMapDataSP', 'carStateSP', gps_location_service],
|
||||||
poll='modelV2', ignore_alive=ignore_services, ignore_avg_freq=ignore_services, ignore_valid=ignore_services)
|
poll='carState', ignore_alive=ignore_services, ignore_avg_freq=ignore_services, ignore_valid=ignore_services)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
sm.update()
|
sm.update()
|
||||||
longitudinal_planner.sla.update_buttons(sm['selfdriveStateSP'].buttonsReleaseToggle)
|
longitudinal_planner.sla.update_car_state(sm['carState'])
|
||||||
if sm.updated['modelV2']:
|
if sm.updated['modelV2']:
|
||||||
longitudinal_planner.update(sm)
|
longitudinal_planner.update(sm)
|
||||||
longitudinal_planner.publish(sm, pm)
|
longitudinal_planner.publish(sm, pm)
|
||||||
|
|
||||||
ldw.update(sm.frame, sm['modelV2'], sm['carState'], sm['carControl'])
|
ldw.update(sm.frame, sm['modelV2'], sm['carState'], sm['carControl'])
|
||||||
msg = messaging.new_message('driverAssistance')
|
msg = messaging.new_message('driverAssistance')
|
||||||
msg.valid = sm.all_checks()
|
msg.valid = sm.all_checks(['carState', 'carControl', 'modelV2', 'liveParameters'])
|
||||||
msg.driverAssistance.leftLaneDeparture = ldw.left
|
msg.driverAssistance.leftLaneDeparture = ldw.left
|
||||||
msg.driverAssistance.rightLaneDeparture = ldw.right
|
msg.driverAssistance.rightLaneDeparture = ldw.right
|
||||||
pm.send('driverAssistance', msg)
|
pm.send('driverAssistance', msg)
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -30,7 +30,6 @@ from openpilot.sunnypilot import get_sanitize_int_param
|
|||||||
from openpilot.sunnypilot.selfdrive.car.car_specific import CarSpecificEventsSP
|
from openpilot.sunnypilot.selfdrive.car.car_specific import CarSpecificEventsSP
|
||||||
from openpilot.sunnypilot.selfdrive.car.cruise_helpers import CruiseHelper
|
from openpilot.sunnypilot.selfdrive.car.cruise_helpers import CruiseHelper
|
||||||
from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.controller import IntelligentCruiseButtonManagement
|
from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.controller import IntelligentCruiseButtonManagement
|
||||||
from openpilot.sunnypilot.selfdrive.selfdrived.button_state_tracker import ButtonStateTracker
|
|
||||||
from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
|
from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
|
||||||
|
|
||||||
REPLAY = "REPLAY" in os.environ
|
REPLAY = "REPLAY" in os.environ
|
||||||
@@ -178,7 +177,6 @@ class SelfdriveD(CruiseHelper):
|
|||||||
self.car_events_sp = CarSpecificEventsSP(self.CP, self.CP_SP)
|
self.car_events_sp = CarSpecificEventsSP(self.CP, self.CP_SP)
|
||||||
|
|
||||||
CruiseHelper.__init__(self, self.CP)
|
CruiseHelper.__init__(self, self.CP)
|
||||||
self.button_state_tracker = ButtonStateTracker()
|
|
||||||
|
|
||||||
def update_events(self, CS):
|
def update_events(self, CS):
|
||||||
"""Compute onroadEvents from carState"""
|
"""Compute onroadEvents from carState"""
|
||||||
@@ -599,8 +597,6 @@ class SelfdriveD(CruiseHelper):
|
|||||||
icbm.sendButton = self.icbm.cruise_button
|
icbm.sendButton = self.icbm.cruise_button
|
||||||
icbm.vTarget = self.icbm.v_target
|
icbm.vTarget = self.icbm.v_target
|
||||||
|
|
||||||
self.button_state_tracker.publish(ss_sp)
|
|
||||||
|
|
||||||
self.pm.send('selfdriveStateSP', ss_sp_msg)
|
self.pm.send('selfdriveStateSP', ss_sp_msg)
|
||||||
|
|
||||||
# onroadEventsSP - logged every second or on change
|
# onroadEventsSP - logged every second or on change
|
||||||
@@ -620,7 +616,6 @@ class SelfdriveD(CruiseHelper):
|
|||||||
self.mads.update(CS)
|
self.mads.update(CS)
|
||||||
self.update_alerts(CS)
|
self.update_alerts(CS)
|
||||||
|
|
||||||
self.button_state_tracker.update(CS)
|
|
||||||
self.publish_selfdriveState(CS)
|
self.publish_selfdriveState(CS)
|
||||||
|
|
||||||
self.CS_prev = CS
|
self.CS_prev = CS
|
||||||
|
|||||||
+2
-5
@@ -7,7 +7,7 @@ See the LICENSE.md file in the root directory for more details.
|
|||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
import pyray as rl
|
import pyray as rl
|
||||||
|
|
||||||
from opendbc.sunnypilot.car.tesla.values import MadsScreenButtonType, TeslaFlagsSP
|
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
|
||||||
from openpilot.selfdrive.ui.ui_state import ui_state
|
from openpilot.selfdrive.ui.ui_state import ui_state
|
||||||
from openpilot.sunnypilot.mads.helpers import MadsSteeringModeOnBrake
|
from openpilot.sunnypilot.mads.helpers import MadsSteeringModeOnBrake
|
||||||
from openpilot.system.ui.lib.multilang import tr, tr_noop
|
from openpilot.system.ui.lib.multilang import tr, tr_noop
|
||||||
@@ -96,10 +96,7 @@ class MadsSettingsLayout(Widget):
|
|||||||
if brand == "rivian":
|
if brand == "rivian":
|
||||||
return True
|
return True
|
||||||
elif brand == "tesla":
|
elif brand == "tesla":
|
||||||
if ui_state.CP_SP is None or not ui_state.CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS:
|
return not (ui_state.CP_SP is not None and ui_state.CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS)
|
||||||
return True
|
|
||||||
screen_button = int(ui_state.params.get("TeslaMadsScreenButton", return_default=True))
|
|
||||||
return screen_button == MadsScreenButtonType.OFF
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _update_steering_mode_description(self, button_index: int):
|
def _update_steering_mode_description(self, button_index: int):
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
|||||||
This file is part of sunnypilot and is licensed under the MIT License.
|
This file is part of sunnypilot and is licensed under the MIT License.
|
||||||
See the LICENSE.md file in the root directory for more details.
|
See the LICENSE.md file in the root directory for more details.
|
||||||
"""
|
"""
|
||||||
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
|
|
||||||
from openpilot.selfdrive.ui.sunnypilot.layouts.settings.vehicle.brands.base import BrandSettings
|
from openpilot.selfdrive.ui.sunnypilot.layouts.settings.vehicle.brands.base import BrandSettings
|
||||||
from openpilot.selfdrive.ui.ui_state import ui_state
|
from openpilot.selfdrive.ui.ui_state import ui_state
|
||||||
from openpilot.system.ui.lib.multilang import tr
|
from openpilot.system.ui.lib.multilang import tr
|
||||||
from openpilot.system.ui.sunnypilot.widgets.list_view import multiple_button_item_sp, toggle_item_sp
|
from openpilot.system.ui.sunnypilot.widgets.list_view import toggle_item_sp
|
||||||
|
|
||||||
COOP_STEERING_MIN_KMH = 23
|
COOP_STEERING_MIN_KMH = 23
|
||||||
OEM_STEERING_MIN_KMH = 48
|
OEM_STEERING_MIN_KMH = 48
|
||||||
@@ -19,14 +18,7 @@ class TeslaSettings(BrandSettings):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.coop_steering_toggle = toggle_item_sp(tr("Cooperative Steering (Beta)"), "", param="TeslaCoopSteering")
|
self.coop_steering_toggle = toggle_item_sp(tr("Cooperative Steering (Beta)"), "", param="TeslaCoopSteering")
|
||||||
self.mads_screen_button = multiple_button_item_sp(
|
self.items = [self.coop_steering_toggle]
|
||||||
title=lambda: tr("MADS Screen Activation"),
|
|
||||||
description="",
|
|
||||||
buttons=[lambda: tr("Off"), lambda: tr("3-Finger"), lambda: tr("4-Finger"), lambda: tr("5-Finger")],
|
|
||||||
param="TeslaMadsScreenButton",
|
|
||||||
inline=False,
|
|
||||||
)
|
|
||||||
self.items = [self.coop_steering_toggle, self.mads_screen_button]
|
|
||||||
|
|
||||||
def update_settings(self):
|
def update_settings(self):
|
||||||
is_metric = ui_state.is_metric
|
is_metric = ui_state.is_metric
|
||||||
@@ -49,18 +41,3 @@ class TeslaSettings(BrandSettings):
|
|||||||
|
|
||||||
self.coop_steering_toggle.set_description(coop_steering_desc)
|
self.coop_steering_toggle.set_description(coop_steering_desc)
|
||||||
self.coop_steering_toggle.action_item.set_enabled(ui_state.is_offroad())
|
self.coop_steering_toggle.action_item.set_enabled(ui_state.is_offroad())
|
||||||
|
|
||||||
has_vehicle_bus = ui_state.CP_SP is not None and bool(ui_state.CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS)
|
|
||||||
self.mads_screen_button.set_visible(has_vehicle_bus)
|
|
||||||
|
|
||||||
mads_screen_button_desc = (
|
|
||||||
f"{tr('Use a multi-finger press on the infotainment screen to toggle MADS.')} " +
|
|
||||||
f"{tr('This allows the use of full MADS functionality when enabled.')}<br><br>" +
|
|
||||||
f"{tr('Selecting a higher finger count may reduce accidental activations.')}<br><br>" +
|
|
||||||
f"<b>{tr('Note: Setting this to Off will reset your MADS settings to default.')}</b>"
|
|
||||||
)
|
|
||||||
if not ui_state.is_offroad():
|
|
||||||
mads_screen_button_disabled_msg = tr("Enable \"Always Offroad\" in Device panel, or turn vehicle off to change.")
|
|
||||||
mads_screen_button_desc = f"<b>{mads_screen_button_disabled_msg}</b><br><br>{mads_screen_button_desc}"
|
|
||||||
self.mads_screen_button.set_description(mads_screen_button_desc)
|
|
||||||
self.mads_screen_button.action_item.set_enabled(ui_state.is_offroad())
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define SUNNYPILOT_VERSION "2026.08.04-4608"
|
#define SUNNYPILOT_VERSION "2026.07.27-4598"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from openpilot.common.params import Params
|
|||||||
from opendbc.car import structs
|
from opendbc.car import structs
|
||||||
from opendbc.safety import ALTERNATIVE_EXPERIENCE
|
from opendbc.safety import ALTERNATIVE_EXPERIENCE
|
||||||
from opendbc.sunnypilot.car.hyundai.values import HyundaiFlagsSP, HyundaiSafetyFlagsSP
|
from opendbc.sunnypilot.car.hyundai.values import HyundaiFlagsSP, HyundaiSafetyFlagsSP
|
||||||
from opendbc.sunnypilot.car.tesla.values import MadsScreenButtonType, TeslaFlagsSP
|
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
|
||||||
|
|
||||||
|
|
||||||
MADS_NO_ACC_MAIN_BUTTON = ("rivian", "tesla")
|
MADS_NO_ACC_MAIN_BUTTON = ("rivian", "tesla")
|
||||||
@@ -21,20 +21,17 @@ class MadsSteeringModeOnBrake:
|
|||||||
DISENGAGE = 2
|
DISENGAGE = 2
|
||||||
|
|
||||||
|
|
||||||
def get_mads_limited_brands(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params) -> bool:
|
def get_mads_limited_brands(CP: structs.CarParams, CP_SP: structs.CarParamsSP) -> bool:
|
||||||
if CP.brand == 'rivian':
|
if CP.brand == 'rivian':
|
||||||
return True
|
return True
|
||||||
if CP.brand == 'tesla':
|
if CP.brand == 'tesla':
|
||||||
if not CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS:
|
return not CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS
|
||||||
return True
|
|
||||||
screen_button = int(params.get("TeslaMadsScreenButton", return_default=True))
|
|
||||||
return screen_button == MadsScreenButtonType.OFF
|
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def read_steering_mode_param(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params):
|
def read_steering_mode_param(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params):
|
||||||
if get_mads_limited_brands(CP, CP_SP, params):
|
if get_mads_limited_brands(CP, CP_SP):
|
||||||
return MadsSteeringModeOnBrake.DISENGAGE
|
return MadsSteeringModeOnBrake.DISENGAGE
|
||||||
|
|
||||||
return params.get("MadsSteeringMode", return_default=True)
|
return params.get("MadsSteeringMode", return_default=True)
|
||||||
@@ -66,7 +63,7 @@ def set_car_specific_params(CP: structs.CarParams, CP_SP: structs.CarParamsSP, p
|
|||||||
# MADS is currently partially supported for these platforms due to lack of consistent states to engage controls
|
# MADS is currently partially supported for these platforms due to lack of consistent states to engage controls
|
||||||
# Only MadsSteeringModeOnBrake.DISENGAGE is supported for these platforms
|
# Only MadsSteeringModeOnBrake.DISENGAGE is supported for these platforms
|
||||||
# TODO-SP: To enable MADS full support for Rivian and most Tesla, identify consistent signals for MADS toggling
|
# TODO-SP: To enable MADS full support for Rivian and most Tesla, identify consistent signals for MADS toggling
|
||||||
mads_partial_support = get_mads_limited_brands(CP, CP_SP, params)
|
mads_partial_support = get_mads_limited_brands(CP, CP_SP)
|
||||||
if mads_partial_support:
|
if mads_partial_support:
|
||||||
params.put("MadsSteeringMode", 2, block=True)
|
params.put("MadsSteeringMode", 2, block=True)
|
||||||
params.put_bool("MadsUnifiedEngagementMode", True, block=True)
|
params.put_bool("MadsUnifiedEngagementMode", True, block=True)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from openpilot.selfdrive.selfdrived.events import Events
|
|||||||
from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
|
from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
|
||||||
from openpilot.sunnypilot.mads.helpers import MadsSteeringModeOnBrake, read_steering_mode_param
|
from openpilot.sunnypilot.mads.helpers import MadsSteeringModeOnBrake, read_steering_mode_param
|
||||||
from openpilot.sunnypilot.mads.mads import ModularAssistiveDrivingSystem
|
from openpilot.sunnypilot.mads.mads import ModularAssistiveDrivingSystem
|
||||||
from opendbc.sunnypilot.car.tesla.values import MadsScreenButtonType, TeslaFlagsSP
|
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
|
||||||
|
|
||||||
State = custom.ModularAssistiveDrivingSystem.ModularAssistiveDrivingSystemState
|
State = custom.ModularAssistiveDrivingSystem.ModularAssistiveDrivingSystemState
|
||||||
EventName = log.OnroadEvent.EventName
|
EventName = log.OnroadEvent.EventName
|
||||||
@@ -38,12 +38,6 @@ def make_panda_state(mocker, controls_allowed_lateral=True):
|
|||||||
return ps
|
return ps
|
||||||
|
|
||||||
|
|
||||||
def make_params_mock(mocker, values):
|
|
||||||
params = mocker.MagicMock()
|
|
||||||
params.get = mocker.MagicMock(side_effect=lambda k, **kwargs: values[k])
|
|
||||||
return params
|
|
||||||
|
|
||||||
|
|
||||||
def make_mads(mocker, steering_mode):
|
def make_mads(mocker, steering_mode):
|
||||||
sd = mocker.MagicMock()
|
sd = mocker.MagicMock()
|
||||||
sd.CP = structs.CarParams()
|
sd.CP = structs.CarParams()
|
||||||
@@ -229,27 +223,15 @@ class TestBrandSteeringModeRestrictions:
|
|||||||
params = mocker.MagicMock()
|
params = mocker.MagicMock()
|
||||||
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.DISENGAGE
|
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.DISENGAGE
|
||||||
|
|
||||||
@pytest.mark.parametrize("screen_button", [MadsScreenButtonType.THREE_FINGER,
|
def test_tesla_with_vehicle_bus_uses_param(self, mocker):
|
||||||
MadsScreenButtonType.FOUR_FINGER,
|
|
||||||
MadsScreenButtonType.FIVE_FINGER])
|
|
||||||
def test_tesla_with_vehicle_bus_uses_param(self, mocker, screen_button):
|
|
||||||
CP = structs.CarParams()
|
CP = structs.CarParams()
|
||||||
CP.brand = "tesla"
|
CP.brand = "tesla"
|
||||||
CP_SP = structs.CarParamsSP()
|
CP_SP = structs.CarParamsSP()
|
||||||
CP_SP.flags = TeslaFlagsSP.HAS_VEHICLE_BUS
|
CP_SP.flags = TeslaFlagsSP.HAS_VEHICLE_BUS
|
||||||
params = make_params_mock(mocker, {"TeslaMadsScreenButton": screen_button,
|
params = mocker.MagicMock()
|
||||||
"MadsSteeringMode": MadsSteeringModeOnBrake.REMAIN_ACTIVE})
|
params.get = mocker.MagicMock(return_value=MadsSteeringModeOnBrake.REMAIN_ACTIVE)
|
||||||
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.REMAIN_ACTIVE
|
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.REMAIN_ACTIVE
|
||||||
|
|
||||||
def test_tesla_with_vehicle_bus_screen_button_off_forced_to_disengage(self, mocker):
|
|
||||||
CP = structs.CarParams()
|
|
||||||
CP.brand = "tesla"
|
|
||||||
CP_SP = structs.CarParamsSP()
|
|
||||||
CP_SP.flags = TeslaFlagsSP.HAS_VEHICLE_BUS
|
|
||||||
params = make_params_mock(mocker, {"TeslaMadsScreenButton": MadsScreenButtonType.OFF,
|
|
||||||
"MadsSteeringMode": MadsSteeringModeOnBrake.REMAIN_ACTIVE})
|
|
||||||
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.DISENGAGE
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("brand", ["hyundai", "toyota", "honda", "gm"])
|
@pytest.mark.parametrize("brand", ["hyundai", "toyota", "honda", "gm"])
|
||||||
def test_other_brands_use_param(self, mocker, brand):
|
def test_other_brands_use_param(self, mocker, brand):
|
||||||
CP = structs.CarParams()
|
CP = structs.CarParams()
|
||||||
|
|||||||
@@ -10,291 +10,471 @@ import argparse
|
|||||||
import os
|
import os
|
||||||
import pickle
|
import pickle
|
||||||
import time
|
import time
|
||||||
from collections import defaultdict
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
os.environ['GMMU'] = '0'
|
from tinygrad.tensor import Tensor
|
||||||
|
|
||||||
def _patch_tinygrad_fetch_fw():
|
|
||||||
import hashlib
|
|
||||||
import pathlib
|
|
||||||
import zstandard
|
|
||||||
from tinygrad import helpers
|
|
||||||
_orig_fetch_fw = helpers.fetch_fw
|
|
||||||
def fetch_fw(path, name, sha256):
|
|
||||||
p = pathlib.Path(f"/lib/firmware/{path}/{name}.zst")
|
|
||||||
if p.is_file():
|
|
||||||
blob = zstandard.ZstdDecompressor().stream_reader(p.read_bytes()).read()
|
|
||||||
if hashlib.sha256(blob).hexdigest() == sha256:
|
|
||||||
return blob
|
|
||||||
return _orig_fetch_fw(path, name, sha256)
|
|
||||||
helpers.fetch_fw = fetch_fw
|
|
||||||
_patch_tinygrad_fetch_fw()
|
|
||||||
|
|
||||||
from openpilot.selfdrive.modeld.compile_modeld import NV12Frame, make_frame_prepare, sample_desire, sample_skip, shift_and_sample
|
|
||||||
from tinygrad import dtypes
|
|
||||||
from tinygrad.device import Device
|
from tinygrad.device import Device
|
||||||
from tinygrad.engine.jit import TinyJit
|
from tinygrad.engine.jit import TinyJit
|
||||||
from tinygrad.tensor import Tensor
|
|
||||||
|
from openpilot.selfdrive.modeld.compile_modeld import (
|
||||||
|
NV12Frame, make_frame_prepare,
|
||||||
|
shift_and_sample, sample_skip, sample_desire,
|
||||||
|
)
|
||||||
|
|
||||||
MODEL_TYPES = ('vision_policy', 'supercombo', 'vision_multi_policy')
|
MODEL_TYPES = ('vision_policy', 'supercombo', 'vision_multi_policy')
|
||||||
|
|
||||||
|
|
||||||
def _detect_desire_key(shapes: dict) -> str | None:
|
def _detect_desire_key(policy_input_shapes):
|
||||||
return next((key for key in shapes if key.startswith('desire')), None)
|
for k in policy_input_shapes:
|
||||||
|
if k.startswith('desire'):
|
||||||
|
return k
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _detect_vision_keys(shapes: dict) -> tuple[str | None, str | None]:
|
def _detect_vision_keys(vision_input_shapes):
|
||||||
img_keys = sorted(key for key in shapes if 'img' in key)
|
img_keys = sorted([k for k in vision_input_shapes if 'img' in k])
|
||||||
return (
|
road_key = next((k for k in img_keys if 'big' not in k), None)
|
||||||
next((key for key in img_keys if 'big' not in key), None),
|
wide_key = next((k for k in img_keys if 'big' in k), None)
|
||||||
next((key for key in img_keys if 'big' in key), None)
|
if road_key is None or wide_key is None:
|
||||||
)
|
raise ValueError(f"Cannot determine road/wide image keys from {list(vision_input_shapes.keys())}")
|
||||||
|
return road_key, wide_key
|
||||||
|
|
||||||
|
|
||||||
def derive_frame_skip(vision_input_shapes: dict, policy_input_shapes: dict) -> int:
|
def make_split_input_queues(vision_input_shapes, policy_input_shapes, frame_skip, device):
|
||||||
features_buffer = policy_input_shapes.get('features_buffer')
|
road_key, _ = _detect_vision_keys(vision_input_shapes)
|
||||||
return 1 if not features_buffer or features_buffer[1] >= 99 else 4
|
img = vision_input_shapes[road_key]
|
||||||
|
n_frames = img[1] // 6
|
||||||
|
img_buf_shape = (frame_skip * (n_frames - 1) + 1, 6, img[2], img[3])
|
||||||
|
|
||||||
|
fb = policy_input_shapes['features_buffer']
|
||||||
|
desire_key = _detect_desire_key(policy_input_shapes)
|
||||||
|
dp = policy_input_shapes[desire_key]
|
||||||
|
tc = policy_input_shapes.get('traffic_convention', (1, 2))
|
||||||
|
|
||||||
def generate_queues_and_npy(input_shapes: dict, frame_skip: int, device: str = Device.DEFAULT) -> tuple[dict, dict]:
|
npy = {
|
||||||
road_key, _ = _detect_vision_keys(input_shapes)
|
'desire': np.zeros(dp[2], dtype=np.float32),
|
||||||
if not road_key:
|
'traffic_convention': np.zeros(tc, dtype=np.float32),
|
||||||
raise ValueError("Vision road key missing from input shapes.")
|
|
||||||
|
|
||||||
img_shape = input_shapes[road_key]
|
|
||||||
n_frames = img_shape[1] // 6
|
|
||||||
img_buf_shape = (frame_skip * (n_frames - 1) + 1, 6, img_shape[2], img_shape[3])
|
|
||||||
|
|
||||||
desire_key = _detect_desire_key(input_shapes)
|
|
||||||
if not desire_key:
|
|
||||||
raise ValueError("Desire key missing from input shapes.")
|
|
||||||
|
|
||||||
desire_shape = input_shapes[desire_key]
|
|
||||||
features_buffer = input_shapes.get('features_buffer')
|
|
||||||
|
|
||||||
npy_arrays = {
|
|
||||||
'desire': np.zeros(desire_shape[2], dtype=np.float32),
|
|
||||||
'tfm': np.zeros((3, 3), dtype=np.float32),
|
'tfm': np.zeros((3, 3), dtype=np.float32),
|
||||||
'big_tfm': np.zeros((3, 3), dtype=np.float32)
|
'big_tfm': np.zeros((3, 3), dtype=np.float32),
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, shape in input_shapes.items():
|
handled = {'features_buffer', desire_key, 'traffic_convention'}
|
||||||
if key not in npy_arrays and 'img' not in key and key not in ('features_buffer', desire_key):
|
for key, shape in policy_input_shapes.items():
|
||||||
npy_arrays[key] = np.zeros(shape, dtype=np.float32)
|
if key in handled:
|
||||||
|
continue
|
||||||
|
npy[key] = np.zeros(shape, dtype=np.float32)
|
||||||
|
|
||||||
queues = {
|
input_queues = {
|
||||||
'img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
|
'img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
|
||||||
'big_img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
|
'big_img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
|
||||||
'desire_q': Tensor(np.zeros((frame_skip * desire_shape[1], desire_shape[0], desire_shape[2]),
|
'feat_q': Tensor(np.zeros((frame_skip * (fb[1] - 1) + 1, fb[0], fb[2]), dtype=np.float32), device=device).contiguous().realize(),
|
||||||
dtype=np.float32), device=device).contiguous().realize()
|
'desire_q': Tensor(np.zeros((frame_skip * dp[1], dp[0], dp[2]), dtype=np.float32), device=device).contiguous().realize(),
|
||||||
|
**{k: Tensor(v, device='NPY').realize() for k, v in npy.items()},
|
||||||
}
|
}
|
||||||
|
return input_queues, npy
|
||||||
if features_buffer:
|
|
||||||
queues['feat_q'] = Tensor(np.zeros((frame_skip * (features_buffer[1] - 1) + 1, features_buffer[0], features_buffer[2]),
|
|
||||||
dtype=np.float32), device=device).contiguous().realize()
|
|
||||||
|
|
||||||
queues.update({key: Tensor(value, device='NPY').realize() for key, value in npy_arrays.items()})
|
|
||||||
return queues, npy_arrays
|
|
||||||
|
|
||||||
|
|
||||||
def make_split_input_queues(vision_input_shapes: dict, policy_input_shapes: dict, frame_skip: int, device: str = Device.DEFAULT) -> tuple[dict, dict]:
|
def make_run_split_policy(vision_runner, policy_runner, nv12: NV12Frame, model_w, model_h,
|
||||||
return generate_queues_and_npy({**vision_input_shapes, **policy_input_shapes}, frame_skip, device)
|
vision_features_slice, frame_skip, desire_key, extra_policy_keys,
|
||||||
|
vision_road_key, vision_wide_key, prepare_only=False):
|
||||||
|
frame_prepare = make_frame_prepare(nv12, model_w, model_h)
|
||||||
def make_supercombo_input_queues(input_shapes: dict, frame_skip: int, device: str = Device.DEFAULT) -> tuple[dict, dict]:
|
|
||||||
return generate_queues_and_npy(input_shapes, frame_skip, device)
|
|
||||||
|
|
||||||
|
|
||||||
def create_jit_runner(vision_runner, policy_runners: list, nv12: NV12Frame, model_size: tuple[int, int],
|
|
||||||
features_slice: slice, frame_skip: int, input_shapes: dict, prepare_only: bool):
|
|
||||||
frame_prepare = make_frame_prepare(nv12, *model_size)
|
|
||||||
sample_skip_fn = partial(sample_skip, frame_skip=frame_skip)
|
sample_skip_fn = partial(sample_skip, frame_skip=frame_skip)
|
||||||
sample_desire_fn = partial(sample_desire, frame_skip=frame_skip)
|
sample_desire_fn = partial(sample_desire, frame_skip=frame_skip)
|
||||||
|
|
||||||
desire_key = _detect_desire_key(input_shapes)
|
def run_policy(img_q, big_img_q, feat_q, desire_q, desire, traffic_convention, tfm, big_tfm, frame, big_frame, **extra):
|
||||||
road_key, wide_key = _detect_vision_keys(input_shapes)
|
npy_tensors = [tfm.to(Device.DEFAULT), big_tfm.to(Device.DEFAULT),
|
||||||
|
desire.to(Device.DEFAULT), traffic_convention.to(Device.DEFAULT)]
|
||||||
|
extra_device = {k: extra[k].to(Device.DEFAULT) for k in extra_policy_keys}
|
||||||
|
Tensor.realize(*npy_tensors, *extra_device.values())
|
||||||
|
tfm, big_tfm, desire, traffic_convention = npy_tensors
|
||||||
|
|
||||||
if not desire_key or not road_key or not wide_key:
|
img = shift_and_sample(img_q, frame_prepare(frame, tfm).unsqueeze(0), sample_skip_fn)
|
||||||
raise ValueError("Missing required vision or desire keys in input shapes.")
|
big_img = shift_and_sample(big_img_q, frame_prepare(big_frame, big_tfm).unsqueeze(0), sample_skip_fn)
|
||||||
|
|
||||||
extra_keys = [key for key in input_shapes if key not in (desire_key, 'features_buffer', 'traffic_convention') and 'img' not in key]
|
|
||||||
|
|
||||||
def runner(img_q, big_img_q, feat_q, frame, big_frame, tfm, big_tfm, **kwargs):
|
|
||||||
desire_q = kwargs['desire_q']
|
|
||||||
desire = kwargs['desire']
|
|
||||||
traffic_convention = kwargs.get('traffic_convention')
|
|
||||||
|
|
||||||
npys = [tfm.to(Device.DEFAULT), big_tfm.to(Device.DEFAULT), desire.to(Device.DEFAULT)]
|
|
||||||
if traffic_convention is not None:
|
|
||||||
npys.append(traffic_convention.to(Device.DEFAULT))
|
|
||||||
|
|
||||||
extra_tensors = {key: kwargs[key].to(Device.DEFAULT) for key in extra_keys if key in kwargs}
|
|
||||||
Tensor.realize(*npys, *extra_tensors.values())
|
|
||||||
|
|
||||||
tfm_dev, big_tfm_dev, desire_dev = npys[:3]
|
|
||||||
traffic_conv_dev = npys[3] if traffic_convention is not None else None
|
|
||||||
|
|
||||||
img = shift_and_sample(img_q, frame_prepare(frame, tfm_dev).unsqueeze(0), sample_skip_fn).realize()
|
|
||||||
big_img = shift_and_sample(big_img_q, frame_prepare(big_frame, big_tfm_dev).unsqueeze(0), sample_skip_fn).realize()
|
|
||||||
|
|
||||||
if prepare_only:
|
if prepare_only:
|
||||||
return img, big_img
|
return img, big_img
|
||||||
|
|
||||||
desire_buf = shift_and_sample(desire_q, desire_dev.reshape(1, 1, -1), sample_desire_fn).realize()
|
vision_out = next(iter(vision_runner({vision_road_key: img, vision_wide_key: big_img}).values())).cast('float32')
|
||||||
inputs = {desire_key: desire_buf, **extra_tensors}
|
|
||||||
|
|
||||||
if traffic_conv_dev is not None:
|
new_feat = vision_out[:, vision_features_slice].reshape(1, -1).unsqueeze(0)
|
||||||
inputs['traffic_convention'] = traffic_conv_dev
|
feat_buf = shift_and_sample(feat_q, new_feat, sample_skip_fn)
|
||||||
|
desire_buf = shift_and_sample(desire_q, desire.reshape(1, 1, -1), sample_desire_fn)
|
||||||
|
|
||||||
if vision_runner:
|
inputs = {'features_buffer': feat_buf, desire_key: desire_buf, 'traffic_convention': traffic_convention, **extra_device}
|
||||||
vision_out_cast = next(iter(vision_runner({road_key: img, wide_key: big_img}).values())).cast('float32').realize()
|
policy_out = next(iter(policy_runner(inputs).values())).cast('float32')
|
||||||
new_feat = vision_out_cast[:, features_slice].reshape(1, -1).unsqueeze(0)
|
|
||||||
inputs['features_buffer'] = shift_and_sample(feat_q, new_feat, sample_skip_fn).realize()
|
|
||||||
policy_outs = [next(iter(pol_runner(inputs).values())).cast('float32').realize() for pol_runner in policy_runners]
|
|
||||||
return (vision_out_cast, *policy_outs) if len(policy_outs) > 1 else (vision_out_cast, policy_outs[0])
|
|
||||||
inputs.update({road_key: img, wide_key: big_img, 'features_buffer': sample_skip_fn(feat_q)})
|
|
||||||
policy_out = next(iter(policy_runners[0](inputs).values())).cast('float32').realize()
|
|
||||||
new_feat = policy_out[:, features_slice].reshape(1, -1).unsqueeze(0)
|
|
||||||
shift_and_sample(feat_q, new_feat, sample_skip_fn).realize()
|
|
||||||
return policy_out
|
|
||||||
|
|
||||||
return runner
|
return vision_out, policy_out
|
||||||
|
return run_policy
|
||||||
|
|
||||||
|
|
||||||
def compile_and_warmup(nv12: NV12Frame, model_size: tuple[int, int], prepare_only: bool, frame_skip: int, vision_runner, policy_runners: list, metadata: dict):
|
def compile_split_policy(nv12: NV12Frame, model_w, model_h, prepare_only, frame_skip,
|
||||||
print(f"Compiling combined JIT for {nv12.width}x{nv12.height} (prepare_only={prepare_only})...")
|
vision_runner, policy_runner, vision_metadata, policy_metadata):
|
||||||
|
print(f"Compiling combined policy JIT for {nv12.width}x{nv12.height} (prepare_only={prepare_only})...")
|
||||||
|
|
||||||
all_shapes = {key: value for meta in metadata.values() for key, value in meta['input_shapes'].items()}
|
vision_features_slice = vision_metadata['output_slices']['hidden_state']
|
||||||
|
vision_input_shapes = vision_metadata['input_shapes']
|
||||||
|
policy_input_shapes = policy_metadata['input_shapes']
|
||||||
|
desire_key = _detect_desire_key(policy_input_shapes)
|
||||||
|
extra_policy_keys = [k for k in policy_input_shapes if k not in ('features_buffer', desire_key, 'traffic_convention')]
|
||||||
|
vision_road_key, vision_wide_key = _detect_vision_keys(vision_input_shapes)
|
||||||
|
|
||||||
feat_meta = metadata.get('vision') or metadata.get('model') or metadata.get('policy')
|
_run = make_run_split_policy(vision_runner, policy_runner, nv12, model_w, model_h,
|
||||||
if not feat_meta:
|
vision_features_slice, frame_skip, desire_key, extra_policy_keys,
|
||||||
raise ValueError("Could not find vision, model, or policy metadata.")
|
vision_road_key, vision_wide_key, prepare_only)
|
||||||
|
run_policy_jit = TinyJit(_run, prune=True)
|
||||||
|
|
||||||
features_slice = feat_meta['output_slices']['hidden_state']
|
SEED = 42
|
||||||
WARP_DEV = 'CPU' if "USBGPU" in os.environ else Device.DEFAULT
|
|
||||||
|
|
||||||
run_func = create_jit_runner(vision_runner, policy_runners, nv12, model_size, features_slice, frame_skip, all_shapes, prepare_only)
|
def random_inputs_run_fn(fn, seed, test_val=None, test_buffers=None, expect_match=True):
|
||||||
run_jit = TinyJit(run_func, prune=True)
|
input_queues, npy = make_split_input_queues(vision_input_shapes, policy_input_shapes, frame_skip, Device.DEFAULT)
|
||||||
queues, npy_arrays = generate_queues_and_npy(all_shapes, frame_skip, Device.DEFAULT)
|
rng = np.random.default_rng(seed)
|
||||||
|
Tensor.manual_seed(seed)
|
||||||
|
|
||||||
|
testing = test_val is not None or test_buffers is not None
|
||||||
|
n_runs = 1 if testing else 3
|
||||||
|
|
||||||
|
for i in range(n_runs):
|
||||||
|
frame = Tensor.randint(nv12.size, low=0, high=256, dtype='uint8').realize()
|
||||||
|
big_frame = Tensor.randint(nv12.size, low=0, high=256, dtype='uint8').realize()
|
||||||
|
for v in npy.values():
|
||||||
|
v[:] = rng.standard_normal(v.shape).astype(v.dtype)
|
||||||
|
Device.default.synchronize()
|
||||||
|
st = time.perf_counter()
|
||||||
|
outs = fn(**input_queues, frame=frame, big_frame=big_frame)
|
||||||
|
mt = time.perf_counter()
|
||||||
|
Device.default.synchronize()
|
||||||
|
et = time.perf_counter()
|
||||||
|
print(f" [{i+1}/{n_runs}] enqueue {(mt-st)*1e3:6.2f} ms -- total {(et-st)*1e3:6.2f} ms")
|
||||||
|
|
||||||
|
if i == 0:
|
||||||
|
val = [np.copy(v.numpy()) for v in outs]
|
||||||
|
buffers = [np.copy(v.numpy().copy()) for v in input_queues.values()]
|
||||||
|
|
||||||
|
if test_val is not None:
|
||||||
|
match = all(np.array_equal(a, b) for a, b in zip(val, test_val, strict=True))
|
||||||
|
assert match == expect_match, f"outputs {'differ from' if expect_match else 'match'} baseline (seed={seed})"
|
||||||
|
if test_buffers is not None:
|
||||||
|
match = all(np.array_equal(a, b) for a, b in zip(buffers, test_buffers, strict=True))
|
||||||
|
assert match == expect_match, f"buffers {'differ from' if expect_match else 'match'} baseline (seed={seed})"
|
||||||
|
return fn, val, buffers
|
||||||
|
|
||||||
|
print('capture + replay')
|
||||||
|
run_policy_jit, test_val, test_buffers = random_inputs_run_fn(run_policy_jit, SEED)
|
||||||
|
|
||||||
|
print('pickle round trip')
|
||||||
|
run_policy_jit = pickle.loads(pickle.dumps(run_policy_jit))
|
||||||
|
random_inputs_run_fn(run_policy_jit, SEED, test_val, test_buffers, expect_match=True)
|
||||||
|
random_inputs_run_fn(run_policy_jit, SEED+1, test_val, test_buffers, expect_match=False)
|
||||||
|
return run_policy_jit
|
||||||
|
|
||||||
|
|
||||||
|
def derive_frame_skip(vision_input_shapes, policy_input_shapes):
|
||||||
|
fb = policy_input_shapes.get('features_buffer')
|
||||||
|
if fb is None:
|
||||||
|
return 1
|
||||||
|
fb_history = fb[1]
|
||||||
|
if fb_history >= 99:
|
||||||
|
return 1
|
||||||
|
return 4
|
||||||
|
|
||||||
|
|
||||||
|
def make_supercombo_input_queues(input_shapes, frame_skip, device):
|
||||||
|
img_shape = input_shapes.get('img', input_shapes.get('input_imgs'))
|
||||||
|
if img_shape is None:
|
||||||
|
raise ValueError("No img input found in model shapes")
|
||||||
|
|
||||||
|
n_frames = img_shape[1] // 6
|
||||||
|
img_buf_shape = (frame_skip * (n_frames - 1) + 1, 6, img_shape[2], img_shape[3])
|
||||||
|
|
||||||
|
numpy_keys = {}
|
||||||
|
queue_keys = {}
|
||||||
|
|
||||||
|
for key, shape in input_shapes.items():
|
||||||
|
if 'img' in key:
|
||||||
|
continue
|
||||||
|
if len(shape) == 3 and shape[1] > 1:
|
||||||
|
if key.startswith('desire'):
|
||||||
|
numpy_keys[key] = np.zeros(shape[2], dtype=np.float32)
|
||||||
|
queue_keys[f'{key}_q'] = Tensor(
|
||||||
|
np.zeros((frame_skip * shape[1], shape[0], shape[2]), dtype=np.float32),
|
||||||
|
device=device).contiguous().realize()
|
||||||
|
elif key == 'features_buffer':
|
||||||
|
queue_keys['feat_q'] = Tensor(
|
||||||
|
np.zeros((frame_skip * (shape[1] - 1) + 1, shape[0], shape[2]), dtype=np.float32),
|
||||||
|
device=device).contiguous().realize()
|
||||||
|
else:
|
||||||
|
numpy_keys[key] = np.zeros(shape, dtype=np.float32)
|
||||||
|
elif len(shape) == 2:
|
||||||
|
numpy_keys[key] = np.zeros(shape, dtype=np.float32)
|
||||||
|
|
||||||
|
if 'traffic_convention' not in numpy_keys:
|
||||||
|
tc_shape = input_shapes.get('traffic_convention', (1, 2))
|
||||||
|
numpy_keys['traffic_convention'] = np.zeros(tc_shape, dtype=np.float32)
|
||||||
|
|
||||||
|
numpy_keys['tfm'] = np.zeros((3, 3), dtype=np.float32)
|
||||||
|
numpy_keys['big_tfm'] = np.zeros((3, 3), dtype=np.float32)
|
||||||
|
|
||||||
|
input_queues = {
|
||||||
|
'img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
|
||||||
|
'big_img_q': Tensor(np.zeros(img_buf_shape, dtype=np.uint8), device=device).contiguous().realize(),
|
||||||
|
**queue_keys,
|
||||||
|
**{k: Tensor(v, device='NPY').realize() for k, v in numpy_keys.items()},
|
||||||
|
}
|
||||||
|
return input_queues, numpy_keys
|
||||||
|
|
||||||
|
|
||||||
|
def make_run_supercombo(model_runner, nv12: NV12Frame, model_w, model_h,
|
||||||
|
features_slice, frame_skip, input_shapes, prepare_only=False):
|
||||||
|
frame_prepare = make_frame_prepare(nv12, model_w, model_h)
|
||||||
|
sample_skip_fn = partial(sample_skip, frame_skip=frame_skip)
|
||||||
|
sample_desire_fn = partial(sample_desire, frame_skip=frame_skip)
|
||||||
|
|
||||||
|
desire_key = _detect_desire_key(input_shapes)
|
||||||
|
if desire_key is None:
|
||||||
|
raise ValueError(f"No desire* key found in input_shapes: {list(input_shapes.keys())}")
|
||||||
|
road_img_key, wide_img_key = _detect_vision_keys(input_shapes)
|
||||||
|
extra_policy_keys = [k for k in input_shapes
|
||||||
|
if k not in (desire_key, 'features_buffer', 'traffic_convention')
|
||||||
|
and 'img' not in k]
|
||||||
|
|
||||||
|
def run_supercombo(img_q, big_img_q, feat_q, desire_q,
|
||||||
|
frame, big_frame, **kwargs):
|
||||||
|
desire = kwargs.get(desire_key)
|
||||||
|
traffic_convention = kwargs.get('traffic_convention')
|
||||||
|
tfm = kwargs['tfm']
|
||||||
|
big_tfm = kwargs['big_tfm']
|
||||||
|
|
||||||
|
tfm = tfm.to(Device.DEFAULT)
|
||||||
|
big_tfm = big_tfm.to(Device.DEFAULT)
|
||||||
|
desire = desire.to(Device.DEFAULT)
|
||||||
|
traffic_convention = traffic_convention.to(Device.DEFAULT)
|
||||||
|
Tensor.realize(tfm, big_tfm, desire, traffic_convention)
|
||||||
|
|
||||||
|
img = shift_and_sample(img_q, frame_prepare(frame, tfm).unsqueeze(0), sample_skip_fn)
|
||||||
|
big_img = shift_and_sample(big_img_q, frame_prepare(big_frame, big_tfm).unsqueeze(0), sample_skip_fn)
|
||||||
|
|
||||||
|
if prepare_only:
|
||||||
|
return img, big_img
|
||||||
|
|
||||||
|
desire_buf = shift_and_sample(desire_q, desire.reshape(1, 1, -1), sample_desire_fn)
|
||||||
|
feat_buf = sample_skip_fn(feat_q)
|
||||||
|
|
||||||
|
inputs = {road_img_key: img, wide_img_key: big_img,
|
||||||
|
desire_key: desire_buf, 'features_buffer': feat_buf,
|
||||||
|
'traffic_convention': traffic_convention}
|
||||||
|
for k in extra_policy_keys:
|
||||||
|
if k in kwargs:
|
||||||
|
inputs[k] = kwargs[k].to(Device.DEFAULT)
|
||||||
|
|
||||||
|
model_out = next(iter(model_runner(inputs).values())).cast('float32')
|
||||||
|
|
||||||
|
new_feat = model_out[:, features_slice].reshape(1, -1).unsqueeze(0)
|
||||||
|
shift_and_sample(feat_q, new_feat, sample_skip_fn)
|
||||||
|
|
||||||
|
return model_out
|
||||||
|
|
||||||
|
return run_supercombo
|
||||||
|
|
||||||
|
|
||||||
|
def make_run_vision_multi_policy(vision_runner, policy_runners, nv12: NV12Frame, model_w, model_h,
|
||||||
|
vision_features_slice, frame_skip, desire_key, extra_policy_keys,
|
||||||
|
vision_road_key, vision_wide_key, prepare_only=False):
|
||||||
|
frame_prepare = make_frame_prepare(nv12, model_w, model_h)
|
||||||
|
sample_skip_fn = partial(sample_skip, frame_skip=frame_skip)
|
||||||
|
sample_desire_fn = partial(sample_desire, frame_skip=frame_skip)
|
||||||
|
|
||||||
|
def run_multi_policy(img_q, big_img_q, feat_q, desire_q, desire,
|
||||||
|
traffic_convention, tfm, big_tfm, frame, big_frame, **extra):
|
||||||
|
npy_tensors = [tfm.to(Device.DEFAULT), big_tfm.to(Device.DEFAULT),
|
||||||
|
desire.to(Device.DEFAULT), traffic_convention.to(Device.DEFAULT)]
|
||||||
|
extra_device = {k: extra[k].to(Device.DEFAULT) for k in extra_policy_keys}
|
||||||
|
Tensor.realize(*npy_tensors, *extra_device.values())
|
||||||
|
tfm, big_tfm, desire, traffic_convention = npy_tensors
|
||||||
|
|
||||||
|
img = shift_and_sample(img_q, frame_prepare(frame, tfm).unsqueeze(0), sample_skip_fn)
|
||||||
|
big_img = shift_and_sample(big_img_q, frame_prepare(big_frame, big_tfm).unsqueeze(0), sample_skip_fn)
|
||||||
|
|
||||||
|
if prepare_only:
|
||||||
|
return img, big_img
|
||||||
|
|
||||||
|
vision_out = next(iter(vision_runner({vision_road_key: img, vision_wide_key: big_img}).values())).cast('float32')
|
||||||
|
|
||||||
|
new_feat = vision_out[:, vision_features_slice].reshape(1, -1).unsqueeze(0)
|
||||||
|
feat_buf = shift_and_sample(feat_q, new_feat, sample_skip_fn)
|
||||||
|
desire_buf = shift_and_sample(desire_q, desire.reshape(1, 1, -1), sample_desire_fn)
|
||||||
|
|
||||||
|
inputs = {'features_buffer': feat_buf, desire_key: desire_buf, 'traffic_convention': traffic_convention, **extra_device}
|
||||||
|
|
||||||
|
policy_outputs = []
|
||||||
|
for runner in policy_runners:
|
||||||
|
policy_out = next(iter(runner(inputs).values())).cast('float32')
|
||||||
|
policy_outputs.append(policy_out)
|
||||||
|
|
||||||
|
return (vision_out, *policy_outputs)
|
||||||
|
|
||||||
|
return run_multi_policy
|
||||||
|
|
||||||
|
|
||||||
|
def _warmup_and_serialize(run_jit, input_queues, npy, nv12):
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
rng = np.random.default_rng(42 + i)
|
rng = np.random.default_rng(42 + i)
|
||||||
frame = Tensor.randint(nv12.size, low=0, high=256, dtype=dtypes.uint8, device=WARP_DEV).realize()
|
frame = Tensor.randint(nv12.size, low=0, high=256, dtype='uint8').realize()
|
||||||
big_frame = Tensor.randint(nv12.size, low=0, high=256, dtype=dtypes.uint8, device=WARP_DEV).realize()
|
big_frame = Tensor.randint(nv12.size, low=0, high=256, dtype='uint8').realize()
|
||||||
for arr in npy_arrays.values():
|
for v in npy.values():
|
||||||
arr[:] = rng.standard_normal(arr.shape).astype(arr.dtype)
|
v[:] = rng.standard_normal(v.shape).astype(v.dtype)
|
||||||
|
|
||||||
Device.default.synchronize()
|
Device.default.synchronize()
|
||||||
start_time = time.perf_counter()
|
st = time.perf_counter()
|
||||||
run_jit(**queues, frame=frame, big_frame=big_frame)
|
run_jit(**input_queues, frame=frame, big_frame=big_frame)
|
||||||
mid_time = time.perf_counter()
|
mt = time.perf_counter()
|
||||||
Device.default.synchronize()
|
Device.default.synchronize()
|
||||||
print(f" [{i + 1}/3] enqueue {(mid_time - start_time) * 1e3:6.2f} ms -- total {(time.perf_counter() - start_time) * 1e3:6.2f} ms")
|
et = time.perf_counter()
|
||||||
|
print(f" [{i + 1}/3] enqueue {(mt - st) * 1e3:6.2f} ms -- total {(et - st) * 1e3:6.2f} ms")
|
||||||
return pickle.loads(pickle.dumps(run_jit)) if not prepare_only else run_jit
|
return pickle.loads(pickle.dumps(run_jit))
|
||||||
|
|
||||||
|
|
||||||
def _parse_size(size_str: str) -> tuple[int, int]:
|
def compile_supercombo(nv12: NV12Frame, model_w, model_h, prepare_only, frame_skip,
|
||||||
width, height = size_str.lower().split('x')
|
model_runner, metadata):
|
||||||
return int(width), int(height)
|
print(f"Compiling combined supercombo JIT for {nv12.width}x{nv12.height} (prepare_only={prepare_only})...")
|
||||||
|
|
||||||
|
features_slice = metadata['output_slices']['hidden_state']
|
||||||
|
input_shapes = metadata['input_shapes']
|
||||||
|
|
||||||
|
_run = make_run_supercombo(model_runner, nv12, model_w, model_h,
|
||||||
|
features_slice, frame_skip, input_shapes, prepare_only)
|
||||||
|
run_jit = TinyJit(_run, prune=True)
|
||||||
|
|
||||||
|
input_queues, npy = make_supercombo_input_queues(input_shapes, frame_skip, Device.DEFAULT)
|
||||||
|
|
||||||
|
run_jit = _warmup_and_serialize(run_jit, input_queues, npy, nv12)
|
||||||
|
return run_jit
|
||||||
|
|
||||||
|
|
||||||
def read_file_chunked_to_shm(path):
|
def compile_multi_policy(nv12: NV12Frame, model_w, model_h, prepare_only, frame_skip,
|
||||||
if not path:
|
vision_runner, policy_runners, vision_metadata, policy_metadata):
|
||||||
return None
|
print(f"Compiling combined multi-policy JIT for {nv12.width}x{nv12.height} (prepare_only={prepare_only})...")
|
||||||
import atexit
|
|
||||||
import shutil
|
vision_features_slice = vision_metadata['output_slices']['hidden_state']
|
||||||
from openpilot.common.file_chunker import open_file_chunked
|
vision_input_shapes = vision_metadata['input_shapes']
|
||||||
from openpilot.common.hardware.hw import Paths
|
policy_input_shapes = policy_metadata['input_shapes']
|
||||||
shm_path = os.path.join(Paths.shm_path(), os.path.basename(path))
|
desire_key = _detect_desire_key(policy_input_shapes)
|
||||||
atexit.register(lambda: os.path.exists(shm_path) and os.remove(shm_path))
|
extra_policy_keys = [k for k in policy_input_shapes if k not in ('features_buffer', desire_key, 'traffic_convention')]
|
||||||
with open(shm_path, 'wb') as dst, open_file_chunked(path) as src:
|
vision_road_key, vision_wide_key = _detect_vision_keys(vision_input_shapes)
|
||||||
shutil.copyfileobj(src, dst)
|
|
||||||
return shm_path
|
_run = make_run_vision_multi_policy(vision_runner, policy_runners, nv12, model_w, model_h,
|
||||||
|
vision_features_slice, frame_skip, desire_key, extra_policy_keys,
|
||||||
|
vision_road_key, vision_wide_key, prepare_only)
|
||||||
|
run_jit = TinyJit(_run, prune=True)
|
||||||
|
|
||||||
|
input_queues, npy = make_split_input_queues(vision_input_shapes, policy_input_shapes, frame_skip, Device.DEFAULT)
|
||||||
|
|
||||||
|
run_jit = _warmup_and_serialize(run_jit, input_queues, npy, nv12)
|
||||||
|
return run_jit
|
||||||
|
|
||||||
|
|
||||||
def _compile_for_resolutions(camera_resolutions: list, model_size: tuple[int, int], frame_skip: int,
|
def _parse_size(s):
|
||||||
vision_runner, policy_runners: list, metadata: dict) -> dict:
|
w, h = s.lower().split('x')
|
||||||
from openpilot.system.camerad.cameras.nv12_info import get_nv12_info
|
return int(w), int(h)
|
||||||
return {
|
|
||||||
(cam_w, cam_h): {
|
|
||||||
name: compile_and_warmup(NV12Frame(cam_w, cam_h, *get_nv12_info(cam_w, cam_h)), model_size, prepare_only,
|
|
||||||
frame_skip, vision_runner, policy_runners, metadata)
|
|
||||||
for name, prepare_only in [('warp_enqueue', True), ('run_policy', False)]
|
|
||||||
}
|
|
||||||
for cam_w, cam_h in camera_resolutions
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def _load_policy_runners(args: argparse.Namespace) -> tuple[list, list]:
|
|
||||||
runners, keys = [], []
|
|
||||||
for name, onnx_arg in [('policy', args.policy_onnx), ('off_policy', args.off_policy_onnx), ('on_policy', args.on_policy_onnx)]:
|
|
||||||
if onnx_arg:
|
|
||||||
runners.append(OnnxRunner(onnx_arg))
|
|
||||||
keys.append(name)
|
|
||||||
return runners, keys
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
from openpilot.selfdrive.modeld.get_model_metadata import make_metadata_dict
|
|
||||||
from tinygrad.nn.onnx import OnnxRunner
|
from tinygrad.nn.onnx import OnnxRunner
|
||||||
|
from openpilot.system.camerad.cameras.nv12_info import get_nv12_info
|
||||||
|
from openpilot.selfdrive.modeld.get_model_metadata import make_metadata_dict
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="Compile combined JIT pkl for sunnypilot modeld_v2")
|
p = argparse.ArgumentParser(description="Compile combined JIT pkl for sunnypilot modeld_v2")
|
||||||
parser.add_argument('--model-type', choices=MODEL_TYPES, required=True)
|
p.add_argument('--model-type', choices=MODEL_TYPES, required=True)
|
||||||
parser.add_argument('--model-size', type=_parse_size, required=True, help='model input WxH')
|
p.add_argument('--model-size', type=_parse_size, required=True, help='model input WxH')
|
||||||
parser.add_argument('--camera-resolutions', type=_parse_size, nargs='+', required=True)
|
p.add_argument('--camera-resolutions', type=_parse_size, nargs='+', required=True)
|
||||||
parser.add_argument('--frame-skip', type=int, default=None, help='frame skip value (auto-derived if not provided)')
|
p.add_argument('--frame-skip', type=int, default=None, help='frame skip value (auto-derived if not provided)')
|
||||||
parser.add_argument('--output', required=True)
|
p.add_argument('--output', required=True)
|
||||||
|
|
||||||
parser.add_argument('--vision-onnx', help='vision ONNX (for split models)')
|
p.add_argument('--vision-onnx', help='vision ONNX (for split models)')
|
||||||
parser.add_argument('--policy-onnx', help='policy ONNX (for vision_policy)')
|
p.add_argument('--policy-onnx', help='policy ONNX (for vision_policy)')
|
||||||
parser.add_argument('--off-policy-onnx', help='off-policy ONNX (for vision_multi_policy)')
|
p.add_argument('--off-policy-onnx', help='off-policy ONNX (for vision_multi_policy)')
|
||||||
parser.add_argument('--on-policy-onnx', help='on-policy ONNX (for vision_multi_policy)')
|
p.add_argument('--on-policy-onnx', help='on-policy ONNX (for vision_multi_policy)')
|
||||||
parser.add_argument('--supercombo-onnx', help='supercombo ONNX (for supercombo)')
|
p.add_argument('--supercombo-onnx', help='supercombo ONNX (for supercombo)')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = p.parse_args()
|
||||||
output_data = defaultdict(dict)
|
out = defaultdict(dict)
|
||||||
|
|
||||||
args.vision_onnx = read_file_chunked_to_shm(args.vision_onnx)
|
|
||||||
args.policy_onnx = read_file_chunked_to_shm(args.policy_onnx)
|
|
||||||
args.off_policy_onnx = read_file_chunked_to_shm(args.off_policy_onnx)
|
|
||||||
args.on_policy_onnx = read_file_chunked_to_shm(args.on_policy_onnx)
|
|
||||||
args.supercombo_onnx = read_file_chunked_to_shm(args.supercombo_onnx)
|
|
||||||
|
|
||||||
vision_runner = OnnxRunner(args.vision_onnx) if args.vision_onnx else None
|
|
||||||
|
|
||||||
if args.model_type == 'vision_policy':
|
if args.model_type == 'vision_policy':
|
||||||
assert vision_runner and args.policy_onnx
|
assert args.vision_onnx and args.policy_onnx
|
||||||
policy_runners = [OnnxRunner(args.policy_onnx)]
|
vision_runner = OnnxRunner(args.vision_onnx)
|
||||||
output_data['metadata'] = {'vision': make_metadata_dict(args.vision_onnx), 'policy': make_metadata_dict(args.policy_onnx)}
|
policy_runner = OnnxRunner(args.policy_onnx)
|
||||||
|
out['metadata']['vision'] = make_metadata_dict(args.vision_onnx)
|
||||||
|
out['metadata']['policy'] = make_metadata_dict(args.policy_onnx)
|
||||||
|
|
||||||
|
frame_skip = args.frame_skip if args.frame_skip is not None else derive_frame_skip(out['metadata']['vision']['input_shapes'],
|
||||||
|
out['metadata']['policy']['input_shapes'])
|
||||||
|
|
||||||
|
for cam_w, cam_h in args.camera_resolutions:
|
||||||
|
nv12 = NV12Frame(cam_w, cam_h, *get_nv12_info(cam_w, cam_h))
|
||||||
|
model_w, model_h = args.model_size
|
||||||
|
out[(cam_w, cam_h)] = {
|
||||||
|
name: compile_split_policy(nv12, model_w, model_h, prepare_only, frame_skip,
|
||||||
|
vision_runner, policy_runner,
|
||||||
|
out['metadata']['vision'], out['metadata']['policy'])
|
||||||
|
for name, prepare_only in [('warp_enqueue', True), ('run_policy', False)]
|
||||||
|
}
|
||||||
|
|
||||||
elif args.model_type == 'supercombo':
|
elif args.model_type == 'supercombo':
|
||||||
assert args.supercombo_onnx
|
assert args.supercombo_onnx
|
||||||
policy_runners = [OnnxRunner(args.supercombo_onnx)]
|
model_runner = OnnxRunner(args.supercombo_onnx)
|
||||||
output_data['metadata'] = {'model': make_metadata_dict(args.supercombo_onnx)}
|
out['metadata']['model'] = make_metadata_dict(args.supercombo_onnx)
|
||||||
|
|
||||||
|
frame_skip = args.frame_skip if args.frame_skip is not None else derive_frame_skip({}, out['metadata']['model']['input_shapes'])
|
||||||
|
|
||||||
|
for cam_w, cam_h in args.camera_resolutions:
|
||||||
|
nv12 = NV12Frame(cam_w, cam_h, *get_nv12_info(cam_w, cam_h))
|
||||||
|
model_w, model_h = args.model_size
|
||||||
|
out[(cam_w, cam_h)] = {
|
||||||
|
name: compile_supercombo(nv12, model_w, model_h, prepare_only, frame_skip,
|
||||||
|
model_runner, out['metadata']['model'])
|
||||||
|
for name, prepare_only in [('warp_enqueue', True), ('run_policy', False)]
|
||||||
|
}
|
||||||
|
|
||||||
elif args.model_type == 'vision_multi_policy':
|
elif args.model_type == 'vision_multi_policy':
|
||||||
assert vision_runner
|
assert args.vision_onnx
|
||||||
policy_runners, policy_names = _load_policy_runners(args)
|
vision_runner = OnnxRunner(args.vision_onnx)
|
||||||
output_data['metadata'] = {'vision': make_metadata_dict(args.vision_onnx)}
|
out['metadata']['vision'] = make_metadata_dict(args.vision_onnx)
|
||||||
for name in policy_names:
|
|
||||||
runner_arg = getattr(args, f"{name}_onnx")
|
|
||||||
output_data['metadata'][name] = make_metadata_dict(runner_arg)
|
|
||||||
|
|
||||||
policy_keys = [key for key in output_data['metadata'].keys() if key != 'vision']
|
policy_runners = []
|
||||||
first_policy_meta = output_data['metadata'][policy_keys[0]] if policy_keys else {}
|
policy_onnxes = []
|
||||||
vision_meta = output_data['metadata'].get('vision', {})
|
if args.policy_onnx:
|
||||||
|
policy_onnxes.append(('policy', args.policy_onnx))
|
||||||
|
if args.off_policy_onnx:
|
||||||
|
policy_onnxes.append(('off_policy', args.off_policy_onnx))
|
||||||
|
if args.on_policy_onnx:
|
||||||
|
policy_onnxes.append(('on_policy', args.on_policy_onnx))
|
||||||
|
|
||||||
derived_frame_skip = args.frame_skip or derive_frame_skip(vision_meta.get('input_shapes', {}), first_policy_meta.get('input_shapes', {}))
|
for name, onnx_path in policy_onnxes:
|
||||||
output_data.update(_compile_for_resolutions(args.camera_resolutions, args.model_size, derived_frame_skip,
|
runner = OnnxRunner(onnx_path)
|
||||||
vision_runner, policy_runners, output_data['metadata']))
|
policy_runners.append(runner)
|
||||||
|
out['metadata'][name] = make_metadata_dict(onnx_path)
|
||||||
|
|
||||||
with open(args.output, "wb") as file:
|
first_policy_key = policy_onnxes[0][0]
|
||||||
pickle.dump(output_data, file)
|
frame_skip = args.frame_skip if args.frame_skip is not None else derive_frame_skip(out['metadata']['vision']['input_shapes'],
|
||||||
|
out['metadata'][first_policy_key]['input_shapes'])
|
||||||
|
|
||||||
|
for cam_w, cam_h in args.camera_resolutions:
|
||||||
|
nv12 = NV12Frame(cam_w, cam_h, *get_nv12_info(cam_w, cam_h))
|
||||||
|
model_w, model_h = args.model_size
|
||||||
|
out[(cam_w, cam_h)] = {
|
||||||
|
name: compile_multi_policy(nv12, model_w, model_h, prepare_only, frame_skip,
|
||||||
|
vision_runner, policy_runners,
|
||||||
|
out['metadata']['vision'], out['metadata'][first_policy_key])
|
||||||
|
for name, prepare_only in [('warp_enqueue', True), ('run_policy', False)]
|
||||||
|
}
|
||||||
|
|
||||||
|
with open(args.output, "wb") as f:
|
||||||
|
pickle.dump(out, f)
|
||||||
pkl_size = os.path.getsize(args.output)
|
pkl_size = os.path.getsize(args.output)
|
||||||
print(f"Saved combined JIT to {args.output} ({pkl_size / 1e6:.2f} MB)")
|
print(f"Saved combined JIT to {args.output} ({pkl_size / 1e6:.2f} MB)")
|
||||||
|
|
||||||
from openpilot.common.file_chunker import chunk_file, get_chunk_targets
|
from openpilot.common.file_chunker import chunk_file, get_chunk_targets
|
||||||
chunk_targets = get_chunk_targets(args.output, pkl_size)
|
chunk_targets = get_chunk_targets(args.output, pkl_size)
|
||||||
chunk_file(args.output, chunk_targets)
|
chunk_file(args.output, chunk_targets)
|
||||||
print(f"Chunked into {len(chunk_targets) - 1} file(s)")
|
num_chunks = len(chunk_targets) - 1
|
||||||
|
print(f"Chunked into {num_chunks} file(s)")
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ See the LICENSE.md file in the root directory for more details.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
os.environ['GMMU'] = '0'
|
|
||||||
from openpilot.common.hardware import TICI
|
from openpilot.common.hardware import TICI
|
||||||
os.environ['DEV'] = 'QCOM' if TICI else 'CPU'
|
os.environ['DEV'] = 'QCOM' if TICI else 'CPU'
|
||||||
USBGPU = "USBGPU" in os.environ
|
USBGPU = "USBGPU" in os.environ
|
||||||
@@ -24,11 +23,6 @@ from setproctitle import setproctitle
|
|||||||
from openpilot.cereal.messaging import PubMaster, SubMaster
|
from openpilot.cereal.messaging import PubMaster, SubMaster
|
||||||
from msgq.visionipc import VisionIpcClient, VisionStreamType, VisionBuf
|
from msgq.visionipc import VisionIpcClient, VisionStreamType, VisionBuf
|
||||||
from opendbc.car.car_helpers import get_demo_car_params
|
from opendbc.car.car_helpers import get_demo_car_params
|
||||||
|
|
||||||
from tinygrad.tensor import Tensor
|
|
||||||
from tinygrad.device import Device
|
|
||||||
|
|
||||||
from openpilot.common.file_chunker import open_file_chunked
|
|
||||||
from openpilot.common.swaglog import cloudlog
|
from openpilot.common.swaglog import cloudlog
|
||||||
from openpilot.common.params import Params
|
from openpilot.common.params import Params
|
||||||
from openpilot.common.filter_simple import FirstOrderFilter
|
from openpilot.common.filter_simple import FirstOrderFilter
|
||||||
@@ -36,7 +30,6 @@ from openpilot.common.realtime import config_realtime_process, DT_MDL
|
|||||||
from openpilot.common.transformations.camera import DEVICE_CAMERAS
|
from openpilot.common.transformations.camera import DEVICE_CAMERAS
|
||||||
from openpilot.common.transformations.model import get_warp_matrix
|
from openpilot.common.transformations.model import get_warp_matrix
|
||||||
from openpilot.system import sentry
|
from openpilot.system import sentry
|
||||||
from openpilot.system.camerad.cameras.nv12_info import get_nv12_info
|
|
||||||
from openpilot.selfdrive.controls.lib.desire_helper import DesireHelper
|
from openpilot.selfdrive.controls.lib.desire_helper import DesireHelper
|
||||||
from openpilot.selfdrive.controls.lib.drive_helpers import get_accel_from_plan, smooth_value
|
from openpilot.selfdrive.controls.lib.drive_helpers import get_accel_from_plan, smooth_value
|
||||||
|
|
||||||
@@ -44,7 +37,6 @@ from openpilot.sunnypilot.modeld_v2.fill_model_msg import fill_model_msg, fill_p
|
|||||||
from openpilot.sunnypilot.modeld_v2.constants import Plan
|
from openpilot.sunnypilot.modeld_v2.constants import Plan
|
||||||
from openpilot.sunnypilot.modeld_v2.meta_helper import load_meta_constants
|
from openpilot.sunnypilot.modeld_v2.meta_helper import load_meta_constants
|
||||||
from openpilot.sunnypilot.modeld_v2.camera_offset_helper import CameraOffsetHelper
|
from openpilot.sunnypilot.modeld_v2.camera_offset_helper import CameraOffsetHelper
|
||||||
from openpilot.sunnypilot.modeld_v2.compile_modeld import derive_frame_skip, make_split_input_queues
|
|
||||||
|
|
||||||
from openpilot.sunnypilot.livedelay.helpers import get_lat_delay
|
from openpilot.sunnypilot.livedelay.helpers import get_lat_delay
|
||||||
from openpilot.sunnypilot.modeld_v2.modeld_base import ModelStateBase
|
from openpilot.sunnypilot.modeld_v2.modeld_base import ModelStateBase
|
||||||
@@ -107,12 +99,17 @@ class ModelState(ModelStateBase):
|
|||||||
self._init_combined(pkl_path, cam_w, cam_h, model_bundle)
|
self._init_combined(pkl_path, cam_w, cam_h, model_bundle)
|
||||||
|
|
||||||
def _init_combined(self, pkl_path, cam_w, cam_h, bundle):
|
def _init_combined(self, pkl_path, cam_w, cam_h, bundle):
|
||||||
|
from tinygrad.tensor import Tensor
|
||||||
|
from openpilot.system.camerad.cameras.nv12_info import get_nv12_info
|
||||||
|
from openpilot.sunnypilot.modeld_v2.compile_modeld import derive_frame_skip, make_split_input_queues
|
||||||
|
from tinygrad.device import Device
|
||||||
|
|
||||||
|
from openpilot.common.file_chunker import open_file_chunked
|
||||||
|
|
||||||
cloudlog.warning(f"loading combined pkl: {pkl_path}")
|
cloudlog.warning(f"loading combined pkl: {pkl_path}")
|
||||||
jits = pickle.load(open_file_chunked(pkl_path))
|
jits = pickle.load(open_file_chunked(pkl_path))
|
||||||
|
|
||||||
self.DEV = Device.DEFAULT
|
self.DEV = Device.DEFAULT
|
||||||
self.WARP_DEV = 'CPU' if USBGPU else self.DEV
|
|
||||||
self.QUEUE_DEV = self.DEV
|
|
||||||
|
|
||||||
metadata = jits['metadata']
|
metadata = jits['metadata']
|
||||||
if 'model' in metadata:
|
if 'model' in metadata:
|
||||||
@@ -121,10 +118,10 @@ class ModelState(ModelStateBase):
|
|||||||
self.policy_output_slices = {}
|
self.policy_output_slices = {}
|
||||||
self._policy_slices_list = []
|
self._policy_slices_list = []
|
||||||
self._combined_model_type = 'supercombo'
|
self._combined_model_type = 'supercombo'
|
||||||
self._vision_input_names = [key for key in model_metadata['input_shapes'] if 'img' in key]
|
self._vision_input_names = [k for k in model_metadata['input_shapes'] if 'img' in k]
|
||||||
from openpilot.sunnypilot.modeld_v2.compile_modeld import make_supercombo_input_queues
|
from openpilot.sunnypilot.modeld_v2.compile_modeld import make_supercombo_input_queues
|
||||||
frame_skip = derive_frame_skip({}, model_metadata['input_shapes'])
|
frame_skip = derive_frame_skip({}, model_metadata['input_shapes'])
|
||||||
self.input_queues, self.numpy_inputs = make_supercombo_input_queues(model_metadata['input_shapes'], frame_skip, device=self.QUEUE_DEV)
|
self.input_queues, self.numpy_inputs = make_supercombo_input_queues(model_metadata['input_shapes'], frame_skip, device=self.DEV)
|
||||||
else:
|
else:
|
||||||
vision_metadata = metadata['vision']
|
vision_metadata = metadata['vision']
|
||||||
policy_keys = [k for k in metadata if k != 'vision']
|
policy_keys = [k for k in metadata if k != 'vision']
|
||||||
@@ -142,11 +139,11 @@ class ModelState(ModelStateBase):
|
|||||||
policy_input_shapes = first_policy_metadata['input_shapes']
|
policy_input_shapes = first_policy_metadata['input_shapes']
|
||||||
self._vision_input_names = [k for k in vision_input_shapes if 'img' in k]
|
self._vision_input_names = [k for k in vision_input_shapes if 'img' in k]
|
||||||
frame_skip = derive_frame_skip(vision_input_shapes, policy_input_shapes)
|
frame_skip = derive_frame_skip(vision_input_shapes, policy_input_shapes)
|
||||||
self.input_queues, self.numpy_inputs = make_split_input_queues(vision_input_shapes, policy_input_shapes, frame_skip, device=self.QUEUE_DEV)
|
self.input_queues, self.numpy_inputs = make_split_input_queues(vision_input_shapes, policy_input_shapes, frame_skip, device=self.DEV)
|
||||||
|
|
||||||
self._desire_key = next(key for key in self.numpy_inputs if key.startswith('desire'))
|
from openpilot.sunnypilot.modeld_v2.parse_model_outputs_split import Parser as SplitParser
|
||||||
self._road_key = next(key for key in self._vision_input_names if 'big' not in key)
|
from openpilot.sunnypilot.modeld_v2.parse_model_outputs import Parser as CombinedParser
|
||||||
self._wide_key = next(key for key in self._vision_input_names if 'big' in key)
|
self.parser = SplitParser() if self._combined_model_type != 'supercombo' else CombinedParser()
|
||||||
|
|
||||||
is_20hz = bundle.is20hz if bundle else self._combined_model_type in ('split', 'multi_policy')
|
is_20hz = bundle.is20hz if bundle else self._combined_model_type in ('split', 'multi_policy')
|
||||||
if is_20hz:
|
if is_20hz:
|
||||||
@@ -156,13 +153,6 @@ class ModelState(ModelStateBase):
|
|||||||
from openpilot.sunnypilot.modeld_v2.constants import ModelConstants
|
from openpilot.sunnypilot.modeld_v2.constants import ModelConstants
|
||||||
self.constants = ModelConstants()
|
self.constants = ModelConstants()
|
||||||
|
|
||||||
if self._combined_model_type != 'supercombo':
|
|
||||||
from openpilot.sunnypilot.modeld_v2.parse_model_outputs_split import Parser as SplitParser
|
|
||||||
self.parser = SplitParser()
|
|
||||||
else:
|
|
||||||
from openpilot.sunnypilot.modeld_v2.parse_model_outputs import Parser as CombinedParser
|
|
||||||
self.parser = CombinedParser()
|
|
||||||
|
|
||||||
self.prev_desire = np.zeros(self.constants.DESIRE_LEN, dtype=np.float32)
|
self.prev_desire = np.zeros(self.constants.DESIRE_LEN, dtype=np.float32)
|
||||||
self.full_frames: dict = {}
|
self.full_frames: dict = {}
|
||||||
self._blob_cache: dict = {}
|
self._blob_cache: dict = {}
|
||||||
@@ -171,11 +161,12 @@ class ModelState(ModelStateBase):
|
|||||||
|
|
||||||
self._run_policy = jits[(cam_w, cam_h)]['run_policy']
|
self._run_policy = jits[(cam_w, cam_h)]['run_policy']
|
||||||
self._warp_enqueue = jits[(cam_w, cam_h)]['warp_enqueue']
|
self._warp_enqueue = jits[(cam_w, cam_h)]['warp_enqueue']
|
||||||
yuv_size = self.frame_buf_params[self._road_key][3]
|
road_name = next(k for k in self._vision_input_names if 'big' not in k)
|
||||||
|
yuv_size = self.frame_buf_params[road_name][3]
|
||||||
self._warp_enqueue(
|
self._warp_enqueue(
|
||||||
**self.input_queues,
|
**self.input_queues,
|
||||||
frame=Tensor(np.zeros(yuv_size, dtype=np.uint8), device=self.WARP_DEV).contiguous().realize(),
|
frame=Tensor(np.zeros(yuv_size, dtype=np.uint8), device=self.DEV).contiguous().realize(),
|
||||||
big_frame=Tensor(np.zeros(yuv_size, dtype=np.uint8), device=self.WARP_DEV).contiguous().realize())
|
big_frame=Tensor(np.zeros(yuv_size, dtype=np.uint8), device=self.DEV).contiguous().realize())
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -188,7 +179,7 @@ class ModelState(ModelStateBase):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def desire_key(self) -> str:
|
def desire_key(self) -> str:
|
||||||
return self._desire_key
|
return next(k for k in self.numpy_inputs if k.startswith('desire'))
|
||||||
|
|
||||||
def run(self, bufs: dict[str, VisionBuf], transforms: dict[str, np.ndarray],
|
def run(self, bufs: dict[str, VisionBuf], transforms: dict[str, np.ndarray],
|
||||||
inputs: dict[str, np.ndarray], prepare_only: bool) -> dict[str, np.ndarray] | None:
|
inputs: dict[str, np.ndarray], prepare_only: bool) -> dict[str, np.ndarray] | None:
|
||||||
@@ -199,19 +190,19 @@ class ModelState(ModelStateBase):
|
|||||||
yuv_size = self.frame_buf_params[key][3]
|
yuv_size = self.frame_buf_params[key][3]
|
||||||
cache_key = (key, ptr)
|
cache_key = (key, ptr)
|
||||||
if cache_key not in self._blob_cache:
|
if cache_key not in self._blob_cache:
|
||||||
self._blob_cache[cache_key] = Tensor.from_blob(ptr, (yuv_size,), dtype='uint8', device=self.WARP_DEV)
|
self._blob_cache[cache_key] = Tensor.from_blob(ptr, (yuv_size,), dtype='uint8', device=self.DEV)
|
||||||
self.full_frames[key] = self._blob_cache[cache_key]
|
self.full_frames[key] = self._blob_cache[cache_key]
|
||||||
|
|
||||||
desire_key = self.desire_key
|
desire_key = self.desire_key
|
||||||
inputs[desire_key][0] = 0
|
inputs[desire_key][0] = 0
|
||||||
self.numpy_inputs[desire_key][:] = np.where(inputs[desire_key] - self.prev_desire > .99, inputs[desire_key], 0)
|
self.numpy_inputs[desire_key][:] = np.where(inputs[desire_key] - self.prev_desire > .99, inputs[desire_key], 0)
|
||||||
self.prev_desire[:] = inputs[desire_key]
|
self.prev_desire[:] = inputs[desire_key]
|
||||||
for key in ('traffic_convention', 'lateral_control_params', 'action_t'):
|
for key in ('traffic_convention', 'lateral_control_params'):
|
||||||
if key in self.numpy_inputs and key in inputs:
|
if key in self.numpy_inputs and key in inputs:
|
||||||
self.numpy_inputs[key][:] = inputs[key]
|
self.numpy_inputs[key][:] = inputs[key]
|
||||||
|
|
||||||
road_key = self._road_key
|
road_key = next(n for n in bufs if 'big' not in n)
|
||||||
wide_key = self._wide_key
|
wide_key = next(n for n in bufs if 'big' in n)
|
||||||
self.numpy_inputs['tfm'][:, :] = transforms[road_key].reshape(3, 3)
|
self.numpy_inputs['tfm'][:, :] = transforms[road_key].reshape(3, 3)
|
||||||
self.numpy_inputs['big_tfm'][:, :] = transforms[wide_key].reshape(3, 3)
|
self.numpy_inputs['big_tfm'][:, :] = transforms[wide_key].reshape(3, 3)
|
||||||
|
|
||||||
@@ -234,12 +225,8 @@ class ModelState(ModelStateBase):
|
|||||||
policy_output = raw_outputs[i + 1].numpy().flatten()
|
policy_output = raw_outputs[i + 1].numpy().flatten()
|
||||||
policy_sliced = {k: policy_output[np.newaxis, v] for k, v in policy_slices.items()}
|
policy_sliced = {k: policy_output[np.newaxis, v] for k, v in policy_slices.items()}
|
||||||
parsed = self.parser.parse_policy_outputs(policy_sliced)
|
parsed = self.parser.parse_policy_outputs(policy_sliced)
|
||||||
if ('off' in self._policy_keys[i]
|
if 'off' in self._policy_keys[i] and self._has_on_policy:
|
||||||
and self._has_on_policy
|
|
||||||
and any('plan' in self._policy_slices_list[j] for j, k in enumerate(self._policy_keys) if 'on' in k.lower())):
|
|
||||||
|
|
||||||
parsed.pop('plan', None)
|
parsed.pop('plan', None)
|
||||||
|
|
||||||
outputs.update(parsed)
|
outputs.update(parsed)
|
||||||
|
|
||||||
if 'planplus' in outputs and 'plan' in outputs:
|
if 'planplus' in outputs and 'plan' in outputs:
|
||||||
@@ -254,20 +241,13 @@ class ModelState(ModelStateBase):
|
|||||||
|
|
||||||
def get_action_from_model(self, model_output: dict[str, np.ndarray], prev_action: log.ModelDataV2.Action,
|
def get_action_from_model(self, model_output: dict[str, np.ndarray], prev_action: log.ModelDataV2.Action,
|
||||||
lat_action_t: float, long_action_t: float, v_ego: float) -> log.ModelDataV2.Action:
|
lat_action_t: float, long_action_t: float, v_ego: float) -> log.ModelDataV2.Action:
|
||||||
if 'action' not in model_output:
|
plan = model_output['plan'][0]
|
||||||
plan = model_output['plan'][0]
|
desired_accel, should_stop = get_accel_from_plan(plan[:, Plan.VELOCITY][:, 0], plan[:, Plan.ACCELERATION][:, 0], self.constants.T_IDXS,
|
||||||
desired_accel, should_stop = get_accel_from_plan(plan[:, Plan.VELOCITY][:, 0], plan[:, Plan.ACCELERATION][:, 0], self.constants.T_IDXS,
|
action_t=long_action_t)
|
||||||
action_t=long_action_t)
|
desired_accel = smooth_value(desired_accel, prev_action.desiredAcceleration, self.LONG_SMOOTH_SECONDS)
|
||||||
desired_accel = smooth_value(desired_accel, prev_action.desiredAcceleration, self.LONG_SMOOTH_SECONDS)
|
|
||||||
|
|
||||||
curvature_plan = (plan + (self.PLANPLUS_CONTROL - 1.0) * model_output['planplus'][0]
|
|
||||||
if 'planplus' in model_output and self.PLANPLUS_CONTROL != 1.0 else plan)
|
|
||||||
desired_curvature = get_curvature_from_output(model_output, curvature_plan, v_ego, lat_action_t, self.mlsim)
|
|
||||||
else:
|
|
||||||
desired_accel = model_output['action'][0, 1]
|
|
||||||
desired_curvature = model_output['action'][0, 0] / (max(1.0, v_ego))**2
|
|
||||||
should_stop = (v_ego < 0.3 and desired_accel < 0.1)
|
|
||||||
|
|
||||||
|
curvature_plan = plan + (self.PLANPLUS_CONTROL - 1.0) * model_output['planplus'][0] if 'planplus' in model_output and self.PLANPLUS_CONTROL != 1.0 else plan
|
||||||
|
desired_curvature = get_curvature_from_output(model_output, curvature_plan, v_ego, lat_action_t, self.mlsim)
|
||||||
if self.generation is not None and self.generation >= 10: # smooth curvature for post FOF models
|
if self.generation is not None and self.generation >= 10: # smooth curvature for post FOF models
|
||||||
if v_ego > self.MIN_LAT_CONTROL_SPEED:
|
if v_ego > self.MIN_LAT_CONTROL_SPEED:
|
||||||
desired_curvature = smooth_value(desired_curvature, prev_action.desiredCurvature, self.LAT_SMOOTH_SECONDS)
|
desired_curvature = smooth_value(desired_curvature, prev_action.desiredCurvature, self.LAT_SMOOTH_SECONDS)
|
||||||
@@ -420,12 +400,6 @@ def main(demo=False):
|
|||||||
|
|
||||||
bufs = {name: buf_extra if 'big' in name else buf_main for name in model.vision_input_names}
|
bufs = {name: buf_extra if 'big' in name else buf_main for name in model.vision_input_names}
|
||||||
transforms = {name: model_transform_extra if 'big' in name else model_transform_main for name in model.vision_input_names}
|
transforms = {name: model_transform_extra if 'big' in name else model_transform_main for name in model.vision_input_names}
|
||||||
|
|
||||||
frame_delay = DT_MDL # compensate for time passed since the frame was captured: current_time - timestamp_eof is 50ms on average
|
|
||||||
action_delay = DT_MDL / 2 # middle of the interval between model output (current state) and next frame (expected state)
|
|
||||||
lat_action_t = lat_delay + frame_delay + action_delay
|
|
||||||
long_action_t = long_delay + frame_delay + action_delay
|
|
||||||
|
|
||||||
inputs:dict[str, np.ndarray] = {
|
inputs:dict[str, np.ndarray] = {
|
||||||
model.desire_key: vec_desire,
|
model.desire_key: vec_desire,
|
||||||
'traffic_convention': traffic_convention,
|
'traffic_convention': traffic_convention,
|
||||||
@@ -434,9 +408,6 @@ def main(demo=False):
|
|||||||
if 'lateral_control_params' in model.numpy_inputs:
|
if 'lateral_control_params' in model.numpy_inputs:
|
||||||
inputs['lateral_control_params'] = np.array([v_ego, lat_delay], dtype=np.float32)
|
inputs['lateral_control_params'] = np.array([v_ego, lat_delay], dtype=np.float32)
|
||||||
|
|
||||||
if 'action_t' in model.numpy_inputs:
|
|
||||||
inputs['action_t'] = np.array([lat_action_t, long_action_t], dtype=np.float32)
|
|
||||||
|
|
||||||
mt1 = time.perf_counter()
|
mt1 = time.perf_counter()
|
||||||
model_output = model.run(bufs, transforms, inputs, prepare_only)
|
model_output = model.run(bufs, transforms, inputs, prepare_only)
|
||||||
mt2 = time.perf_counter()
|
mt2 = time.perf_counter()
|
||||||
@@ -448,7 +419,7 @@ def main(demo=False):
|
|||||||
posenet_send = messaging.new_message('cameraOdometry')
|
posenet_send = messaging.new_message('cameraOdometry')
|
||||||
mdv2sp_send = messaging.new_message('modelDataV2SP')
|
mdv2sp_send = messaging.new_message('modelDataV2SP')
|
||||||
|
|
||||||
action = model.get_action_from_model(model_output, prev_action, lat_action_t, long_action_t, v_ego)
|
action = model.get_action_from_model(model_output, prev_action, lat_delay + DT_MDL, long_delay + DT_MDL, v_ego)
|
||||||
prev_action = action
|
prev_action = action
|
||||||
fill_model_msg(drivingdata_send, modelv2_send, model_output, action,
|
fill_model_msg(drivingdata_send, modelv2_send, model_output, action,
|
||||||
publish_state, meta_main.frame_id, meta_extra.frame_id, frame_id,
|
publish_state, meta_main.frame_id, meta_extra.frame_id, frame_id,
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from openpilot.sunnypilot.modeld_v2.constants import ModelConstants
|
from openpilot.sunnypilot.modeld_v2.constants import ModelConstants
|
||||||
|
|
||||||
|
|
||||||
def safe_exp(x, out=None):
|
def safe_exp(x, out=None):
|
||||||
# -11 is around 10**14, more causes float16 overflow
|
# -11 is around 10**14, more causes float16 overflow
|
||||||
return np.exp(np.clip(x, -np.inf, 11), out=out)
|
return np.exp(np.clip(x, -np.inf, 11), out=out)
|
||||||
|
|
||||||
|
|
||||||
def sigmoid(x):
|
def sigmoid(x):
|
||||||
return 1. / (1. + safe_exp(-x))
|
return 1. / (1. + safe_exp(-x))
|
||||||
|
|
||||||
|
|
||||||
def softmax(x, axis=-1):
|
def softmax(x, axis=-1):
|
||||||
x -= np.max(x, axis=axis, keepdims=True)
|
x -= np.max(x, axis=axis, keepdims=True)
|
||||||
if x.dtype == np.float32 or x.dtype == np.float64:
|
if x.dtype == np.float32 or x.dtype == np.float64:
|
||||||
@@ -20,19 +17,6 @@ def softmax(x, axis=-1):
|
|||||||
x /= np.sum(x, axis=axis, keepdims=True)
|
x /= np.sum(x, axis=axis, keepdims=True)
|
||||||
return x
|
return x
|
||||||
|
|
||||||
|
|
||||||
def _infer_mhp(slice_size: int, prod_out_shape: int, max_in_n: int = 16, max_out_n: int = 6) -> tuple[int, int]:
|
|
||||||
for out_n in range(max_out_n + 1):
|
|
||||||
per = 2 * prod_out_shape + out_n
|
|
||||||
if per <= 0:
|
|
||||||
continue
|
|
||||||
if slice_size % per == 0:
|
|
||||||
in_n = slice_size // per
|
|
||||||
if 1 <= in_n <= max_in_n:
|
|
||||||
return in_n, out_n
|
|
||||||
return 1, 0 # single hypothesis, no weights — matches a non-MDN output
|
|
||||||
|
|
||||||
|
|
||||||
class Parser:
|
class Parser:
|
||||||
def __init__(self, ignore_missing=False):
|
def __init__(self, ignore_missing=False):
|
||||||
self.ignore_missing = ignore_missing
|
self.ignore_missing = ignore_missing
|
||||||
@@ -56,22 +40,17 @@ class Parser:
|
|||||||
raw = outs[name]
|
raw = outs[name]
|
||||||
outs[name] = sigmoid(raw)
|
outs[name] = sigmoid(raw)
|
||||||
|
|
||||||
def parse_mdn(self, name, outs, out_shape, in_N=0, out_N=0):
|
def parse_mdn(self, name, outs, in_N=0, out_N=1, out_shape=None):
|
||||||
if self.check_missing(outs, name):
|
if self.check_missing(outs, name):
|
||||||
return
|
return
|
||||||
raw = outs[name]
|
raw = outs[name]
|
||||||
|
raw = raw.reshape((raw.shape[0], max(in_N, 1), -1))
|
||||||
if in_N == 0 and out_N == 0:
|
|
||||||
prod = int(np.prod(out_shape))
|
|
||||||
in_N, out_N = _infer_mhp(raw.shape[1], prod)
|
|
||||||
|
|
||||||
raw = raw.reshape((raw.shape[0], in_N, -1))
|
|
||||||
|
|
||||||
n_values = (raw.shape[2] - out_N)//2
|
n_values = (raw.shape[2] - out_N)//2
|
||||||
pred_mu = raw[:,:,:n_values]
|
pred_mu = raw[:,:,:n_values]
|
||||||
pred_std = safe_exp(raw[:,:,n_values: 2*n_values])
|
pred_std = safe_exp(raw[:,:,n_values: 2*n_values])
|
||||||
|
|
||||||
if in_N > 1 and out_N > 0:
|
if in_N > 1:
|
||||||
weights = np.zeros((raw.shape[0], in_N, out_N), dtype=raw.dtype)
|
weights = np.zeros((raw.shape[0], in_N, out_N), dtype=raw.dtype)
|
||||||
for i in range(out_N):
|
for i in range(out_N):
|
||||||
weights[:,:,i - out_N] = softmax(raw[:,:,i - out_N], axis=-1)
|
weights[:,:,i - out_N] = softmax(raw[:,:,i - out_N], axis=-1)
|
||||||
@@ -82,6 +61,7 @@ class Parser:
|
|||||||
weights[fidx] = weights[fidx][idxs]
|
weights[fidx] = weights[fidx][idxs]
|
||||||
pred_mu[fidx] = pred_mu[fidx][idxs]
|
pred_mu[fidx] = pred_mu[fidx][idxs]
|
||||||
pred_std[fidx] = pred_std[fidx][idxs]
|
pred_std[fidx] = pred_std[fidx][idxs]
|
||||||
|
assert out_shape is not None
|
||||||
full_shape = tuple([raw.shape[0], in_N] + list(out_shape))
|
full_shape = tuple([raw.shape[0], in_N] + list(out_shape))
|
||||||
outs[name + '_weights'] = weights
|
outs[name + '_weights'] = weights
|
||||||
outs[name + '_hypotheses'] = pred_mu.reshape(full_shape)
|
outs[name + '_hypotheses'] = pred_mu.reshape(full_shape)
|
||||||
@@ -94,43 +74,37 @@ class Parser:
|
|||||||
idxs = np.argsort(weights[fidx,:,hidx])[::-1]
|
idxs = np.argsort(weights[fidx,:,hidx])[::-1]
|
||||||
pred_mu_final[fidx, hidx] = pred_mu[fidx, idxs[0]]
|
pred_mu_final[fidx, hidx] = pred_mu[fidx, idxs[0]]
|
||||||
pred_std_final[fidx, hidx] = pred_std[fidx, idxs[0]]
|
pred_std_final[fidx, hidx] = pred_std[fidx, idxs[0]]
|
||||||
elif in_N > 1 and out_N == 0:
|
|
||||||
# MHP without weights: keep every hypothesis intact, surface them as
|
|
||||||
# ``*_hypotheses`` and propagate the full multi-hypothesis tensor.
|
|
||||||
full_shape = tuple([raw.shape[0], in_N] + list(out_shape))
|
|
||||||
outs[name + '_hypotheses'] = pred_mu.reshape(full_shape)
|
|
||||||
outs[name + '_stds_hypotheses'] = pred_std.reshape(full_shape)
|
|
||||||
pred_mu_final = pred_mu
|
|
||||||
pred_std_final = pred_std
|
|
||||||
else:
|
else:
|
||||||
pred_mu_final = pred_mu
|
pred_mu_final = pred_mu
|
||||||
pred_std_final = pred_std
|
pred_std_final = pred_std
|
||||||
|
|
||||||
if out_N > 1 or (in_N > 1 and out_N == 0):
|
if out_N > 1:
|
||||||
n_selections = out_N if out_N > 1 else in_N
|
assert out_shape is not None
|
||||||
final_shape = tuple([raw.shape[0], n_selections] + list(out_shape))
|
final_shape = tuple([raw.shape[0], out_N] + list(out_shape))
|
||||||
else:
|
else:
|
||||||
|
assert out_shape is not None
|
||||||
final_shape = tuple([raw.shape[0],] + list(out_shape))
|
final_shape = tuple([raw.shape[0],] + list(out_shape))
|
||||||
outs[name] = pred_mu_final.reshape(final_shape)
|
outs[name] = pred_mu_final.reshape(final_shape)
|
||||||
outs[name + '_stds'] = pred_std_final.reshape(final_shape)
|
outs[name + '_stds'] = pred_std_final.reshape(final_shape)
|
||||||
|
|
||||||
def parse_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]:
|
def parse_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]:
|
||||||
# supercombo (4955 / 102) and newer variants (e.g. 990 / 144).
|
self.parse_mdn('plan', outs, in_N=ModelConstants.PLAN_MHP_N, out_N=ModelConstants.PLAN_MHP_SELECTION,
|
||||||
self.parse_mdn('plan', outs, out_shape=(ModelConstants.IDX_N, ModelConstants.PLAN_WIDTH))
|
out_shape=(ModelConstants.IDX_N,ModelConstants.PLAN_WIDTH))
|
||||||
self.parse_mdn('lane_lines', outs, out_shape=(ModelConstants.NUM_LANE_LINES, ModelConstants.IDX_N, ModelConstants.LANE_LINES_WIDTH))
|
self.parse_mdn('lane_lines', outs, in_N=0, out_N=0, out_shape=(ModelConstants.NUM_LANE_LINES,ModelConstants.IDX_N,ModelConstants.LANE_LINES_WIDTH))
|
||||||
self.parse_mdn('road_edges', outs, out_shape=(ModelConstants.NUM_ROAD_EDGES, ModelConstants.IDX_N, ModelConstants.LANE_LINES_WIDTH))
|
self.parse_mdn('road_edges', outs, in_N=0, out_N=0, out_shape=(ModelConstants.NUM_ROAD_EDGES,ModelConstants.IDX_N,ModelConstants.LANE_LINES_WIDTH))
|
||||||
self.parse_mdn('pose', outs, out_shape=(ModelConstants.POSE_WIDTH,))
|
self.parse_mdn('pose', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,))
|
||||||
self.parse_mdn('road_transform', outs, out_shape=(ModelConstants.POSE_WIDTH,))
|
self.parse_mdn('road_transform', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,))
|
||||||
if 'sim_pose' in outs:
|
if 'sim_pose' in outs:
|
||||||
self.parse_mdn('sim_pose', outs, out_shape=(ModelConstants.POSE_WIDTH,))
|
self.parse_mdn('sim_pose', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,))
|
||||||
self.parse_mdn('wide_from_device_euler', outs, out_shape=(ModelConstants.WIDE_FROM_DEVICE_WIDTH,))
|
self.parse_mdn('wide_from_device_euler', outs, in_N=0, out_N=0, out_shape=(ModelConstants.WIDE_FROM_DEVICE_WIDTH,))
|
||||||
self.parse_mdn('lead', outs, out_shape=(ModelConstants.LEAD_TRAJ_LEN, ModelConstants.LEAD_WIDTH))
|
self.parse_mdn('lead', outs, in_N=ModelConstants.LEAD_MHP_N, out_N=ModelConstants.LEAD_MHP_SELECTION,
|
||||||
|
out_shape=(ModelConstants.LEAD_TRAJ_LEN,ModelConstants.LEAD_WIDTH))
|
||||||
if 'lat_planner_solution' in outs:
|
if 'lat_planner_solution' in outs:
|
||||||
self.parse_mdn('lat_planner_solution', outs, out_shape=(ModelConstants.IDX_N, ModelConstants.LAT_PLANNER_SOLUTION_WIDTH))
|
self.parse_mdn('lat_planner_solution', outs, in_N=0, out_N=0, out_shape=(ModelConstants.IDX_N,ModelConstants.LAT_PLANNER_SOLUTION_WIDTH))
|
||||||
if 'desired_curvature' in outs:
|
if 'desired_curvature' in outs:
|
||||||
self.parse_mdn('desired_curvature', outs, out_shape=(ModelConstants.DESIRED_CURV_WIDTH,))
|
self.parse_mdn('desired_curvature', outs, in_N=0, out_N=0, out_shape=(ModelConstants.DESIRED_CURV_WIDTH,))
|
||||||
for k in ['lead_prob', 'lane_lines_prob', 'meta']:
|
for k in ['lead_prob', 'lane_lines_prob', 'meta']:
|
||||||
self.parse_binary_crossentropy(k, outs)
|
self.parse_binary_crossentropy(k, outs)
|
||||||
self.parse_categorical_crossentropy('desire_state', outs, out_shape=(ModelConstants.DESIRE_PRED_WIDTH,))
|
self.parse_categorical_crossentropy('desire_state', outs, out_shape=(ModelConstants.DESIRE_PRED_WIDTH,))
|
||||||
self.parse_categorical_crossentropy('desire_pred', outs, out_shape=(ModelConstants.DESIRE_PRED_LEN, ModelConstants.DESIRE_PRED_WIDTH))
|
self.parse_categorical_crossentropy('desire_pred', outs, out_shape=(ModelConstants.DESIRE_PRED_LEN,ModelConstants.DESIRE_PRED_WIDTH))
|
||||||
return outs
|
return outs
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ class Parser:
|
|||||||
self.parse_categorical_crossentropy('desire_state', outs, out_shape=(SplitModelConstants.DESIRE_PRED_WIDTH,))
|
self.parse_categorical_crossentropy('desire_state', outs, out_shape=(SplitModelConstants.DESIRE_PRED_WIDTH,))
|
||||||
if 'lane_lines' in outs:
|
if 'lane_lines' in outs:
|
||||||
self.parse_mdn('lane_lines', outs, in_N=0, out_N=0,
|
self.parse_mdn('lane_lines', outs, in_N=0, out_N=0,
|
||||||
out_shape=(SplitModelConstants.NUM_LANE_LINES,SplitModelConstants.IDX_N,SplitModelConstants.LANE_LINES_WIDTH))
|
out_shape=(SplitModelConstants.NUM_LANE_LINES,SplitModelConstants.IDX_N,SplitModelConstants.LANE_LINES_WIDTH))
|
||||||
if 'lane_lines_prob' in outs:
|
if 'lane_lines_prob' in outs:
|
||||||
self.parse_binary_crossentropy('lane_lines_prob', outs)
|
self.parse_binary_crossentropy('lane_lines_prob', outs)
|
||||||
if 'lead_prob' in outs:
|
if 'lead_prob' in outs:
|
||||||
@@ -134,11 +134,9 @@ class Parser:
|
|||||||
self.parse_binary_crossentropy('meta', outs)
|
self.parse_binary_crossentropy('meta', outs)
|
||||||
if 'road_edges' in outs:
|
if 'road_edges' in outs:
|
||||||
self.parse_mdn('road_edges', outs, in_N=0, out_N=0,
|
self.parse_mdn('road_edges', outs, in_N=0, out_N=0,
|
||||||
out_shape=(SplitModelConstants.NUM_ROAD_EDGES,SplitModelConstants.IDX_N,SplitModelConstants.LANE_LINES_WIDTH))
|
out_shape=(SplitModelConstants.NUM_ROAD_EDGES,SplitModelConstants.IDX_N,SplitModelConstants.LANE_LINES_WIDTH))
|
||||||
if 'sim_pose' in outs:
|
if 'sim_pose' in outs:
|
||||||
self.parse_mdn('sim_pose', outs, in_N=0, out_N=0, out_shape=(SplitModelConstants.POSE_WIDTH,))
|
self.parse_mdn('sim_pose', outs, in_N=0, out_N=0, out_shape=(SplitModelConstants.POSE_WIDTH,))
|
||||||
if 'action' in outs:
|
|
||||||
self.parse_mdn('action', outs, in_N=0, out_N=0, out_shape=(SplitModelConstants.ACTION_WIDTH,))
|
|
||||||
|
|
||||||
def parse_vision_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]:
|
def parse_vision_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]:
|
||||||
self.parse_mdn('pose', outs, in_N=0, out_N=0, out_shape=(SplitModelConstants.POSE_WIDTH,))
|
self.parse_mdn('pose', outs, in_N=0, out_N=0, out_shape=(SplitModelConstants.POSE_WIDTH,))
|
||||||
|
|||||||
@@ -67,14 +67,22 @@ class TestStockEquivalence:
|
|||||||
state = model_state_factory(ARCHETYPES['vision_policy_split'])
|
state = model_state_factory(ARCHETYPES['vision_policy_split'])
|
||||||
|
|
||||||
frame_skip = derive_frame_skip(SPLIT_VISION_INPUT_SHAPES, SPLIT_POLICY_INPUT_SHAPES)
|
frame_skip = derive_frame_skip(SPLIT_VISION_INPUT_SHAPES, SPLIT_POLICY_INPUT_SHAPES)
|
||||||
|
# action_t is a deep-model prerequisite the SP loader doesn't provide yet; see skip_keys below
|
||||||
stock_shapes = {**SPLIT_VISION_INPUT_SHAPES, **SPLIT_POLICY_INPUT_SHAPES, 'action_t': (1, 2)}
|
stock_shapes = {**SPLIT_VISION_INPUT_SHAPES, **SPLIT_POLICY_INPUT_SHAPES, 'action_t': (1, 2)}
|
||||||
stock_queues, stock_npy = make_input_queues(stock_shapes, frame_skip, device='NPY')
|
stock_queues, stock_npy = make_input_queues(stock_shapes, frame_skip, device='NPY')
|
||||||
|
|
||||||
assert set(state.input_queues.keys()) - {'desire', 'traffic_convention'} == \
|
# TODO-SP: remove action_t skip once SP adds prerequisite for deep models (action_t input queue)
|
||||||
set(stock_queues.keys()) - {'packed_npy_inputs'}
|
# prev_feat is a stock QCOM corruption workaround handled inside the SP loader's JIT path
|
||||||
assert {'desire', 'traffic_convention'} <= set(state.input_queues.keys())
|
skip_keys = {'action_t', 'prev_feat'}
|
||||||
# We generate action_t and prev_feat dynamically based on the metadata
|
# stock packs the per-key policy inputs into packed_npy_inputs; the npy views carry the individual keys
|
||||||
assert set(state.numpy_inputs.keys()) == set(stock_npy.keys()) - {'action_t', 'prev_feat'}
|
stock_queue_keys = set(stock_queues.keys())
|
||||||
|
if 'packed_npy_inputs' in stock_queue_keys:
|
||||||
|
stock_queue_keys.remove('packed_npy_inputs')
|
||||||
|
stock_queue_keys |= set(stock_npy.keys())
|
||||||
|
assert set(state.input_queues.keys()) == stock_queue_keys - skip_keys, \
|
||||||
|
f"Queue keys differ: v2={set(state.input_queues.keys())}, stock={stock_queue_keys}"
|
||||||
|
assert set(state.numpy_inputs.keys()) == set(stock_npy.keys()) - skip_keys, \
|
||||||
|
f"Npy keys differ: v2={set(state.numpy_inputs.keys())}, stock={set(stock_npy.keys())}"
|
||||||
|
|
||||||
def test_split_queue_keys_work_with_desire_key(self, model_state_factory):
|
def test_split_queue_keys_work_with_desire_key(self, model_state_factory):
|
||||||
from openpilot.sunnypilot.modeld_v2.compile_modeld import derive_frame_skip, make_split_input_queues
|
from openpilot.sunnypilot.modeld_v2.compile_modeld import derive_frame_skip, make_split_input_queues
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import os
|
||||||
|
os.environ['DEV'] = 'CPU'
|
||||||
|
import pytest
|
||||||
|
import numpy as np
|
||||||
|
from openpilot.system.camerad.cameras.nv12_info import get_nv12_info
|
||||||
|
from openpilot.sunnypilot.modeld_v2.warp import CAMERA_CONFIGS
|
||||||
|
from openpilot.sunnypilot.modeld_v2.warp import Warp, MODEL_W, MODEL_H
|
||||||
|
|
||||||
|
VISION_NAME_PAIRS = [ # needed to account for supercombos input_imgs
|
||||||
|
('img', 'big_img'),
|
||||||
|
('input_imgs', 'big_input_imgs'),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class MockVisionBuf:
|
||||||
|
def __init__(self, w, h):
|
||||||
|
self.width = w
|
||||||
|
self.height = h
|
||||||
|
_, _, _, yuv_size = get_nv12_info(w, h)
|
||||||
|
self.data = np.zeros(yuv_size, dtype=np.uint8)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("buffer_length", [2, 5])
|
||||||
|
def test_warp_initialization(buffer_length):
|
||||||
|
warp = Warp(buffer_length)
|
||||||
|
assert warp.buffer_length == buffer_length
|
||||||
|
assert warp.img_buffer_shape == (buffer_length * 6, MODEL_H // 2, MODEL_W // 2)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("buffer_length", [2, 5])
|
||||||
|
@pytest.mark.parametrize("cam_w, cam_h", CAMERA_CONFIGS)
|
||||||
|
@pytest.mark.parametrize("road, wide", VISION_NAME_PAIRS)
|
||||||
|
def test_warp_process(buffer_length, cam_w, cam_h, road, wide):
|
||||||
|
warp = Warp(buffer_length)
|
||||||
|
mock_buf = MockVisionBuf(cam_w, cam_h)
|
||||||
|
transform = np.eye(3, dtype=np.float32).flatten()
|
||||||
|
bufs = {road: mock_buf, wide: mock_buf}
|
||||||
|
transforms = {road: transform, wide: transform}
|
||||||
|
|
||||||
|
out = warp.process(bufs, transforms)
|
||||||
|
assert isinstance(out, dict)
|
||||||
|
assert road in out and wide in out
|
||||||
|
assert out[road].shape == (1, 12, MODEL_H // 2, MODEL_W // 2)
|
||||||
|
assert out[wide].shape == (1, 12, MODEL_H // 2, MODEL_W // 2)
|
||||||
|
|
||||||
|
key = (cam_w, cam_h)
|
||||||
|
assert key in warp.jit_cache
|
||||||
|
|
||||||
|
out2 = warp.process(bufs, transforms)
|
||||||
|
assert out2[road].shape == out[road].shape
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("road, wide", VISION_NAME_PAIRS)
|
||||||
|
def test_warp_buffer_shift(road, wide):
|
||||||
|
warp = Warp(2)
|
||||||
|
cam_w, cam_h = CAMERA_CONFIGS[1]
|
||||||
|
transform = np.eye(3, dtype=np.float32).flatten()
|
||||||
|
|
||||||
|
buf1 = MockVisionBuf(cam_w, cam_h)
|
||||||
|
buf1.data[0] = 255
|
||||||
|
bufs1 = {road: buf1, wide: buf1}
|
||||||
|
transforms = {road: transform, wide: transform}
|
||||||
|
out1 = warp.process(bufs1, transforms)
|
||||||
|
road1 = out1[road].numpy().copy()
|
||||||
|
|
||||||
|
buf2 = MockVisionBuf(cam_w, cam_h)
|
||||||
|
buf2.data[0] = 128
|
||||||
|
bufs2 = {road: buf2, wide: buf2}
|
||||||
|
out2 = warp.process(bufs2, transforms)
|
||||||
|
assert not np.array_equal(road1, out2[road].numpy())
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("buffer_length", [2, 5])
|
||||||
|
@pytest.mark.parametrize("road, wide", VISION_NAME_PAIRS)
|
||||||
|
def test_warp_buffer_accumulation(buffer_length, road, wide):
|
||||||
|
warp = Warp(buffer_length)
|
||||||
|
cam_w, cam_h = CAMERA_CONFIGS[0]
|
||||||
|
transform = np.eye(3, dtype=np.float32).flatten()
|
||||||
|
transforms = {road: transform, wide: transform}
|
||||||
|
outputs = []
|
||||||
|
|
||||||
|
for i in range(buffer_length + 1):
|
||||||
|
buf = MockVisionBuf(cam_w, cam_h)
|
||||||
|
buf.data[:] = i * 10
|
||||||
|
out = warp.process({road: buf, wide: buf}, transforms)
|
||||||
|
outputs.append(out[road].numpy().copy())
|
||||||
|
|
||||||
|
assert warp.full_buffers['img'].shape == (buffer_length * 6, MODEL_H // 2, MODEL_W // 2)
|
||||||
|
for i in range(1, len(outputs)):
|
||||||
|
assert not np.array_equal(outputs[i - 1], outputs[i])
|
||||||
|
|
||||||
|
|
||||||
|
def test_warp_different_cameras_same_instance():
|
||||||
|
warp = Warp(2)
|
||||||
|
transform = np.eye(3, dtype=np.float32).flatten()
|
||||||
|
|
||||||
|
buf1 = MockVisionBuf(*CAMERA_CONFIGS[0])
|
||||||
|
warp.process({'img': buf1, 'big_img': buf1}, {'img': transform, 'big_img': transform})
|
||||||
|
assert len(warp.jit_cache) == 1
|
||||||
|
|
||||||
|
buf2 = MockVisionBuf(*CAMERA_CONFIGS[1])
|
||||||
|
warp.process({'img': buf2, 'big_img': buf2}, {'img': transform, 'big_img': transform})
|
||||||
|
assert len(warp.jit_cache) == 2
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
import pickle
|
||||||
|
import time
|
||||||
|
import numpy as np
|
||||||
|
from pathlib import Path
|
||||||
|
from tinygrad.tensor import Tensor
|
||||||
|
from tinygrad.engine.jit import TinyJit
|
||||||
|
from tinygrad.device import Device
|
||||||
|
|
||||||
|
from openpilot.system.camerad.cameras.nv12_info import get_nv12_info
|
||||||
|
from openpilot.common.transformations.model import MEDMODEL_INPUT_SIZE
|
||||||
|
from openpilot.common.transformations.camera import _ar_ox_fisheye, _os_fisheye
|
||||||
|
from openpilot.selfdrive.modeld.compile_modeld import NV12Frame, make_frame_prepare as _make_frame_prepare
|
||||||
|
|
||||||
|
CAMERA_CONFIGS = [
|
||||||
|
(_ar_ox_fisheye.width, _ar_ox_fisheye.height),
|
||||||
|
(_os_fisheye.width, _os_fisheye.height),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def make_frame_prepare(cam_w, cam_h, model_w, model_h):
|
||||||
|
nv12 = NV12Frame(cam_w, cam_h, *get_nv12_info(cam_w, cam_h))
|
||||||
|
return _make_frame_prepare(nv12, model_w, model_h)
|
||||||
|
|
||||||
|
|
||||||
|
def warp_pkl_path(w, h):
|
||||||
|
from openpilot.selfdrive.modeld.helpers import MODELS_DIR
|
||||||
|
return MODELS_DIR / f'warp_{w}x{h}_tinygrad.pkl'
|
||||||
|
|
||||||
|
|
||||||
|
def make_update_img_input(frame_prepare, model_w, model_h):
|
||||||
|
def update_img_input_tinygrad(tensor, frame, M_inv):
|
||||||
|
M_inv = M_inv.to(Device.DEFAULT)
|
||||||
|
new_img = frame_prepare(frame, M_inv)
|
||||||
|
tensor.assign(tensor[6:].cat(new_img, dim=0).contiguous())
|
||||||
|
return Tensor.cat(tensor[:6], tensor[-6:], dim=0).contiguous().reshape(1, 12, model_h//2, model_w//2)
|
||||||
|
return update_img_input_tinygrad
|
||||||
|
|
||||||
|
|
||||||
|
def make_update_both_imgs(frame_prepare, model_w, model_h):
|
||||||
|
update_img = make_update_img_input(frame_prepare, model_w, model_h)
|
||||||
|
def update_both_imgs_tinygrad(calib_img_buffer, new_img, M_inv,
|
||||||
|
calib_big_img_buffer, new_big_img, M_inv_big):
|
||||||
|
calib_img_pair = update_img(calib_img_buffer, new_img, M_inv)
|
||||||
|
calib_big_img_pair = update_img(calib_big_img_buffer, new_big_img, M_inv_big)
|
||||||
|
return calib_img_pair, calib_big_img_pair
|
||||||
|
return update_both_imgs_tinygrad
|
||||||
|
|
||||||
|
MODELS_DIR = Path(__file__).parent / 'models'
|
||||||
|
MODEL_W, MODEL_H = MEDMODEL_INPUT_SIZE
|
||||||
|
UPSTREAM_BUFFER_LENGTH = 5
|
||||||
|
|
||||||
|
|
||||||
|
def v2_warp_pkl_path(cam_w, cam_h, buffer_length):
|
||||||
|
return MODELS_DIR / f'warp_{cam_w}x{cam_h}_b{buffer_length}_tinygrad.pkl'
|
||||||
|
|
||||||
|
|
||||||
|
def compile_v2_warp(cam_w, cam_h, buffer_length):
|
||||||
|
_, _, _, yuv_size = get_nv12_info(cam_w, cam_h)
|
||||||
|
img_buffer_shape = (buffer_length * 6, MODEL_H // 2, MODEL_W // 2)
|
||||||
|
|
||||||
|
print(f"Compiling v2 warp for {cam_w}x{cam_h} buffer_length={buffer_length}...")
|
||||||
|
|
||||||
|
frame_prepare = make_frame_prepare(cam_w, cam_h, MODEL_W, MODEL_H)
|
||||||
|
update_both_imgs = make_update_both_imgs(frame_prepare, MODEL_W, MODEL_H)
|
||||||
|
update_img_jit = TinyJit(update_both_imgs, prune=True)
|
||||||
|
|
||||||
|
full_buffer = Tensor.zeros(img_buffer_shape, dtype='uint8').contiguous().realize()
|
||||||
|
big_full_buffer = Tensor.zeros(img_buffer_shape, dtype='uint8').contiguous().realize()
|
||||||
|
new_frame_np = np.random.default_rng(0).integers(0, 256, yuv_size, dtype=np.uint8)
|
||||||
|
new_big_frame_np = np.random.default_rng(1).integers(0, 256, yuv_size, dtype=np.uint8)
|
||||||
|
for i in range(10):
|
||||||
|
img_inputs = [full_buffer,
|
||||||
|
Tensor.from_blob(new_frame_np.ctypes.data, (yuv_size,), dtype='uint8').realize(),
|
||||||
|
Tensor(Tensor.randn(3, 3).mul(8).realize().numpy(), device='NPY')]
|
||||||
|
big_img_inputs = [big_full_buffer,
|
||||||
|
Tensor.from_blob(new_big_frame_np.ctypes.data, (yuv_size,), dtype='uint8').realize(),
|
||||||
|
Tensor(Tensor.randn(3, 3).mul(8).realize().numpy(), device='NPY')]
|
||||||
|
inputs = img_inputs + big_img_inputs
|
||||||
|
Device.default.synchronize()
|
||||||
|
|
||||||
|
st = time.perf_counter()
|
||||||
|
_ = update_img_jit(*inputs)
|
||||||
|
mt = time.perf_counter()
|
||||||
|
Device.default.synchronize()
|
||||||
|
et = time.perf_counter()
|
||||||
|
print(f" [{i+1}/10] enqueue {(mt-st)*1e3:6.2f} ms -- total {(et-st)*1e3:6.2f} ms")
|
||||||
|
|
||||||
|
pkl_path = v2_warp_pkl_path(cam_w, cam_h, buffer_length)
|
||||||
|
with open(pkl_path, "wb") as f:
|
||||||
|
pickle.dump(update_img_jit, f)
|
||||||
|
print(f" Saved to {pkl_path}")
|
||||||
|
|
||||||
|
jit = pickle.load(open(pkl_path, "rb"))
|
||||||
|
verify_frame = np.random.default_rng(0).integers(0, 256, yuv_size, dtype=np.uint8)
|
||||||
|
verify_big_frame = np.random.default_rng(1).integers(0, 256, yuv_size, dtype=np.uint8)
|
||||||
|
fresh_inputs = [
|
||||||
|
Tensor.zeros(img_buffer_shape, dtype='uint8').contiguous().realize(),
|
||||||
|
Tensor.from_blob(verify_frame.ctypes.data, (yuv_size,), dtype='uint8').realize(),
|
||||||
|
Tensor(Tensor.randn(3, 3).mul(8).realize().numpy(), device='NPY'),
|
||||||
|
Tensor.zeros(img_buffer_shape, dtype='uint8').contiguous().realize(),
|
||||||
|
Tensor.from_blob(verify_big_frame.ctypes.data, (yuv_size,), dtype='uint8').realize(),
|
||||||
|
Tensor(Tensor.randn(3, 3).mul(8).realize().numpy(), device='NPY'),
|
||||||
|
]
|
||||||
|
jit(*fresh_inputs)
|
||||||
|
|
||||||
|
|
||||||
|
class Warp:
|
||||||
|
def __init__(self, buffer_length=2):
|
||||||
|
self.buffer_length = buffer_length
|
||||||
|
self.img_buffer_shape = (buffer_length * 6, MODEL_H // 2, MODEL_W // 2)
|
||||||
|
|
||||||
|
self.jit_cache = {}
|
||||||
|
self.full_buffers = {k: Tensor.zeros(self.img_buffer_shape, dtype='uint8').contiguous().realize() for k in ['img', 'big_img']}
|
||||||
|
self._blob_cache: dict[int, Tensor] = {}
|
||||||
|
self._nv12_cache: dict[tuple[int, int], int] = {}
|
||||||
|
self.transforms_np = {k: np.zeros((3, 3), dtype=np.float32) for k in ['img', 'big_img']}
|
||||||
|
self.transforms = {k: Tensor(v, device='NPY').realize() for k, v in self.transforms_np.items()}
|
||||||
|
|
||||||
|
def process(self, bufs, transforms):
|
||||||
|
if not bufs:
|
||||||
|
return {}
|
||||||
|
road = next(n for n in bufs if 'big' not in n)
|
||||||
|
wide = next(n for n in bufs if 'big' in n)
|
||||||
|
cam_w, cam_h = bufs[road].width, bufs[road].height
|
||||||
|
key = (cam_w, cam_h)
|
||||||
|
|
||||||
|
if key not in self.jit_cache:
|
||||||
|
v2_pkl = v2_warp_pkl_path(cam_w, cam_h, self.buffer_length)
|
||||||
|
if v2_pkl.exists():
|
||||||
|
with open(v2_pkl, 'rb') as f:
|
||||||
|
self.jit_cache[key] = pickle.load(f)
|
||||||
|
elif self.buffer_length == UPSTREAM_BUFFER_LENGTH:
|
||||||
|
upstream_pkl = warp_pkl_path(cam_w, cam_h)
|
||||||
|
if upstream_pkl.exists():
|
||||||
|
with open(upstream_pkl, 'rb') as f:
|
||||||
|
self.jit_cache[key] = pickle.load(f)
|
||||||
|
if key not in self.jit_cache:
|
||||||
|
frame_prepare = make_frame_prepare(cam_w, cam_h, MODEL_W, MODEL_H)
|
||||||
|
update_both_imgs = make_update_both_imgs(frame_prepare, MODEL_W, MODEL_H)
|
||||||
|
self.jit_cache[key] = TinyJit(update_both_imgs, prune=True)
|
||||||
|
|
||||||
|
if key not in self._nv12_cache:
|
||||||
|
self._nv12_cache[key] = get_nv12_info(cam_w, cam_h)[3]
|
||||||
|
yuv_size = self._nv12_cache[key]
|
||||||
|
|
||||||
|
road_ptr = bufs[road].data.ctypes.data
|
||||||
|
wide_ptr = bufs[wide].data.ctypes.data
|
||||||
|
if road_ptr not in self._blob_cache:
|
||||||
|
self._blob_cache[road_ptr] = Tensor.from_blob(road_ptr, (yuv_size,), dtype='uint8')
|
||||||
|
if wide_ptr not in self._blob_cache:
|
||||||
|
self._blob_cache[wide_ptr] = Tensor.from_blob(wide_ptr, (yuv_size,), dtype='uint8')
|
||||||
|
road_blob = self._blob_cache[road_ptr]
|
||||||
|
wide_blob = self._blob_cache[wide_ptr] if wide_ptr != road_ptr else Tensor.from_blob(wide_ptr, (yuv_size,), dtype='uint8')
|
||||||
|
np.copyto(self.transforms_np['img'], transforms[road].reshape(3, 3))
|
||||||
|
np.copyto(self.transforms_np['big_img'], transforms[wide].reshape(3, 3))
|
||||||
|
|
||||||
|
Device.default.synchronize()
|
||||||
|
res = self.jit_cache[key](
|
||||||
|
self.full_buffers['img'], road_blob, self.transforms['img'],
|
||||||
|
self.full_buffers['big_img'], wide_blob, self.transforms['big_img'],
|
||||||
|
)
|
||||||
|
out_road = res[0].realize()
|
||||||
|
out_wide = res[1].realize()
|
||||||
|
|
||||||
|
return {road: out_road, wide: out_wide}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
for cam_w, cam_h in CAMERA_CONFIGS:
|
||||||
|
for bl in [2, 5]:
|
||||||
|
compile_v2_warp(cam_w, cam_h, bl)
|
||||||
@@ -6,12 +6,11 @@ See the LICENSE.md file in the root directory for more details.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import time
|
import time
|
||||||
import os
|
|
||||||
import requests
|
import requests
|
||||||
from requests.exceptions import (SSLError, RequestException, HTTPError)
|
from requests.exceptions import (SSLError, RequestException, HTTPError)
|
||||||
from openpilot.common.params import Params
|
from openpilot.common.params import Params
|
||||||
from openpilot.common.swaglog import cloudlog
|
from openpilot.common.swaglog import cloudlog
|
||||||
from openpilot.common.hardware.hw import Paths
|
|
||||||
from openpilot.sunnypilot.models.helpers import is_bundle_version_compatible
|
from openpilot.sunnypilot.models.helpers import is_bundle_version_compatible
|
||||||
|
|
||||||
from openpilot.cereal import custom
|
from openpilot.cereal import custom
|
||||||
@@ -27,35 +26,11 @@ class ModelParser:
|
|||||||
download_uri.sha256 = download_uri_data.get("sha256")
|
download_uri.sha256 = download_uri_data.get("sha256")
|
||||||
return download_uri
|
return download_uri
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _parse_chunk(chunk_data) -> custom.ModelManagerSP.Chunk:
|
|
||||||
chunk = custom.ModelManagerSP.Chunk()
|
|
||||||
chunk.fileName = chunk_data.get("file_name")
|
|
||||||
chunk.sha256 = chunk_data.get("sha256")
|
|
||||||
return chunk
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_artifact(artifact_data) -> custom.ModelManagerSP.Artifact:
|
def _parse_artifact(artifact_data) -> custom.ModelManagerSP.Artifact:
|
||||||
artifact = custom.ModelManagerSP.Artifact()
|
artifact = custom.ModelManagerSP.Artifact()
|
||||||
artifact.fileName = artifact_data.get("file_name")
|
artifact.fileName = artifact_data.get("file_name")
|
||||||
artifact.downloadUri = ModelParser._parse_download_uri(artifact_data.get("download_uri", {}))
|
artifact.downloadUri = ModelParser._parse_download_uri(artifact_data.get("download_uri", {}))
|
||||||
|
|
||||||
if "chunks" in artifact_data:
|
|
||||||
artifact.chunks = [ModelParser._parse_chunk(chunk_data) for chunk_data in artifact_data["chunks"]]
|
|
||||||
|
|
||||||
try:
|
|
||||||
model_dir = Paths.model_root()
|
|
||||||
os.makedirs(model_dir, exist_ok=True)
|
|
||||||
manifest_path = os.path.join(model_dir, f"{artifact.fileName}.chunkmanifest")
|
|
||||||
num_chunks = str(len(artifact.chunks))
|
|
||||||
|
|
||||||
if not os.path.exists(manifest_path) or open(manifest_path).read().strip() != num_chunks:
|
|
||||||
with open(manifest_path, "w") as f:
|
|
||||||
f.write(num_chunks)
|
|
||||||
cloudlog.info(f"Wrote chunk manifest for {artifact.fileName}: {num_chunks} chunks")
|
|
||||||
except Exception as e:
|
|
||||||
cloudlog.warning(f"Failed to write chunk manifest for {artifact.fileName}: {e}")
|
|
||||||
|
|
||||||
return artifact
|
return artifact
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -64,6 +39,8 @@ class ModelParser:
|
|||||||
|
|
||||||
model.type = model_data.get("type")
|
model.type = model_data.get("type")
|
||||||
model.artifact = ModelParser._parse_artifact(model_data.get("artifact", {}))
|
model.artifact = ModelParser._parse_artifact(model_data.get("artifact", {}))
|
||||||
|
if metadata := model_data.get("metadata"):
|
||||||
|
model.metadata = ModelParser._parse_artifact(metadata)
|
||||||
return model
|
return model
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -139,7 +116,7 @@ class ModelCache:
|
|||||||
|
|
||||||
class ModelFetcher:
|
class ModelFetcher:
|
||||||
"""Handles fetching and caching of model data from remote source"""
|
"""Handles fetching and caching of model data from remote source"""
|
||||||
MODEL_URL = "https://raw.githubusercontent.com/sunnypilot/sunnypilot-models/refs/heads/gh-pages/docs/driving_models_v18.json"
|
MODEL_URL = "https://raw.githubusercontent.com/sunnypilot/sunnypilot-models/refs/heads/gh-pages/docs/driving_models_v17.json"
|
||||||
|
|
||||||
def __init__(self, params: Params):
|
def __init__(self, params: Params):
|
||||||
self.params = params
|
self.params = params
|
||||||
@@ -207,5 +184,4 @@ if __name__ == "__main__":
|
|||||||
# Print artifact details
|
# Print artifact details
|
||||||
print(f"Artifact: {model.artifact.fileName}, Download URI: {model.artifact.downloadUri.uri}")
|
print(f"Artifact: {model.artifact.fileName}, Download URI: {model.artifact.downloadUri.uri}")
|
||||||
# Print metadata details
|
# Print metadata details
|
||||||
if model.artifact.chunks:
|
print(f"Metadata: {model.metadata.fileName}, Download URI: {model.metadata.downloadUri.uri}")
|
||||||
print(f"Contains {len(model.artifact.chunks)} chunks.")
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from openpilot.sunnypilot.models.constants import Meta, MetaSimPose, MetaTombRai
|
|||||||
from openpilot.common.hardware.hw import Paths
|
from openpilot.common.hardware.hw import Paths
|
||||||
|
|
||||||
# SET ME TO THE EXACT JSON VERSION WE SET IN SUNNYPILOT_MODELS REPO
|
# SET ME TO THE EXACT JSON VERSION WE SET IN SUNNYPILOT_MODELS REPO
|
||||||
REQUIRED_JSON_VERSION = 16
|
REQUIRED_JSON_VERSION = 15
|
||||||
|
|
||||||
CUSTOM_MODEL_PATH = Paths.model_root()
|
CUSTOM_MODEL_PATH = Paths.model_root()
|
||||||
METADATA_PATH = Path(__file__).parent / '../models/supercombo_metadata.pkl'
|
METADATA_PATH = Path(__file__).parent / '../models/supercombo_metadata.pkl'
|
||||||
@@ -56,20 +56,12 @@ def is_bundle_version_compatible(bundle: dict) -> bool:
|
|||||||
|
|
||||||
def _bundle_artifacts(bundle: custom.ModelManagerSP.ModelBundle) -> list[tuple[str, str]]:
|
def _bundle_artifacts(bundle: custom.ModelManagerSP.ModelBundle) -> list[tuple[str, str]]:
|
||||||
artifacts = []
|
artifacts = []
|
||||||
from openpilot.common.file_chunker import get_chunk_name
|
|
||||||
for model in getattr(bundle, 'models', []) or []:
|
for model in getattr(bundle, 'models', []) or []:
|
||||||
for artifact in (getattr(model, 'artifact', None),):
|
for artifact in (getattr(model, 'artifact', None), getattr(model, 'metadata', None)):
|
||||||
if artifact and getattr(artifact, 'fileName', None):
|
if artifact and getattr(artifact, 'fileName', None) and getattr(artifact, 'downloadUri', None):
|
||||||
if len(artifact.chunks) > 0:
|
sha256 = getattr(artifact.downloadUri, 'sha256', None)
|
||||||
for i, chunk in enumerate(artifact.chunks):
|
if sha256:
|
||||||
chunk_name = get_chunk_name(artifact.fileName, i, len(artifact.chunks))
|
artifacts.append((artifact.fileName, sha256))
|
||||||
if getattr(chunk, 'sha256', None):
|
|
||||||
artifacts.append((chunk_name, chunk.sha256))
|
|
||||||
else:
|
|
||||||
if getattr(artifact, 'downloadUri', None):
|
|
||||||
sha256 = getattr(artifact.downloadUri, 'sha256', None)
|
|
||||||
if sha256:
|
|
||||||
artifacts.append((artifact.fileName, sha256))
|
|
||||||
return artifacts
|
return artifacts
|
||||||
|
|
||||||
|
|
||||||
@@ -164,7 +156,8 @@ def _get_model():
|
|||||||
|
|
||||||
|
|
||||||
def load_metadata():
|
def load_metadata():
|
||||||
metadata_path = METADATA_PATH
|
model = _get_model()
|
||||||
|
metadata_path = f"{CUSTOM_MODEL_PATH}/{model.metadata.fileName}" if model else METADATA_PATH
|
||||||
|
|
||||||
with open(metadata_path, 'rb') as f:
|
with open(metadata_path, 'rb') as f:
|
||||||
return pickle.load(f)
|
return pickle.load(f)
|
||||||
|
|||||||
@@ -38,11 +38,11 @@ class ModelManagerSP:
|
|||||||
if not self.selected_bundle:
|
if not self.selected_bundle:
|
||||||
return
|
return
|
||||||
for model in self.selected_bundle.models:
|
for model in self.selected_bundle.models:
|
||||||
artifact = model.artifact
|
for artifact in (model.artifact, model.metadata):
|
||||||
if artifact is not source_artifact and artifact.fileName == source_artifact.fileName:
|
if artifact is not source_artifact and artifact.fileName == source_artifact.fileName:
|
||||||
artifact.downloadProgress.status = source_artifact.downloadProgress.status
|
artifact.downloadProgress.status = source_artifact.downloadProgress.status
|
||||||
artifact.downloadProgress.progress = source_artifact.downloadProgress.progress
|
artifact.downloadProgress.progress = source_artifact.downloadProgress.progress
|
||||||
artifact.downloadProgress.eta = source_artifact.downloadProgress.eta
|
artifact.downloadProgress.eta = source_artifact.downloadProgress.eta
|
||||||
|
|
||||||
def _calculate_eta(self, filename: str, progress: float) -> int:
|
def _calculate_eta(self, filename: str, progress: float) -> int:
|
||||||
"""Calculate ETA based on elapsed time and current progress"""
|
"""Calculate ETA based on elapsed time and current progress"""
|
||||||
@@ -89,16 +89,20 @@ class ModelManagerSP:
|
|||||||
del self._download_start_times[model.fileName]
|
del self._download_start_times[model.fileName]
|
||||||
|
|
||||||
async def _download_chunked(self, base_url: str, base_path: str, artifact) -> None:
|
async def _download_chunked(self, base_url: str, base_path: str, artifact) -> None:
|
||||||
from openpilot.common.file_chunker import get_chunk_name, get_manifest_path
|
from openpilot.common.file_chunker import get_manifest_path, get_chunk_name
|
||||||
|
manifest_url = get_manifest_path(base_url)
|
||||||
num_chunks = len(artifact.chunks)
|
|
||||||
if num_chunks == 0:
|
|
||||||
raise ValueError("No chunks defined in artifact")
|
|
||||||
|
|
||||||
manifest_path = get_manifest_path(base_path)
|
manifest_path = get_manifest_path(base_path)
|
||||||
|
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get(manifest_url) as resp:
|
||||||
|
if resp.status == 404:
|
||||||
|
raise FileNotFoundError
|
||||||
|
resp.raise_for_status()
|
||||||
|
num_chunks = int((await resp.read()).strip())
|
||||||
|
|
||||||
self._download_start_times[artifact.fileName] = time.monotonic()
|
self._download_start_times[artifact.fileName] = time.monotonic()
|
||||||
|
|
||||||
for i, _ in enumerate(artifact.chunks):
|
for i in range(num_chunks):
|
||||||
chunk_url = get_chunk_name(base_url, i, num_chunks)
|
chunk_url = get_chunk_name(base_url, i, num_chunks)
|
||||||
chunk_path = get_chunk_name(base_path, i, num_chunks)
|
chunk_path = get_chunk_name(base_path, i, num_chunks)
|
||||||
chunk_downloaded = 0
|
chunk_downloaded = 0
|
||||||
@@ -113,7 +117,7 @@ class ModelManagerSP:
|
|||||||
if self.params.get("ModelManager_DownloadIndex") is None:
|
if self.params.get("ModelManager_DownloadIndex") is None:
|
||||||
raise Exception("Download cancelled")
|
raise Exception("Download cancelled")
|
||||||
intra = chunk_downloaded / max(chunk_size, 1)
|
intra = chunk_downloaded / max(chunk_size, 1)
|
||||||
progress = min(99.0, ((i + intra) / num_chunks) * 100)
|
progress = min(99, (i + intra) / num_chunks * 100)
|
||||||
artifact.downloadProgress.status = custom.ModelManagerSP.DownloadStatus.downloading
|
artifact.downloadProgress.status = custom.ModelManagerSP.DownloadStatus.downloading
|
||||||
artifact.downloadProgress.progress = progress
|
artifact.downloadProgress.progress = progress
|
||||||
artifact.downloadProgress.eta = self._calculate_eta(artifact.fileName, progress)
|
artifact.downloadProgress.eta = self._calculate_eta(artifact.fileName, progress)
|
||||||
@@ -136,22 +140,7 @@ class ModelManagerSP:
|
|||||||
full_path = os.path.join(destination_path, filename)
|
full_path = os.path.join(destination_path, filename)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
is_cached = False
|
if await verify_file(full_path, expected_hash):
|
||||||
if len(artifact.chunks) > 0:
|
|
||||||
from openpilot.common.file_chunker import get_chunk_name
|
|
||||||
chunks_valid = True
|
|
||||||
for i, chunk in enumerate(artifact.chunks):
|
|
||||||
chunk_path = get_chunk_name(full_path, i, len(artifact.chunks))
|
|
||||||
if not await verify_file(chunk_path, chunk.sha256):
|
|
||||||
chunks_valid = False
|
|
||||||
break
|
|
||||||
if chunks_valid and len(artifact.chunks) > 0:
|
|
||||||
is_cached = True
|
|
||||||
else:
|
|
||||||
if await verify_file(full_path, expected_hash):
|
|
||||||
is_cached = True
|
|
||||||
|
|
||||||
if is_cached:
|
|
||||||
artifact.downloadProgress.status = custom.ModelManagerSP.DownloadStatus.cached
|
artifact.downloadProgress.status = custom.ModelManagerSP.DownloadStatus.cached
|
||||||
artifact.downloadProgress.progress = 100
|
artifact.downloadProgress.progress = 100
|
||||||
artifact.downloadProgress.eta = 0
|
artifact.downloadProgress.eta = 0
|
||||||
@@ -159,17 +148,13 @@ class ModelManagerSP:
|
|||||||
self._report_status()
|
self._report_status()
|
||||||
return
|
return
|
||||||
|
|
||||||
if len(artifact.chunks) > 0:
|
try:
|
||||||
await self._download_chunked(url, full_path, artifact)
|
await self._download_chunked(url, full_path, artifact)
|
||||||
from openpilot.common.file_chunker import get_chunk_name
|
except (FileNotFoundError, aiohttp.ClientResponseError):
|
||||||
for i, chunk in enumerate(artifact.chunks):
|
|
||||||
chunk_path = get_chunk_name(full_path, i, len(artifact.chunks))
|
|
||||||
if not await verify_file(chunk_path, chunk.sha256):
|
|
||||||
raise ValueError(f"Hash validation failed for chunk {i+1} of {filename}")
|
|
||||||
else:
|
|
||||||
await self._download_file(url, full_path, artifact)
|
await self._download_file(url, full_path, artifact)
|
||||||
if not await verify_file(full_path, expected_hash):
|
|
||||||
raise ValueError(f"Hash validation failed for {filename}")
|
if not await verify_file(full_path, expected_hash):
|
||||||
|
raise ValueError(f"Hash validation failed for {filename}")
|
||||||
|
|
||||||
artifact.downloadProgress.status = custom.ModelManagerSP.DownloadStatus.downloaded
|
artifact.downloadProgress.status = custom.ModelManagerSP.DownloadStatus.downloaded
|
||||||
artifact.downloadProgress.progress = 100
|
artifact.downloadProgress.progress = 100
|
||||||
@@ -185,15 +170,18 @@ class ModelManagerSP:
|
|||||||
artifact.downloadProgress.status = custom.ModelManagerSP.DownloadStatus.failed
|
artifact.downloadProgress.status = custom.ModelManagerSP.DownloadStatus.failed
|
||||||
artifact.downloadProgress.eta = 0
|
artifact.downloadProgress.eta = 0
|
||||||
self._sync_artifact_progress(artifact)
|
self._sync_artifact_progress(artifact)
|
||||||
if self.selected_bundle:
|
self.selected_bundle.status = custom.ModelManagerSP.DownloadStatus.failed
|
||||||
self.selected_bundle.status = custom.ModelManagerSP.DownloadStatus.failed
|
|
||||||
self._report_status()
|
self._report_status()
|
||||||
self._download_start_times.pop(artifact.fileName, None)
|
self._download_start_times.pop(artifact.fileName, None)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
async def _process_model(self, model, destination_path: str) -> None:
|
async def _process_model(self, model, destination_path: str) -> None:
|
||||||
"""Processes a single model download including verification"""
|
"""Processes a single model download including verification"""
|
||||||
await self._process_artifact(model.artifact, destination_path)
|
model_artifact = model.artifact
|
||||||
|
metadata_artifact = model.metadata
|
||||||
|
|
||||||
|
await self._process_artifact(metadata_artifact, destination_path)
|
||||||
|
await self._process_artifact(model_artifact, destination_path)
|
||||||
|
|
||||||
def _report_status(self) -> None:
|
def _report_status(self) -> None:
|
||||||
"""Reports current status through messaging system"""
|
"""Reports current status through messaging system"""
|
||||||
@@ -217,16 +205,16 @@ class ModelManagerSP:
|
|||||||
try:
|
try:
|
||||||
seen_artifacts: set[str] = set()
|
seen_artifacts: set[str] = set()
|
||||||
for model in self.selected_bundle.models:
|
for model in self.selected_bundle.models:
|
||||||
artifact = model.artifact
|
for artifact in (model.metadata, model.artifact):
|
||||||
if not artifact.fileName:
|
if not artifact.fileName:
|
||||||
continue
|
continue
|
||||||
if artifact.fileName in seen_artifacts:
|
if artifact.fileName in seen_artifacts:
|
||||||
artifact.downloadProgress.status = custom.ModelManagerSP.DownloadStatus.cached
|
artifact.downloadProgress.status = custom.ModelManagerSP.DownloadStatus.cached
|
||||||
artifact.downloadProgress.progress = 100
|
artifact.downloadProgress.progress = 100
|
||||||
artifact.downloadProgress.eta = 0
|
artifact.downloadProgress.eta = 0
|
||||||
else:
|
else:
|
||||||
seen_artifacts.add(artifact.fileName)
|
seen_artifacts.add(artifact.fileName)
|
||||||
await self._process_artifact(artifact, destination_path)
|
await self._process_artifact(artifact, destination_path)
|
||||||
|
|
||||||
self.active_bundle = self.selected_bundle
|
self.active_bundle = self.selected_bundle
|
||||||
self.active_bundle.status = custom.ModelManagerSP.DownloadStatus.downloaded
|
self.active_bundle.status = custom.ModelManagerSP.DownloadStatus.downloaded
|
||||||
@@ -287,6 +275,8 @@ class ModelManagerSP:
|
|||||||
for model in self.active_bundle.models:
|
for model in self.active_bundle.models:
|
||||||
if hasattr(model, 'artifact') and model.artifact.fileName:
|
if hasattr(model, 'artifact') and model.artifact.fileName:
|
||||||
active_files.append(model.artifact.fileName)
|
active_files.append(model.artifact.fileName)
|
||||||
|
if hasattr(model, 'metadata') and model.metadata.fileName:
|
||||||
|
active_files.append(model.metadata.fileName)
|
||||||
|
|
||||||
# Remove all files except active ones (including their chunk files)
|
# Remove all files except active ones (including their chunk files)
|
||||||
model_dir = Paths.model_root()
|
model_dir = Paths.model_root()
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
from openpilot.sunnypilot.models.helpers import get_active_bundle
|
||||||
|
from openpilot.sunnypilot.models.runners.model_runner import ModelRunner
|
||||||
|
from openpilot.sunnypilot.models.runners.tinygrad.tinygrad_runner import TinygradRunner, TinygradSplitRunner
|
||||||
|
from openpilot.sunnypilot.models.runners.constants import ModelType
|
||||||
|
|
||||||
|
|
||||||
|
def get_model_runner() -> ModelRunner:
|
||||||
|
"""
|
||||||
|
Factory function to create and return the appropriate ModelRunner instance.
|
||||||
|
|
||||||
|
Selects TinygradRunner, choosing TinygradSplitRunner if separate vision/policy
|
||||||
|
models are detected in the active bundle.
|
||||||
|
|
||||||
|
:return: An instance of a ModelRunner subclass (ONNXRunner, TinygradRunner, or TinygradSplitRunner).
|
||||||
|
"""
|
||||||
|
bundle = get_active_bundle()
|
||||||
|
if bundle and bundle.models:
|
||||||
|
model_types = {m.type.raw for m in bundle.models}
|
||||||
|
# Check if the bundle uses separate vision and policy models (legacy or new split format)
|
||||||
|
split_types = {ModelType.vision, ModelType.policy, ModelType.offPolicy, ModelType.onPolicy}
|
||||||
|
if model_types & split_types:
|
||||||
|
return TinygradSplitRunner()
|
||||||
|
# Otherwise, assume a single model (likely supercombo)
|
||||||
|
if bundle.models:
|
||||||
|
return TinygradRunner(bundle.models[0].type.raw)
|
||||||
|
|
||||||
|
# Default fallback to TinygradRunner with the supercombo type if bundle info is missing/incomplete
|
||||||
|
return TinygradRunner(ModelType.supercombo)
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
from abc import abstractmethod, ABC
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from openpilot.sunnypilot.models.helpers import get_active_bundle
|
||||||
|
from openpilot.sunnypilot.models.runners.constants import NumpyDict, ShapeDict, Model, SliceDict, SEND_RAW_PRED
|
||||||
|
from openpilot.common.hardware.hw import Paths
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
CUSTOM_MODEL_PATH = Paths.model_root()
|
||||||
|
|
||||||
|
|
||||||
|
class ModelData:
|
||||||
|
"""
|
||||||
|
Stores metadata and configuration for a specific machine learning model.
|
||||||
|
|
||||||
|
This class loads model metadata (like input shapes and output slices)
|
||||||
|
from a pickle file associated with a model instance.
|
||||||
|
|
||||||
|
:param model: The machine learning model object containing metadata.
|
||||||
|
"""
|
||||||
|
def __init__(self, model: Model):
|
||||||
|
self.model = model
|
||||||
|
self.metadata = model.metadata
|
||||||
|
self.input_shapes: ShapeDict = {}
|
||||||
|
self.output_slices: SliceDict = {}
|
||||||
|
if self.metadata:
|
||||||
|
self._load_metadata()
|
||||||
|
|
||||||
|
def _load_metadata(self) -> None:
|
||||||
|
"""Loads input shapes and output slices from the model's metadata pickle file."""
|
||||||
|
metadata_path = f"{CUSTOM_MODEL_PATH}/{self.metadata.fileName}"
|
||||||
|
with open(metadata_path, 'rb') as f:
|
||||||
|
model_metadata = pickle.load(f)
|
||||||
|
self.input_shapes = model_metadata.get('input_shapes', {})
|
||||||
|
self.output_slices = model_metadata.get('output_slices', {})
|
||||||
|
|
||||||
|
|
||||||
|
class ModularRunner(ABC):
|
||||||
|
"""
|
||||||
|
Represents a modular runner for handling and slicing model outputs.
|
||||||
|
|
||||||
|
This abstract base class is designed to provide an interface for modular
|
||||||
|
parsing and processing of model outputs. Classes inheriting from it must
|
||||||
|
implement the specified abstract methods, defining how model outputs
|
||||||
|
should be handled and stored. The primary goal is to enable structured
|
||||||
|
parsing of outputs through a dictionary-based method mapping.
|
||||||
|
|
||||||
|
:ivar parser_method_dict: Mapping dictionary containing parser methods
|
||||||
|
for handling specific types of outputs.
|
||||||
|
:type parser_method_dict: dict
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def parser_method_dict(self) -> dict:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@parser_method_dict.setter
|
||||||
|
@abstractmethod
|
||||||
|
def parser_method_dict(self, value: dict) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def _slice_outputs(self, model_outputs: np.ndarray) -> NumpyDict:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ModelRunner(ModularRunner):
|
||||||
|
"""
|
||||||
|
Abstract base class for managing and executing machine learning models.
|
||||||
|
|
||||||
|
Provides a common interface for loading models, preparing inputs, running
|
||||||
|
inference, and slicing/parsing outputs based on model metadata. Derived
|
||||||
|
classes implement the specifics of input preparation and model execution
|
||||||
|
for different frameworks (e.g., Tinygrad, ONNX).
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Initializes the model runner, loading the active model bundle."""
|
||||||
|
self.is_20hz: bool | None = None
|
||||||
|
self.is_20hz_3d: bool | None = None
|
||||||
|
self.models: dict[int, ModelData] = {}
|
||||||
|
self._model_data: ModelData | None = None # Active model data for current operation
|
||||||
|
self._parser_method_dict: dict = {}
|
||||||
|
self.inputs: dict = {}
|
||||||
|
self._parser = None
|
||||||
|
self._load_models()
|
||||||
|
self._constants = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def constants(self):
|
||||||
|
return self._constants
|
||||||
|
|
||||||
|
@property
|
||||||
|
def parser_method_dict(self) -> dict:
|
||||||
|
"""Returns the dictionary mapping model types to their respective parsing methods."""
|
||||||
|
return self._parser_method_dict
|
||||||
|
|
||||||
|
@parser_method_dict.setter
|
||||||
|
def parser_method_dict(self, value: dict) -> None:
|
||||||
|
"""Sets the dictionary mapping model types to their respective parsing methods."""
|
||||||
|
self._parser_method_dict = value
|
||||||
|
|
||||||
|
def _load_models(self) -> None:
|
||||||
|
"""Loads the active model bundle configuration and sets up ModelData."""
|
||||||
|
bundle = get_active_bundle()
|
||||||
|
if not bundle:
|
||||||
|
raise ValueError("No active model bundle found, why are we being executed?")
|
||||||
|
|
||||||
|
self.models = {model.type.raw: ModelData(model) for model in bundle.models}
|
||||||
|
self.is_20hz = bundle.is20hz
|
||||||
|
self.is_20hz_3d = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def input_shapes(self) -> ShapeDict:
|
||||||
|
"""Returns the input shapes for the currently active model."""
|
||||||
|
if self._model_data:
|
||||||
|
return self._model_data.input_shapes
|
||||||
|
raise ValueError("Model data is not available. Ensure the model is loaded correctly.")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def output_slices(self) -> SliceDict:
|
||||||
|
"""Returns the output slices for the currently active model."""
|
||||||
|
if self._model_data:
|
||||||
|
return self._model_data.output_slices
|
||||||
|
raise ValueError("Model data is not available. Ensure the model is loaded correctly.")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def vision_input_names(self) -> list[str]:
|
||||||
|
"""Returns the list of vision input names from the input shapes."""
|
||||||
|
if self._model_data:
|
||||||
|
return list(self._model_data.input_shapes.keys())
|
||||||
|
raise ValueError("Model data is not available. Ensure the model is loaded correctly.")
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def prepare_inputs(self, numpy_inputs: NumpyDict) -> dict:
|
||||||
|
"""
|
||||||
|
Abstract method to prepare inputs for model inference.
|
||||||
|
|
||||||
|
:param numpy_inputs: Dictionary of numpy arrays for non-image inputs.
|
||||||
|
:return: Dictionary of prepared inputs ready for the model.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def _run_model(self) -> NumpyDict:
|
||||||
|
"""
|
||||||
|
Abstract method to execute model inference with prepared inputs.
|
||||||
|
|
||||||
|
:return: Dictionary containing the model's raw output arrays.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def _slice_outputs(self, model_outputs: np.ndarray) -> NumpyDict:
|
||||||
|
"""
|
||||||
|
Slices the raw model output array based on the output_slices metadata.
|
||||||
|
|
||||||
|
:param model_outputs: The raw numpy array output from the model.
|
||||||
|
:return: A dictionary where keys are output names and values are sliced numpy arrays.
|
||||||
|
"""
|
||||||
|
if not self._model_data:
|
||||||
|
raise ValueError("Model data is not available. Ensure the model is loaded correctly.")
|
||||||
|
sliced_outputs = {k: model_outputs[np.newaxis, v] for k, v in self._model_data.output_slices.items()}
|
||||||
|
if SEND_RAW_PRED:
|
||||||
|
sliced_outputs['raw_pred'] = model_outputs.copy() # Optionally include the full raw output
|
||||||
|
return sliced_outputs
|
||||||
|
|
||||||
|
def run_model(self) -> NumpyDict:
|
||||||
|
"""
|
||||||
|
Executes the model inference pipeline: runs the model and parses outputs.
|
||||||
|
|
||||||
|
:return: Dictionary containing the final parsed model outputs.
|
||||||
|
"""
|
||||||
|
return self._run_model() # Parsing is handled within specific runner implementations
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import os
|
||||||
|
from abc import ABC
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from openpilot.sunnypilot.modeld_v2.parse_model_outputs import Parser as CombinedParser
|
||||||
|
from openpilot.sunnypilot.modeld_v2.parse_model_outputs_split import Parser as SplitParser
|
||||||
|
from openpilot.sunnypilot.models.runners.constants import ModelType, NumpyDict
|
||||||
|
from openpilot.sunnypilot.models.runners.model_runner import ModularRunner
|
||||||
|
from openpilot.common.hardware.hw import Paths
|
||||||
|
|
||||||
|
|
||||||
|
SEND_RAW_PRED = os.getenv('SEND_RAW_PRED')
|
||||||
|
CUSTOM_MODEL_PATH = Paths.model_root()
|
||||||
|
|
||||||
|
|
||||||
|
class OffPolicyTinygrad(ModularRunner, ABC):
|
||||||
|
"""
|
||||||
|
A TinygradRunner specialized for off-policy models.
|
||||||
|
|
||||||
|
Uses a SplitParser to handle outputs specific to the off-policy part of a split model setup.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._off_policy_parser = SplitParser()
|
||||||
|
self.parser_method_dict[ModelType.offPolicy] = self._parse_off_policy_outputs
|
||||||
|
|
||||||
|
def _parse_off_policy_outputs(self, model_outputs: np.ndarray) -> NumpyDict:
|
||||||
|
"""Parses off-policy model outputs using SplitParser."""
|
||||||
|
result: NumpyDict = self._off_policy_parser.parse_policy_outputs(self._slice_outputs(model_outputs))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class OnPolicyTinygrad(ModularRunner, ABC):
|
||||||
|
"""
|
||||||
|
A TinygradRunner specialized for on-policy models.
|
||||||
|
|
||||||
|
Uses a SplitParser to handle outputs specific to the on-policy part of a split model setup.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._on_policy_parser = SplitParser()
|
||||||
|
self.parser_method_dict[ModelType.onPolicy] = self._parse_on_policy_outputs
|
||||||
|
|
||||||
|
def _parse_on_policy_outputs(self, model_outputs: np.ndarray) -> NumpyDict:
|
||||||
|
"""Parses on-policy model outputs using SplitParser."""
|
||||||
|
result: NumpyDict = self._on_policy_parser.parse_policy_outputs(self._slice_outputs(model_outputs))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class PolicyTinygrad(ModularRunner, ABC):
|
||||||
|
"""
|
||||||
|
A TinygradRunner specialized for policy-only models.
|
||||||
|
|
||||||
|
Uses a SplitParser to handle outputs specific to the policy part of a split model setup.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._policy_parser = SplitParser()
|
||||||
|
self.parser_method_dict[ModelType.policy] = self._parse_policy_outputs
|
||||||
|
|
||||||
|
def _parse_policy_outputs(self, model_outputs: np.ndarray) -> NumpyDict:
|
||||||
|
"""Parses policy model outputs using SplitParser."""
|
||||||
|
result: NumpyDict = self._policy_parser.parse_policy_outputs(self._slice_outputs(model_outputs))
|
||||||
|
return result
|
||||||
|
|
||||||
|
class VisionTinygrad(ModularRunner, ABC):
|
||||||
|
"""
|
||||||
|
A TinygradRunner specialized for vision-only models.
|
||||||
|
|
||||||
|
Uses a SplitParser to handle outputs specific to the vision part of a split model setup.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._vision_parser = SplitParser()
|
||||||
|
self.parser_method_dict[ModelType.vision] = self._parse_vision_outputs
|
||||||
|
|
||||||
|
def _parse_vision_outputs(self, model_outputs: np.ndarray) -> NumpyDict:
|
||||||
|
"""Parses vision model outputs using SplitParser."""
|
||||||
|
result: NumpyDict = self._vision_parser.parse_vision_outputs(self._slice_outputs(model_outputs))
|
||||||
|
return result
|
||||||
|
|
||||||
|
class SupercomboTinygrad(ModularRunner, ABC):
|
||||||
|
"""
|
||||||
|
A TinygradRunner specialized for vision-only models.
|
||||||
|
|
||||||
|
Uses a SplitParser to handle outputs specific to the vision part of a split model setup.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self._supercombo_parser = CombinedParser()
|
||||||
|
self.parser_method_dict[ModelType.supercombo] = self._parse_supercombo_outputs
|
||||||
|
|
||||||
|
def _parse_supercombo_outputs(self, model_outputs: np.ndarray) -> NumpyDict:
|
||||||
|
"""Parses vision model outputs using SplitParser."""
|
||||||
|
result: NumpyDict = self._supercombo_parser.parse_outputs(self._slice_outputs(model_outputs))
|
||||||
|
return result
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
import pickle
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from openpilot.sunnypilot.models.runners.constants import NumpyDict, ModelType, ShapeDict, CUSTOM_MODEL_PATH, SliceDict
|
||||||
|
from openpilot.sunnypilot.models.runners.model_runner import ModelRunner
|
||||||
|
from openpilot.sunnypilot.models.runners.tinygrad.model_types import PolicyTinygrad, VisionTinygrad, SupercomboTinygrad, OffPolicyTinygrad, OnPolicyTinygrad
|
||||||
|
from openpilot.sunnypilot.models.split_model_constants import SplitModelConstants
|
||||||
|
from openpilot.sunnypilot.modeld_v2.constants import ModelConstants
|
||||||
|
|
||||||
|
from tinygrad.tensor import Tensor
|
||||||
|
|
||||||
|
|
||||||
|
class TinygradRunner(ModelRunner, SupercomboTinygrad, PolicyTinygrad, VisionTinygrad, OffPolicyTinygrad, OnPolicyTinygrad):
|
||||||
|
"""
|
||||||
|
A ModelRunner implementation for executing Tinygrad models.
|
||||||
|
|
||||||
|
Handles loading Tinygrad model artifacts (.pkl), preparing inputs as Tinygrad
|
||||||
|
Tensors (potentially using QCOM extensions on TICI), running inference,
|
||||||
|
and parsing the outputs.
|
||||||
|
|
||||||
|
:param model_type: The type of model (e.g., supercombo) to load and run.
|
||||||
|
"""
|
||||||
|
def __init__(self, model_type: int = ModelType.supercombo):
|
||||||
|
ModelRunner.__init__(self)
|
||||||
|
SupercomboTinygrad.__init__(self)
|
||||||
|
PolicyTinygrad.__init__(self)
|
||||||
|
VisionTinygrad.__init__(self)
|
||||||
|
OffPolicyTinygrad.__init__(self)
|
||||||
|
OnPolicyTinygrad.__init__(self)
|
||||||
|
self._constants = ModelConstants
|
||||||
|
self._model_data = self.models.get(model_type)
|
||||||
|
if not self._model_data or not self._model_data.model:
|
||||||
|
raise ValueError(f"Model data for type {model_type} not available.")
|
||||||
|
|
||||||
|
artifact_filename = self._model_data.model.artifact.fileName
|
||||||
|
assert artifact_filename.endswith('_tinygrad.pkl'), \
|
||||||
|
f"Invalid model file {artifact_filename} for TinygradRunner"
|
||||||
|
|
||||||
|
model_pkl_path = f"{CUSTOM_MODEL_PATH}/{artifact_filename}"
|
||||||
|
with open(model_pkl_path, "rb") as f:
|
||||||
|
try:
|
||||||
|
# Load the compiled Tinygrad model runner function
|
||||||
|
self.model_run = pickle.load(f)
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
# Provide a helpful error message if the model was built for a different platform
|
||||||
|
assert "/dev/kgsl-3d0" not in str(e), "Model was built on C3 or C3X, but is being loaded on PC"
|
||||||
|
raise
|
||||||
|
|
||||||
|
# Map input names to their required dtype and device from the loaded model
|
||||||
|
self.input_to_dtype = {}
|
||||||
|
self.input_to_device = {}
|
||||||
|
for idx, name in enumerate(self.model_run.captured.expected_names):
|
||||||
|
info = self.model_run.captured.expected_input_info[idx]
|
||||||
|
self.input_to_dtype[name] = info[2] # dtype
|
||||||
|
self.input_to_device[name] = info[3] # device
|
||||||
|
self._policy_cached = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def vision_input_names(self) -> list[str]:
|
||||||
|
"""Returns the list of vision input names from the input shapes."""
|
||||||
|
return [name for name in self.input_shapes.keys() if 'img' in name]
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_policy_inputs(self, numpy_inputs: NumpyDict):
|
||||||
|
if not self._policy_cached:
|
||||||
|
for key, value in numpy_inputs.items():
|
||||||
|
self.inputs[key] = Tensor(value, device='NPY').realize()
|
||||||
|
self._policy_cached = True
|
||||||
|
|
||||||
|
def prepare_inputs(self, numpy_inputs: NumpyDict) -> dict:
|
||||||
|
"""Prepares all vision and policy inputs for the model."""
|
||||||
|
self.prepare_policy_inputs(numpy_inputs)
|
||||||
|
for key in self.vision_input_names:
|
||||||
|
if key in self.inputs:
|
||||||
|
self.inputs[key] = self.inputs[key].cast(self.input_to_dtype[key])
|
||||||
|
return self.inputs
|
||||||
|
|
||||||
|
def _run_model(self) -> NumpyDict:
|
||||||
|
"""Runs the Tinygrad model inference and parses the outputs."""
|
||||||
|
outputs = self.model_run(**self.inputs).contiguous().realize().uop.base.buffer.numpy().flatten()
|
||||||
|
return self._parse_outputs(outputs)
|
||||||
|
|
||||||
|
def _parse_outputs(self, model_outputs: np.ndarray) -> NumpyDict:
|
||||||
|
"""Parses the raw model outputs using the standard Parser."""
|
||||||
|
if self._model_data is None:
|
||||||
|
raise ValueError("Model data is not available. Ensure the model is loaded correctly.")
|
||||||
|
|
||||||
|
result: NumpyDict = self.parser_method_dict[self._model_data.model.type.raw](model_outputs)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class TinygradSplitRunner(ModelRunner):
|
||||||
|
"""
|
||||||
|
A ModelRunner that coordinates separate TinygradVisionRunner and TinygradPolicyRunner instances.
|
||||||
|
|
||||||
|
Manages the execution of split vision and policy models, combining their inputs and outputs.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.is_20hz_3d = True
|
||||||
|
self.vision_runner = TinygradRunner(ModelType.vision)
|
||||||
|
self.policy_runner = TinygradRunner(ModelType.policy) if self.models.get(ModelType.policy) else None
|
||||||
|
self.off_policy_runner = TinygradRunner(ModelType.offPolicy) if self.models.get(ModelType.offPolicy) else None
|
||||||
|
self.on_policy_runner = TinygradRunner(ModelType.onPolicy) if self.models.get(ModelType.onPolicy) else None
|
||||||
|
self._constants = SplitModelConstants
|
||||||
|
|
||||||
|
def _run_model(self) -> NumpyDict:
|
||||||
|
"""Runs both vision and policy models and merges their parsed outputs."""
|
||||||
|
vision_output = self.vision_runner.run_model()
|
||||||
|
outputs = {**vision_output}
|
||||||
|
|
||||||
|
if self.policy_runner:
|
||||||
|
policy_output = self.policy_runner.run_model()
|
||||||
|
outputs.update(policy_output)
|
||||||
|
|
||||||
|
if self.off_policy_runner:
|
||||||
|
off_policy_output = self.off_policy_runner.run_model()
|
||||||
|
if self.on_policy_runner:
|
||||||
|
off_policy_output.pop('plan', None)
|
||||||
|
outputs.update(off_policy_output)
|
||||||
|
|
||||||
|
if self.on_policy_runner:
|
||||||
|
on_policy_output = self.on_policy_runner.run_model()
|
||||||
|
outputs.update(on_policy_output)
|
||||||
|
|
||||||
|
if 'planplus' in outputs and 'plan' in outputs:
|
||||||
|
outputs['plan'] = outputs['plan'] + outputs['planplus']
|
||||||
|
|
||||||
|
return outputs
|
||||||
|
|
||||||
|
@property
|
||||||
|
def vision_input_names(self) -> list[str]:
|
||||||
|
"""Returns the list of vision input names from the vision runner."""
|
||||||
|
return list(self.vision_runner.vision_input_names)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def input_shapes(self) -> ShapeDict:
|
||||||
|
"""Returns the combined input shapes from both vision and policy models."""
|
||||||
|
shapes = {**self.vision_runner.input_shapes}
|
||||||
|
if self.policy_runner:
|
||||||
|
shapes.update(self.policy_runner.input_shapes)
|
||||||
|
if self.off_policy_runner:
|
||||||
|
shapes.update(self.off_policy_runner.input_shapes)
|
||||||
|
if self.on_policy_runner:
|
||||||
|
shapes.update(self.on_policy_runner.input_shapes)
|
||||||
|
return shapes
|
||||||
|
|
||||||
|
@property
|
||||||
|
def output_slices(self) -> SliceDict:
|
||||||
|
"""Returns the combined output slices from both vision and policy models."""
|
||||||
|
slices = {**self.vision_runner.output_slices}
|
||||||
|
if self.policy_runner:
|
||||||
|
slices.update(self.policy_runner.output_slices)
|
||||||
|
if self.off_policy_runner:
|
||||||
|
slices.update(self.off_policy_runner.output_slices)
|
||||||
|
if self.on_policy_runner:
|
||||||
|
slices.update(self.on_policy_runner.output_slices)
|
||||||
|
return slices
|
||||||
|
|
||||||
|
def prepare_inputs(self, numpy_inputs: NumpyDict) -> dict:
|
||||||
|
"""Prepares inputs for both vision and policy models."""
|
||||||
|
if self.policy_runner:
|
||||||
|
self.policy_runner.prepare_policy_inputs(numpy_inputs)
|
||||||
|
|
||||||
|
for key in self.vision_input_names:
|
||||||
|
if key in self.inputs:
|
||||||
|
self.vision_runner.inputs[key] = self.inputs[key].cast(self.vision_runner.input_to_dtype[key])
|
||||||
|
|
||||||
|
inputs = {**self.vision_runner.inputs}
|
||||||
|
if self.policy_runner:
|
||||||
|
inputs.update(self.policy_runner.inputs)
|
||||||
|
|
||||||
|
if self.off_policy_runner:
|
||||||
|
self.off_policy_runner.prepare_policy_inputs(numpy_inputs)
|
||||||
|
inputs.update(self.off_policy_runner.inputs)
|
||||||
|
if self.on_policy_runner:
|
||||||
|
self.on_policy_runner.prepare_policy_inputs(numpy_inputs)
|
||||||
|
inputs.update(self.on_policy_runner.inputs)
|
||||||
|
return inputs
|
||||||
@@ -43,7 +43,6 @@ class SplitModelConstants:
|
|||||||
LANE_LINES_WIDTH = 2
|
LANE_LINES_WIDTH = 2
|
||||||
ROAD_EDGES_WIDTH = 2
|
ROAD_EDGES_WIDTH = 2
|
||||||
PLAN_WIDTH = 15
|
PLAN_WIDTH = 15
|
||||||
ACTION_WIDTH = 2
|
|
||||||
DESIRE_PRED_WIDTH = 8
|
DESIRE_PRED_WIDTH = 8
|
||||||
LAT_PLANNER_SOLUTION_WIDTH = 4
|
LAT_PLANNER_SOLUTION_WIDTH = 4
|
||||||
DESIRED_CURV_WIDTH = 1
|
DESIRED_CURV_WIDTH = 1
|
||||||
|
|||||||
@@ -123,7 +123,6 @@ def initialize_params(params) -> list[dict[str, Any]]:
|
|||||||
# tesla
|
# tesla
|
||||||
keys.extend([
|
keys.extend([
|
||||||
"TeslaCoopSteering",
|
"TeslaCoopSteering",
|
||||||
"TeslaMadsScreenButton",
|
|
||||||
])
|
])
|
||||||
|
|
||||||
# toyota
|
# toyota
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class SpeedLimitAssist:
|
|||||||
|
|
||||||
self._plus_hold = 0.
|
self._plus_hold = 0.
|
||||||
self._minus_hold = 0.
|
self._minus_hold = 0.
|
||||||
self._release_toggle_prev = 0
|
self._last_carstate_ts = 0.
|
||||||
|
|
||||||
# TODO-SP: SLA's own output_a_target for planner
|
# TODO-SP: SLA's own output_a_target for planner
|
||||||
# Solution functions mapped to respective states
|
# Solution functions mapped to respective states
|
||||||
@@ -146,16 +146,16 @@ class SpeedLimitAssist:
|
|||||||
set_speed_limit_assist_availability(self.CP, self.CP_SP, self.params)
|
set_speed_limit_assist_availability(self.CP, self.CP_SP, self.params)
|
||||||
self.enabled = self.params.get("SpeedLimitMode", return_default=True) == Mode.assist
|
self.enabled = self.params.get("SpeedLimitMode", return_default=True) == Mode.assist
|
||||||
|
|
||||||
def update_buttons(self, release_toggle: int) -> None:
|
def update_car_state(self, CS: car.CarState) -> None:
|
||||||
released = self._release_toggle_prev ^ release_toggle
|
|
||||||
self._release_toggle_prev = release_toggle
|
|
||||||
if not released:
|
|
||||||
return
|
|
||||||
now = time.monotonic()
|
now = time.monotonic()
|
||||||
if any((released >> b) & 1 for b in CRUISE_BUTTONS_PLUS):
|
self._last_carstate_ts = now
|
||||||
self._plus_hold = max(self._plus_hold, now + CRUISE_BUTTON_CONFIRM_HOLD)
|
|
||||||
if any((released >> b) & 1 for b in CRUISE_BUTTONS_MINUS):
|
for b in CS.buttonEvents:
|
||||||
self._minus_hold = max(self._minus_hold, now + CRUISE_BUTTON_CONFIRM_HOLD)
|
if not b.pressed:
|
||||||
|
if b.type in CRUISE_BUTTONS_PLUS:
|
||||||
|
self._plus_hold = max(self._plus_hold, now + CRUISE_BUTTON_CONFIRM_HOLD)
|
||||||
|
elif b.type in CRUISE_BUTTONS_MINUS:
|
||||||
|
self._minus_hold = max(self._minus_hold, now + CRUISE_BUTTON_CONFIRM_HOLD)
|
||||||
|
|
||||||
def _get_button_release(self, req_plus: bool, req_minus: bool) -> bool:
|
def _get_button_release(self, req_plus: bool, req_minus: bool) -> bool:
|
||||||
now = time.monotonic()
|
now = time.monotonic()
|
||||||
|
|||||||
+1
-91
@@ -5,14 +5,11 @@ This file is part of sunnypilot and is licensed under the MIT License.
|
|||||||
See the LICENSE.md file in the root directory for more details.
|
See the LICENSE.md file in the root directory for more details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import time
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from openpilot.cereal import custom
|
from openpilot.cereal import custom
|
||||||
from opendbc.car.car_helpers import interfaces
|
from opendbc.car.car_helpers import interfaces
|
||||||
from opendbc.car.rivian.values import CAR as RIVIAN
|
from opendbc.car.rivian.values import CAR as RIVIAN
|
||||||
from opendbc.car.structs import car
|
|
||||||
from opendbc.car.tesla.values import CAR as TESLA
|
from opendbc.car.tesla.values import CAR as TESLA
|
||||||
from opendbc.car.toyota.values import CAR as TOYOTA
|
from opendbc.car.toyota.values import CAR as TOYOTA
|
||||||
from openpilot.common.constants import CV
|
from openpilot.common.constants import CV
|
||||||
@@ -24,13 +21,9 @@ from openpilot.sunnypilot.selfdrive.car import interfaces as sunnypilot_interfac
|
|||||||
from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit import PCM_LONG_REQUIRED_MAX_SET_SPEED
|
from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit import PCM_LONG_REQUIRED_MAX_SET_SPEED
|
||||||
from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.common import Mode
|
from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.common import Mode
|
||||||
from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.speed_limit_assist import SpeedLimitAssist, \
|
from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.speed_limit_assist import SpeedLimitAssist, \
|
||||||
PRE_ACTIVE_GUARD_PERIOD, ACTIVE_STATES, CRUISE_BUTTON_CONFIRM_HOLD
|
PRE_ACTIVE_GUARD_PERIOD, ACTIVE_STATES
|
||||||
from openpilot.sunnypilot.selfdrive.selfdrived.button_state_tracker import ButtonStateTracker
|
|
||||||
from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
|
from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
|
||||||
|
|
||||||
ButtonEvent = car.CarState.ButtonEvent
|
|
||||||
ButtonType = car.CarState.ButtonEvent.Type
|
|
||||||
|
|
||||||
SpeedLimitAssistState = custom.LongitudinalPlanSP.SpeedLimit.AssistState
|
SpeedLimitAssistState = custom.LongitudinalPlanSP.SpeedLimit.AssistState
|
||||||
|
|
||||||
ALL_STATES = tuple(SpeedLimitAssistState.schema.enumerants.values())
|
ALL_STATES = tuple(SpeedLimitAssistState.schema.enumerants.values())
|
||||||
@@ -283,86 +276,3 @@ class TestSpeedLimitAssist:
|
|||||||
assert self.sla.state in [SpeedLimitAssistState.preActive, SpeedLimitAssistState.active]
|
assert self.sla.state in [SpeedLimitAssistState.preActive, SpeedLimitAssistState.active]
|
||||||
elif initial_state in ACTIVE_STATES:
|
elif initial_state in ACTIVE_STATES:
|
||||||
assert self.sla.state in ACTIVE_STATES
|
assert self.sla.state in ACTIVE_STATES
|
||||||
|
|
||||||
|
|
||||||
class TestButtonStateTrackerSLAIntegration:
|
|
||||||
|
|
||||||
def setup_method(self, method):
|
|
||||||
self.tracker = ButtonStateTracker()
|
|
||||||
self.params = Params()
|
|
||||||
self.params.put("IsReleaseSpBranch", True, block=True)
|
|
||||||
self.params.put("SpeedLimitMode", int(Mode.assist), block=True)
|
|
||||||
self.params.put_bool("IsMetric", False, block=True)
|
|
||||||
self.params.put("SpeedLimitOffsetType", 0, block=True)
|
|
||||||
self.params.put("SpeedLimitValueOffset", 0, block=True)
|
|
||||||
|
|
||||||
CarInterface = interfaces[DEFAULT_CAR]
|
|
||||||
CP = CarInterface.get_non_essential_params(DEFAULT_CAR)
|
|
||||||
CP.openpilotLongitudinalControl = True
|
|
||||||
CP_SP = CarInterface.get_non_essential_params_sp(CP, DEFAULT_CAR)
|
|
||||||
self.sla = SpeedLimitAssist(CP, CP_SP)
|
|
||||||
|
|
||||||
def _make_cs(self, events=None) -> car.CarState:
|
|
||||||
CS = car.CarState()
|
|
||||||
CS.buttonEvents = events or []
|
|
||||||
return CS
|
|
||||||
|
|
||||||
def _run_ctrl_frames(self, frames: list[car.CarState]) -> None:
|
|
||||||
for cs in frames:
|
|
||||||
self.tracker.update(cs)
|
|
||||||
|
|
||||||
def test_button_confirm_via_tracker(self) -> None:
|
|
||||||
self._run_ctrl_frames([
|
|
||||||
self._make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=True)]),
|
|
||||||
self._make_cs(),
|
|
||||||
self._make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=False)]),
|
|
||||||
self._make_cs(),
|
|
||||||
self._make_cs(),
|
|
||||||
])
|
|
||||||
self.sla.update_buttons(self.tracker.release_toggle)
|
|
||||||
assert self.sla._get_button_release(req_plus=True, req_minus=False)
|
|
||||||
|
|
||||||
def test_rapid_press_release_between_polls(self) -> None:
|
|
||||||
self.sla.update_buttons(self.tracker.release_toggle)
|
|
||||||
|
|
||||||
self._run_ctrl_frames([
|
|
||||||
self._make_cs([ButtonEvent(type=ButtonType.decelCruise, pressed=True)]),
|
|
||||||
self._make_cs([ButtonEvent(type=ButtonType.decelCruise, pressed=False)]),
|
|
||||||
self._make_cs(),
|
|
||||||
self._make_cs(),
|
|
||||||
self._make_cs(),
|
|
||||||
])
|
|
||||||
self.sla.update_buttons(self.tracker.release_toggle)
|
|
||||||
assert self.sla._get_button_release(req_plus=False, req_minus=True)
|
|
||||||
|
|
||||||
def test_multiple_releases_between_polls(self) -> None:
|
|
||||||
self.sla.update_buttons(self.tracker.release_toggle)
|
|
||||||
|
|
||||||
self._run_ctrl_frames([
|
|
||||||
self._make_cs([
|
|
||||||
ButtonEvent(type=ButtonType.accelCruise, pressed=True),
|
|
||||||
ButtonEvent(type=ButtonType.decelCruise, pressed=True),
|
|
||||||
]),
|
|
||||||
self._make_cs([
|
|
||||||
ButtonEvent(type=ButtonType.accelCruise, pressed=False),
|
|
||||||
ButtonEvent(type=ButtonType.decelCruise, pressed=False),
|
|
||||||
]),
|
|
||||||
])
|
|
||||||
self.sla.update_buttons(self.tracker.release_toggle)
|
|
||||||
assert self.sla._get_button_release(req_plus=True, req_minus=False)
|
|
||||||
assert self.sla._get_button_release(req_plus=False, req_minus=True)
|
|
||||||
|
|
||||||
def test_no_false_positive_same_toggle(self) -> None:
|
|
||||||
self.sla.update_buttons(self.tracker.release_toggle)
|
|
||||||
self.sla.update_buttons(self.tracker.release_toggle)
|
|
||||||
assert not self.sla._get_button_release(req_plus=True, req_minus=False)
|
|
||||||
assert not self.sla._get_button_release(req_plus=False, req_minus=True)
|
|
||||||
|
|
||||||
def test_button_confirm_expires(self) -> None:
|
|
||||||
self._run_ctrl_frames([
|
|
||||||
self._make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=True)]),
|
|
||||||
self._make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=False)]),
|
|
||||||
])
|
|
||||||
self.sla.update_buttons(self.tracker.release_toggle)
|
|
||||||
time.sleep(CRUISE_BUTTON_CONFIRM_HOLD + 0.1)
|
|
||||||
assert not self.sla._get_button_release(req_plus=True, req_minus=False)
|
|
||||||
|
|||||||
Binary file not shown.
@@ -1,26 +0,0 @@
|
|||||||
"""
|
|
||||||
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
|
||||||
|
|
||||||
This file is part of sunnypilot and is licensed under the MIT License.
|
|
||||||
See the LICENSE.md file in the root directory for more details.
|
|
||||||
"""
|
|
||||||
from opendbc.car import structs
|
|
||||||
|
|
||||||
|
|
||||||
class ButtonStateTracker:
|
|
||||||
def __init__(self) -> None:
|
|
||||||
self.pressed: int = 0
|
|
||||||
self.release_toggle: int = 0
|
|
||||||
|
|
||||||
def update(self, CS: structs.CarState) -> None:
|
|
||||||
for b in CS.buttonEvents:
|
|
||||||
bit = 1 << b.type.raw
|
|
||||||
if b.pressed:
|
|
||||||
self.pressed |= bit
|
|
||||||
else:
|
|
||||||
self.pressed &= ~bit
|
|
||||||
self.release_toggle ^= bit
|
|
||||||
|
|
||||||
def publish(self, ss_sp) -> None:
|
|
||||||
ss_sp.buttonsPressed = self.pressed
|
|
||||||
ss_sp.buttonsReleaseToggle = self.release_toggle
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
"""
|
|
||||||
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
|
||||||
|
|
||||||
This file is part of sunnypilot and is licensed under the MIT License.
|
|
||||||
See the LICENSE.md file in the root directory for more details.
|
|
||||||
"""
|
|
||||||
from opendbc.car.structs import car
|
|
||||||
from openpilot.sunnypilot.selfdrive.selfdrived.button_state_tracker import ButtonStateTracker
|
|
||||||
|
|
||||||
ButtonEvent = car.CarState.ButtonEvent
|
|
||||||
ButtonType = car.CarState.ButtonEvent.Type
|
|
||||||
|
|
||||||
|
|
||||||
class TestButtonStateTracker:
|
|
||||||
def setup_method(self) -> None:
|
|
||||||
self.tracker = ButtonStateTracker()
|
|
||||||
|
|
||||||
def make_cs(self, events: list) -> car.CarState:
|
|
||||||
CS = car.CarState()
|
|
||||||
CS.buttonEvents = events
|
|
||||||
return CS
|
|
||||||
|
|
||||||
def test_initial_state(self) -> None:
|
|
||||||
assert self.tracker.pressed == 0
|
|
||||||
assert self.tracker.release_toggle == 0
|
|
||||||
|
|
||||||
def test_press_sets_bit(self) -> None:
|
|
||||||
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=True)]))
|
|
||||||
assert self.tracker.pressed == (1 << ButtonType.accelCruise)
|
|
||||||
assert self.tracker.release_toggle == 0
|
|
||||||
|
|
||||||
def test_release_clears_and_toggles(self) -> None:
|
|
||||||
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=True)]))
|
|
||||||
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=False)]))
|
|
||||||
assert self.tracker.pressed == 0
|
|
||||||
assert self.tracker.release_toggle == (1 << ButtonType.accelCruise)
|
|
||||||
|
|
||||||
def test_multiple_buttons(self) -> None:
|
|
||||||
self.tracker.update(self.make_cs([
|
|
||||||
ButtonEvent(type=ButtonType.accelCruise, pressed=True),
|
|
||||||
ButtonEvent(type=ButtonType.decelCruise, pressed=True),
|
|
||||||
]))
|
|
||||||
assert self.tracker.pressed == (1 << ButtonType.accelCruise) | (1 << ButtonType.decelCruise)
|
|
||||||
|
|
||||||
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=False)]))
|
|
||||||
assert self.tracker.pressed == (1 << ButtonType.decelCruise)
|
|
||||||
assert self.tracker.release_toggle == (1 << ButtonType.accelCruise)
|
|
||||||
|
|
||||||
def test_release_toggle_flips(self) -> None:
|
|
||||||
for _ in range(2):
|
|
||||||
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.gapAdjustCruise, pressed=True)]))
|
|
||||||
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.gapAdjustCruise, pressed=False)]))
|
|
||||||
assert self.tracker.release_toggle == 0
|
|
||||||
|
|
||||||
def test_publish(self) -> None:
|
|
||||||
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=True)]))
|
|
||||||
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.decelCruise, pressed=True)]))
|
|
||||||
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=False)]))
|
|
||||||
|
|
||||||
class MockSP:
|
|
||||||
buttonsPressed = 0
|
|
||||||
buttonsReleaseToggle = 0
|
|
||||||
|
|
||||||
sp = MockSP()
|
|
||||||
self.tracker.publish(sp)
|
|
||||||
assert sp.buttonsPressed == self.tracker.pressed
|
|
||||||
assert sp.buttonsReleaseToggle == self.tracker.release_toggle
|
|
||||||
@@ -2161,42 +2161,6 @@
|
|||||||
"type": "offroad_only"
|
"type": "offroad_only"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "TeslaMadsScreenButton",
|
|
||||||
"widget": "multiple_button",
|
|
||||||
"title": "MADS Screen Activation",
|
|
||||||
"description": "Use a multi-finger press on the infotainment screen to toggle MADS. This allows the use of full MADS functionality when enabled. Selecting a higher finger count may reduce accidental activations. Note: Setting this to Off will reset your MADS settings to default.",
|
|
||||||
"options": [
|
|
||||||
{
|
|
||||||
"value": 0,
|
|
||||||
"label": "Off"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": 1,
|
|
||||||
"label": "3-Finger"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": 2,
|
|
||||||
"label": "4-Finger"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": 3,
|
|
||||||
"label": "5-Finger"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"visibility": [
|
|
||||||
{
|
|
||||||
"type": "capability",
|
|
||||||
"field": "tesla_has_vehicle_bus",
|
|
||||||
"equals": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"enablement": [
|
|
||||||
{
|
|
||||||
"type": "offroad_only"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -56,28 +56,6 @@ sections:
|
|||||||
title: Cooperative Steering (Beta)
|
title: Cooperative Steering (Beta)
|
||||||
enablement:
|
enablement:
|
||||||
- $ref: '#/macros/offroad'
|
- $ref: '#/macros/offroad'
|
||||||
- key: TeslaMadsScreenButton
|
|
||||||
widget: multiple_button
|
|
||||||
title: MADS Screen Activation
|
|
||||||
description: 'Use a multi-finger press on the infotainment screen to toggle MADS.
|
|
||||||
This allows the use of full MADS functionality when enabled. Selecting a higher
|
|
||||||
finger count may reduce accidental activations. Note: Setting this to Off will
|
|
||||||
reset your MADS settings to default.'
|
|
||||||
options:
|
|
||||||
- value: 0
|
|
||||||
label: 'Off'
|
|
||||||
- value: 1
|
|
||||||
label: 3-Finger
|
|
||||||
- value: 2
|
|
||||||
label: 4-Finger
|
|
||||||
- value: 3
|
|
||||||
label: 5-Finger
|
|
||||||
visibility:
|
|
||||||
- type: capability
|
|
||||||
field: tesla_has_vehicle_bus
|
|
||||||
equals: true
|
|
||||||
enablement:
|
|
||||||
- $ref: '#/macros/offroad'
|
|
||||||
- id: toyota
|
- id: toyota
|
||||||
title: Toyota / Lexus Settings
|
title: Toyota / Lexus Settings
|
||||||
description: ''
|
description: ''
|
||||||
|
|||||||
@@ -17,26 +17,6 @@ ONROAD_BRIGHTNESS_TIMER_VALUES = {0: 3, 1: 5, 2: 7, 3: 10, 4: 15, 5: 30, **{i: (
|
|||||||
VALID_TIMER_VALUES = set(ONROAD_BRIGHTNESS_TIMER_VALUES.values())
|
VALID_TIMER_VALUES = set(ONROAD_BRIGHTNESS_TIMER_VALUES.values())
|
||||||
|
|
||||||
|
|
||||||
def _resolve_brand(_params) -> str:
|
|
||||||
bundle = _params.get("CarPlatformBundle")
|
|
||||||
if isinstance(bundle, dict) and bundle.get("brand"):
|
|
||||||
return str(bundle["brand"])
|
|
||||||
|
|
||||||
# Auto-fingerprinted cars have no bundle, fall back to the last known CarParams.
|
|
||||||
CP_bytes = _params.get("CarParamsPersistent")
|
|
||||||
if CP_bytes is None:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
# Never raises: callers rely on "" to mean "brand unknown, skip the migration".
|
|
||||||
try:
|
|
||||||
from openpilot.cereal import messaging # lazy: avoids heavy import at module level
|
|
||||||
from opendbc.car.structs import car
|
|
||||||
return str(messaging.log_from_bytes(CP_bytes, car.CarParams).brand)
|
|
||||||
except Exception as e:
|
|
||||||
cloudlog.exception(f"params_migration: failed to resolve brand from CarParamsPersistent: {e}")
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
def _migrate_car_platform_bundle(_params):
|
def _migrate_car_platform_bundle(_params):
|
||||||
bundle = _params.get("CarPlatformBundle")
|
bundle = _params.get("CarPlatformBundle")
|
||||||
if bundle is None:
|
if bundle is None:
|
||||||
@@ -67,23 +47,6 @@ def _migrate_car_platform_bundle(_params):
|
|||||||
cloudlog.info(f"params_migration: CarPlatformBundle migrated {old_platform!r} -> {new_platform!r}")
|
cloudlog.info(f"params_migration: CarPlatformBundle migrated {old_platform!r} -> {new_platform!r}")
|
||||||
|
|
||||||
|
|
||||||
def _migrate_tesla_mads_screen_button(_params):
|
|
||||||
# TeslaMadsScreenButton defaults to Off for fresh installs, but the screen button was previously always
|
|
||||||
# active on Teslas with a vehicle bus. Seed existing Tesla installs with 3-finger to preserve that.
|
|
||||||
try:
|
|
||||||
if _params.get("TeslaMadsScreenButton") is not None:
|
|
||||||
return
|
|
||||||
|
|
||||||
if _resolve_brand(_params) != "tesla":
|
|
||||||
return
|
|
||||||
|
|
||||||
from opendbc.sunnypilot.car.tesla.values import MadsScreenButtonType # lazy: avoids heavy import at module level
|
|
||||||
_params.put("TeslaMadsScreenButton", MadsScreenButtonType.THREE_FINGER, block=True)
|
|
||||||
cloudlog.info("params_migration: seeded TeslaMadsScreenButton with 3-finger to preserve existing behavior")
|
|
||||||
except Exception as e:
|
|
||||||
cloudlog.exception(f"Error migrating TeslaMadsScreenButton: {e}")
|
|
||||||
|
|
||||||
|
|
||||||
def run_migration(_params):
|
def run_migration(_params):
|
||||||
# migrate OnroadScreenOffBrightness
|
# migrate OnroadScreenOffBrightness
|
||||||
if _params.get("OnroadScreenOffBrightnessMigrated") != ONROAD_BRIGHTNESS_MIGRATION_VERSION:
|
if _params.get("OnroadScreenOffBrightnessMigrated") != ONROAD_BRIGHTNESS_MIGRATION_VERSION:
|
||||||
@@ -117,6 +80,3 @@ def run_migration(_params):
|
|||||||
cloudlog.exception(f"Error migrating OnroadScreenOffTimer: {e}")
|
cloudlog.exception(f"Error migrating OnroadScreenOffTimer: {e}")
|
||||||
|
|
||||||
_migrate_car_platform_bundle(_params)
|
_migrate_car_platform_bundle(_params)
|
||||||
|
|
||||||
# seed TeslaMadsScreenButton for existing Tesla installs
|
|
||||||
_migrate_tesla_mads_screen_button(_params)
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -140,8 +140,8 @@ Documentation along with a quick start guide can be found on the [docs website](
|
|||||||
```python
|
```python
|
||||||
from tinygrad import Tensor
|
from tinygrad import Tensor
|
||||||
|
|
||||||
x = Tensor.eye(3)
|
x = Tensor.eye(3, requires_grad=True)
|
||||||
y = Tensor([[2.0,0,-2.0]])
|
y = Tensor([[2.0,0,-2.0]], requires_grad=True)
|
||||||
z = y.matmul(x).sum()
|
z = y.matmul(x).sum()
|
||||||
z.backward()
|
z.backward()
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ For our loss function we will be using sparse categorical cross entropy loss. Th
|
|||||||
```python
|
```python
|
||||||
def sparse_categorical_crossentropy(self, Y, ignore_index=-1) -> Tensor:
|
def sparse_categorical_crossentropy(self, Y, ignore_index=-1) -> Tensor:
|
||||||
loss_mask = Y != ignore_index
|
loss_mask = Y != ignore_index
|
||||||
y_counter = Tensor.arange(self.shape[-1], dtype=dtypes.int32, device=self.device).unsqueeze(0).expand(Y.numel(), self.shape[-1])
|
y_counter = Tensor.arange(self.shape[-1], dtype=dtypes.int32, requires_grad=False, device=self.device).unsqueeze(0).expand(Y.numel(), self.shape[-1])
|
||||||
y = ((y_counter == Y.flatten().reshape(-1, 1)).where(-1.0, 0) * loss_mask.reshape(-1, 1)).reshape(*Y.shape, self.shape[-1])
|
y = ((y_counter == Y.flatten().reshape(-1, 1)).where(-1.0, 0) * loss_mask.reshape(-1, 1)).reshape(*Y.shape, self.shape[-1])
|
||||||
return self.log_softmax().mul(y).sum() / loss_mask.sum()
|
return self.log_softmax().mul(y).sum() / loss_mask.sum()
|
||||||
```
|
```
|
||||||
@@ -175,7 +175,7 @@ with Tensor.train():
|
|||||||
for step in range(1000):
|
for step in range(1000):
|
||||||
# random sample a batch
|
# random sample a batch
|
||||||
samp = np.random.randint(0, X_train.shape[0], size=(64))
|
samp = np.random.randint(0, X_train.shape[0], size=(64))
|
||||||
batch = Tensor(X_train[samp])
|
batch = Tensor(X_train[samp], requires_grad=False)
|
||||||
# get the corresponding labels
|
# get the corresponding labels
|
||||||
labels = Tensor(Y_train[samp])
|
labels = Tensor(Y_train[samp])
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ with Timing("Time: "):
|
|||||||
for step in range(1000):
|
for step in range(1000):
|
||||||
# random sample a batch
|
# random sample a batch
|
||||||
samp = np.random.randint(0, X_test.shape[0], size=(64))
|
samp = np.random.randint(0, X_test.shape[0], size=(64))
|
||||||
batch = Tensor(X_test[samp])
|
batch = Tensor(X_test[samp], requires_grad=False)
|
||||||
# get the corresponding labels
|
# get the corresponding labels
|
||||||
labels = Y_test[samp]
|
labels = Y_test[samp]
|
||||||
|
|
||||||
@@ -257,7 +257,7 @@ with Timing("Time: "):
|
|||||||
for step in range(1000):
|
for step in range(1000):
|
||||||
# random sample a batch
|
# random sample a batch
|
||||||
samp = np.random.randint(0, X_test.shape[0], size=(64))
|
samp = np.random.randint(0, X_test.shape[0], size=(64))
|
||||||
batch = Tensor(X_test[samp])
|
batch = Tensor(X_test[samp], requires_grad=False)
|
||||||
# get the corresponding labels
|
# get the corresponding labels
|
||||||
labels = Y_test[samp]
|
labels = Y_test[samp]
|
||||||
|
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ if __name__ == "__main__":
|
|||||||
# *** render to device ***
|
# *** render to device ***
|
||||||
|
|
||||||
from tinygrad.codegen import to_program
|
from tinygrad.codegen import to_program
|
||||||
with Context(PCONTIG=2, SPEC=0):
|
with Context(PCONTIG=2, DEVECTORIZE=2, SPEC=0):
|
||||||
out = tree_traversal(forest_t, val_t, height, rounds)
|
out = tree_traversal(forest_t, val_t, height, rounds)
|
||||||
sink = out.schedule_linear().src[-1].src[0]
|
sink = out.schedule_linear().src[-1].src[0]
|
||||||
prg = to_program(sink, VLIWRenderer())
|
prg = to_program(sink, VLIWRenderer())
|
||||||
|
|||||||
@@ -67,8 +67,8 @@ class ConvGroup:
|
|||||||
self.conv2 = nn.Conv2d(channels_out, channels_out, kernel_size=3, padding=1, bias=False)
|
self.conv2 = nn.Conv2d(channels_out, channels_out, kernel_size=3, padding=1, bias=False)
|
||||||
self.norm1 = nn.BatchNorm(channels_out, track_running_stats=False, eps=1e-12, momentum=hyp['net']['batch_norm_momentum'])
|
self.norm1 = nn.BatchNorm(channels_out, track_running_stats=False, eps=1e-12, momentum=hyp['net']['batch_norm_momentum'])
|
||||||
self.norm2 = nn.BatchNorm(channels_out, track_running_stats=False, eps=1e-12, momentum=hyp['net']['batch_norm_momentum'])
|
self.norm2 = nn.BatchNorm(channels_out, track_running_stats=False, eps=1e-12, momentum=hyp['net']['batch_norm_momentum'])
|
||||||
cast(Tensor, self.norm1.weight).is_param_(False)
|
cast(Tensor, self.norm1.weight).requires_grad = False
|
||||||
cast(Tensor, self.norm2.weight).is_param_(False)
|
cast(Tensor, self.norm2.weight).requires_grad = False
|
||||||
def __call__(self, x:Tensor) -> Tensor:
|
def __call__(self, x:Tensor) -> Tensor:
|
||||||
x = self.norm1(self.conv1(x).max_pool2d().float()).cast(dtypes.default_float).quick_gelu()
|
x = self.norm1(self.conv1(x).max_pool2d().float()).cast(dtypes.default_float).quick_gelu()
|
||||||
return self.norm2(self.conv2(x).float()).cast(dtypes.default_float).quick_gelu() + x
|
return self.norm2(self.conv2(x).float()).cast(dtypes.default_float).quick_gelu() + x
|
||||||
|
|||||||
@@ -41,15 +41,15 @@ if __name__ == "__main__":
|
|||||||
Tensor.realize(*params)
|
Tensor.realize(*params)
|
||||||
|
|
||||||
# split params (with grads) and buffers (without)
|
# split params (with grads) and buffers (without)
|
||||||
params, buffers = partition(params, lambda x: x.is_param)
|
params, buffers = partition(params, lambda x: x.requires_grad)
|
||||||
print(f"params: {len(params)} buffers: {len(buffers)}")
|
print(f"params: {len(params)} buffers: {len(buffers)}")
|
||||||
|
|
||||||
# optim params
|
# optim params
|
||||||
pos_params = list(itertools.accumulate(params, lambda x,y: x+y.numel(), initial=0))
|
pos_params = list(itertools.accumulate(params, lambda x,y: x+y.numel(), initial=0))
|
||||||
adam_m = Tensor.zeros(pos_params[-1], device="CPU").contiguous()
|
adam_m = Tensor.zeros(pos_params[-1], device="CPU").contiguous()
|
||||||
adam_v = Tensor.zeros(pos_params[-1], device="CPU").contiguous()
|
adam_v = Tensor.zeros(pos_params[-1], device="CPU").contiguous()
|
||||||
adam_b1_t = Tensor.ones((1,), dtype=dtypes.float32, device="CPU").contiguous()
|
adam_b1_t = Tensor.ones((1,), dtype=dtypes.float32, device="CPU", requires_grad=False).contiguous()
|
||||||
adam_b2_t = Tensor.ones((1,), dtype=dtypes.float32, device="CPU").contiguous()
|
adam_b2_t = Tensor.ones((1,), dtype=dtypes.float32, device="CPU", requires_grad=False).contiguous()
|
||||||
adam_params = [adam_m, adam_v, adam_b1_t, adam_b2_t]
|
adam_params = [adam_m, adam_v, adam_b1_t, adam_b2_t]
|
||||||
|
|
||||||
# create loss and grads. init all state so the JIT works on microbatch
|
# create loss and grads. init all state so the JIT works on microbatch
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ class UnsyncedBatchNorm:
|
|||||||
if affine: self.weight, self.bias = Tensor.ones(sz, dtype=dtypes.float32), Tensor.zeros(sz, dtype=dtypes.float32)
|
if affine: self.weight, self.bias = Tensor.ones(sz, dtype=dtypes.float32), Tensor.zeros(sz, dtype=dtypes.float32)
|
||||||
else: self.weight, self.bias = None, None
|
else: self.weight, self.bias = None, None
|
||||||
|
|
||||||
self.running_mean = Tensor.zeros(num_devices, sz, dtype=dtypes.float32).is_param_(False)
|
self.running_mean = Tensor.zeros(num_devices, sz, dtype=dtypes.float32, requires_grad=False)
|
||||||
self.running_var = Tensor.ones(num_devices, sz, dtype=dtypes.float32).is_param_(False)
|
self.running_var = Tensor.ones(num_devices, sz, dtype=dtypes.float32, requires_grad=False)
|
||||||
self.num_batches_tracked = Tensor.zeros(1, dtype=dtypes.int).is_param_(False)
|
self.num_batches_tracked = Tensor.zeros(1, dtype=dtypes.int, requires_grad=False)
|
||||||
|
|
||||||
def __call__(self, x:Tensor):
|
def __call__(self, x:Tensor):
|
||||||
xr = x.reshape(self.num_devices, -1, *x.shape[1:]).cast(dtypes.float32)
|
xr = x.reshape(self.num_devices, -1, *x.shape[1:]).cast(dtypes.float32)
|
||||||
@@ -68,7 +68,8 @@ class UnsyncedBatchNorm:
|
|||||||
class BatchNorm(nn.BatchNorm2d if getenv("SYNCBN") else UnsyncedBatchNorm):
|
class BatchNorm(nn.BatchNorm2d if getenv("SYNCBN") else UnsyncedBatchNorm):
|
||||||
def __init__(self, num_features):
|
def __init__(self, num_features):
|
||||||
super().__init__(num_features, track_running_stats=False, eps=1e-12, momentum=0.85, affine=True)
|
super().__init__(num_features, track_running_stats=False, eps=1e-12, momentum=0.85, affine=True)
|
||||||
self.weight.is_param_(False)
|
self.weight.requires_grad = False
|
||||||
|
self.bias.requires_grad = True
|
||||||
|
|
||||||
class ConvGroup:
|
class ConvGroup:
|
||||||
def __init__(self, channels_in, channels_out):
|
def __init__(self, channels_in, channels_out):
|
||||||
@@ -171,7 +172,7 @@ def train_cifar():
|
|||||||
Λ, V = _eigens(_patches(X.float().numpy()))
|
Λ, V = _eigens(_patches(X.float().numpy()))
|
||||||
W = V/np.sqrt(Λ+1e-2)[:,None,None,None]
|
W = V/np.sqrt(Λ+1e-2)[:,None,None,None]
|
||||||
|
|
||||||
return Tensor(W.astype(np.float32)).cast(dtypes.default_float).is_param_(False)
|
return Tensor(W.astype(np.float32), requires_grad=False).cast(dtypes.default_float)
|
||||||
|
|
||||||
# ========== Loss ==========
|
# ========== Loss ==========
|
||||||
def cross_entropy(x:Tensor, y:Tensor, reduction:str='mean', label_smoothing:float=0.0) -> Tensor:
|
def cross_entropy(x:Tensor, y:Tensor, reduction:str='mean', label_smoothing:float=0.0) -> Tensor:
|
||||||
@@ -263,6 +264,7 @@ def train_cifar():
|
|||||||
# self.model_ema = copy.deepcopy(net) # won't work for opencl due to unpickeable pyopencl._cl.Buffer
|
# self.model_ema = copy.deepcopy(net) # won't work for opencl due to unpickeable pyopencl._cl.Buffer
|
||||||
self.net_ema = SpeedyResNet(w)
|
self.net_ema = SpeedyResNet(w)
|
||||||
for net_ema_param, net_param in zip(get_state_dict(self.net_ema).values(), get_state_dict(net).values()):
|
for net_ema_param, net_param in zip(get_state_dict(self.net_ema).values(), get_state_dict(net).values()):
|
||||||
|
net_ema_param.requires_grad = False
|
||||||
net_ema_param.assign(net_param.numpy())
|
net_ema_param.assign(net_param.numpy())
|
||||||
|
|
||||||
@TinyJit
|
@TinyJit
|
||||||
@@ -305,7 +307,7 @@ def train_cifar():
|
|||||||
params_bias = []
|
params_bias = []
|
||||||
params_non_bias = []
|
params_non_bias = []
|
||||||
for params in params_dict:
|
for params in params_dict:
|
||||||
if params_dict[params].is_param:
|
if params_dict[params].requires_grad is not False:
|
||||||
if 'bias' in params:
|
if 'bias' in params:
|
||||||
params_bias.append(params_dict[params])
|
params_bias.append(params_dict[params])
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ class Int8Embedding:
|
|||||||
self.weight, self.scale = Tensor.ones(vocab_size, embed_size, dtype=dtypes.int8), Tensor.ones(vocab_size, dtype=dtypes.half)
|
self.weight, self.scale = Tensor.ones(vocab_size, embed_size, dtype=dtypes.int8), Tensor.ones(vocab_size, dtype=dtypes.half)
|
||||||
|
|
||||||
def __call__(self, idx:Tensor) -> Tensor:
|
def __call__(self, idx:Tensor) -> Tensor:
|
||||||
if not hasattr(self, 'arange'): self.arange = Tensor.arange(self.vocab_sz, device=self.weight.device).unsqueeze(-1)
|
if not hasattr(self, 'arange'): self.arange = Tensor.arange(self.vocab_sz, requires_grad=False, device=self.weight.device).unsqueeze(-1)
|
||||||
big_shp = idx.shape+(self.vocab_sz, self.embed_sz)
|
big_shp = idx.shape+(self.vocab_sz, self.embed_sz)
|
||||||
arange, idx, vals = self.arange.expand(big_shp), idx.reshape(idx.shape+(1, 1)).expand(big_shp), (self.weight.cast(self.scale.dtype).T*self.scale).T
|
arange, idx, vals = self.arange.expand(big_shp), idx.reshape(idx.shape+(1, 1)).expand(big_shp), (self.weight.cast(self.scale.dtype).T*self.scale).T
|
||||||
return (arange == idx).mul(vals).sum(-2, dtype=vals.dtype)
|
return (arange == idx).mul(vals).sum(-2, dtype=vals.dtype)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class CausalSelfAttention:
|
|||||||
self.n_embd = config.n_embd
|
self.n_embd = config.n_embd
|
||||||
# not really a 'bias', more of a mask, but following the OpenAI/HF naming though
|
# not really a 'bias', more of a mask, but following the OpenAI/HF naming though
|
||||||
self.bias = Tensor.ones(1, 1, config.block_size, config.block_size).tril()
|
self.bias = Tensor.ones(1, 1, config.block_size, config.block_size).tril()
|
||||||
self.bias.is_param_(False)
|
self.bias.requires_grad = False
|
||||||
|
|
||||||
def __call__(self, x:Tensor):
|
def __call__(self, x:Tensor):
|
||||||
B, T, C = x.shape
|
B, T, C = x.shape
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import functools, argparse, pathlib
|
import functools, argparse, pathlib
|
||||||
from tinygrad import Tensor, nn, Device, GlobalCounters, Variable
|
from tinygrad import Tensor, nn, Device, GlobalCounters, Variable
|
||||||
from tinygrad.helpers import Timing, Profiling, tqdm
|
from tinygrad.helpers import Timing, Profiling, CI, tqdm
|
||||||
from tinygrad.nn.state import torch_load, get_state_dict
|
from tinygrad.nn.state import torch_load, get_state_dict
|
||||||
from extra.models.llama import FeedForward, Transformer
|
from extra.models.llama import FeedForward, Transformer
|
||||||
from extra.bench_log import BenchEvent, WallTimeEvent
|
from extra.bench_log import BenchEvent, WallTimeEvent
|
||||||
@@ -36,7 +36,7 @@ if __name__ == "__main__":
|
|||||||
model = Transformer(n_layers=32, dim=4096, hidden_dim=14336, n_heads=32, n_kv_heads=8, norm_eps=1e-5, vocab_size=32000, feed_forward=functools.partial(MixtureFeedForward, 8), jit=False)
|
model = Transformer(n_layers=32, dim=4096, hidden_dim=14336, n_heads=32, n_kv_heads=8, norm_eps=1e-5, vocab_size=32000, feed_forward=functools.partial(MixtureFeedForward, 8), jit=False)
|
||||||
model_state_dict = get_state_dict(model)
|
model_state_dict = get_state_dict(model)
|
||||||
|
|
||||||
for k in (t := tqdm(state, disable=None)):
|
for k in (t := tqdm(state, disable=CI)):
|
||||||
if 'feed_forward.experts.' in k:
|
if 'feed_forward.experts.' in k:
|
||||||
expert_no = int(k.split('feed_forward.experts.')[1].split('.')[0])
|
expert_no = int(k.split('feed_forward.experts.')[1].split('.')[0])
|
||||||
device = Device.DEFAULT + ":" + str((expert_no//2)+1)
|
device = Device.DEFAULT + ":" + str((expert_no//2)+1)
|
||||||
@@ -44,7 +44,7 @@ if __name__ == "__main__":
|
|||||||
device = Device.DEFAULT
|
device = Device.DEFAULT
|
||||||
t.set_description(f"ram used: {GlobalCounters.mem_used/1e9:5.2f} GB, loading {k} to {device}")
|
t.set_description(f"ram used: {GlobalCounters.mem_used/1e9:5.2f} GB, loading {k} to {device}")
|
||||||
model_state_dict[k].replace(state[k].to(device).half()).realize()
|
model_state_dict[k].replace(state[k].to(device).half()).realize()
|
||||||
if t.disable: print(f"ram used: {GlobalCounters.mem_used/1e9:5.2f} GB")
|
if CI: print(f"ram used: {GlobalCounters.mem_used/1e9:5.2f} GB")
|
||||||
|
|
||||||
from sentencepiece import SentencePieceProcessor
|
from sentencepiece import SentencePieceProcessor
|
||||||
spp = SentencePieceProcessor(model_file=args.weights + "/tokenizer.model")
|
spp = SentencePieceProcessor(model_file=args.weights + "/tokenizer.model")
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class EmbeddingBert(nn.Embedding):
|
|||||||
def __call__(self, idx:Tensor) -> Tensor:
|
def __call__(self, idx:Tensor) -> Tensor:
|
||||||
if idx.numel() == 0: return Tensor.empty(idx.shape+(self.embed_sz,), dtype=self.weight.dtype, device=self.weight.device)
|
if idx.numel() == 0: return Tensor.empty(idx.shape+(self.embed_sz,), dtype=self.weight.dtype, device=self.weight.device)
|
||||||
arange_shp, weight_shp, big_shp = (1, 1, self.vocab_sz, 1), (1, 1, self.vocab_sz, self.embed_sz), idx.shape+(self.vocab_sz, self.embed_sz,)
|
arange_shp, weight_shp, big_shp = (1, 1, self.vocab_sz, 1), (1, 1, self.vocab_sz, self.embed_sz), idx.shape+(self.vocab_sz, self.embed_sz,)
|
||||||
if not hasattr(self, 'arange'): self.arange = Tensor.arange(self.vocab_sz, device=self.weight.device).reshape(arange_shp)
|
if not hasattr(self, 'arange'): self.arange = Tensor.arange(self.vocab_sz, requires_grad=False, device=self.weight.device).reshape(arange_shp)
|
||||||
arange, idx, vals = self.arange.expand(big_shp), idx.reshape(idx.shape+(1, 1,)).expand(big_shp), self.weight.cast(dtypes.default_float).reshape(weight_shp).expand(big_shp)
|
arange, idx, vals = self.arange.expand(big_shp), idx.reshape(idx.shape+(1, 1,)).expand(big_shp), self.weight.cast(dtypes.default_float).reshape(weight_shp).expand(big_shp)
|
||||||
return (arange == idx).where(vals, 0).sum(2, dtype=vals.dtype)
|
return (arange == idx).where(vals, 0).sum(2, dtype=vals.dtype)
|
||||||
|
|
||||||
@@ -77,11 +77,11 @@ class FrozenBatchNorm2dRetinaNet(nn.BatchNorm2d):
|
|||||||
def __init__(self, sz:int, eps=1e-5, affine=True, track_running_stats=True, momentum=0.1):
|
def __init__(self, sz:int, eps=1e-5, affine=True, track_running_stats=True, momentum=0.1):
|
||||||
self.eps, self.track_running_stats, self.momentum = eps, track_running_stats, momentum
|
self.eps, self.track_running_stats, self.momentum = eps, track_running_stats, momentum
|
||||||
|
|
||||||
self.weight = Tensor.ones(sz, dtype=dtypes.float32).is_param_(False) if affine else None
|
self.weight = Tensor.ones(sz, dtype=dtypes.float32, requires_grad=False) if affine else None
|
||||||
self.bias = Tensor.zeros(sz, dtype=dtypes.float32).is_param_(False) if affine else None
|
self.bias = Tensor.zeros(sz, dtype=dtypes.float32, requires_grad=False) if affine else None
|
||||||
|
|
||||||
if track_running_stats: self.running_mean, self.running_var = Tensor.zeros(sz, dtype=dtypes.float32).is_param_(False), Tensor.ones(sz, dtype=dtypes.float32).is_param_(False)
|
if track_running_stats: self.running_mean, self.running_var = Tensor.zeros(sz, dtype=dtypes.float32, requires_grad=False), Tensor.ones(sz, dtype=dtypes.float32, requires_grad=False)
|
||||||
self.num_batches_tracked = Tensor.zeros(1, dtype=dtypes.long).is_param_(False)
|
self.num_batches_tracked = Tensor.zeros(1, dtype=dtypes.long, requires_grad=False)
|
||||||
|
|
||||||
def __call__(self, x:Tensor) -> Tensor:
|
def __call__(self, x:Tensor) -> Tensor:
|
||||||
batch_mean, batch_var = super().calc_stats(x.cast(dtypes.float32))
|
batch_mean, batch_var = super().calc_stats(x.cast(dtypes.float32))
|
||||||
|
|||||||
@@ -180,11 +180,11 @@ def train_resnet():
|
|||||||
def fake_data_get(batch_size):
|
def fake_data_get(batch_size):
|
||||||
x = Tensor.zeros(batch_size, 224, 224, 3, dtype=dtypes.uchar).contiguous()
|
x = Tensor.zeros(batch_size, 224, 224, 3, dtype=dtypes.uchar).contiguous()
|
||||||
y = [0] * batch_size
|
y = [0] * batch_size
|
||||||
return x.shard(GPUS, axis=0).realize(), Tensor(y).shard(GPUS, axis=0), y, None
|
return x.shard(GPUS, axis=0).realize(), Tensor(y, requires_grad=False).shard(GPUS, axis=0), y, None
|
||||||
|
|
||||||
def data_get(it):
|
def data_get(it):
|
||||||
x, y, cookie = next(it)
|
x, y, cookie = next(it)
|
||||||
return x.shard(GPUS, axis=0).realize(), Tensor(y).shard(GPUS, axis=0), y, cookie
|
return x.shard(GPUS, axis=0).realize(), Tensor(y, requires_grad=False).shard(GPUS, axis=0), y, cookie
|
||||||
|
|
||||||
# ** epoch loop **
|
# ** epoch loop **
|
||||||
step_times = []
|
step_times = []
|
||||||
@@ -413,7 +413,7 @@ def train_retinanet():
|
|||||||
layers_to_train = ["layer4", "layer3", "layer2", "layer1", "conv1"][:trainable_layers]
|
layers_to_train = ["layer4", "layer3", "layer2", "layer1", "conv1"][:trainable_layers]
|
||||||
for k, v in get_state_dict(backbone).items():
|
for k, v in get_state_dict(backbone).items():
|
||||||
if all([not k.startswith(layer) for layer in layers_to_train]):
|
if all([not k.startswith(layer) for layer in layers_to_train]):
|
||||||
v.is_param_(False)
|
v.requires_grad = False
|
||||||
|
|
||||||
def _data_get(it:Iterator[tuple[Tensor, ...]], val:bool=False):
|
def _data_get(it:Iterator[tuple[Tensor, ...]], val:bool=False):
|
||||||
if val:
|
if val:
|
||||||
@@ -798,7 +798,7 @@ def train_unet3d():
|
|||||||
@Tensor.train(mode=False)
|
@Tensor.train(mode=False)
|
||||||
def eval_step(model, x, y):
|
def eval_step(model, x, y):
|
||||||
y_hat, y = sliding_window_inference(model, x, y, gpus=GPUS)
|
y_hat, y = sliding_window_inference(model, x, y, gpus=GPUS)
|
||||||
y_hat, y = Tensor(y_hat), Tensor(y)
|
y_hat, y = Tensor(y_hat), Tensor(y, requires_grad=False)
|
||||||
loss = dice_ce_loss(y_hat, y)
|
loss = dice_ce_loss(y_hat, y)
|
||||||
score = dice_score(y_hat, y)
|
score = dice_score(y_hat, y)
|
||||||
return loss.realize(), score.realize()
|
return loss.realize(), score.realize()
|
||||||
@@ -1419,7 +1419,10 @@ def train_llama3():
|
|||||||
|
|
||||||
for p in optim.params:
|
for p in optim.params:
|
||||||
grad_dtype = dtypes.bfloat16 if p.dtype == FP8_DTYPE else p.dtype
|
grad_dtype = dtypes.bfloat16 if p.dtype == FP8_DTYPE else p.dtype
|
||||||
p.grad = p.zeros_like(dtype=grad_dtype).contiguous()
|
if isinstance(p.device, tuple) and p.uop.axis is not None:
|
||||||
|
p.grad = Tensor.zeros(p.shape, dtype=grad_dtype, device=p.device[0]).shard_(p.device, axis=p.uop.axis).contiguous()
|
||||||
|
else:
|
||||||
|
p.grad = Tensor.zeros(p.shape, dtype=grad_dtype, device=p.device).contiguous()
|
||||||
grads = [p.grad for p in optim.params]
|
grads = [p.grad for p in optim.params]
|
||||||
|
|
||||||
scheduler = CosineAnnealingLRWithWarmup(optim, opt_base_learning_rate, opt_end_learning_rate, opt_learning_rate_warmup_steps, opt_learning_rate_decay_steps)
|
scheduler = CosineAnnealingLRWithWarmup(optim, opt_base_learning_rate, opt_end_learning_rate, opt_learning_rate_warmup_steps, opt_learning_rate_decay_steps)
|
||||||
@@ -1435,19 +1438,16 @@ def train_llama3():
|
|||||||
|
|
||||||
fp8_amax = [t for ts in model._fp8_amax.values() for t in ts]
|
fp8_amax = [t for ts in model._fp8_amax.values() for t in ts]
|
||||||
fp8_grad_amax = [t for ts in model._fp8_grad_amax.values() for t in ts] if hasattr(model, "_fp8_grad_amax") else []
|
fp8_grad_amax = [t for ts in model._fp8_grad_amax.values() for t in ts] if hasattr(model, "_fp8_grad_amax") else []
|
||||||
fp8_inv_scales = list(model._fp8_inv_scale.values()) + list(model._fp8_next_inv_scale.values())
|
fp8_inv_scales = list(model._fp8_inv_scale.values())
|
||||||
|
|
||||||
from tinygrad.nn.state import get_state_dict
|
from tinygrad.nn.state import get_state_dict
|
||||||
model_state = get_state_dict(model)
|
model_state = get_state_dict(model)
|
||||||
for wname in model._fp8_inv_scale:
|
for wname in model._fp8_inv_scale:
|
||||||
w = model_state[wname]
|
w = model_state[wname]
|
||||||
w._inv_scale = model._fp8_inv_scale[wname]
|
w._inv_scale = model._fp8_inv_scale[wname]
|
||||||
w._next_inv_scale = model._fp8_next_inv_scale[wname]
|
|
||||||
if optim.master_params:
|
if optim.master_params:
|
||||||
idx = next(j for j, p in enumerate(optim.params) if p is w)
|
idx = next(j for j, p in enumerate(optim.params) if p is w)
|
||||||
master = optim.master_params[idx]
|
optim.master_params[idx].assign((optim.master_params[idx] * w._inv_scale.reshape(-1, *([1]*(w.ndim-1)))).contiguous())
|
||||||
inv = w._inv_scale if w._inv_scale.device == master.device else w._inv_scale.to(master.device)
|
|
||||||
master.assign((master * inv.reshape(-1, *([1]*(w.ndim-1)))).contiguous())
|
|
||||||
|
|
||||||
# realize everything here
|
# realize everything here
|
||||||
if optim.master_params: Tensor.realize(*optim.master_params)
|
if optim.master_params: Tensor.realize(*optim.master_params)
|
||||||
@@ -1476,7 +1476,7 @@ def train_llama3():
|
|||||||
grad_norm = optim.fstep(grads)
|
grad_norm = optim.fstep(grads)
|
||||||
scheduler.step()
|
scheduler.step()
|
||||||
|
|
||||||
for g in grads: g.assign(g.const_like(0))
|
for g in grads: g.assign(g.zeros_like())
|
||||||
|
|
||||||
lr_cpu = optim.lr.float().to("CPU")
|
lr_cpu = optim.lr.float().to("CPU")
|
||||||
grad_norm_cpu = grad_norm.float().to("CPU")
|
grad_norm_cpu = grad_norm.float().to("CPU")
|
||||||
@@ -1498,7 +1498,7 @@ def train_llama3():
|
|||||||
def fake_data(bs, samples):
|
def fake_data(bs, samples):
|
||||||
import numpy as np
|
import numpy as np
|
||||||
for _ in range(samples // bs):
|
for _ in range(samples // bs):
|
||||||
fake_data_np = np.random.randint(0, real_vocab_size, size=(bs, SEQLEN + 1), dtype=np.int32)
|
fake_data_np = np.random.randint(0, model_params["vocab_size"], size=(bs, SEQLEN + 1), dtype=np.int32)
|
||||||
yield Tensor(fake_data_np, device="NPY")
|
yield Tensor(fake_data_np, device="NPY")
|
||||||
|
|
||||||
def get_train_iter():
|
def get_train_iter():
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ import math, os
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
os.environ["DEFAULT_FLOAT"] = "bfloat16"
|
os.environ["DEFAULT_FLOAT"] = "bfloat16"
|
||||||
os.environ["OPTIM_DTYPE"] = "bfloat16"
|
os.environ["OPTIM_DTYPE"] = "bfloat16"
|
||||||
if "DEV" not in os.environ: os.environ["DEV"] = "NULL::gfx950"
|
if "DEV" not in os.environ: os.environ["DEV"] = "NULL"
|
||||||
# CDNA
|
# CDNA
|
||||||
|
os.environ["EMULATE"] = "AMD_CDNA4"
|
||||||
os.environ["DEVICE_IN_FUNCTION_BUG"] = "1"
|
os.environ["DEVICE_IN_FUNCTION_BUG"] = "1"
|
||||||
os.environ["ALL2ALL"] = "1"
|
os.environ["ALL2ALL"] = "1"
|
||||||
os.environ["USE_ATOMICS"] = "1"
|
os.environ["USE_ATOMICS"] = "1"
|
||||||
@@ -12,7 +13,7 @@ if __name__ == "__main__":
|
|||||||
if "ASM_GEMM" not in os.environ:
|
if "ASM_GEMM" not in os.environ:
|
||||||
os.environ["ASM_GEMM"] = "1"
|
os.environ["ASM_GEMM"] = "1"
|
||||||
from tinygrad import Tensor, nn, function, getenv, dtypes, TinyJit
|
from tinygrad import Tensor, nn, function, getenv, dtypes, TinyJit
|
||||||
from tinygrad.helpers import Timing, colored, GlobalCounters, profile_marker, round_up
|
from tinygrad.helpers import Timing, colored, GlobalCounters, profile_marker
|
||||||
from tinygrad.uop.ops import Ops, UOp
|
from tinygrad.uop.ops import Ops, UOp
|
||||||
from extra.models.llama import apply_rotary_emb, precompute_freqs_cis
|
from extra.models.llama import apply_rotary_emb, precompute_freqs_cis
|
||||||
from extra.llama_kernels.rmsnorm import rmsnorm
|
from extra.llama_kernels.rmsnorm import rmsnorm
|
||||||
@@ -52,8 +53,8 @@ def matmul(x:Tensor, w:Tensor, fp8:bool=True, amax_x:Tensor|None=None, w_inv_sca
|
|||||||
if ASM_GEMM:
|
if ASM_GEMM:
|
||||||
from extra.gemm.cdna_asm_gemm import can_use_asm_gemm, asm_gemm
|
from extra.gemm.cdna_asm_gemm import can_use_asm_gemm, asm_gemm
|
||||||
if can_use_asm_gemm(x_fp8, w.T):
|
if can_use_asm_gemm(x_fp8, w.T):
|
||||||
return asm_gemm(x_fp8, w.T, x_scale=x_scale, w_scale=w_inv_scale, grad_amax_state=grad_amax_state), x_new_amax, x_fp8
|
return asm_gemm(x_fp8, w.T, x_scale=x_scale, w_scale=w_inv_scale, grad_amax_state=grad_amax_state), x_new_amax, x_fp8, w
|
||||||
return (x_fp8.dot(w.T, dtype=dtypes.float) * x_scale * w_inv_scale).cast(dtypes.bfloat16), x_new_amax, x_fp8
|
return (x_fp8.dot(w.T, dtype=dtypes.float) * x_scale * w_inv_scale).cast(dtypes.bfloat16), x_new_amax, x_fp8, w
|
||||||
|
|
||||||
def norm_quantize_matmul(x:Tensor, norm:Tensor, w:Tensor, w_inv_scale:Tensor, eps:float, amax_x:Tensor, grad_amax_state:Tensor):
|
def norm_quantize_matmul(x:Tensor, norm:Tensor, w:Tensor, w_inv_scale:Tensor, eps:float, amax_x:Tensor, grad_amax_state:Tensor):
|
||||||
if FUSED_ADD_NORM_MUL_QUANTIZE:
|
if FUSED_ADD_NORM_MUL_QUANTIZE:
|
||||||
@@ -124,9 +125,9 @@ class FlatTransformer:
|
|||||||
self.tok_embeddings = nn.Embedding(vocab_size, dim)
|
self.tok_embeddings = nn.Embedding(vocab_size, dim)
|
||||||
self.tok_embeddings.weight = Tensor.normal(vocab_size, dim, mean=0.0, std=0.02, dtype=dtypes.bfloat16)
|
self.tok_embeddings.weight = Tensor.normal(vocab_size, dim, mean=0.0, std=0.02, dtype=dtypes.bfloat16)
|
||||||
self.output = Tensor.normal(1, vocab_size, dim, mean=0.0, std=0.02, dtype=dtypes.bfloat16)
|
self.output = Tensor.normal(1, vocab_size, dim, mean=0.0, std=0.02, dtype=dtypes.bfloat16)
|
||||||
self.freqs_cis = precompute_freqs_cis(dim // n_heads, max_context * 2, rope_theta).contiguous().is_param_(False)
|
self.freqs_cis = precompute_freqs_cis(dim // n_heads, max_context * 2, rope_theta).contiguous().requires_grad_(False)
|
||||||
|
|
||||||
def _amax(): return Tensor.full((), FP8_MAX, dtype=dtypes.float32).contiguous().is_param_(False)
|
def _amax(): return Tensor.full((), FP8_MAX, dtype=dtypes.float32).contiguous().requires_grad_(False)
|
||||||
names = ["xqkv", "xo", "x2"]
|
names = ["xqkv", "xo", "x2"]
|
||||||
names += ["x1", "x3"] if SPLIT_W13 else ["x13"]
|
names += ["x1", "x3"] if SPLIT_W13 else ["x13"]
|
||||||
self._fp8_amax = {name: [_amax() for _ in range(n_layers)] for name in names}
|
self._fp8_amax = {name: [_amax() for _ in range(n_layers)] for name in names}
|
||||||
@@ -135,8 +136,7 @@ class FlatTransformer:
|
|||||||
self._fp8_grad_amax = {name: [_amax() for _ in range(n_layers)] for name in grad_names}
|
self._fp8_grad_amax = {name: [_amax() for _ in range(n_layers)] for name in grad_names}
|
||||||
w_scales = [("wqkv", s_qkv), ("wo", s_o), ("w2", s_2)]
|
w_scales = [("wqkv", s_qkv), ("wo", s_o), ("w2", s_2)]
|
||||||
w_scales += [("w1", s_1), ("w3", s_3)] if SPLIT_W13 else [("w13", s_13)]
|
w_scales += [("w1", s_1), ("w3", s_3)] if SPLIT_W13 else [("w13", s_13)]
|
||||||
self._fp8_inv_scale = {name: s.float().contiguous().is_param_(False) for name, s in w_scales}
|
self._fp8_inv_scale = {name: s.float().contiguous().requires_grad_(False) for name, s in w_scales}
|
||||||
self._fp8_next_inv_scale = {name: s.float().contiguous().is_param_(False) for name, s in w_scales}
|
|
||||||
|
|
||||||
def lin_per_layer(self, in_features:int, out_features:int, std:float=0.02):
|
def lin_per_layer(self, in_features:int, out_features:int, std:float=0.02):
|
||||||
if getenv("ZEROS"): w = Tensor.zeros(self.n_layers, out_features, in_features)
|
if getenv("ZEROS"): w = Tensor.zeros(self.n_layers, out_features, in_features)
|
||||||
@@ -212,9 +212,8 @@ class FlatTransformer:
|
|||||||
attn, attn_amaxs, attn_saves = self.attention(x, freqs_cis, **attn_kwargs)
|
attn, attn_amaxs, attn_saves = self.attention(x, freqs_cis, **attn_kwargs)
|
||||||
ffn, h, ffn_amaxs, ffn_saves = self.feed_forward(x, attn, **ffn_kwargs)
|
ffn, h, ffn_amaxs, ffn_saves = self.feed_forward(x, attn, **ffn_kwargs)
|
||||||
h = h + ffn
|
h = h + ffn
|
||||||
amaxs = tuple(a.detach() for a in (*attn_amaxs, *ffn_amaxs))
|
if save: return (h, *attn_amaxs, *ffn_amaxs, *attn_saves, *ffn_saves)
|
||||||
if save: return (h, *amaxs, *attn_saves, *ffn_saves)
|
else: return (h, *attn_amaxs, *ffn_amaxs)
|
||||||
else: return (h, *amaxs)
|
|
||||||
|
|
||||||
def shard(self, device:tuple[str, ...], mp:bool=False):
|
def shard(self, device:tuple[str, ...], mp:bool=False):
|
||||||
from tinygrad.nn.state import get_parameters
|
from tinygrad.nn.state import get_parameters
|
||||||
@@ -222,19 +221,14 @@ class FlatTransformer:
|
|||||||
for v in get_parameters(self): v.shard_(device, axis=None)
|
for v in get_parameters(self): v.shard_(device, axis=None)
|
||||||
else:
|
else:
|
||||||
# flat per-layer weights: axis 0 is n_layers, so shard axes are +1 vs per-layer Transformer
|
# flat per-layer weights: axis 0 is n_layers, so shard axes are +1 vs per-layer Transformer
|
||||||
def _shard_fp8(name:str, axis:int):
|
self.wqkv.shard_(device, axis=1).realize() # (n_layers, out, dim) shard out
|
||||||
getattr(self, name).shard_(device, axis=axis)
|
self.wo.shard_(device, axis=2).realize() # (n_layers, dim, in) shard in
|
||||||
self._fp8_inv_scale[name] = self._fp8_inv_scale[name].to(device).contiguous().is_param_(False)
|
|
||||||
self._fp8_next_inv_scale[name] = self._fp8_next_inv_scale[name].to(device).contiguous().is_param_(False)
|
|
||||||
Tensor.realize(getattr(self, name), self._fp8_inv_scale[name], self._fp8_next_inv_scale[name])
|
|
||||||
_shard_fp8("wqkv", 1) # (n_layers, out, dim) shard out
|
|
||||||
_shard_fp8("wo", 2) # (n_layers, dim, in) shard in
|
|
||||||
if SPLIT_W13:
|
if SPLIT_W13:
|
||||||
_shard_fp8("w1", 1)
|
self.w1.shard_(device, axis=1).realize()
|
||||||
_shard_fp8("w3", 1)
|
self.w3.shard_(device, axis=1).realize()
|
||||||
else:
|
else:
|
||||||
_shard_fp8("w13", 1) # (n_layers, hidden*2, dim) shard out
|
self.w13.shard_(device, axis=1).realize() # (n_layers, hidden*2, dim) shard out
|
||||||
_shard_fp8("w2", 2) # (n_layers, dim, hidden) shard in
|
self.w2.shard_(device, axis=2).realize() # (n_layers, dim, hidden) shard in
|
||||||
self.attention_norm.shard_(device, axis=None).realize()
|
self.attention_norm.shard_(device, axis=None).realize()
|
||||||
self.ffn_norm.shard_(device, axis=None).realize()
|
self.ffn_norm.shard_(device, axis=None).realize()
|
||||||
self.norm.weight.shard_(device, axis=None).realize()
|
self.norm.weight.shard_(device, axis=None).realize()
|
||||||
@@ -244,7 +238,9 @@ class FlatTransformer:
|
|||||||
for amax_dict in (self._fp8_amax, self._fp8_grad_amax):
|
for amax_dict in (self._fp8_amax, self._fp8_grad_amax):
|
||||||
for name in amax_dict:
|
for name in amax_dict:
|
||||||
for i in range(len(amax_dict[name])):
|
for i in range(len(amax_dict[name])):
|
||||||
amax_dict[name][i] = amax_dict[name][i].to(device).contiguous().is_param_(False)
|
amax_dict[name][i] = amax_dict[name][i].to(device).contiguous().requires_grad_(False)
|
||||||
|
for name in self._fp8_inv_scale:
|
||||||
|
self._fp8_inv_scale[name] = self._fp8_inv_scale[name].to(device).contiguous().requires_grad_(False)
|
||||||
|
|
||||||
def __call__(self, tokens:Tensor, save:bool=True):
|
def __call__(self, tokens:Tensor, save:bool=True):
|
||||||
h = self.tok_embeddings(tokens)
|
h = self.tok_embeddings(tokens)
|
||||||
@@ -277,59 +273,41 @@ def apply_grad(grad_buf:Tensor, new_grad:UOp):
|
|||||||
pads = _get_pads(new_grad)
|
pads = _get_pads(new_grad)
|
||||||
if len(pads) <= 1:
|
if len(pads) <= 1:
|
||||||
new_grad = new_grad.cast(grad_buf.dtype)
|
new_grad = new_grad.cast(grad_buf.dtype)
|
||||||
grad_buf.uop = grad_buf.uop.after(grad_buf.uop.store(grad_buf.uop + new_grad))
|
store = grad_buf.uop.store(grad_buf.uop + new_grad)
|
||||||
|
grad_buf.uop = grad_buf.uop.after(store)
|
||||||
return
|
return
|
||||||
cur = grad_buf.uop
|
sorted_pads = sorted(pads, key=lambda p: p.marg[0][0] if p.op == Ops.PAD else 0)
|
||||||
for pad in sorted(pads, key=lambda p: p.marg[0][0] if p.op == Ops.PAD else 0, reverse=True):
|
inners_raw = [Tensor(p.src[0] if p.op == Ops.PAD else p, device=grad_buf.device) for p in sorted_pads]
|
||||||
if pad.op == Ops.PAD:
|
if getenv("FUSED_PAD_GRAD_ACCUM", 0):
|
||||||
grad_shrink = tuple([(p[0], s+p[0]) for s,p in zip(pad.src[0].shape, pad.marg)])
|
from extra.llama_kernels.fused_pad_grad_accum import fused_pad_grad_accum, can_fused_pad_grad_accum
|
||||||
buf_slice = cur.shrink(grad_shrink)
|
if can_fused_pad_grad_accum(grad_buf, inners_raw):
|
||||||
cur = cur.after(buf_slice.store(buf_slice + pad.src[0].cast(cur.dtype)))
|
grad_buf.uop = fused_pad_grad_accum(grad_buf, inners_raw).uop
|
||||||
else:
|
return
|
||||||
cur = cur.after(cur.store(cur + pad.cast(cur.dtype)))
|
inners = [t.cast(grad_buf.dtype) for t in inners_raw]
|
||||||
grad_buf.uop = cur
|
grad_buf.assign(grad_buf + inners[0].cat(*inners[1:], dim=0))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
config = {}
|
config = {}
|
||||||
BS = config["BS"] = getenv("BS", 16)
|
BS = config["BS"] = getenv("BS", 16)
|
||||||
SEQLEN = config["SEQLEN"] = getenv("SEQLEN", 8192)
|
SEQLEN = config["SEQLEN"] = getenv("SEQLEN", 8192)
|
||||||
SMALL = config["SMALL"] = getenv("SMALL", 0)
|
|
||||||
|
|
||||||
from examples.llama3 import MODEL_PARAMS
|
from examples.llama3 import MODEL_PARAMS
|
||||||
model_params = MODEL_PARAMS[llama_size:=getenv("LLAMA3_SIZE", "8B")]["args"]
|
model_params = MODEL_PARAMS[getenv("LLAMA3_SIZE", "8B")]["args"]
|
||||||
# vocab_size from mixtral tokenizer
|
if (llama_layers:=getenv("LLAMA_LAYERS")) != 0: model_params['n_layers'] = llama_layers
|
||||||
if not SMALL: model_params |= {"vocab_size": 32000}
|
|
||||||
real_vocab_size = model_params['vocab_size']
|
|
||||||
if (llama_layers:=getenv("LLAMA_LAYERS")) != 0: model_params["n_layers"] = llama_layers
|
|
||||||
|
|
||||||
# pad vocab
|
|
||||||
if (MP := getenv("MP", 1)) > 1: model_params["vocab_size"] = round_up(model_params["vocab_size"], 256 * MP)
|
|
||||||
vocab_mask:Tensor = Tensor.arange(model_params["vocab_size"]).reshape(1, 1, -1) >= real_vocab_size
|
|
||||||
|
|
||||||
model = FlatTransformer(**model_params, max_context=SEQLEN)
|
model = FlatTransformer(**model_params, max_context=SEQLEN)
|
||||||
|
|
||||||
state = nn.state.get_state_dict(model)
|
state = nn.state.get_state_dict(model)
|
||||||
print("tensor count:", len(state))
|
print("tensor count:", len(state))
|
||||||
|
|
||||||
# shard the model
|
# shard the model
|
||||||
from tinygrad import Device
|
from tinygrad import Device
|
||||||
is_dp = (DP := getenv("DP", 1)) > 1
|
if (DP := getenv("DP", 1)) > 1:
|
||||||
is_mp = (MP := getenv("MP", 1)) > 1
|
model.shard(tuple(f"{Device.DEFAULT}:{i}" for i in range(DP)))
|
||||||
is_sharding = is_dp or is_mp
|
if (MP := getenv("MP", 1)) > 1:
|
||||||
device_count = max(DP, MP)
|
model.shard(tuple(f"{Device.DEFAULT}:{i}" for i in range(MP)), mp=True)
|
||||||
device = tuple(f"{Device.DEFAULT}:{i}" for i in range(device_count))
|
|
||||||
|
|
||||||
model.shard(device, is_mp)
|
|
||||||
|
|
||||||
if is_dp: vocab_mask.shard_(device, axis=None).realize()
|
|
||||||
if is_mp: vocab_mask.shard_(device, axis=2).realize()
|
|
||||||
|
|
||||||
# preallocate all the grad buffers and zero them out
|
# preallocate all the grad buffers and zero them out
|
||||||
grad_dtype = lambda x: dtypes.bfloat16 if x.dtype in dtypes.fp8s else x.dtype
|
grads = {x:Tensor.zeros(x.shape, dtype=x.dtype, device=x.device).contiguous()
|
||||||
grads = {x:x.zeros_like(dtype=grad_dtype(x)).contiguous() for x in state.values() if x.is_param}
|
for x in state.values() if x.requires_grad}
|
||||||
|
|
||||||
fp8_amax = [t for ts in model._fp8_amax.values() for t in ts]
|
|
||||||
fp8_grad_amax = [t for ts in model._fp8_grad_amax.values() for t in ts]
|
|
||||||
|
|
||||||
# print model size
|
# print model size
|
||||||
sz = 0
|
sz = 0
|
||||||
@@ -338,31 +316,23 @@ if __name__ == "__main__":
|
|||||||
sz += v.nbytes()
|
sz += v.nbytes()
|
||||||
print(f"total sz: {sz/1e9:.2f} GB")
|
print(f"total sz: {sz/1e9:.2f} GB")
|
||||||
|
|
||||||
with Timing("fake data: "): tokens = Tensor.randint(BS, SEQLEN+1, low=0, high=real_vocab_size, dtype=dtypes.int)
|
with Timing("fake data: "): tokens = Tensor.randint(BS, SEQLEN+1, low=0, high=model.vocab_size, dtype=dtypes.int)
|
||||||
with Timing("realize weights/grads/data: "): Tensor.realize(*state.values(), *grads.values(), tokens)
|
with Timing("realize weights/grads/data: "): Tensor.realize(*state.values(), *grads.values(), tokens)
|
||||||
print("mem per device: " + ', '.join(f"{dev}: {mem/1e9:.2f} GB" for dev, mem in sorted(GlobalCounters.mem_used_per_device.items())))
|
print("mem per device: " + ', '.join(f"{dev}: {mem/1e9:.2f} GB" for dev, mem in sorted(GlobalCounters.mem_used_per_device.items())))
|
||||||
if DP > 1: tokens = tokens.shard(tuple(f"{Device.DEFAULT}:{i}" for i in range(DP)), axis=0)
|
if DP > 1: tokens = tokens.shard(tuple(f"{Device.DEFAULT}:{i}" for i in range(DP)), axis=0)
|
||||||
if MP > 1: tokens = tokens.shard(tuple(f"{Device.DEFAULT}:{i}" for i in range(MP)))
|
if MP > 1: tokens = tokens.shard(tuple(f"{Device.DEFAULT}:{i}" for i in range(MP)))
|
||||||
|
|
||||||
@TinyJit
|
@TinyJit
|
||||||
def fwd_bwd(tokens:Tensor):
|
def jit_step(tokens:Tensor):
|
||||||
with Timing("python forward: "):
|
with Timing("python forward: "): loss = model(tokens[:, :-1]).sparse_categorical_crossentropy(tokens[:, 1:])
|
||||||
logits = model(tokens[:, :-1], save=llama_size=="8B")
|
|
||||||
loss = vocab_mask.where(-1e9, logits).sparse_categorical_crossentropy(tokens[:, 1:])
|
|
||||||
with Timing("python backward: "):
|
with Timing("python backward: "):
|
||||||
for t,g in zip(grads, loss.gradient(*grads)):
|
for t,g in zip(grads, loss.gradient(*grads)):
|
||||||
apply_grad(grads[t], g.uop)
|
apply_grad(grads[t], g.uop)
|
||||||
with Timing("run fwd_bwd: "): loss.realize(*grads.values(), *fp8_amax, *fp8_grad_amax)
|
with Timing("run step: "): loss.realize(*grads.values())
|
||||||
|
|
||||||
@TinyJit
|
|
||||||
def optim_step():
|
|
||||||
for g in grads.values(): g.assign(g.zeros_like())
|
|
||||||
Tensor.realize(*grads.values())
|
|
||||||
|
|
||||||
for i in range(6):
|
for i in range(6):
|
||||||
GlobalCounters.reset()
|
GlobalCounters.reset()
|
||||||
profile_marker(f"step {i}")
|
profile_marker(f"step {i}")
|
||||||
with Timing(colored(f"*** step {i}: ", "red")):
|
with Timing(colored(f"*** step {i}: ", "red")):
|
||||||
fwd_bwd(tokens)
|
jit_step(tokens)
|
||||||
optim_step()
|
|
||||||
print("mem per device: " + ', '.join(f"{dev}: {mem/1e9:.2f} GB" for dev, mem in sorted(GlobalCounters.mem_used_per_device.items())))
|
print("mem per device: " + ', '.join(f"{dev}: {mem/1e9:.2f} GB" for dev, mem in sorted(GlobalCounters.mem_used_per_device.items())))
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
import unittest
|
|
||||||
from tinygrad import Tensor, TinyJit
|
|
||||||
from tinygrad.nn.state import get_parameters
|
|
||||||
from examples.mlperf.models.flat_llama import apply_grad
|
|
||||||
|
|
||||||
class FlatModel:
|
|
||||||
def __init__(self, n_layers:int, dim:int, hidden:int):
|
|
||||||
self.n_layers = n_layers
|
|
||||||
self.w1 = Tensor.uniform(n_layers, dim, hidden, low=-0.1, high=0.1)
|
|
||||||
self.w2 = Tensor.uniform(n_layers, hidden, dim, low=-0.1, high=0.1)
|
|
||||||
self.scale = Tensor.uniform(dim, low=0.9, high=1.1)
|
|
||||||
self.bias = Tensor.zeros(dim).contiguous()
|
|
||||||
|
|
||||||
def __call__(self, x:Tensor) -> Tensor:
|
|
||||||
h = x
|
|
||||||
for i in range(self.n_layers):
|
|
||||||
h = (h @ self.w1[i]).relu() @ self.w2[i] + h
|
|
||||||
return (h * self.scale + self.bias).sum()
|
|
||||||
|
|
||||||
class TestApplyGradE2E(unittest.TestCase):
|
|
||||||
def _run_with_apply_grad(self, model, xs):
|
|
||||||
grads = {p: Tensor.zeros(p.shape, dtype=p.dtype).contiguous().realize() for p in get_parameters(model)}
|
|
||||||
for x in xs:
|
|
||||||
loss = model(x)
|
|
||||||
for p, g in zip(grads, loss.gradient(*grads)):
|
|
||||||
apply_grad(grads[p], g.uop)
|
|
||||||
Tensor.realize(loss, *grads.values())
|
|
||||||
return [grads[p] for p in get_parameters(model)]
|
|
||||||
|
|
||||||
def _run_reference(self, model, xs):
|
|
||||||
for x in xs: model(x).backward()
|
|
||||||
return [p.grad for p in get_parameters(model)]
|
|
||||||
|
|
||||||
def _assert_close(self, got, expected, atol, rtol):
|
|
||||||
for g, e in zip(got, expected):
|
|
||||||
self.assertTrue(g.allclose(e, atol=atol, rtol=rtol).item(), f"grad mismatch (max abs diff {(g - e).abs().max().item()})")
|
|
||||||
|
|
||||||
def _assert_match(self, model, xs, atol, rtol):
|
|
||||||
self._assert_close(self._run_with_apply_grad(model, xs), self._run_reference(model, xs), atol, rtol)
|
|
||||||
|
|
||||||
def test_e2e_single_step(self):
|
|
||||||
model = FlatModel(n_layers=3, dim=8, hidden=16)
|
|
||||||
Tensor.realize(*get_parameters(model))
|
|
||||||
self._assert_match(model, [Tensor.randn(2, 8).realize()], atol=1e-4, rtol=1e-4)
|
|
||||||
|
|
||||||
def test_e2e_multi_step_accumulation(self):
|
|
||||||
model = FlatModel(n_layers=4, dim=8, hidden=16)
|
|
||||||
Tensor.realize(*get_parameters(model))
|
|
||||||
self._assert_match(model, [Tensor.randn(2, 8).realize() for _ in range(3)], atol=1e-4, rtol=1e-4)
|
|
||||||
|
|
||||||
def test_e2e_jit(self):
|
|
||||||
model = FlatModel(n_layers=3, dim=8, hidden=16)
|
|
||||||
Tensor.realize(*get_parameters(model))
|
|
||||||
grads = {p: Tensor.zeros(p.shape, dtype=p.dtype).contiguous().realize() for p in get_parameters(model)}
|
|
||||||
|
|
||||||
@TinyJit
|
|
||||||
def fwd_bwd(x:Tensor):
|
|
||||||
loss = model(x)
|
|
||||||
for p, g in zip(grads, loss.gradient(*grads)): apply_grad(grads[p], g.uop)
|
|
||||||
Tensor.realize(loss, *grads.values())
|
|
||||||
|
|
||||||
xs = [Tensor.randn(2, 8).realize() for _ in range(3)]
|
|
||||||
for x in xs: fwd_bwd(x)
|
|
||||||
self._assert_close([grads[p] for p in get_parameters(model)], self._run_reference(model, xs), atol=1e-3, rtol=1e-3)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
@@ -3,7 +3,8 @@ os.environ["WQKV"] = "1"
|
|||||||
import unittest
|
import unittest
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from tinygrad import Tensor, nn, dtypes
|
from tinygrad import Tensor, nn, dtypes
|
||||||
from tinygrad.device import Device
|
from tinygrad.nn.state import get_parameters
|
||||||
|
from tinygrad.device import is_dtype_supported, Device
|
||||||
from examples.mlperf.models.llama import Transformer
|
from examples.mlperf.models.llama import Transformer
|
||||||
from examples.mlperf.models.flat_llama import FlatTransformer
|
from examples.mlperf.models.flat_llama import FlatTransformer
|
||||||
|
|
||||||
@@ -44,6 +45,8 @@ class TestFlatLlama(unittest.TestCase):
|
|||||||
flat = FlatTransformer(**params)
|
flat = FlatTransformer(**params)
|
||||||
copy_weights(flat, ref)
|
copy_weights(flat, ref)
|
||||||
|
|
||||||
|
for p in get_parameters(ref): p.requires_grad_(True)
|
||||||
|
for p in get_parameters(flat): p.requires_grad_(True)
|
||||||
Tensor.realize(*nn.state.get_state_dict(flat).values())
|
Tensor.realize(*nn.state.get_state_dict(flat).values())
|
||||||
|
|
||||||
tokens = Tensor([[1, 50, 100, 999, 2, 10]])
|
tokens = Tensor([[1, 50, 100, 999, 2, 10]])
|
||||||
@@ -111,7 +114,7 @@ class TestFlatLlama(unittest.TestCase):
|
|||||||
self.assertEqual(ref_logits.shape, flat_logits.shape)
|
self.assertEqual(ref_logits.shape, flat_logits.shape)
|
||||||
np.testing.assert_allclose(flat_logits, ref_logits, atol=1e-4, rtol=1e-4)
|
np.testing.assert_allclose(flat_logits, ref_logits, atol=1e-4, rtol=1e-4)
|
||||||
|
|
||||||
@unittest.skipUnless(dtypes.fp8e4m3 in Device[Device.DEFAULT].renderer.supported_dtypes(), "fp8 not supported on this device")
|
@unittest.skipUnless(is_dtype_supported(dtypes.fp8e4m3), "fp8 not supported on this device")
|
||||||
def test_forward_fp8(self):
|
def test_forward_fp8(self):
|
||||||
import examples.mlperf.models.flat_llama as flat_llama_mod
|
import examples.mlperf.models.flat_llama as flat_llama_mod
|
||||||
old_fp8 = flat_llama_mod.FP8
|
old_fp8 = flat_llama_mod.FP8
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ from tinygrad.uop.ops import UOp, Ops
|
|||||||
|
|
||||||
STOCHASTIC_ROUND = getenv("STOCHASTIC_ROUND", 0)
|
STOCHASTIC_ROUND = getenv("STOCHASTIC_ROUND", 0)
|
||||||
MASTER_WEIGHTS = getenv("MASTER_WEIGHTS", 0)
|
MASTER_WEIGHTS = getenv("MASTER_WEIGHTS", 0)
|
||||||
FP8_AMAX_MARGIN = getenv("FP8_AMAX_MARGIN", 1.1)
|
|
||||||
|
|
||||||
def stochastic_round_bf16(x:Tensor) -> Tensor:
|
def stochastic_round_bf16(x:Tensor) -> Tensor:
|
||||||
bits = x.bitcast(dtypes.uint32)
|
bits = x.bitcast(dtypes.uint32)
|
||||||
@@ -22,14 +21,11 @@ class GradAccClipAdamW(Optimizer):
|
|||||||
def __init__(self, params:list[Tensor], lr=0.001, b1=0.9, b2=0.999, eps=1e-6, weight_decay=0.0, grad_acc=1, clip_norm=1.0, device=None, fused=FUSE_OPTIM):
|
def __init__(self, params:list[Tensor], lr=0.001, b1=0.9, b2=0.999, eps=1e-6, weight_decay=0.0, grad_acc=1, clip_norm=1.0, device=None, fused=FUSE_OPTIM):
|
||||||
super().__init__(params, lr, device, fused)
|
super().__init__(params, lr, device, fused)
|
||||||
self.b1, self.b2, self.eps, self.wd = b1, b2, eps, weight_decay
|
self.b1, self.b2, self.eps, self.wd = b1, b2, eps, weight_decay
|
||||||
self.b1_t, self.b2_t = (Tensor.ones((1,), dtype=dtypes.float32, device=self.device) for _ in [b1, b2])
|
self.b1_t, self.b2_t = (Tensor.ones((1,), dtype=dtypes.float32, device=self.device, requires_grad=False) for _ in [b1, b2])
|
||||||
self.m = self._new_optim_param()
|
self.m = self._new_optim_param()
|
||||||
self.v = self._new_optim_param()
|
self.v = self._new_optim_param()
|
||||||
self.grad_acc, self.clip_norm = grad_acc, clip_norm
|
self.grad_acc, self.clip_norm = grad_acc, clip_norm
|
||||||
if MASTER_WEIGHTS and self.params[0].dtype != dtypes.float32:
|
self.master_params:list[Tensor]|None = [p.float().contiguous() for p in self.params] if MASTER_WEIGHTS and self.params[0].dtype != dtypes.float32 else None
|
||||||
self.master_params:list[Tensor]|None = [p.to(self.device).float().contiguous() for p in self.params]
|
|
||||||
else:
|
|
||||||
self.master_params = None
|
|
||||||
|
|
||||||
def fstep(self, grads:list[Tensor]):
|
def fstep(self, grads:list[Tensor]):
|
||||||
if self.fused:
|
if self.fused:
|
||||||
@@ -40,8 +36,7 @@ class GradAccClipAdamW(Optimizer):
|
|||||||
for i, tt in enumerate(self.params): tt.assign(self._apply_update(tt, updates[i], self.master_params[i] if self.master_params else None))
|
for i, tt in enumerate(self.params): tt.assign(self._apply_update(tt, updates[i], self.master_params[i] if self.master_params else None))
|
||||||
# collect inv_scale tensors attached to fp8 params (set by _apply_update)
|
# collect inv_scale tensors attached to fp8 params (set by _apply_update)
|
||||||
fp8_inv_scales = [tt._inv_scale for tt in self.params if hasattr(tt, '_inv_scale')]
|
fp8_inv_scales = [tt._inv_scale for tt in self.params if hasattr(tt, '_inv_scale')]
|
||||||
fp8_next_inv_scales = [tt._next_inv_scale for tt in self.params if hasattr(tt, '_next_inv_scale')]
|
to_realize = extra+self.params+self.buffers+(self.master_params or [])+fp8_inv_scales
|
||||||
to_realize = extra+self.params+self.buffers+(self.master_params or [])+fp8_inv_scales+fp8_next_inv_scales
|
|
||||||
|
|
||||||
Tensor.realize(*to_realize)
|
Tensor.realize(*to_realize)
|
||||||
return extra[-1]
|
return extra[-1]
|
||||||
@@ -83,23 +78,13 @@ class GradAccClipAdamW(Optimizer):
|
|||||||
up = up.float().shard_like(w) + self.lr.to(w.device) * wd * w.detach()
|
up = up.float().shard_like(w) + self.lr.to(w.device) * wd * w.detach()
|
||||||
new_w = w.detach() - up
|
new_w = w.detach() - up
|
||||||
if master is not None: master.assign(new_w)
|
if master is not None: master.assign(new_w)
|
||||||
# when master is offloaded to a different device than the param, results are resharded back onto the param's (sharded) device
|
if STOCHASTIC_ROUND and t.dtype == dtypes.bfloat16: return stochastic_round_bf16(new_w)
|
||||||
offloaded = master is not None and master.device != t.device
|
|
||||||
if STOCHASTIC_ROUND and t.dtype == dtypes.bfloat16:
|
|
||||||
out = stochastic_round_bf16(new_w)
|
|
||||||
return out.shard_like(t) if offloaded else out
|
|
||||||
if t.dtype in dtypes.fp8s:
|
if t.dtype in dtypes.fp8s:
|
||||||
from examples.mlperf.models.flat_llama import FP8_MAX
|
from examples.mlperf.models.flat_llama import FP8_MAX
|
||||||
# delayed scaling: reuse previous step's inv_scale
|
amax = new_w.float().abs().max(axis=tuple(range(1, new_w.ndim))).detach() # per-layer amax for (n_layers, out, in)
|
||||||
t._inv_scale.assign(t._next_inv_scale)
|
scale = FP8_MAX / (amax + 1e-8)
|
||||||
inv_scale = t._inv_scale.to(new_w.device) if offloaded else t._inv_scale
|
fp8_w = (new_w * scale.reshape(-1, *([1]*(new_w.ndim-1)))).clamp(-FP8_MAX, FP8_MAX).cast(t.dtype)
|
||||||
scale = inv_scale.reciprocal().reshape(-1, *([1]*(new_w.ndim-1)))
|
if hasattr(t, '_inv_scale'):
|
||||||
scaled = (new_w * scale).clamp(-FP8_MAX, FP8_MAX)
|
t._inv_scale.assign(((amax + 1e-8) / FP8_MAX).cast(t._inv_scale.dtype))
|
||||||
ret = scaled.cast(t.dtype)
|
return fp8_w
|
||||||
# update inv_scale for next step from quantized result
|
return new_w.cast(t.dtype)
|
||||||
new_amax = (ret.float().abs().max(axis=tuple(range(1, ret.ndim))) * inv_scale * FP8_AMAX_MARGIN).detach()
|
|
||||||
new_inv = ((new_amax + 1e-8) / FP8_MAX).cast(t._inv_scale.dtype)
|
|
||||||
t._next_inv_scale.assign(new_inv.shard_like(t._next_inv_scale) if offloaded else new_inv)
|
|
||||||
return ret.shard_like(t) if offloaded else ret
|
|
||||||
out = new_w.cast(t.dtype)
|
|
||||||
return out.shard_like(t) if offloaded else out
|
|
||||||
|
|||||||
+4
-8
@@ -1,8 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
export PYTHONPATH="."
|
export PYTHONPATH="."
|
||||||
export PATH="/opt/rocm-7.1.1/bin:$PATH"
|
|
||||||
export ROCM_PATH="/opt/rocm-7.1.1"
|
|
||||||
export DEV=${DEV:-AMD}
|
export DEV=${DEV:-AMD}
|
||||||
export CHECK_OOB=0
|
export CHECK_OOB=0
|
||||||
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
||||||
@@ -18,12 +16,10 @@ export MASTER_WEIGHTS=${MASTER_WEIGHTS:-1}
|
|||||||
export FP8=${FP8:-1}
|
export FP8=${FP8:-1}
|
||||||
export ALLREDUCE_CAST=${ALLREDUCE_CAST:-1}
|
export ALLREDUCE_CAST=${ALLREDUCE_CAST:-1}
|
||||||
export FAST_CE=${FAST_CE:-0}
|
export FAST_CE=${FAST_CE:-0}
|
||||||
export FUSED_INPUT_QUANTIZE=${FUSED_INPUT_QUANTIZE:-0}
|
export FUSED_INPUT_QUANTIZE=${FUSED_INPUT_QUANTIZE:-1}
|
||||||
export FUSED_GRAD_QUANTIZE=${FUSED_GRAD_QUANTIZE:-0}
|
export FUSED_ADD_NORM_MUL_QUANTIZE=${FUSED_ADD_NORM_MUL_QUANTIZE:-1}
|
||||||
export FUSED_ADD_NORM_MUL_QUANTIZE=${FUSED_ADD_NORM_MUL_QUANTIZE:-0}
|
export FUSED_SILU_W13=${FUSED_SILU_W13:-1}
|
||||||
export FUSED_SILU_W13=${FUSED_SILU_W13:-0}
|
export FUSED_PAD_GRAD_ACCUM=${FUSED_PAD_GRAD_ACCUM:-1}
|
||||||
export FUSED_PAD_GRAD_ACCUM=${FUSED_PAD_GRAD_ACCUM:-0}
|
|
||||||
export SPLIT_W13=${SPLIT_W13:-1}
|
|
||||||
export OFFLOAD_OPTIM=${OFFLOAD_OPTIM:-1}
|
export OFFLOAD_OPTIM=${OFFLOAD_OPTIM:-1}
|
||||||
|
|
||||||
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16"
|
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16"
|
||||||
|
|||||||
+4
-16
@@ -1,34 +1,22 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
export PYTHONPATH="."
|
export PYTHONPATH="."
|
||||||
export PATH="/opt/rocm-7.1.1/bin:$PATH"
|
|
||||||
export ROCM_PATH="/opt/rocm-7.1.1"
|
|
||||||
export DEV=${DEV:-AMD}
|
export DEV=${DEV:-AMD}
|
||||||
|
export EMULATE="AMD_CDNA4"
|
||||||
export CHECK_OOB=0
|
export CHECK_OOB=0
|
||||||
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
||||||
export DEVICE_IN_FUNCTION_BUG=1
|
|
||||||
|
|
||||||
export DEBUG=${DEBUG:-0}
|
export DEBUG=${DEBUG:-0}
|
||||||
export HK_FLASH_ATTENTION=${HK_FLASH_ATTENTION:-1}
|
export HK_FLASH_ATTENTION=${HK_FLASH_ATTENTION:-1}
|
||||||
export ALL2ALL=${ALL2ALL:-1}
|
export ALL2ALL=${ALL2ALL:-1}
|
||||||
export USE_ATOMICS=${USE_ATOMICS:-1}
|
export USE_ATOMICS=${USE_ATOMICS:-0}
|
||||||
export ASM_GEMM=${ASM_GEMM:-1}
|
export ASM_GEMM=${ASM_GEMM:-1}
|
||||||
export WQKV=${WQKV:-1}
|
export WQKV=${WQKV:-1}
|
||||||
export MASTER_WEIGHTS=${MASTER_WEIGHTS:-1}
|
|
||||||
export FP8=${FP8:-1}
|
|
||||||
export ALLREDUCE_CAST=${ALLREDUCE_CAST:-1}
|
|
||||||
export FAST_CE=${FAST_CE:-0}
|
|
||||||
export FUSED_INPUT_QUANTIZE=${FUSED_INPUT_QUANTIZE:-0}
|
|
||||||
export FUSED_GRAD_QUANTIZE=${FUSED_GRAD_QUANTIZE:-0}
|
|
||||||
export FUSED_ADD_NORM_MUL_QUANTIZE=${FUSED_ADD_NORM_MUL_QUANTIZE:-0}
|
|
||||||
export FUSED_SILU_W13=${FUSED_SILU_W13:-0}
|
|
||||||
export FUSED_PAD_GRAD_ACCUM=${FUSED_PAD_GRAD_ACCUM:-0}
|
|
||||||
export SPLIT_W13=${SPLIT_W13:-1}
|
|
||||||
export OFFLOAD_OPTIM=${OFFLOAD_OPTIM:-1}
|
export OFFLOAD_OPTIM=${OFFLOAD_OPTIM:-1}
|
||||||
|
|
||||||
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16"
|
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16"
|
||||||
export DP=${DP:-1} MP=${MP:-8} BS=${BS:-1} EVAL_BS=${EVAL_BS:-1} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-1152}
|
export DP=${DP:-1} MP=${MP:-8}
|
||||||
export GBS=$((BS * GRADIENT_ACC_STEPS))
|
export BS=${BS:-1} EVAL_BS=${EVAL_BS:-1} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-1152}
|
||||||
|
|
||||||
export MODEL="llama3"
|
export MODEL="llama3"
|
||||||
export BASEDIR="/raid/datasets/c4/"
|
export BASEDIR="/raid/datasets/c4/"
|
||||||
|
|||||||
+1
-3
@@ -1,8 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
export PYTHONPATH="."
|
export PYTHONPATH="."
|
||||||
export PATH="/opt/rocm-7.1.1/bin:$PATH"
|
|
||||||
export ROCM_PATH="/opt/rocm-7.1.1"
|
|
||||||
export DEV=${DEV:-AMD}
|
export DEV=${DEV:-AMD}
|
||||||
export CHECK_OOB=0
|
export CHECK_OOB=0
|
||||||
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
||||||
@@ -23,7 +21,7 @@ export FUSED_INPUT_QUANTIZE=${FUSED_INPUT_QUANTIZE:-1}
|
|||||||
export FUSED_GRAD_QUANTIZE=${FUSED_GRAD_QUANTIZE:-1}
|
export FUSED_GRAD_QUANTIZE=${FUSED_GRAD_QUANTIZE:-1}
|
||||||
export FUSED_ADD_NORM_MUL_QUANTIZE=${FUSED_ADD_NORM_MUL_QUANTIZE:-1}
|
export FUSED_ADD_NORM_MUL_QUANTIZE=${FUSED_ADD_NORM_MUL_QUANTIZE:-1}
|
||||||
export FUSED_SILU_W13=${FUSED_SILU_W13:-1}
|
export FUSED_SILU_W13=${FUSED_SILU_W13:-1}
|
||||||
export SPLIT_W13=${SPLIT_W13:-0}
|
export FUSED_PAD_GRAD_ACCUM=${FUSED_PAD_GRAD_ACCUM:-1}
|
||||||
|
|
||||||
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16"
|
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16"
|
||||||
export DP=${DP:-8} MP=${MP:-1} BS=${BS:-16} EVAL_BS=${EVAL_BS:-8} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-2}
|
export DP=${DP:-8} MP=${MP:-1} BS=${BS:-16} EVAL_BS=${EVAL_BS:-8} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-2}
|
||||||
|
|||||||
+1
-2
@@ -1,8 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
export PYTHONPATH="."
|
export PYTHONPATH="."
|
||||||
export PATH="/opt/rocm-7.1.1/bin:$PATH"
|
|
||||||
export ROCM_PATH="/opt/rocm-7.1.1"
|
|
||||||
export DEV=${DEV:-AMD}
|
export DEV=${DEV:-AMD}
|
||||||
export CHECK_OOB=0
|
export CHECK_OOB=0
|
||||||
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
||||||
@@ -22,6 +20,7 @@ export FUSED_INPUT_QUANTIZE=${FUSED_INPUT_QUANTIZE:-0}
|
|||||||
export FUSED_GRAD_QUANTIZE=${FUSED_GRAD_QUANTIZE:-0}
|
export FUSED_GRAD_QUANTIZE=${FUSED_GRAD_QUANTIZE:-0}
|
||||||
export FUSED_ADD_NORM_MUL_QUANTIZE=${FUSED_ADD_NORM_MUL_QUANTIZE:-0}
|
export FUSED_ADD_NORM_MUL_QUANTIZE=${FUSED_ADD_NORM_MUL_QUANTIZE:-0}
|
||||||
export FUSED_SILU_W13=${FUSED_SILU_W13:-0}
|
export FUSED_SILU_W13=${FUSED_SILU_W13:-0}
|
||||||
|
export FUSED_PAD_GRAD_ACCUM=${FUSED_PAD_GRAD_ACCUM:-0}
|
||||||
export SPLIT_W13=${SPLIT_W13:-1}
|
export SPLIT_W13=${SPLIT_W13:-1}
|
||||||
export OFFLOAD_OPTIM=${OFFLOAD_OPTIM:-1}
|
export OFFLOAD_OPTIM=${OFFLOAD_OPTIM:-1}
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -1,8 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
export PYTHONPATH="."
|
export PYTHONPATH="."
|
||||||
export PATH="/opt/rocm-7.1.1/bin:$PATH"
|
|
||||||
export ROCM_PATH="/opt/rocm-7.1.1"
|
|
||||||
export DEV=${DEV:-AMD}
|
export DEV=${DEV:-AMD}
|
||||||
export CHECK_OOB=0
|
export CHECK_OOB=0
|
||||||
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
||||||
@@ -23,7 +21,7 @@ export FUSED_INPUT_QUANTIZE=${FUSED_INPUT_QUANTIZE:-1}
|
|||||||
export FUSED_GRAD_QUANTIZE=${FUSED_GRAD_QUANTIZE:-1}
|
export FUSED_GRAD_QUANTIZE=${FUSED_GRAD_QUANTIZE:-1}
|
||||||
export FUSED_ADD_NORM_MUL_QUANTIZE=${FUSED_ADD_NORM_MUL_QUANTIZE:-1}
|
export FUSED_ADD_NORM_MUL_QUANTIZE=${FUSED_ADD_NORM_MUL_QUANTIZE:-1}
|
||||||
export FUSED_SILU_W13=${FUSED_SILU_W13:-1}
|
export FUSED_SILU_W13=${FUSED_SILU_W13:-1}
|
||||||
export SPLIT_W13=${SPLIT_W13:-0}
|
export FUSED_PAD_GRAD_ACCUM=${FUSED_PAD_GRAD_ACCUM:-1}
|
||||||
|
|
||||||
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16"
|
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16"
|
||||||
export DP=${DP:-8} MP=${MP:-1} BS=${BS:-16} EVAL_BS=${EVAL_BS:-8} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-2}
|
export DP=${DP:-8} MP=${MP:-1} BS=${BS:-16} EVAL_BS=${EVAL_BS:-8} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-2}
|
||||||
|
|||||||
+2
-2
@@ -1,9 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
export PYTHONPATH="."
|
export PYTHONPATH="."
|
||||||
export PATH="/opt/rocm-7.1.1/bin:$PATH"
|
|
||||||
export ROCM_PATH="/opt/rocm-7.1.1"
|
|
||||||
export DEV=${DEV:-AMD}
|
export DEV=${DEV:-AMD}
|
||||||
|
export EMULATE="AMD_CDNA4"
|
||||||
export CHECK_OOB=0
|
export CHECK_OOB=0
|
||||||
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
||||||
export DEVICE_IN_FUNCTION_BUG=1
|
export DEVICE_IN_FUNCTION_BUG=1
|
||||||
@@ -22,6 +21,7 @@ export FUSED_INPUT_QUANTIZE=${FUSED_INPUT_QUANTIZE:-0}
|
|||||||
export FUSED_GRAD_QUANTIZE=${FUSED_GRAD_QUANTIZE:-0}
|
export FUSED_GRAD_QUANTIZE=${FUSED_GRAD_QUANTIZE:-0}
|
||||||
export FUSED_ADD_NORM_MUL_QUANTIZE=${FUSED_ADD_NORM_MUL_QUANTIZE:-0}
|
export FUSED_ADD_NORM_MUL_QUANTIZE=${FUSED_ADD_NORM_MUL_QUANTIZE:-0}
|
||||||
export FUSED_SILU_W13=${FUSED_SILU_W13:-0}
|
export FUSED_SILU_W13=${FUSED_SILU_W13:-0}
|
||||||
|
export FUSED_PAD_GRAD_ACCUM=${FUSED_PAD_GRAD_ACCUM:-0}
|
||||||
export SPLIT_W13=${SPLIT_W13:-1}
|
export SPLIT_W13=${SPLIT_W13:-1}
|
||||||
export OFFLOAD_OPTIM=${OFFLOAD_OPTIM:-1}
|
export OFFLOAD_OPTIM=${OFFLOAD_OPTIM:-1}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
export BENCHMARK=5
|
export BENCHMARK=5
|
||||||
export EVAL_BS=0
|
export EVAL_BS=0
|
||||||
VIZ=${VIZ:--1} FULL_LAYERS=1 DEBUG=0 examples/mlperf/training_submission_v6.0/tinycorp/benchmarks/llama31_8b/implementations/tinybox_8xMI350X/dev_beam.sh
|
VIZ=${VIZ:--1} FULL_LAYERS=1 DEBUG=0 examples/mlperf/training_submission_v6.0/tinycorp/benchmarks/llama8b/implementations/tinybox_8xMI350X/dev_beam.sh
|
||||||
SRC="AMD"; [[ $DEV == NULL* ]] && SRC="NULL"
|
SRC="AMD"; [[ $DEV == NULL* ]] && SRC="NULL"
|
||||||
python -m tinygrad.viz.cli -s "$SRC" -t --interval "train @ 2" "train @ 3"
|
python -m tinygrad.viz.cli -s "$SRC" -t
|
||||||
|
|||||||
+1
-3
@@ -3,8 +3,6 @@ set -e # Exit on any error
|
|||||||
set -o pipefail # Make pipeline fail if any command fails
|
set -o pipefail # Make pipeline fail if any command fails
|
||||||
|
|
||||||
export PYTHONPATH="."
|
export PYTHONPATH="."
|
||||||
export PATH="/opt/rocm-7.1.1/bin:$PATH"
|
|
||||||
export ROCM_PATH="/opt/rocm-7.1.1"
|
|
||||||
export DEV=AMD
|
export DEV=AMD
|
||||||
export CHECK_OOB=0
|
export CHECK_OOB=0
|
||||||
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
export REWRITE_STACK_LIMIT=5000000 HCQDEV_WAIT_TIMEOUT_MS=240000
|
||||||
@@ -24,7 +22,7 @@ export FUSED_INPUT_QUANTIZE=1
|
|||||||
export FUSED_GRAD_QUANTIZE=1
|
export FUSED_GRAD_QUANTIZE=1
|
||||||
export FUSED_ADD_NORM_MUL_QUANTIZE=1
|
export FUSED_ADD_NORM_MUL_QUANTIZE=1
|
||||||
export FUSED_SILU_W13=1
|
export FUSED_SILU_W13=1
|
||||||
export SPLIT_W13=0
|
export FUSED_PAD_GRAD_ACCUM=1
|
||||||
|
|
||||||
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16"
|
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16"
|
||||||
export DP=8 MP=1 BS=16 EVAL_BS=8 GRADIENT_ACC_STEPS=2
|
export DP=8 MP=1 BS=16 EVAL_BS=8 GRADIENT_ACC_STEPS=2
|
||||||
|
|||||||
+2
-2
@@ -4,7 +4,7 @@ export EVAL_BS=0
|
|||||||
export FAKEDATA=1
|
export FAKEDATA=1
|
||||||
export NULL_ALLOW_COPYOUT=1
|
export NULL_ALLOW_COPYOUT=1
|
||||||
export HIP_VISIBLE_DEVICES=""
|
export HIP_VISIBLE_DEVICES=""
|
||||||
export DEV=NULL:HIP:gfx950
|
export DEV=NULL
|
||||||
export JITBEAM=0
|
export JITBEAM=0
|
||||||
export LLAMA_LAYERS=${LLAMA_LAYERS:-"2"}
|
export LLAMA_LAYERS=${LLAMA_LAYERS:-"2"}
|
||||||
time examples/mlperf/training_submission_v6.0/tinycorp/benchmarks/llama31_8b/implementations/tinybox_8xMI350X/dev_run.sh
|
time examples/mlperf/training_submission_v6.0/tinycorp/benchmarks/llama8b/implementations/tinybox_8xMI350X/dev_run.sh
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ def train_generator(optimizer, data_fake):
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# data for training and validation
|
# data for training and validation
|
||||||
X_train, _, _, _ = mnist()
|
X_train, _, _, _ = mnist()
|
||||||
ds_noise = Tensor.randn(64, 128)
|
ds_noise = Tensor.randn(64, 128, requires_grad=False)
|
||||||
# parameters
|
# parameters
|
||||||
epochs, batch_size, k = 300, 512, 1
|
epochs, batch_size, k = 300, 512, 1
|
||||||
sample_interval = epochs // 10
|
sample_interval = epochs // 10
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user