diff --git a/RELEASES.md b/RELEASES.md
index 35ed1b9520..51387091b8 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -12,6 +12,7 @@ Version 0.8.17 (2022-XX-XX)
* Border turns grey while overriding steering
* Added button to bookmark events while driving; view them later in comma connect
* AGNOS 6
+* Kia Sportage Hybrid 2023 support thanks to sunnyhaibin!
Version 0.8.16 (2022-08-26)
========================
diff --git a/cereal b/cereal
index 107048c83e..1e3dd70a39 160000
--- a/cereal
+++ b/cereal
@@ -1 +1 @@
-Subproject commit 107048c83ec2f488286a1be314e7aece0a20a6b1
+Subproject commit 1e3dd70a391bc1bbe437d3eea8be30947f929a75
diff --git a/docs/CARS.md b/docs/CARS.md
index 40eef06102..a03da5ca6a 100644
--- a/docs/CARS.md
+++ b/docs/CARS.md
@@ -4,7 +4,7 @@
A supported vehicle is one that just works when you install a comma three. All supported cars provide a better experience than any stock system.
-# 208 Supported Cars
+# 209 Supported Cars
|Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|Harness|
|---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|
@@ -18,8 +18,8 @@ A supported vehicle is one that just works when you install a comma three. All s
|Audi|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|Stock|0 mph|0 mph|[](##)|[](##)|VW|
|Audi|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|Stock|0 mph|0 mph|[](##)|[](##)|VW|
|Cadillac|Escalade ESV 2016[1](#footnotes)|Adaptive Cruise Control (ACC) & LKAS|openpilot|0 mph|6 mph|[](##)|[](##)|OBD-II|
-|Chevrolet|Bolt EUV 2022-23|Premier or Premier Redline Trim without Super Cruise Package|Stock|0 mph|6 mph|[](##)|[](##)|GM|
-|Chevrolet|Silverado 1500 2020-21|Safety Package II|Stock|0 mph|6 mph|[](##)|[](##)|GM|
+|Chevrolet|Bolt EUV 2022-23|Premier or Premier Redline Trim without Super Cruise Package|Stock|3 mph|6 mph|[](##)|[](##)|GM|
+|Chevrolet|Silverado 1500 2020-21|Safety Package II|Stock|3 mph|6 mph|[](##)|[](##)|GM|
|Chevrolet|Volt 2017-18[1](#footnotes)|Adaptive Cruise Control (ACC)|openpilot|0 mph|6 mph|[](##)|[](##)|OBD-II|
|Chrysler|Pacifica 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|FCA|
|Chrysler|Pacifica 2019-20|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|FCA|
@@ -32,7 +32,7 @@ A supported vehicle is one that just works when you install a comma three. All s
|Genesis|G80 2017-19|All|Stock|0 mph|0 mph|[](##)|[](##)|Hyundai H|
|Genesis|G90 2017-18|All|openpilot|0 mph|0 mph|[](##)|[](##)|Hyundai C|
|GMC|Acadia 2018[1](#footnotes)|Adaptive Cruise Control (ACC)|openpilot|0 mph|6 mph|[](##)|[](##)|OBD-II|
-|GMC|Sierra 1500 2020-21|Driver Alert Package II|Stock|0 mph|6 mph|[](##)|[](##)|GM|
+|GMC|Sierra 1500 2020-21|Driver Alert Package II|Stock|3 mph|6 mph|[](##)|[](##)|GM|
|Honda|Accord 2018-22|All|openpilot|0 mph|3 mph|[](##)|[](##)|Honda Bosch A|
|Honda|Accord Hybrid 2018-22|All|openpilot|0 mph|3 mph|[](##)|[](##)|Honda Bosch A|
|Honda|Civic 2016-18|Honda Sensing|openpilot|0 mph|12 mph|[](##)|[](##)|Honda Nidec|
@@ -100,6 +100,7 @@ A supported vehicle is one that just works when you install a comma three. All s
|Kia|Seltos 2021|Smart Cruise Control (SCC)|openpilot|0 mph|0 mph|[](##)|[](##)|Hyundai A|
|Kia|Sorento 2018|Advanced Smart Cruise Control|Stock|0 mph|0 mph|[](##)|[](##)|Hyundai C|
|Kia|Sorento 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|Hyundai E|
+|Kia|Sportage Hybrid 2023|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|Hyundai N|
|Kia|Stinger 2018-20|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|Hyundai C|
|Kia|Telluride 2020|All|openpilot|0 mph|0 mph|[](##)|[](##)|Hyundai H|
|Lexus|CT Hybrid 2017-18|Lexus Safety System+|Stock[3](#footnotes)|0 mph|0 mph|[](##)|[](##)|Toyota|
diff --git a/panda b/panda
index b1ca52f86d..02b74fcfe1 160000
--- a/panda
+++ b/panda
@@ -1 +1 @@
-Subproject commit b1ca52f86d59500c6232df6afac97a51daf7bd51
+Subproject commit 02b74fcfe19cbb000e5fb696e028f6f67690c20c
diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py
index 248828e757..e25f203772 100755
--- a/selfdrive/car/gm/interface.py
+++ b/selfdrive/car/gm/interface.py
@@ -62,11 +62,14 @@ class CarInterface(CarInterfaceBase):
ret.radarOffCan = True # no radar
ret.pcmCruise = True
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM
+ ret.minEnableSpeed = 5 * CV.KPH_TO_MS
else: # ASCM, OBD-II harness
ret.openpilotLongitudinalControl = True
ret.networkLocation = NetworkLocation.gateway
ret.radarOffCan = False
ret.pcmCruise = False # stock non-adaptive cruise control is kept off
+ # supports stop and go, but initial engage must (conservatively) be above 18mph
+ ret.minEnableSpeed = 18 * CV.MPH_TO_MS
# These cars have been put into dashcam only due to both a lack of users and test coverage.
# These cars likely still work fine. Once a user confirms each car works and a test route is
@@ -90,9 +93,6 @@ class CarInterface(CarInterfaceBase):
ret.steerLimitTimer = 0.4
ret.radarTimeStep = 0.0667 # GM radar runs at 15Hz instead of standard 20Hz
- # supports stop and go, but initial engage must (conservatively) be above 18mph
- ret.minEnableSpeed = 18 * CV.MPH_TO_MS
-
if candidate == CAR.VOLT:
ret.mass = 1607. + STD_CARGO_KG
ret.wheelbase = 2.69
@@ -153,7 +153,6 @@ class CarInterface(CarInterfaceBase):
tire_stiffness_factor = 1.0
elif candidate in (CAR.BOLT_EV, CAR.BOLT_EUV):
- ret.minEnableSpeed = -1
ret.mass = 1669. + STD_CARGO_KG
ret.wheelbase = 2.63779
ret.steerRatio = 16.8
@@ -163,7 +162,6 @@ class CarInterface(CarInterfaceBase):
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
elif candidate == CAR.SILVERADO:
- ret.minEnableSpeed = -1
ret.mass = 2200. + STD_CARGO_KG
ret.wheelbase = 3.75
ret.steerRatio = 16.3
@@ -172,7 +170,6 @@ class CarInterface(CarInterfaceBase):
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
elif candidate == CAR.EQUINOX:
- ret.minEnableSpeed = -1
ret.mass = 3500. * CV.LB_TO_KG + STD_CARGO_KG
ret.wheelbase = 2.72
ret.steerRatio = 14.4
@@ -207,19 +204,16 @@ class CarInterface(CarInterfaceBase):
GearShifter.eco, GearShifter.manumatic],
pcm_enable=self.CP.pcmCruise)
- if ret.vEgo < self.CP.minEnableSpeed:
+ # Enabling at a standstill with brake is allowed
+ # TODO: verify 17 Volt can enable for the first time at a stop and allow for all GMs
+ if ret.vEgo < self.CP.minEnableSpeed and not (ret.standstill and ret.brake >= 20 and
+ self.CP.networkLocation == NetworkLocation.fwdCamera):
events.add(EventName.belowEngageSpeed)
if ret.cruiseState.standstill:
events.add(EventName.resumeRequired)
if ret.vEgo < self.CP.minSteerSpeed:
events.add(EventName.belowSteerSpeed)
- if self.CP.networkLocation == NetworkLocation.fwdCamera and self.CP.pcmCruise:
- # The ECM has a higher brake pressed threshold than the camera, causing an
- # ACC fault when you engage at a stop with your foot partially on the brake
- if ret.vEgoRaw < 0.1 and ret.brake < 20:
- events.add(EventName.gmAccFaultedTemp)
-
ret.events = events.to_msg()
return ret
diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py
index e48edc42ba..638008934a 100644
--- a/selfdrive/car/honda/values.py
+++ b/selfdrive/car/honda/values.py
@@ -105,7 +105,6 @@ class Footnote(Enum):
@dataclass
class HondaCarInfo(CarInfo):
package: str = "Honda Sensing"
- min_steer_speed: float = 12. * CV.MPH_TO_MS
CAR_INFO: Dict[str, Optional[Union[HondaCarInfo, List[HondaCarInfo]]]] = {
@@ -114,31 +113,31 @@ CAR_INFO: Dict[str, Optional[Union[HondaCarInfo, List[HondaCarInfo]]]] = {
HondaCarInfo("Honda Inspire 2018", "All", min_steer_speed=3. * CV.MPH_TO_MS, harness=Harness.bosch_a),
],
CAR.ACCORDH: HondaCarInfo("Honda Accord Hybrid 2018-22", "All", min_steer_speed=3. * CV.MPH_TO_MS, harness=Harness.bosch_a),
- CAR.CIVIC: HondaCarInfo("Honda Civic 2016-18", harness=Harness.nidec, video_link="https://youtu.be/-IkImTe1NYE"),
+ CAR.CIVIC: HondaCarInfo("Honda Civic 2016-18", min_steer_speed=12. * CV.MPH_TO_MS, harness=Harness.nidec, video_link="https://youtu.be/-IkImTe1NYE"),
CAR.CIVIC_BOSCH: [
- HondaCarInfo("Honda Civic 2019-21", "All", "https://www.youtube.com/watch?v=4Iz1Mz5LGF8", [Footnote.CIVIC_DIESEL], min_steer_speed=2. * CV.MPH_TO_MS, harness=Harness.bosch_a),
- HondaCarInfo("Honda Civic Hatchback 2017-21", harness=Harness.bosch_a),
+ HondaCarInfo("Honda Civic 2019-21", "All", "https://www.youtube.com/watch?v=4Iz1Mz5LGF8", [Footnote.CIVIC_DIESEL], 2. * CV.MPH_TO_MS, harness=Harness.bosch_a),
+ HondaCarInfo("Honda Civic Hatchback 2017-21", min_steer_speed=12. * CV.MPH_TO_MS, harness=Harness.bosch_a),
],
CAR.CIVIC_BOSCH_DIESEL: None, # same platform
CAR.CIVIC_2022: [
- HondaCarInfo("Honda Civic 2022", "All", min_steer_speed=0., harness=Harness.bosch_b),
- HondaCarInfo("Honda Civic Hatchback 2022", "All", min_steer_speed=0., harness=Harness.bosch_b),
+ HondaCarInfo("Honda Civic 2022", "All", harness=Harness.bosch_b),
+ HondaCarInfo("Honda Civic Hatchback 2022", "All", harness=Harness.bosch_b),
],
CAR.ACURA_ILX: HondaCarInfo("Acura ILX 2016-19", "AcuraWatch Plus", min_steer_speed=25. * CV.MPH_TO_MS, harness=Harness.nidec),
- CAR.CRV: HondaCarInfo("Honda CR-V 2015-16", "Touring Trim", harness=Harness.nidec),
- CAR.CRV_5G: HondaCarInfo("Honda CR-V 2017-22", harness=Harness.bosch_a),
+ CAR.CRV: HondaCarInfo("Honda CR-V 2015-16", "Touring Trim", min_steer_speed=12. * CV.MPH_TO_MS, harness=Harness.nidec),
+ CAR.CRV_5G: HondaCarInfo("Honda CR-V 2017-22", min_steer_speed=12. * CV.MPH_TO_MS, harness=Harness.bosch_a),
CAR.CRV_EU: None, # HondaCarInfo("Honda CR-V EU", "Touring"), # Euro version of CRV Touring
- CAR.CRV_HYBRID: HondaCarInfo("Honda CR-V Hybrid 2017-19", harness=Harness.bosch_a),
- CAR.FIT: HondaCarInfo("Honda Fit 2018-20", harness=Harness.nidec),
- CAR.FREED: HondaCarInfo("Honda Freed 2020", harness=Harness.nidec),
- CAR.HRV: HondaCarInfo("Honda HR-V 2019-22", harness=Harness.nidec),
- CAR.ODYSSEY: HondaCarInfo("Honda Odyssey 2018-20", min_steer_speed=0., harness=Harness.nidec),
+ CAR.CRV_HYBRID: HondaCarInfo("Honda CR-V Hybrid 2017-19", min_steer_speed=12. * CV.MPH_TO_MS, harness=Harness.bosch_a),
+ CAR.FIT: HondaCarInfo("Honda Fit 2018-20", min_steer_speed=12. * CV.MPH_TO_MS, harness=Harness.nidec),
+ CAR.FREED: HondaCarInfo("Honda Freed 2020", min_steer_speed=12. * CV.MPH_TO_MS, harness=Harness.nidec),
+ CAR.HRV: HondaCarInfo("Honda HR-V 2019-22", min_steer_speed=12. * CV.MPH_TO_MS, harness=Harness.nidec),
+ CAR.ODYSSEY: HondaCarInfo("Honda Odyssey 2018-20", harness=Harness.nidec),
CAR.ODYSSEY_CHN: None, # Chinese version of Odyssey
- CAR.ACURA_RDX: HondaCarInfo("Acura RDX 2016-18", "AcuraWatch Plus", harness=Harness.nidec),
+ CAR.ACURA_RDX: HondaCarInfo("Acura RDX 2016-18", "AcuraWatch Plus", min_steer_speed=12. * CV.MPH_TO_MS, harness=Harness.nidec),
CAR.ACURA_RDX_3G: HondaCarInfo("Acura RDX 2019-22", "All", min_steer_speed=3. * CV.MPH_TO_MS, harness=Harness.bosch_a),
- CAR.PILOT: HondaCarInfo("Honda Pilot 2016-22", harness=Harness.nidec),
- CAR.PASSPORT: HondaCarInfo("Honda Passport 2019-21", "All", harness=Harness.nidec),
- CAR.RIDGELINE: HondaCarInfo("Honda Ridgeline 2017-22", harness=Harness.nidec),
+ CAR.PILOT: HondaCarInfo("Honda Pilot 2016-22", min_steer_speed=12. * CV.MPH_TO_MS, harness=Harness.nidec),
+ CAR.PASSPORT: HondaCarInfo("Honda Passport 2019-21", "All", min_steer_speed=12. * CV.MPH_TO_MS, harness=Harness.nidec),
+ CAR.RIDGELINE: HondaCarInfo("Honda Ridgeline 2017-22", min_steer_speed=12. * CV.MPH_TO_MS, harness=Harness.nidec),
CAR.INSIGHT: HondaCarInfo("Honda Insight 2019-22", "All", min_steer_speed=3. * CV.MPH_TO_MS, harness=Harness.bosch_a),
CAR.HONDA_E: HondaCarInfo("Honda e 2020", "All", min_steer_speed=3. * CV.MPH_TO_MS, harness=Harness.bosch_a),
}
diff --git a/selfdrive/car/hyundai/carcontroller.py b/selfdrive/car/hyundai/carcontroller.py
index 6b38297eb9..913f683e2c 100644
--- a/selfdrive/car/hyundai/carcontroller.py
+++ b/selfdrive/car/hyundai/carcontroller.py
@@ -135,14 +135,17 @@ class CarController:
self.last_button_frame = self.frame
else:
for _ in range(20):
- can_sends.append(hyundaicanfd.create_buttons(self.packer, CS.buttons_counter+1, Buttons.CANCEL))
+ can_sends.append(hyundaicanfd.create_buttons(self.packer, self.CP, CS.buttons_counter+1, Buttons.CANCEL))
self.last_button_frame = self.frame
# cruise standstill resume
elif CC.cruiseControl.resume:
- if not (self.CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS):
+ if self.CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS:
+ # TODO: resume for alt button cars
+ pass
+ else:
for _ in range(20):
- can_sends.append(hyundaicanfd.create_buttons(self.packer, CS.buttons_counter+1, Buttons.RES_ACCEL))
+ can_sends.append(hyundaicanfd.create_buttons(self.packer, self.CP, CS.buttons_counter+1, Buttons.RES_ACCEL))
self.last_button_frame = self.frame
else:
can_sends.append(hyundaican.create_lkas11(self.packer, self.frame, self.car_fingerprint, apply_steer, lat_active,
diff --git a/selfdrive/car/hyundai/hyundaicanfd.py b/selfdrive/car/hyundai/hyundaicanfd.py
index f2cbafdcf0..e1478e6f18 100644
--- a/selfdrive/car/hyundai/hyundaicanfd.py
+++ b/selfdrive/car/hyundai/hyundaicanfd.py
@@ -3,7 +3,7 @@ from selfdrive.car.hyundai.values import HyundaiFlags
def get_e_can_bus(CP):
# On the CAN-FD platforms, the LKAS camera is on both A-CAN and E-CAN. HDA2 cars
- # have a a different harness than the HDA1 and non-HDA variants in order to split
+ # have a different harness than the HDA1 and non-HDA variants in order to split
# a different bus, since the steering is done by different ECUs.
return 5 if CP.flags & HyundaiFlags.CANFD_HDA2 else 4
@@ -39,13 +39,15 @@ def create_cam_0x2a4(packer, camera_values):
})
return packer.make_can_msg("CAM_0x2a4", 4, camera_values)
-def create_buttons(packer, cnt, btn):
+def create_buttons(packer, CP, cnt, btn):
values = {
"COUNTER": cnt,
"SET_ME_1": 1,
"CRUISE_BUTTONS": btn,
}
- return packer.make_can_msg("CRUISE_BUTTONS", 5, values)
+
+ bus = 5 if CP.flags & HyundaiFlags.CANFD_HDA2 else 6
+ return packer.make_can_msg("CRUISE_BUTTONS", bus, values)
def create_acc_cancel(packer, CP, cruise_info_copy):
values = cruise_info_copy
diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py
index 13e93c7d06..b1fa8d9e1d 100644
--- a/selfdrive/car/hyundai/interface.py
+++ b/selfdrive/car/hyundai/interface.py
@@ -8,6 +8,7 @@ from selfdrive.car import STD_CARGO_KG, create_button_event, scale_rot_inertia,
from selfdrive.car.interfaces import CarInterfaceBase
from selfdrive.car.disable_ecu import disable_ecu
+Ecu = car.CarParams.Ecu
ButtonType = car.CarState.ButtonEvent.Type
EventName = car.CarEvent.EventName
ENABLE_BUTTONS = (Buttons.RES_ACCEL, Buttons.SET_DECEL, Buttons.CANCEL)
@@ -33,8 +34,8 @@ class CarInterface(CarInterfaceBase):
ret.dashcamOnly = candidate in {CAR.KIA_OPTIMA_H, CAR.ELANTRA_GT_I30}
if candidate in CANFD_CAR:
- # detect HDA2 with LKAS message
- if 0x50 in fingerprint[6]:
+ # detect HDA2 with ADAS Driving ECU
+ if Ecu.adas in [fw.ecu for fw in car_fw]:
ret.flags |= HyundaiFlags.CANFD_HDA2.value
else:
# non-HDA2
@@ -247,6 +248,11 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 16.
tire_stiffness_factor = 0.65
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
+ elif candidate == CAR.KIA_SPORTAGE_HYBRID_5TH_GEN:
+ ret.mass = 1767. + STD_CARGO_KG # SX Prestige trim support only
+ ret.wheelbase = 2.756
+ ret.steerRatio = 13.6
+ CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
# Genesis
elif candidate == CAR.GENESIS_G70:
diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py
index f69273ba55..d5b8427f66 100644
--- a/selfdrive/car/hyundai/values.py
+++ b/selfdrive/car/hyundai/values.py
@@ -36,7 +36,7 @@ class CarControllerParams:
# If the max stock LKAS request is <384, add your car to this list.
elif CP.carFingerprint in (CAR.GENESIS_G80, CAR.GENESIS_G90, CAR.ELANTRA, CAR.HYUNDAI_GENESIS, CAR.ELANTRA_GT_I30, CAR.IONIQ,
CAR.IONIQ_EV_LTD, CAR.SANTA_FE_PHEV_2022, CAR.SONATA_LF, CAR.KIA_FORTE, CAR.KIA_NIRO_PHEV,
- CAR.KIA_OPTIMA_H, CAR.KIA_SORENTO, CAR.KIA_STINGER):
+ CAR.KIA_OPTIMA_H, CAR.KIA_SORENTO):
self.STEER_MAX = 255
# Default for most HKG
@@ -90,6 +90,7 @@ class CAR:
KIA_OPTIMA_H = "KIA OPTIMA HYBRID 2017 & SPORTS 2019"
KIA_SELTOS = "KIA SELTOS 2021"
KIA_SORENTO = "KIA SORENTO GT LINE 2018"
+ KIA_SPORTAGE_HYBRID_5TH_GEN = "KIA SPORTAGE HYBRID 5TH GEN"
KIA_STINGER = "KIA STINGER GT2 2018"
KIA_CEED = "KIA CEED INTRO ED 2019"
KIA_EV6 = "KIA EV6 2022"
@@ -172,6 +173,7 @@ CAR_INFO: Dict[str, Optional[Union[HyundaiCarInfo, List[HyundaiCarInfo]]]] = {
HyundaiCarInfo("Kia Sorento 2018", "Advanced Smart Cruise Control", "https://www.youtube.com/watch?v=Fkh3s6WHJz8", harness=Harness.hyundai_c),
HyundaiCarInfo("Kia Sorento 2019", video_link="https://www.youtube.com/watch?v=Fkh3s6WHJz8", harness=Harness.hyundai_e),
],
+ CAR.KIA_SPORTAGE_HYBRID_5TH_GEN: HyundaiCarInfo("Kia Sportage Hybrid 2023", harness=Harness.hyundai_n),
CAR.KIA_STINGER: HyundaiCarInfo("Kia Stinger 2018-20", video_link="https://www.youtube.com/watch?v=MJ94qoofYw0", harness=Harness.hyundai_c),
CAR.KIA_CEED: HyundaiCarInfo("Kia Ceed 2019", harness=Harness.hyundai_e),
CAR.KIA_EV6: [
@@ -304,7 +306,7 @@ FW_QUERY_CONFIG = FwQueryConfig(
Request(
[HYUNDAI_VERSION_REQUEST_LONG],
[HYUNDAI_VERSION_RESPONSE],
- whitelist_ecus=[Ecu.fwdRadar],
+ whitelist_ecus=[Ecu.fwdCamera, Ecu.fwdRadar],
bus=4,
),
Request(
@@ -1367,6 +1369,14 @@ FW_VERSIONS = {
b'\xf1\x00NX4__ 1.00 1.00 99110-N9100 ',
],
},
+ CAR.KIA_SPORTAGE_HYBRID_5TH_GEN: {
+ (Ecu.fwdCamera, 0x7c4, None): [
+ b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.00 99211-P1060 665',
+ ],
+ (Ecu.fwdRadar, 0x7d0, None): [
+ b'\xf1\x00NQ5__ 1.01 1.03 99110-CH000 ',
+ ],
+ },
}
CHECKSUM = {
@@ -1384,12 +1394,12 @@ FEATURES = {
"use_fca": {CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.ELANTRA_GT_I30, CAR.KIA_STINGER, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KONA_EV, CAR.KIA_FORTE, CAR.KIA_NIRO_EV, CAR.PALISADE, CAR.GENESIS_G70, CAR.GENESIS_G70_2020, CAR.KONA, CAR.SANTA_FE, CAR.KIA_SELTOS, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.TUCSON, CAR.KONA_EV_2022},
}
-CANFD_CAR = {CAR.KIA_EV6, CAR.IONIQ_5, CAR.TUCSON_HYBRID_4TH_GEN}
+CANFD_CAR = {CAR.KIA_EV6, CAR.IONIQ_5, CAR.TUCSON_HYBRID_4TH_GEN, CAR.KIA_SPORTAGE_HYBRID_5TH_GEN}
# The camera does SCC on these cars, rather than the radar
CAMERA_SCC_CAR = {CAR.KONA_EV_2022, }
-HYBRID_CAR = {CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021, CAR.KIA_NIRO_PHEV, CAR.KIA_NIRO_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.IONIQ, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.IONIQ_PHEV_2019, CAR.TUCSON_HYBRID_4TH_GEN} # these cars use a different gas signal
+HYBRID_CAR = {CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021, CAR.KIA_NIRO_PHEV, CAR.KIA_NIRO_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.IONIQ, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.IONIQ_PHEV_2019, CAR.TUCSON_HYBRID_4TH_GEN, CAR.KIA_SPORTAGE_HYBRID_5TH_GEN} # these cars use a different gas signal
EV_CAR = {CAR.IONIQ_EV_2020, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.KIA_NIRO_EV, CAR.KONA_EV_2022, CAR.KIA_EV6, CAR.IONIQ_5}
# these cars require a special panda safety mode due to missing counters and checksums in the messages
@@ -1442,4 +1452,5 @@ DBC = {
CAR.SONATA_HYBRID: dbc_dict('hyundai_kia_generic', 'hyundai_kia_mando_front_radar_generated'),
CAR.TUCSON_HYBRID_4TH_GEN: dbc_dict('hyundai_canfd', None),
CAR.IONIQ_5: dbc_dict('hyundai_canfd', None),
+ CAR.KIA_SPORTAGE_HYBRID_5TH_GEN: dbc_dict('hyundai_canfd', None),
}
diff --git a/selfdrive/car/tests/routes.py b/selfdrive/car/tests/routes.py
index 85787ae88d..8c4efe3061 100644
--- a/selfdrive/car/tests/routes.py
+++ b/selfdrive/car/tests/routes.py
@@ -91,13 +91,14 @@ routes = [
CarTestRoute("7653b2bce7bcfdaa|2020-03-04--15-34-32", HYUNDAI.KIA_OPTIMA_G4),
CarTestRoute("018654717bc93d7d|2022-09-19--23-11-10", HYUNDAI.KIA_OPTIMA_G4_FL, segment=0),
CarTestRoute("c75a59efa0ecd502|2021-03-11--20-52-55", HYUNDAI.KIA_SELTOS),
+ CarTestRoute("b3537035ffe6a7d6|2022-10-17--15-23-49", HYUNDAI.KIA_SPORTAGE_HYBRID_5TH_GEN),
CarTestRoute("5b7c365c50084530|2020-04-15--16-13-24", HYUNDAI.SONATA),
CarTestRoute("b2a38c712dcf90bd|2020-05-18--18-12-48", HYUNDAI.SONATA_LF),
CarTestRoute("fb3fd42f0baaa2f8|2022-03-30--15-25-05", HYUNDAI.TUCSON),
CarTestRoute("36e10531feea61a4|2022-07-25--13-37-42", HYUNDAI.TUCSON_HYBRID_4TH_GEN),
CarTestRoute("5875672fc1d4bf57|2020-07-23--21-33-28", HYUNDAI.KIA_SORENTO),
CarTestRoute("9c917ba0d42ffe78|2020-04-17--12-43-19", HYUNDAI.PALISADE),
- CarTestRoute("22de8111a8c5463c|2022-07-29--13-34-49", HYUNDAI.IONIQ_5),
+ CarTestRoute("05a8f0197fdac372|2022-10-19--14-14-09", HYUNDAI.IONIQ_5), # HDA2
CarTestRoute("3f29334d6134fcd4|2022-03-30--22-00-50", HYUNDAI.IONIQ_PHEV_2019),
CarTestRoute("fa8db5869167f821|2021-06-10--22-50-10", HYUNDAI.IONIQ_PHEV),
CarTestRoute("2c5cf2dd6102e5da|2020-12-17--16-06-44", HYUNDAI.IONIQ_EV_2020),
@@ -110,7 +111,7 @@ routes = [
CarTestRoute("49f3c13141b6bc87|2021-07-28--08-05-13", HYUNDAI.KONA_HEV),
CarTestRoute("5dddcbca6eb66c62|2020-07-26--13-24-19", HYUNDAI.KIA_STINGER),
CarTestRoute("d624b3d19adce635|2020-08-01--14-59-12", HYUNDAI.VELOSTER),
- CarTestRoute("d824e27e8c60172c|2022-05-19--16-15-28", HYUNDAI.KIA_EV6), # HDA2
+ CarTestRoute("d545129f3ca90f28|2022-10-19--09-22-54", HYUNDAI.KIA_EV6), # HDA2
CarTestRoute("68d6a96e703c00c9|2022-09-10--16-09-39", HYUNDAI.KIA_EV6), # HDA1
CarTestRoute("007d5e4ad9f86d13|2021-09-30--15-09-23", HYUNDAI.KIA_K5_2021),
CarTestRoute("50c6c9b85fd1ff03|2020-10-26--17-56-06", HYUNDAI.KIA_NIRO_EV),
diff --git a/selfdrive/car/tests/test_fw_fingerprint.py b/selfdrive/car/tests/test_fw_fingerprint.py
index ed323b0563..b9926301f1 100755
--- a/selfdrive/car/tests/test_fw_fingerprint.py
+++ b/selfdrive/car/tests/test_fw_fingerprint.py
@@ -45,6 +45,7 @@ class TestFwFingerprint(unittest.TestCase):
self.assertFalse(len(duplicates), f"{car_model}: Duplicate FW versions: Ecu.{ECU_NAME[ecu[0]]}, {duplicates}")
def test_data_collection_ecus(self):
+ # Asserts no extra ECUs are in the fingerprinting database
for brand, config in FW_QUERY_CONFIGS.items():
for car_model, ecus in VERSIONS[brand].items():
bad_ecus = set(ecus).intersection(config.extra_ecus)
@@ -80,10 +81,11 @@ class TestFwFingerprint(unittest.TestCase):
def test_fw_request_ecu_whitelist(self):
for brand, config in FW_QUERY_CONFIGS.items():
with self.subTest(brand=brand):
- whitelisted_ecus = set([ecu for r in config.requests for ecu in r.whitelist_ecus])
- brand_ecus = set([fw[0] for car_fw in VERSIONS[brand].values() for fw in car_fw])
+ whitelisted_ecus = {ecu for r in config.requests for ecu in r.whitelist_ecus}
+ brand_ecus = {fw[0] for car_fw in VERSIONS[brand].values() for fw in car_fw}
+ brand_ecus |= {ecu[0] for ecu in config.extra_ecus}
- # each ecu in brand's fw versions needs to be whitelisted at least once
+ # each ecu in brand's fw versions + extra ecus needs to be whitelisted at least once
ecus_not_whitelisted = brand_ecus - whitelisted_ecus
ecu_strings = ", ".join([f'Ecu.{ECU_NAME[ecu]}' for ecu in ecus_not_whitelisted])
diff --git a/selfdrive/car/torque_data/override.yaml b/selfdrive/car/torque_data/override.yaml
index 889eeffb25..13a0dae7a7 100644
--- a/selfdrive/car/torque_data/override.yaml
+++ b/selfdrive/car/torque_data/override.yaml
@@ -32,6 +32,7 @@ CHEVROLET EQUINOX 2019: [2.0, 2.0, 0.05]
VOLKSWAGEN PASSAT NMS: [2.5, 2.5, 0.1]
VOLKSWAGEN SHARAN 2ND GEN: [2.5, 2.5, 0.1]
HYUNDAI TUCSON HYBRID 4TH GEN: [2.5, 2.5, 0.0]
+KIA SPORTAGE HYBRID 5TH GEN: [2.5, 2.5, 0.0]
# Dashcam or fallback configured as ideal car
mock: [10.0, 10, 0.0]
diff --git a/selfdrive/controls/lib/events.py b/selfdrive/controls/lib/events.py
index 5bfe89b31c..44426620e9 100644
--- a/selfdrive/controls/lib/events.py
+++ b/selfdrive/controls/lib/events.py
@@ -811,7 +811,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = {
ET.NO_ENTRY: NoEntryAlert("Cruise Faulted"),
},
- EventName.gmAccFaultedTemp: {
+ EventName.accFaultedTemp: {
ET.NO_ENTRY: NoEntryAlert("Cruise Temporarily Faulted"),
},
diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py
index 7d656b55a9..51676086ba 100644
--- a/selfdrive/controls/lib/latcontrol_torque.py
+++ b/selfdrive/controls/lib/latcontrol_torque.py
@@ -17,7 +17,7 @@ from selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_GRAVITY
# friction in the steering wheel that needs to be overcome to
# move it at all, this is compensated for too.
-LOW_SPEED_FACTOR = 100
+LOW_SPEED_FACTOR = 200
class LatControlTorque(LatControl):
diff --git a/selfdrive/controls/lib/lateral_planner.py b/selfdrive/controls/lib/lateral_planner.py
index 9fbfd4a11f..29137defd3 100644
--- a/selfdrive/controls/lib/lateral_planner.py
+++ b/selfdrive/controls/lib/lateral_planner.py
@@ -22,8 +22,7 @@ LATERAL_JERK_COST = 0.05
# TODO this cost should be lowered when low
# speed lateral control is stable on all cars
STEERING_RATE_COST = 800.0
-
-MIN_SPEED = .3
+MIN_SPEED = 1.5
class LateralPlanner:
diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit
index 998bf4e756..b0613393ad 100644
--- a/selfdrive/test/process_replay/ref_commit
+++ b/selfdrive/test/process_replay/ref_commit
@@ -1 +1 @@
-6bb7d8baae51d88dd61f0baf561e386664ddd266
\ No newline at end of file
+a87455caf93e91fae0f3704aa476e0732d066b77
\ No newline at end of file
diff --git a/selfdrive/test/process_replay/test_processes.py b/selfdrive/test/process_replay/test_processes.py
index 683387dce8..cecabd8a3a 100755
--- a/selfdrive/test/process_replay/test_processes.py
+++ b/selfdrive/test/process_replay/test_processes.py
@@ -18,7 +18,7 @@ from tools.lib.logreader import LogReader
source_segments = [
("BODY", "937ccb7243511b65|2022-05-24--16-03-09--1"), # COMMA.BODY
("HYUNDAI", "02c45f73a2e5c6e9|2021-01-01--19-08-22--1"), # HYUNDAI.SONATA
- ("HYUNDAI2", "d824e27e8c60172c|2022-09-13--11-26-50--2"), # HYUNDAI.KIA_EV6
+ ("HYUNDAI2", "d545129f3ca90f28|2022-10-19--09-22-54--9"), # HYUNDAI.KIA_EV6
("TOYOTA", "0982d79ebb0de295|2021-01-04--17-13-21--13"), # TOYOTA.PRIUS (INDI)
("TOYOTA2", "0982d79ebb0de295|2021-01-03--20-03-36--6"), # TOYOTA.RAV4 (LQR)
("TOYOTA3", "f7d7e3538cda1a2a|2021-08-16--08-55-34--6"), # TOYOTA.COROLLA_TSS2
@@ -40,7 +40,7 @@ source_segments = [
segments = [
("BODY", "regenFA002A80700|2022-09-27--15-37-02--0"),
("HYUNDAI", "regenBE53A59065B|2022-09-27--16-52-03--0"),
- ("HYUNDAI2", "regenFA8B5CA9840|2022-10-12--21-47-06--0"),
+ ("HYUNDAI2", "d545129f3ca90f28|2022-10-19--09-22-54--9"),
("TOYOTA", "regen929C5790007|2022-09-27--16-27-47--0"),
("TOYOTA2", "regenEA3950D7F22|2022-09-27--15-43-24--0"),
("TOYOTA3", "regen89026F6BD8D|2022-09-27--15-45-37--0"),
diff --git a/selfdrive/test/update_ci_routes.py b/selfdrive/test/update_ci_routes.py
index 201ffb745a..a2b971999c 100755
--- a/selfdrive/test/update_ci_routes.py
+++ b/selfdrive/test/update_ci_routes.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python3
+from functools import lru_cache
import sys
import subprocess
+from tqdm import tqdm
from azure.storage.blob import BlockBlobService # pylint: disable=import-error
from selfdrive.car.tests.routes import routes as test_car_models_routes
@@ -10,11 +12,11 @@ from xx.chffr.lib.storage import _DATA_ACCOUNT_PRODUCTION, _DATA_ACCOUNT_CI, _DA
SOURCES = [
(_DATA_ACCOUNT_PRODUCTION, _DATA_BUCKET_PRODUCTION),
- (_DATA_ACCOUNT_PRODUCTION, "preserve"),
(_DATA_ACCOUNT_CI, "commadataci"),
]
+@lru_cache
def get_azure_keys():
dest_key = azureutil.get_user_token(_DATA_ACCOUNT_CI, "openpilotci")
source_keys = [azureutil.get_user_token(account, bucket) for account, bucket in SOURCES]
@@ -82,7 +84,7 @@ if __name__ == "__main__":
to_sync.extend([rt.route for rt in test_car_models_routes])
to_sync.extend([s[1].rsplit('--', 1)[0] for s in replay_segments])
- for r in to_sync:
+ for r in tqdm(to_sync):
if not sync_to_ci_public(r):
failed_routes.append(r)
diff --git a/tools/cabana/.gitignore b/tools/cabana/.gitignore
index 88ffab2717..d7a552eabb 100644
--- a/tools/cabana/.gitignore
+++ b/tools/cabana/.gitignore
@@ -3,3 +3,5 @@ moc_*
_cabana
settings
+car_fingerprint_to_dbc.json
+
diff --git a/tools/cabana/README.md b/tools/cabana/README.md
index f64e6b2d2d..99d0d4c9ce 100644
--- a/tools/cabana/README.md
+++ b/tools/cabana/README.md
@@ -6,4 +6,19 @@ Cabana is a tool developed to view raw CAN data. One use for this is creating an
## Usage Instructions
+```bash
+$ ./cabana -h
+Usage: ./_cabana [options] route
+
+Options:
+ -h, --help Displays this help.
+ --demo use a demo route instead of providing your own
+ --qcam load qcamera
+ --data_dir local directory with routes
+
+Arguments:
+ route the drive to replay. find your drives at
+ connect.comma.ai
+```
+
See [openpilot wiki](https://github.com/commaai/openpilot/wiki/Cabana)
diff --git a/tools/cabana/SConscript b/tools/cabana/SConscript
index fd44ecd138..d791466ce7 100644
--- a/tools/cabana/SConscript
+++ b/tools/cabana/SConscript
@@ -12,5 +12,6 @@ else:
qt_libs = ['qt_util', 'Qt5Charts'] + base_libs
cabana_libs = [widgets, cereal, messaging, visionipc, replay_lib, opendbc,'avutil', 'avcodec', 'avformat', 'bz2', 'curl', 'yuv'] + qt_libs
+qt_env.Execute('./generate_dbc_json.py --out car_fingerprint_to_dbc.json')
qt_env.Program('_cabana', ['cabana.cc', 'mainwin.cc', 'binaryview.cc', 'chartswidget.cc', 'historylog.cc', 'videowidget.cc', 'signaledit.cc', 'dbcmanager.cc',
'canmessages.cc', 'messageswidget.cc', 'detailwidget.cc'], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc
index 71175e783e..168edc75f4 100644
--- a/tools/cabana/binaryview.cc
+++ b/tools/cabana/binaryview.cc
@@ -1,8 +1,11 @@
#include "tools/cabana/binaryview.h"
#include
+#include
#include
+#include
#include
+#include
#include "tools/cabana/canmessages.h"
@@ -18,6 +21,7 @@ BinaryView::BinaryView(QWidget *parent) : QTableView(parent) {
horizontalHeader()->hide();
verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setMouseTracking(true);
// replace selection model
auto old_model = selectionModel();
@@ -29,6 +33,24 @@ BinaryView::BinaryView(QWidget *parent) : QTableView(parent) {
});
}
+void BinaryView::highlight(const Signal *sig) {
+ if (sig != hovered_sig) {
+ hovered_sig = sig;
+ model->dataChanged(model->index(0, 0), model->index(model->rowCount() - 1, model->columnCount() - 1));
+ emit signalHovered(hovered_sig);
+ }
+}
+
+void BinaryView::mouseMoveEvent(QMouseEvent *event) {
+ if (auto index = indexAt(event->pos()); index.isValid()) {
+ auto item = (BinaryViewModel::Item *)index.internalPointer();
+ highlight(item->sig);
+ if (item->sig)
+ QToolTip::showText(event->globalPos(), item->sig->name.c_str(), this, rect());
+ }
+ QTableView::mouseMoveEvent(event);
+}
+
void BinaryView::mouseReleaseEvent(QMouseEvent *event) {
QTableView::mouseReleaseEvent(event);
@@ -39,6 +61,11 @@ void BinaryView::mouseReleaseEvent(QMouseEvent *event) {
}
}
+void BinaryView::leaveEvent(QEvent *event) {
+ highlight(nullptr);
+ QTableView::leaveEvent(event);
+}
+
void BinaryView::setMessage(const QString &message_id) {
msg_id = message_id;
model->setMessage(message_id);
@@ -79,7 +106,8 @@ void BinaryViewModel::setMessage(const QString &message_id) {
} else if (j == end) {
sig.is_little_endian ? items[idx].is_msb = true : items[idx].is_lsb = true;
}
- items[idx].bg_color = QColor(getColor(i));
+ items[idx].bg_color = getColor(i);
+ items[idx].sig = &dbc_msg->sigs[i];
}
}
}
@@ -157,7 +185,8 @@ void BinarySelectionModel::select(const QItemSelection &selection, QItemSelectio
BinaryItemDelegate::BinaryItemDelegate(QObject *parent) : QStyledItemDelegate(parent) {
// cache fonts and color
small_font.setPointSize(6);
- bold_font.setBold(true);
+ hex_font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
+ hex_font.setBold(true);
highlight_color = QApplication::style()->standardPalette().color(QPalette::Active, QPalette::Highlight);
}
@@ -168,11 +197,19 @@ QSize BinaryItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo
void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
auto item = (const BinaryViewModel::Item *)index.internalPointer();
+ BinaryView *bin_view = (BinaryView *)parent();
painter->save();
- // TODO: highlight signal cells on mouse over
- painter->fillRect(option.rect, option.state & QStyle::State_Selected ? highlight_color : item->bg_color);
+
+ // background
+ QColor bg_color = item->sig && bin_view->hoveredSignal() == item->sig ? hoverColor(item->bg_color) : item->bg_color;
+ if (option.state & QStyle::State_Selected) {
+ bg_color = highlight_color;
+ }
+ painter->fillRect(option.rect, bg_color);
+
+ // text
if (index.column() == 8) {
- painter->setFont(bold_font);
+ painter->setFont(hex_font);
}
painter->drawText(option.rect, Qt::AlignCenter, item->val);
if (item->is_msb || item->is_lsb) {
diff --git a/tools/cabana/binaryview.h b/tools/cabana/binaryview.h
index 631797ca48..48eb5eff8a 100644
--- a/tools/cabana/binaryview.h
+++ b/tools/cabana/binaryview.h
@@ -14,7 +14,7 @@ public:
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
private:
- QFont small_font, bold_font;
+ QFont small_font, hex_font;
QColor highlight_color;
};
@@ -37,6 +37,7 @@ public:
bool is_msb = false;
bool is_lsb = false;
QString val = "0";
+ const Signal *sig = nullptr;
};
private:
@@ -59,14 +60,21 @@ class BinaryView : public QTableView {
public:
BinaryView(QWidget *parent = nullptr);
- void mouseReleaseEvent(QMouseEvent *event) override;
void setMessage(const QString &message_id);
void updateState();
+ void highlight(const Signal *sig);
+ const Signal *hoveredSignal() const { return hovered_sig; }
signals:
void cellsSelected(int start_bit, int size);
+ void signalHovered(const Signal *sig);
private:
+ void mouseMoveEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
+ void leaveEvent(QEvent *event) override;
+
QString msg_id;
BinaryViewModel *model;
+ const Signal *hovered_sig = nullptr;
};
diff --git a/tools/cabana/canmessages.cc b/tools/cabana/canmessages.cc
index 252a8c680c..897381b3f2 100644
--- a/tools/cabana/canmessages.cc
+++ b/tools/cabana/canmessages.cc
@@ -3,6 +3,8 @@
#include
#include
+#include "tools/cabana/dbcmanager.h"
+
Q_DECLARE_METATYPE(std::vector);
Settings settings;
@@ -38,6 +40,33 @@ bool CANMessages::loadRoute(const QString &route, const QString &data_dir, bool
return false;
}
+QList CANMessages::findSignalValues(const QString &id, const Signal *signal, double value, FindFlags flag, int max_count) {
+ auto evts = events();
+ if (!evts) return {};
+
+ auto l = id.split(':');
+ int bus = l[0].toInt();
+ uint32_t address = l[1].toUInt(nullptr, 16);
+
+ QList ret;
+ ret.reserve(max_count);
+ for (auto &evt : *evts) {
+ if (evt->which != cereal::Event::Which::CAN) continue;
+
+ for (auto c : evt->event.getCan()) {
+ if (bus == c.getSrc() && address == c.getAddress()) {
+ double val = get_raw_value((uint8_t *)c.getDat().begin(), c.getDat().size(), *signal);
+ if ((flag == EQ && val == value) || (flag == LT && val < value) || (flag == GT && val > value)) {
+ ret.push_back({(evt->mono_time / (double)1e9) - can->routeStartTime(), val});
+ }
+ if (ret.size() >= max_count)
+ return ret;
+ }
+ }
+ }
+ return ret;
+}
+
void CANMessages::process(QHash> *messages) {
for (auto it = messages->begin(); it != messages->end(); ++it) {
++counters[it.key()];
diff --git a/tools/cabana/canmessages.h b/tools/cabana/canmessages.h
index 58f5ad70b7..a468fb2956 100644
--- a/tools/cabana/canmessages.h
+++ b/tools/cabana/canmessages.h
@@ -4,8 +4,11 @@
#include
#include