diff --git a/.github/workflows/selfdrive_tests.yaml b/.github/workflows/selfdrive_tests.yaml
index e921cd3d00..598f2c592b 100644
--- a/.github/workflows/selfdrive_tests.yaml
+++ b/.github/workflows/selfdrive_tests.yaml
@@ -232,6 +232,7 @@ jobs:
./selfdrive/loggerd/tests/test_logger &&\
./system/proclogd/tests/test_proclog && \
./tools/replay/tests/test_replay && \
+ ./tools/cabana/tests/test_cabana && \
./system/camerad/test/ae_gray_test && \
coverage xml"
- name: "Upload coverage to Codecov"
diff --git a/RELEASES.md b/RELEASES.md
index b424259581..744168c8fb 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -6,6 +6,7 @@ Version 0.8.17 (2022-XX-XX)
* New end-to-end distracted trigger
* Self-tuning torque lateral controller parameters
* Parameters learned live for each car
+* Torque controller used on all Toyota, Lexus, Hyundai, Kia, and Genesis models
* UI updates
* Multi-language in navigation
* Matched speeds shown on car's dash
diff --git a/cereal b/cereal
index 38133307b2..1d25fc3f20 160000
--- a/cereal
+++ b/cereal
@@ -1 +1 @@
-Subproject commit 38133307b2e6036e76684b39878e79212e545e06
+Subproject commit 1d25fc3f202d5ddeee97848480323e9b14f9bdfa
diff --git a/docs/CARS.md b/docs/CARS.md
index a03da5ca6a..2df2b96e24 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.
-# 209 Supported Cars
+# 211 Supported Cars
|Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|Harness|
|---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|
@@ -55,8 +55,10 @@ A supported vehicle is one that just works when you install a comma three. All s
|Honda|Ridgeline 2017-22|Honda Sensing|openpilot|25 mph|12 mph|[](##)|[](##)|Honda Nidec|
|Hyundai|Elantra 2017-19|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|Hyundai B|
|Hyundai|Elantra 2021-22|Smart Cruise Control (SCC)|openpilot|0 mph|0 mph|[](##)|[](##)|Hyundai K|
+|Hyundai|Elantra GT 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|Hyundai E|
|Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|openpilot|0 mph|0 mph|[](##)|[](##)|Hyundai K|
|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[](##)|[](##)|Hyundai J|
+|Hyundai|i30 2019|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|Hyundai E|
|Hyundai|Ioniq 5 (with HDA II) 2022|Highway Driving Assist II|Stock|0 mph|0 mph|[](##)|[](##)|Hyundai Q|
|Hyundai|Ioniq 5 (without HDA II) 2022|Highway Driving Assist|Stock|0 mph|0 mph|[](##)|[](##)|Hyundai K|
|Hyundai|Ioniq Electric 2019|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|Hyundai C|
@@ -120,7 +122,7 @@ A supported vehicle is one that just works when you install a comma three. All s
|Lexus|RX Hybrid 2017-19|All|Stock[3](#footnotes)|0 mph|0 mph|[](##)|[](##)|Toyota|
|Lexus|RX Hybrid 2020-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|Toyota|
|Lexus|UX Hybrid 2019-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|Toyota|
-|Mazda|CX-5 2022|All|Stock|0 mph|0 mph|[](##)|[](##)|Mazda|
+|Mazda|CX-5 2022-23|All|Stock|0 mph|0 mph|[](##)|[](##)|Mazda|
|Mazda|CX-9 2021-22|All|Stock|0 mph|28 mph|[](##)|[](##)|Mazda|
|Nissan|Altima 2019-20|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|Nissan B|
|Nissan|Leaf 2018-22|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|Nissan A|
diff --git a/opendbc b/opendbc
index 7bd94e3ff4..b3dc569994 160000
--- a/opendbc
+++ b/opendbc
@@ -1 +1 @@
-Subproject commit 7bd94e3ff4a2890eb69118f0dfadb64f9d32d618
+Subproject commit b3dc569994fd10e4de04afd650980c51ddfce5e1
diff --git a/panda b/panda
index 2db69bc941..187fdee385 160000
--- a/panda
+++ b/panda
@@ -1 +1 @@
-Subproject commit 2db69bc94120a3c10f39cdedc9d83315f9ba801e
+Subproject commit 187fdee385e59a2a19f85760f529e8e381845dff
diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py
index 7b3140fbbf..5114f8d065 100644
--- a/selfdrive/car/ford/values.py
+++ b/selfdrive/car/ford/values.py
@@ -61,10 +61,10 @@ class FordCarInfo(CarInfo):
CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = {
CAR.ESCAPE_MK4: [
- FordCarInfo("Ford Escape 2020"),
- FordCarInfo("Ford Kuga EU", "Driver Assistance Pack"),
+ FordCarInfo("Ford Escape 2020-21"),
+ FordCarInfo("Ford Kuga 2020-21", "Driver Assistance Pack"),
],
- CAR.EXPLORER_MK6: FordCarInfo("Ford Explorer 2020-21"),
+ CAR.EXPLORER_MK6: FordCarInfo("Ford Explorer 2020-22"),
CAR.FOCUS_MK4: FordCarInfo("Ford Focus EU 2019", "Driver Assistance Pack"),
}
@@ -87,31 +87,41 @@ FW_QUERY_CONFIG = FwQueryConfig(
FW_VERSIONS = {
CAR.ESCAPE_MK4: {
(Ecu.eps, 0x730, None): [
+ b'LX6C-14D003-AF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
b'LX6C-14D003-AH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
],
(Ecu.abs, 0x760, None): [
b'LX6C-2D053-NS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'LX6C-2D053-NY\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'LX6C-2D053-SA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
],
(Ecu.fwdRadar, 0x764, None): [
b'LB5T-14D049-AB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
],
(Ecu.fwdCamera, 0x706, None): [
b'LJ6T-14F397-AD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'LJ6T-14F397-AE\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
],
(Ecu.engine, 0x7E0, None): [
+ b'LX6A-14C204-BJV\x00\x00\x00\x00\x00\x00\x00\x00\x00',
b'LX6A-14C204-ESG\x00\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'MX6A-14C204-BEF\x00\x00\x00\x00\x00\x00\x00\x00\x00',
],
(Ecu.shiftByWire, 0x732, None): [
+ b'LX6P-14G395-AB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'LX6P-14G395-AD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
],
},
CAR.EXPLORER_MK6: {
(Ecu.eps, 0x730, None): [
b'L1MC-14D003-AK\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
b'L1MC-14D003-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'M1MC-14D003-AB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
],
(Ecu.abs, 0x760, None): [
b'L1MC-2D053-BB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
b'L1MC-2D053-BF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'L1MC-2D053-KB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
],
(Ecu.fwdRadar, 0x764, None): [
b'LB5T-14D049-AB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
@@ -123,10 +133,12 @@ FW_VERSIONS = {
(Ecu.engine, 0x7E0, None): [
b'LB5A-14C204-EAC\x00\x00\x00\x00\x00\x00\x00\x00\x00',
b'MB5A-14C204-MD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'NB5A-14C204-HB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
],
(Ecu.shiftByWire, 0x732, None): [
b'L1MP-14G395-AD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
b'L1MP-14G395-AE\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'L1MP-14G395-JB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
],
},
CAR.FOCUS_MK4: {
diff --git a/selfdrive/car/gm/carcontroller.py b/selfdrive/car/gm/carcontroller.py
index b56b3bfca6..a75eb89f25 100644
--- a/selfdrive/car/gm/carcontroller.py
+++ b/selfdrive/car/gm/carcontroller.py
@@ -22,6 +22,7 @@ class CarController:
self.apply_gas = 0
self.apply_brake = 0
self.frame = 0
+ self.last_steer_frame = 0
self.last_button_frame = 0
self.cancel_counter = 0
@@ -46,15 +47,21 @@ class CarController:
# Send CAN commands.
can_sends = []
- # Steering (50Hz)
+ # Steering (Active: 50Hz, inactive: 10Hz)
+ # Attempt to sync with camera on startup at 50Hz, first few msgs are blocked
+ init_lka_counter = not self.sent_lka_steering_cmd and self.CP.networkLocation == NetworkLocation.fwdCamera
+ steer_step = self.params.INACTIVE_STEER_STEP
+ if CC.latActive or init_lka_counter:
+ steer_step = self.params.ACTIVE_STEER_STEP
+
# Avoid GM EPS faults when transmitting messages too close together: skip this transmit if we just received the
# next Panda loopback confirmation in the current CS frame.
if CS.loopback_lka_steering_cmd_updated:
self.lka_steering_cmd_counter += 1
self.sent_lka_steering_cmd = True
- elif (self.frame % self.params.STEER_STEP) == 0:
- # Initialize ASCMLKASteeringCmd counter using the camera
- if not self.sent_lka_steering_cmd and self.CP.networkLocation == NetworkLocation.fwdCamera:
+ elif (self.frame - self.last_steer_frame) >= steer_step:
+ # Initialize ASCMLKASteeringCmd counter using the camera until we get a msg on the bus
+ if init_lka_counter:
self.lka_steering_cmd_counter = CS.camera_lka_steering_cmd_counter + 1
if CC.latActive:
@@ -63,6 +70,7 @@ class CarController:
else:
apply_steer = 0
+ self.last_steer_frame = self.frame
self.apply_steer_last = apply_steer
idx = self.lka_steering_cmd_counter % 4
can_sends.append(gmcan.create_steering_control(self.packer_pt, CanBus.POWERTRAIN, apply_steer, idx, CC.latActive))
diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py
index f8f9e7f043..85e291aaf6 100644
--- a/selfdrive/car/gm/values.py
+++ b/selfdrive/car/gm/values.py
@@ -11,7 +11,8 @@ Ecu = car.CarParams.Ecu
class CarControllerParams:
STEER_MAX = 300 # GM limit is 3Nm. Used by carcontroller to generate LKA output
- STEER_STEP = 2 # Control frames per command (50hz)
+ ACTIVE_STEER_STEP = 2 # Active control frames per command (50hz)
+ INACTIVE_STEER_STEP = 10 # Inactive control frames per command (10hz)
STEER_DELTA_UP = 7 # Delta rates require review due to observed EPS weakness
STEER_DELTA_DOWN = 17
STEER_DRIVER_ALLOWANCE = 50
diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py
index c884f586a0..e397f02838 100755
--- a/selfdrive/car/honda/interface.py
+++ b/selfdrive/car/honda/interface.py
@@ -220,23 +220,17 @@ class CarInterface(CarInterfaceBase):
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2], [0.06]]
tire_stiffness_factor = 0.677
- elif candidate == CAR.ODYSSEY:
- ret.mass = 4471. * CV.LB_TO_KG + STD_CARGO_KG
+ elif candidate in (CAR.ODYSSEY, CAR.ODYSSEY_CHN):
+ ret.mass = 1900. + STD_CARGO_KG
ret.wheelbase = 3.00
ret.centerToFront = ret.wheelbase * 0.41
ret.steerRatio = 14.35 # as spec
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
- tire_stiffness_factor = 0.82
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.28], [0.08]]
-
- elif candidate == CAR.ODYSSEY_CHN:
- ret.mass = 1849.2 + STD_CARGO_KG # mean of 4 models in kg
- ret.wheelbase = 2.90
- ret.centerToFront = ret.wheelbase * 0.41 # from CAR.ODYSSEY
- ret.steerRatio = 14.35
- ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 32767], [0, 32767]] # TODO: determine if there is a dead zone at the top end
tire_stiffness_factor = 0.82
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.28], [0.08]]
+ if candidate == CAR.ODYSSEY_CHN:
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 32767], [0, 32767]] # TODO: determine if there is a dead zone at the top end
+ else:
+ ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end
elif candidate in (CAR.PILOT, CAR.PASSPORT):
ret.mass = 4204. * CV.LB_TO_KG + STD_CARGO_KG # average weight
diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py
index 638008934a..2510f2e1ff 100644
--- a/selfdrive/car/honda/values.py
+++ b/selfdrive/car/honda/values.py
@@ -446,7 +446,7 @@ FW_VERSIONS = {
b'78109-TED-Q510\x00\x00',
b'78109-TEG-A310\x00\x00',
],
- (Ecu.fwdCamera, 0x18dab0f1, None): [
+ (Ecu.fwdRadar, 0x18dab0f1, None): [
b'36161-TBA-A020\x00\x00',
b'36161-TBA-A030\x00\x00',
b'36161-TBA-A040\x00\x00',
@@ -964,7 +964,7 @@ FW_VERSIONS = {
b'77959-THR-A110\x00\x00',
b'77959-THR-X010\x00\x00',
],
- (Ecu.fwdCamera, 0x18dab0f1, None): [
+ (Ecu.fwdRadar, 0x18dab0f1, None): [
b'36161-THR-A020\x00\x00',
b'36161-THR-A030\x00\x00',
b'36161-THR-A110\x00\x00',
@@ -1031,6 +1031,23 @@ FW_VERSIONS = {
b'54008-THR-A020\x00\x00',
],
},
+ CAR.ODYSSEY_CHN: {
+ (Ecu.eps, 0x18da30f1, None): [
+ b'39990-T6D-H220\x00\x00',
+ ],
+ (Ecu.gateway, 0x18daeff1, None): [
+ b'38897-T6A-J010\x00\x00',
+ ],
+ (Ecu.combinationMeter, 0x18da60f1, None): [
+ b'78109-T6A-F310\x00\x00',
+ ],
+ (Ecu.fwdRadar, 0x18dab0f1, None): [
+ b'36161-T6A-P040\x00\x00',
+ ],
+ (Ecu.srs, 0x18da53f1, None): [
+ b'77959-T6A-P110\x00\x00',
+ ],
+ },
CAR.PILOT: {
(Ecu.shiftByWire, 0x18da0bf1, None): [
b'54008-TG7-A520\x00\x00',
@@ -1068,7 +1085,7 @@ FW_VERSIONS = {
b'39990-TG7-A070\x00\x00',
b'39990-TGS-A230\x00\x00',
],
- (Ecu.fwdCamera, 0x18dab0f1, None): [
+ (Ecu.fwdRadar, 0x18dab0f1, None): [
b'36161-TG7-A310\x00\x00',
b'36161-TG7-A520\x00\x00',
b'36161-TG7-A630\x00\x00',
@@ -1176,7 +1193,7 @@ FW_VERSIONS = {
b'57114-TX5-A220\x00\x00',
b'57114-TX4-A220\x00\x00',
],
- (Ecu.fwdCamera, 0x18dab0f1, None): [
+ (Ecu.fwdRadar, 0x18dab0f1, None): [
b'36161-TX5-A030\x00\x00',
b'36161-TX4-A030\x00\x00',
],
@@ -1273,7 +1290,7 @@ FW_VERSIONS = {
b'39990-T6Z-A030\x00\x00',
b'39990-T6Z-A050\x00\x00',
],
- (Ecu.fwdCamera, 0x18dab0f1, None): [
+ (Ecu.fwdRadar, 0x18dab0f1, None): [
b'36161-T6Z-A020\x00\x00',
b'36161-T6Z-A310\x00\x00',
b'36161-T6Z-A420\x00\x00',
diff --git a/selfdrive/car/hyundai/carcontroller.py b/selfdrive/car/hyundai/carcontroller.py
index 913f683e2c..2f944edc0f 100644
--- a/selfdrive/car/hyundai/carcontroller.py
+++ b/selfdrive/car/hyundai/carcontroller.py
@@ -49,6 +49,7 @@ class CarController:
self.angle_limit_counter = 0
self.frame = 0
+ self.accel_last = 0
self.apply_steer_last = 0
self.car_fingerprint = CP.carFingerprint
self.last_button_frame = 0
@@ -123,8 +124,9 @@ class CarController:
if self.CP.openpilotLongitudinalControl:
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.frame))
if self.frame % 2 == 0:
- can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CP, CC.enabled, accel, stopping, CC.cruiseControl.override,
+ can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CP, CC.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
set_speed_in_units))
+ self.accel_last = accel
else:
# button presses
if (self.frame - self.last_button_frame) * DT_CTRL > 0.25:
diff --git a/selfdrive/car/hyundai/carstate.py b/selfdrive/car/hyundai/carstate.py
index e27432e23b..3cce581868 100644
--- a/selfdrive/car/hyundai/carstate.py
+++ b/selfdrive/car/hyundai/carstate.py
@@ -187,16 +187,19 @@ class CarState(CarStateBase):
ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, cp.vl["BLINKERS"]["LEFT_LAMP"],
cp.vl["BLINKERS"]["RIGHT_LAMP"])
+ if self.CP.enableBsm:
+ ret.leftBlindspot = cp.vl["BLINDSPOTS_REAR_CORNERS"]["FL_INDICATOR"] != 0
+ ret.rightBlindspot = cp.vl["BLINDSPOTS_REAR_CORNERS"]["FR_INDICATOR"] != 0
ret.cruiseState.available = True
self.is_metric = cp.vl["CLUSTER_INFO"]["DISTANCE_UNIT"] != 1
if not self.CP.openpilotLongitudinalControl:
speed_factor = CV.KPH_TO_MS if self.is_metric else CV.MPH_TO_MS
cp_cruise_info = cp if self.CP.flags & HyundaiFlags.CANFD_HDA2 else cp_cam
- ret.cruiseState.speed = cp_cruise_info.vl["CRUISE_INFO"]["SET_SPEED"] * speed_factor
- ret.cruiseState.standstill = cp_cruise_info.vl["CRUISE_INFO"]["CRUISE_STANDSTILL"] == 1
- ret.cruiseState.enabled = cp_cruise_info.vl["CRUISE_INFO"]["CRUISE_STATUS"] != 0
- self.cruise_info = copy.copy(cp_cruise_info.vl["CRUISE_INFO"])
+ ret.cruiseState.speed = cp_cruise_info.vl["SCC_CONTROL"]["VSetDis"] * speed_factor
+ ret.cruiseState.standstill = cp_cruise_info.vl["SCC_CONTROL"]["CRUISE_STANDSTILL"] == 1
+ ret.cruiseState.enabled = cp_cruise_info.vl["SCC_CONTROL"]["ACCMode"] in (1, 2)
+ self.cruise_info = copy.copy(cp_cruise_info.vl["SCC_CONTROL"])
cruise_btn_msg = "CRUISE_BUTTONS_ALT" if self.CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS else "CRUISE_BUTTONS"
self.prev_cruise_buttons = self.cruise_buttons[-1]
@@ -450,14 +453,23 @@ class CarState(CarStateBase):
("DOORS_SEATBELTS", 4),
]
+ if CP.enableBsm:
+ signals += [
+ ("FL_INDICATOR", "BLINDSPOTS_REAR_CORNERS"),
+ ("FR_INDICATOR", "BLINDSPOTS_REAR_CORNERS"),
+ ]
+ checks += [
+ ("BLINDSPOTS_REAR_CORNERS", 20),
+ ]
+
if CP.flags & HyundaiFlags.CANFD_HDA2 and not CP.openpilotLongitudinalControl:
signals += [
- ("CRUISE_STATUS", "CRUISE_INFO"),
- ("SET_SPEED", "CRUISE_INFO"),
- ("CRUISE_STANDSTILL", "CRUISE_INFO"),
+ ("ACCMode", "SCC_CONTROL"),
+ ("VSetDis", "SCC_CONTROL"),
+ ("CRUISE_STANDSTILL", "SCC_CONTROL"),
]
checks += [
- ("CRUISE_INFO", 50),
+ ("SCC_CONTROL", 50),
]
if CP.carFingerprint in EV_CAR:
@@ -485,21 +497,20 @@ class CarState(CarStateBase):
checks = [("CAM_0x2a4", 20)]
else:
signals = [
- ("COUNTER", "CRUISE_INFO"),
- ("NEW_SIGNAL_1", "CRUISE_INFO"),
- ("CRUISE_MAIN", "CRUISE_INFO"),
- ("CRUISE_STATUS", "CRUISE_INFO"),
- ("CRUISE_INACTIVE", "CRUISE_INFO"),
- ("ZEROS_9", "CRUISE_INFO"),
- ("CRUISE_STANDSTILL", "CRUISE_INFO"),
- ("ZEROS_5", "CRUISE_INFO"),
- ("DISTANCE_SETTING", "CRUISE_INFO"),
- ("SET_SPEED", "CRUISE_INFO"),
- ("NEW_SIGNAL_4", "CRUISE_INFO"),
+ ("COUNTER", "SCC_CONTROL"),
+ ("NEW_SIGNAL_1", "SCC_CONTROL"),
+ ("MainMode_ACC", "SCC_CONTROL"),
+ ("ACCMode", "SCC_CONTROL"),
+ ("CRUISE_INACTIVE", "SCC_CONTROL"),
+ ("ZEROS_9", "SCC_CONTROL"),
+ ("CRUISE_STANDSTILL", "SCC_CONTROL"),
+ ("ZEROS_5", "SCC_CONTROL"),
+ ("DISTANCE_SETTING", "SCC_CONTROL"),
+ ("VSetDis", "SCC_CONTROL"),
]
checks = [
- ("CRUISE_INFO", 50),
+ ("SCC_CONTROL", 50),
]
return CANParser(DBC[CP.carFingerprint]["pt"], signals, checks, 6)
diff --git a/selfdrive/car/hyundai/hyundaicanfd.py b/selfdrive/car/hyundai/hyundaicanfd.py
index e1478e6f18..8b53e7c378 100644
--- a/selfdrive/car/hyundai/hyundaicanfd.py
+++ b/selfdrive/car/hyundai/hyundaicanfd.py
@@ -1,3 +1,4 @@
+from common.numpy_fast import clip
from selfdrive.car.hyundai.values import HyundaiFlags
@@ -52,10 +53,9 @@ def create_buttons(packer, CP, cnt, btn):
def create_acc_cancel(packer, CP, cruise_info_copy):
values = cruise_info_copy
values.update({
- "CRUISE_STATUS": 0,
- "CRUISE_INACTIVE": 1,
+ "ACCMode": 4,
})
- return packer.make_can_msg("CRUISE_INFO", get_e_can_bus(CP), values)
+ return packer.make_can_msg("SCC_CONTROL", get_e_can_bus(CP), values)
def create_lfahda_cluster(packer, CP, enabled):
values = {
@@ -65,33 +65,37 @@ def create_lfahda_cluster(packer, CP, enabled):
return packer.make_can_msg("LFAHDA_CLUSTER", get_e_can_bus(CP), values)
-def create_acc_control(packer, CP, enabled, accel, stopping, gas_override, set_speed):
- cruise_status = 0 if not enabled else (4 if gas_override else 2)
+def create_acc_control(packer, CP, enabled, accel_last, accel, stopping, gas_override, set_speed):
+ jerk = 5
+ jn = jerk / 50
if not enabled or gas_override:
- accel = 0
+ a_val, a_raw = 0, 0
+ else:
+ a_raw = accel
+ a_val = clip(accel, accel_last - jn, accel_last + jn)
+ if stopping:
+ a_raw = 0
+
values = {
- "CRUISE_STATUS": cruise_status,
- "CRUISE_INACTIVE": 0 if enabled else 1,
- "CRUISE_MAIN": 1,
- "CRUISE_STANDSTILL": 0,
- "STOP_REQ": 1 if stopping else 0,
- "ACCEL_REQ": accel,
- "ACCEL_REQ2": accel,
- "SET_SPEED": set_speed,
- "DISTANCE_SETTING": 4,
+ "ACCMode": 0 if not enabled else (2 if gas_override else 1),
+ "MainMode_ACC": 1,
+ "StopReq": 1 if stopping else 0,
+ "aReqValue": a_val,
+ "aReqRaw": a_raw,
+ "VSetDis": set_speed,
+ "JerkLowerLimit": jerk if enabled else 1,
"ACC_ObjDist": 1,
- "ObjValid": 1,
+ "ObjValid": 0,
"OBJ_STATUS": 2,
- "SET_ME_2": 0x2,
+ "SET_ME_2": 0x4,
"SET_ME_3": 0x3,
"SET_ME_TMP_64": 0x64,
-
- "NEW_SIGNAL_9": 2,
"NEW_SIGNAL_10": 4,
+ "DISTANCE_SETTING": 4,
}
- return packer.make_can_msg("CRUISE_INFO", get_e_can_bus(CP), values)
+ return packer.make_can_msg("SCC_CONTROL", get_e_can_bus(CP), values)
diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py
index b1fa8d9e1d..4b4d51f3f1 100644
--- a/selfdrive/car/hyundai/interface.py
+++ b/selfdrive/car/hyundai/interface.py
@@ -31,7 +31,7 @@ class CarInterface(CarInterfaceBase):
# 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
# added to selfdrive/car/tests/routes.py, we can remove it from this list.
- ret.dashcamOnly = candidate in {CAR.KIA_OPTIMA_H, CAR.ELANTRA_GT_I30}
+ ret.dashcamOnly = candidate in {CAR.KIA_OPTIMA_H, }
if candidate in CANFD_CAR:
# detect HDA2 with ADAS Driving ECU
@@ -45,141 +45,92 @@ class CarInterface(CarInterfaceBase):
ret.steerActuatorDelay = 0.1 # Default delay
ret.steerLimitTimer = 0.4
tire_stiffness_factor = 1.
+ CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
if candidate in (CAR.SANTA_FE, CAR.SANTA_FE_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022):
- ret.lateralTuning.pid.kf = 0.00005
ret.mass = 3982. * CV.LB_TO_KG + STD_CARGO_KG
ret.wheelbase = 2.766
# Values from optimizer
ret.steerRatio = 16.55 # 13.8 is spec end-to-end
tire_stiffness_factor = 0.82
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[9., 22.], [9., 22.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2, 0.35], [0.05, 0.09]]
elif candidate in (CAR.SONATA, CAR.SONATA_HYBRID):
ret.mass = 1513. + STD_CARGO_KG
ret.wheelbase = 2.84
ret.steerRatio = 13.27 * 1.15 # 15% higher at the center seems reasonable
tire_stiffness_factor = 0.65
- CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
elif candidate == CAR.SONATA_LF:
- ret.lateralTuning.pid.kf = 0.00005
ret.mass = 4497. * CV.LB_TO_KG
ret.wheelbase = 2.804
ret.steerRatio = 13.27 * 1.15 # 15% higher at the center seems reasonable
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
elif candidate == CAR.PALISADE:
- ret.lateralTuning.pid.kf = 0.00005
ret.mass = 1999. + STD_CARGO_KG
ret.wheelbase = 2.90
ret.steerRatio = 15.6 * 1.15
tire_stiffness_factor = 0.63
- CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
- elif candidate in (CAR.ELANTRA, CAR.ELANTRA_GT_I30):
- ret.lateralTuning.pid.kf = 0.00006
+ elif candidate == CAR.ELANTRA:
ret.mass = 1275. + STD_CARGO_KG
ret.wheelbase = 2.7
ret.steerRatio = 15.4 # 14 is Stock | Settled Params Learner values are steerRatio: 15.401566348670535
tire_stiffness_factor = 0.385 # stiffnessFactor settled on 1.0081302973865127
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
ret.minSteerSpeed = 32 * CV.MPH_TO_MS
elif candidate == CAR.ELANTRA_2021:
ret.mass = (2800. * CV.LB_TO_KG) + STD_CARGO_KG
ret.wheelbase = 2.72
ret.steerRatio = 12.9
tire_stiffness_factor = 0.65
- CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
elif candidate == CAR.ELANTRA_HEV_2021:
ret.mass = (3017. * CV.LB_TO_KG) + STD_CARGO_KG
ret.wheelbase = 2.72
ret.steerRatio = 12.9
tire_stiffness_factor = 0.65
- CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
elif candidate == CAR.HYUNDAI_GENESIS:
- ret.lateralTuning.pid.kf = 0.00005
ret.mass = 2060. + STD_CARGO_KG
ret.wheelbase = 3.01
ret.steerRatio = 16.5
- ret.lateralTuning.init('indi')
- ret.lateralTuning.indi.innerLoopGainBP = [0.]
- ret.lateralTuning.indi.innerLoopGainV = [3.5]
- ret.lateralTuning.indi.outerLoopGainBP = [0.]
- ret.lateralTuning.indi.outerLoopGainV = [2.0]
- ret.lateralTuning.indi.timeConstantBP = [0.]
- ret.lateralTuning.indi.timeConstantV = [1.4]
- ret.lateralTuning.indi.actuatorEffectivenessBP = [0.]
- ret.lateralTuning.indi.actuatorEffectivenessV = [2.3]
ret.minSteerSpeed = 60 * CV.KPH_TO_MS
elif candidate in (CAR.KONA, CAR.KONA_EV, CAR.KONA_HEV, CAR.KONA_EV_2022):
ret.mass = {CAR.KONA_EV: 1685., CAR.KONA_HEV: 1425., CAR.KONA_EV_2022: 1743.}.get(candidate, 1275.) + STD_CARGO_KG
ret.wheelbase = 2.6
ret.steerRatio = 13.42 # Spec
tire_stiffness_factor = 0.385
- CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
elif candidate in (CAR.IONIQ, CAR.IONIQ_EV_LTD, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.IONIQ_HEV_2022):
- ret.lateralTuning.pid.kf = 0.00006
ret.mass = 1490. + STD_CARGO_KG # weight per hyundai site https://www.hyundaiusa.com/ioniq-electric/specifications.aspx
ret.wheelbase = 2.7
ret.steerRatio = 13.73 # Spec
tire_stiffness_factor = 0.385
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
if candidate not in (CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.IONIQ_HEV_2022):
ret.minSteerSpeed = 32 * CV.MPH_TO_MS
elif candidate == CAR.IONIQ_PHEV_2019:
ret.mass = 1550. + STD_CARGO_KG # weight per hyundai site https://www.hyundaiusa.com/us/en/vehicles/2019-ioniq-plug-in-hybrid/compare-specs
ret.wheelbase = 2.7
ret.steerRatio = 13.73
- ret.lateralTuning.init('indi')
- ret.lateralTuning.indi.innerLoopGainBP = [0.]
- ret.lateralTuning.indi.innerLoopGainV = [2.5]
- ret.lateralTuning.indi.outerLoopGainBP = [0.]
- ret.lateralTuning.indi.outerLoopGainV = [3.5]
- ret.lateralTuning.indi.timeConstantBP = [0.]
- ret.lateralTuning.indi.timeConstantV = [1.4]
- ret.lateralTuning.indi.actuatorEffectivenessBP = [0.]
- ret.lateralTuning.indi.actuatorEffectivenessV = [1.8]
ret.minSteerSpeed = 32 * CV.MPH_TO_MS
elif candidate == CAR.VELOSTER:
- ret.lateralTuning.pid.kf = 0.00005
ret.mass = 3558. * CV.LB_TO_KG
ret.wheelbase = 2.80
ret.steerRatio = 13.75 * 1.15
tire_stiffness_factor = 0.5
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
elif candidate == CAR.TUCSON:
- ret.lateralTuning.pid.kf = 0.00005
ret.mass = 3520. * CV.LB_TO_KG
ret.wheelbase = 2.67
ret.steerRatio = 14.00 * 1.15
tire_stiffness_factor = 0.385
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
elif candidate == CAR.TUCSON_HYBRID_4TH_GEN:
ret.mass = 1680. + STD_CARGO_KG # average of all 3 trims
ret.wheelbase = 2.756
ret.steerRatio = 16.
tire_stiffness_factor = 0.385
- CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
# Kia
elif candidate == CAR.KIA_SORENTO:
- ret.lateralTuning.pid.kf = 0.00005
ret.mass = 1985. + STD_CARGO_KG
ret.wheelbase = 2.78
ret.steerRatio = 14.4 * 1.1 # 10% higher at the center seems reasonable
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
elif candidate in (CAR.KIA_NIRO_EV, CAR.KIA_NIRO_PHEV, CAR.KIA_NIRO_HEV_2021):
- ret.lateralTuning.pid.kf = 0.00006
ret.mass = 1737. + STD_CARGO_KG
ret.wheelbase = 2.7
ret.steerRatio = 13.9 if CAR.KIA_NIRO_HEV_2021 else 13.73 # Spec
tire_stiffness_factor = 0.385
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
if candidate == CAR.KIA_NIRO_PHEV:
ret.minSteerSpeed = 32 * CV.MPH_TO_MS
elif candidate == CAR.KIA_SELTOS:
@@ -187,15 +138,6 @@ class CarInterface(CarInterfaceBase):
ret.wheelbase = 2.63
ret.steerRatio = 14.56
tire_stiffness_factor = 1
- ret.lateralTuning.init('indi')
- ret.lateralTuning.indi.innerLoopGainBP = [0.]
- ret.lateralTuning.indi.innerLoopGainV = [4.]
- ret.lateralTuning.indi.outerLoopGainBP = [0.]
- ret.lateralTuning.indi.outerLoopGainV = [3.]
- ret.lateralTuning.indi.timeConstantBP = [0.]
- ret.lateralTuning.indi.timeConstantV = [1.4]
- ret.lateralTuning.indi.actuatorEffectivenessBP = [0.]
- ret.lateralTuning.indi.actuatorEffectivenessV = [1.8]
elif candidate in (CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL, CAR.KIA_OPTIMA_H):
ret.mass = 3558. * CV.LB_TO_KG
ret.wheelbase = 2.80
@@ -203,105 +145,67 @@ class CarInterface(CarInterfaceBase):
tire_stiffness_factor = 0.5
if candidate == CAR.KIA_OPTIMA_G4:
ret.minSteerSpeed = 32 * CV.MPH_TO_MS
- CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
elif candidate == CAR.KIA_STINGER:
- ret.lateralTuning.pid.kf = 0.00005
ret.mass = 1825. + STD_CARGO_KG
ret.wheelbase = 2.78
ret.steerRatio = 14.4 * 1.15 # 15% higher at the center seems reasonable
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
elif candidate == CAR.KIA_FORTE:
- ret.lateralTuning.pid.kf = 0.00005
ret.mass = 3558. * CV.LB_TO_KG
ret.wheelbase = 2.80
ret.steerRatio = 13.75
tire_stiffness_factor = 0.5
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
elif candidate == CAR.KIA_CEED:
- ret.lateralTuning.pid.kf = 0.00005
ret.mass = 1450. + STD_CARGO_KG
ret.wheelbase = 2.65
ret.steerRatio = 13.75
tire_stiffness_factor = 0.5
- ret.lateralTuning.pid.kf = 0.00005
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
elif candidate == CAR.KIA_K5_2021:
- ret.lateralTuning.pid.kf = 0.00005
ret.mass = 3228. * CV.LB_TO_KG
ret.wheelbase = 2.85
ret.steerRatio = 13.27 # 2021 Kia K5 Steering Ratio (all trims)
tire_stiffness_factor = 0.5
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.25], [0.05]]
elif candidate == CAR.KIA_EV6:
ret.mass = 2055 + STD_CARGO_KG
ret.wheelbase = 2.9
ret.steerRatio = 16.
tire_stiffness_factor = 0.65
- CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
elif candidate == CAR.IONIQ_5:
ret.mass = 2012 + STD_CARGO_KG
ret.wheelbase = 3.0
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:
- ret.lateralTuning.init('indi')
- ret.lateralTuning.indi.innerLoopGainBP = [0.]
- ret.lateralTuning.indi.innerLoopGainV = [2.5]
- ret.lateralTuning.indi.outerLoopGainBP = [0.]
- ret.lateralTuning.indi.outerLoopGainV = [3.5]
- ret.lateralTuning.indi.timeConstantBP = [0.]
- ret.lateralTuning.indi.timeConstantV = [1.4]
- ret.lateralTuning.indi.actuatorEffectivenessBP = [0.]
- ret.lateralTuning.indi.actuatorEffectivenessV = [1.8]
ret.steerActuatorDelay = 0.1
ret.mass = 1640.0 + STD_CARGO_KG
ret.wheelbase = 2.84
ret.steerRatio = 13.56
elif candidate == CAR.GENESIS_G70_2020:
- ret.lateralTuning.pid.kf = 0.
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.112], [0.004]]
ret.mass = 3673.0 * CV.LB_TO_KG + STD_CARGO_KG
ret.wheelbase = 2.83
ret.steerRatio = 12.9
elif candidate == CAR.GENESIS_G80:
- ret.lateralTuning.pid.kf = 0.00005
ret.mass = 2060. + STD_CARGO_KG
ret.wheelbase = 3.01
ret.steerRatio = 16.5
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.16], [0.01]]
elif candidate == CAR.GENESIS_G90:
ret.mass = 2200
ret.wheelbase = 3.15
ret.steerRatio = 12.069
- ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
- ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.16], [0.01]]
# *** longitudinal control ***
if candidate in CANFD_CAR:
ret.longitudinalTuning.kpV = [0.1]
ret.longitudinalTuning.kiV = [0.0]
- ret.longitudinalActuatorDelayLowerBound = 0.15
- ret.longitudinalActuatorDelayUpperBound = 0.5
ret.experimentalLongitudinalAvailable = bool(ret.flags & HyundaiFlags.CANFD_HDA2)
else:
ret.longitudinalTuning.kpV = [0.5]
ret.longitudinalTuning.kiV = [0.0]
- ret.longitudinalActuatorDelayLowerBound = 0.5
- ret.longitudinalActuatorDelayUpperBound = 0.5
ret.experimentalLongitudinalAvailable = candidate not in (LEGACY_SAFETY_MODE_CAR | CAMERA_SCC_CAR)
ret.openpilotLongitudinalControl = experimental_long and ret.experimentalLongitudinalAvailable
ret.pcmCruise = not ret.openpilotLongitudinalControl
@@ -310,6 +214,15 @@ class CarInterface(CarInterfaceBase):
ret.startingState = True
ret.vEgoStarting = 0.1
ret.startAccel = 2.0
+ ret.longitudinalActuatorDelayLowerBound = 0.5
+ ret.longitudinalActuatorDelayUpperBound = 0.5
+
+ # *** feature detection ***
+ if candidate in CANFD_CAR:
+ bus = 5 if ret.flags & HyundaiFlags.CANFD_HDA2 else 4
+ ret.enableBsm = 0x1e5 in fingerprint[bus]
+ else:
+ ret.enableBsm = 0x58b in fingerprint[0]
# *** panda safety config ***
if candidate in CANFD_CAR:
@@ -321,8 +234,6 @@ class CarInterface(CarInterfaceBase):
if ret.flags & HyundaiFlags.CANFD_ALT_BUTTONS:
ret.safetyConfigs[1].safetyParam |= Panda.FLAG_HYUNDAI_CANFD_ALT_BUTTONS
else:
- ret.enableBsm = 0x58b in fingerprint[0]
-
if candidate in LEGACY_SAFETY_MODE_CAR:
# these cars require a special panda safety mode due to missing counters and checksums in the messages
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hyundaiLegacy)]
diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py
index 96c4201773..98cb72293f 100644
--- a/selfdrive/car/hyundai/values.py
+++ b/selfdrive/car/hyundai/values.py
@@ -34,7 +34,7 @@ class CarControllerParams:
# To determine the limit for your car, find the maximum value that the stock LKAS will request.
# 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,
+ elif CP.carFingerprint in (CAR.GENESIS_G80, CAR.GENESIS_G90, CAR.ELANTRA, CAR.HYUNDAI_GENESIS, 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):
self.STEER_MAX = 255
@@ -54,7 +54,6 @@ class CAR:
ELANTRA = "HYUNDAI ELANTRA 2017"
ELANTRA_2021 = "HYUNDAI ELANTRA 2021"
ELANTRA_HEV_2021 = "HYUNDAI ELANTRA HYBRID 2021"
- ELANTRA_GT_I30 = "HYUNDAI I30 N LINE 2019 & GT 2018 DCT"
HYUNDAI_GENESIS = "HYUNDAI GENESIS 2015-2016"
IONIQ = "HYUNDAI IONIQ HYBRID 2017-2019"
IONIQ_HEV_2022 = "HYUNDAI IONIQ HYBRID 2020-2022"
@@ -108,13 +107,13 @@ class HyundaiCarInfo(CarInfo):
CAR_INFO: Dict[str, Optional[Union[HyundaiCarInfo, List[HyundaiCarInfo]]]] = {
- CAR.ELANTRA: HyundaiCarInfo("Hyundai Elantra 2017-19", min_enable_speed=19 * CV.MPH_TO_MS, harness=Harness.hyundai_b),
- CAR.ELANTRA_2021: HyundaiCarInfo("Hyundai Elantra 2021-22", video_link="https://youtu.be/_EdYQtV52-c", harness=Harness.hyundai_k),
- CAR.ELANTRA_HEV_2021: HyundaiCarInfo("Hyundai Elantra Hybrid 2021-23", video_link="https://youtu.be/_EdYQtV52-c", harness=Harness.hyundai_k),
- CAR.ELANTRA_GT_I30: [
+ CAR.ELANTRA: [
+ HyundaiCarInfo("Hyundai Elantra 2017-19", min_enable_speed=19 * CV.MPH_TO_MS, harness=Harness.hyundai_b),
HyundaiCarInfo("Hyundai Elantra GT 2017-19", harness=Harness.hyundai_e),
HyundaiCarInfo("Hyundai i30 2019", harness=Harness.hyundai_e),
],
+ CAR.ELANTRA_2021: HyundaiCarInfo("Hyundai Elantra 2021-22", video_link="https://youtu.be/_EdYQtV52-c", harness=Harness.hyundai_k),
+ CAR.ELANTRA_HEV_2021: HyundaiCarInfo("Hyundai Elantra Hybrid 2021-23", video_link="https://youtu.be/_EdYQtV52-c", harness=Harness.hyundai_k),
CAR.HYUNDAI_GENESIS: HyundaiCarInfo("Hyundai Genesis 2015-16", min_enable_speed=19 * CV.MPH_TO_MS, harness=Harness.hyundai_j), # TODO: check 2015 packages
CAR.IONIQ: HyundaiCarInfo("Hyundai Ioniq Hybrid 2017-19", harness=Harness.hyundai_c),
CAR.IONIQ_HEV_2022: HyundaiCarInfo("Hyundai Ioniq Hybrid 2020-22", harness=Harness.hyundai_h), # TODO: confirm 2020-21 harness
@@ -199,15 +198,6 @@ FINGERPRINTS = {
CAR.ELANTRA: [{
66: 8, 67: 8, 68: 8, 127: 8, 273: 8, 274: 8, 275: 8, 339: 8, 356: 4, 399: 8, 512: 6, 544: 8, 593: 8, 608: 8, 688: 5, 790: 8, 809: 8, 897: 8, 832: 8, 899: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1170: 8, 1265: 4, 1280: 1, 1282: 4, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1314: 8, 1322: 8, 1345: 8, 1349: 8, 1351: 8, 1353: 8, 1363: 8, 1366: 8, 1367: 8, 1369: 8, 1407: 8, 1415: 8, 1419: 8, 1425: 2, 1427: 6, 1440: 8, 1456: 4, 1472: 8, 1486: 8, 1487: 8, 1491: 8, 1530: 8, 1532: 5, 2001: 8, 2003: 8, 2004: 8, 2009: 8, 2012: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8
}],
- CAR.ELANTRA_GT_I30: [{
- 66: 8, 67: 8, 68: 8, 127: 8, 128: 8, 129: 8, 273: 8, 274: 8, 275: 8, 339: 8, 354: 3, 356: 4, 399: 8, 512: 6, 544: 8, 593: 8, 608: 8, 688: 5, 790: 8, 809: 8, 884: 8, 897: 8, 899: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1151: 6, 1168: 7, 1170: 8, 1193: 8, 1265: 4, 1280: 1, 1282: 4, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1345: 8, 1348: 8, 1349: 8, 1351: 8, 1353: 8, 1356: 8, 1363: 8, 1365: 8, 1366: 8, 1367: 8, 1369: 8, 1407: 8, 1414: 3, 1415: 8, 1427: 6, 1440: 8, 1456: 4, 1470: 8, 1486: 8, 1487: 8, 1491: 8, 1530: 8, 1952: 8, 1960: 8, 1988: 8, 2000: 8, 2001: 8, 2005: 8, 2008: 8, 2009: 8, 2013: 8, 2017: 8, 2025: 8
- },
- {
- 66: 8, 67: 8, 68: 8, 127: 8, 128: 8, 129: 8, 273: 8, 274: 8, 275: 8, 339: 8, 354: 3, 356: 4, 399: 8, 512: 6, 544: 8, 593: 8, 608: 8, 688: 5, 790: 8, 809: 8, 832: 8, 897: 8, 899: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1151: 6, 1168: 7, 1170: 8, 1265: 4, 1280: 1, 1282: 4, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1349: 8, 1351: 8, 1353: 8, 1356: 8, 1363: 8, 1366: 8, 1367: 8, 1369: 8, 1407: 8, 1414: 3, 1415: 8, 1419: 8, 1440: 8, 1456: 4, 1470: 8, 1486: 8, 1487: 8, 1491: 8, 1530: 8
- },
- {
- 66: 8, 67: 8, 68: 8, 127: 8, 128: 8, 129: 8, 273: 8, 274: 8, 275: 8, 339: 8, 354: 3, 356: 4, 399: 8, 512: 6, 544: 8, 593: 8, 608: 8, 688: 5, 790: 8, 809: 8, 832: 8, 897: 8, 899: 8, 902: 8, 903: 8, 905: 8, 909: 8, 916: 8, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1151: 6, 1168: 7, 1170: 8, 1265: 4, 1280: 1, 1282: 4, 1287: 4, 1290: 8, 1292: 8, 1294: 8, 1312: 8, 1322: 8, 1342: 6, 1345: 8, 1348: 8, 1349: 8, 1351: 8, 1353: 8, 1356: 8, 1363: 8, 1366: 8, 1367: 8, 1369: 8, 1407: 8, 1414: 3, 1419: 8, 1427: 6, 1440: 8, 1456: 4, 1470: 8, 1486: 8, 1487: 8, 1491: 8, 1960: 8, 1990: 8, 1998: 8, 2000: 8, 2001: 8, 2004: 8, 2005: 8, 2008: 8, 2009: 8, 2012: 8, 2013: 8, 2015: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8
- }],
CAR.HYUNDAI_GENESIS: [{
67: 8, 68: 8, 304: 8, 320: 8, 339: 8, 356: 4, 544: 7, 593: 8, 608: 8, 688: 5, 809: 8, 832: 8, 854: 7, 870: 7, 871: 8, 872: 5, 897: 8, 902: 8, 903: 6, 916: 8, 1024: 2, 1040: 8, 1056: 8, 1057: 8, 1078: 4, 1107: 5, 1136: 8, 1151: 6, 1168: 7, 1170: 8, 1173: 8, 1184: 8, 1265: 4, 1280: 1, 1287: 4, 1292: 8, 1312: 8, 1322: 8, 1331: 8, 1332: 8, 1333: 8, 1334: 8, 1335: 8, 1342: 6, 1345: 8, 1363: 8, 1369: 8, 1370: 8, 1371: 8, 1378: 4, 1384: 5, 1407: 8, 1419: 8, 1427: 6, 1434: 2, 1456: 4
},
@@ -1214,6 +1204,23 @@ FW_VERSIONS = {
b'\xf1\x87\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf1\x816T6B8051\x00\x00\xf1\x006T6H0_C2\x00\x006T6B8051\x00\x00TJFSG24NH27\xa7\xc2\xb4',
],
},
+ CAR.ELANTRA: {
+ (Ecu.fwdCamera, 0x7c4, None): [
+ b'\xf1\x00PD LKAS AT USA LHD 1.01 1.01 95740-G3100 A54',
+ ],
+ (Ecu.transmission, 0x7e1, None): [
+ b'\xf1\x006U2V0_C2\x00\x006U2VA051\x00\x00DPD0H16NS0e\x0e\xcd\x8e',
+ ],
+ (Ecu.eps, 0x7d4, None): [
+ b'\xf1\x00PD MDPS C 1.00 1.04 56310/G3300 4PDDC104',
+ ],
+ (Ecu.abs, 0x7d1, None): [
+ b'\xf1\x00PD ESC \x0b 104\x18\t\x03 58920-G3350',
+ ],
+ (Ecu.fwdRadar, 0x7d0, None): [
+ b'\xf1\x00PD__ SCC F-CUP 1.00 1.00 96400-G3300 ',
+ ],
+ },
CAR.ELANTRA_2021: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00CN7_ SCC F-CUP 1.00 1.01 99110-AA000 ',
@@ -1372,6 +1379,7 @@ FW_VERSIONS = {
CAR.TUCSON_HYBRID_4TH_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N9240 14Q',
+ b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N9220 14K',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00NX4__ 1.00 1.00 99110-N9100 ',
@@ -1394,12 +1402,12 @@ CHECKSUM = {
FEATURES = {
# which message has the gear
- "use_cluster_gears": {CAR.ELANTRA, CAR.ELANTRA_GT_I30, CAR.KONA},
+ "use_cluster_gears": {CAR.ELANTRA, CAR.KONA},
"use_tcu_gears": {CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL, CAR.SONATA_LF, CAR.VELOSTER, CAR.TUCSON},
"use_elect_gears": {CAR.KIA_NIRO_EV, CAR.KIA_NIRO_PHEV, CAR.KIA_NIRO_HEV_2021, CAR.KIA_OPTIMA_H, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.IONIQ, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.IONIQ_PHEV_2019, CAR.KONA_EV_2022},
# these cars use the FCA11 message for the AEB and FCW signals, all others use SCC12
- "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},
+ "use_fca": {CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, 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, CAR.KIA_SPORTAGE_HYBRID_5TH_GEN}
@@ -1419,7 +1427,6 @@ DBC = {
CAR.ELANTRA: dbc_dict('hyundai_kia_generic', None),
CAR.ELANTRA_2021: dbc_dict('hyundai_kia_generic', None),
CAR.ELANTRA_HEV_2021: dbc_dict('hyundai_kia_generic', None),
- CAR.ELANTRA_GT_I30: dbc_dict('hyundai_kia_generic', None),
CAR.GENESIS_G70: dbc_dict('hyundai_kia_generic', None),
CAR.GENESIS_G70_2020: dbc_dict('hyundai_kia_generic', 'hyundai_kia_mando_front_radar_generated'),
CAR.GENESIS_G80: dbc_dict('hyundai_kia_generic', None),
diff --git a/selfdrive/car/mazda/values.py b/selfdrive/car/mazda/values.py
index 921dc7a634..129273efee 100644
--- a/selfdrive/car/mazda/values.py
+++ b/selfdrive/car/mazda/values.py
@@ -43,7 +43,7 @@ CAR_INFO: Dict[str, Union[MazdaCarInfo, List[MazdaCarInfo]]] = {
CAR.MAZDA3: MazdaCarInfo("Mazda 3 2017-18"),
CAR.MAZDA6: MazdaCarInfo("Mazda 6 2017-20"),
CAR.CX9_2021: MazdaCarInfo("Mazda CX-9 2021-22", video_link="https://youtu.be/dA3duO4a0O4"),
- CAR.CX5_2022: MazdaCarInfo("Mazda CX-5 2022"),
+ CAR.CX5_2022: MazdaCarInfo("Mazda CX-5 2022-23"),
}
@@ -89,6 +89,7 @@ FW_VERSIONS = {
],
(Ecu.fwdCamera, 0x706, None): [
b'GSH7-67XK2-S\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
+ b'GSH7-67XK2-T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
],
(Ecu.transmission, 0x7e1, None): [
b'PYB2-21PS1-H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
diff --git a/selfdrive/car/tests/routes.py b/selfdrive/car/tests/routes.py
index 8c4efe3061..5c6d214bcc 100644
--- a/selfdrive/car/tests/routes.py
+++ b/selfdrive/car/tests/routes.py
@@ -23,9 +23,9 @@ non_tested_cars = [
GM.MALIBU,
GM.EQUINOX,
GM.BOLT_EV,
- HYUNDAI.ELANTRA_GT_I30,
HYUNDAI.GENESIS_G90,
HYUNDAI.KIA_OPTIMA_H,
+ HONDA.ODYSSEY_CHN,
]
CarTestRoute = namedtuple('CarTestRoute', ['route', 'car_model', 'segment'], defaults=(None,))
@@ -62,7 +62,6 @@ routes = [
CarTestRoute("2c4292a5cd10536c|2021-08-19--21-32-15", HONDA.FREED),
CarTestRoute("03be5f2fd5c508d1|2020-04-19--18-44-15", HONDA.HRV),
CarTestRoute("917b074700869333|2021-05-24--20-40-20", HONDA.ACURA_ILX),
- CarTestRoute("81722949a62ea724|2019-04-06--15-19-25", HONDA.ODYSSEY_CHN),
CarTestRoute("08a3deb07573f157|2020-03-06--16-11-19", HONDA.ACCORD), # 1.5T
CarTestRoute("1da5847ac2488106|2021-05-24--19-31-50", HONDA.ACCORD), # 2.0T
CarTestRoute("085ac1d942c35910|2021-03-25--20-11-15", HONDA.ACCORD), # 2021 with new style HUD msgs
@@ -119,6 +118,7 @@ routes = [
CarTestRoute("34a875f29f69841a|2021-07-29--13-02-09", HYUNDAI.KIA_NIRO_HEV_2021),
CarTestRoute("50a2212c41f65c7b|2021-05-24--16-22-06", HYUNDAI.KIA_FORTE),
CarTestRoute("c5ac319aa9583f83|2021-06-01--18-18-31", HYUNDAI.ELANTRA),
+ CarTestRoute("734ef96182ddf940|2022-10-02--16-41-44", HYUNDAI.ELANTRA), # 2019 Elantra GT
CarTestRoute("82e9cdd3f43bf83e|2021-05-15--02-42-51", HYUNDAI.ELANTRA_2021),
CarTestRoute("715ac05b594e9c59|2021-06-20--16-21-07", HYUNDAI.ELANTRA_HEV_2021),
CarTestRoute("7120aa90bbc3add7|2021-08-02--07-12-31", HYUNDAI.SONATA_HYBRID),
diff --git a/selfdrive/car/tests/test_fw_fingerprint.py b/selfdrive/car/tests/test_fw_fingerprint.py
index b9926301f1..2e43103852 100755
--- a/selfdrive/car/tests/test_fw_fingerprint.py
+++ b/selfdrive/car/tests/test_fw_fingerprint.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
import random
import unittest
+from collections import defaultdict
from parameterized import parameterized
from cereal import car
@@ -44,6 +45,16 @@ class TestFwFingerprint(unittest.TestCase):
duplicates = {fw for fw in ecu_fw if ecu_fw.count(fw) > 1}
self.assertFalse(len(duplicates), f"{car_model}: Duplicate FW versions: Ecu.{ECU_NAME[ecu[0]]}, {duplicates}")
+ def test_all_addrs_map_to_one_ecu(self):
+ for brand, cars in VERSIONS.items():
+ addr_to_ecu = defaultdict(set)
+ for ecus in cars.values():
+ for ecu_type, addr, sub_addr in ecus.keys():
+ addr_to_ecu[(addr, sub_addr)].add(ecu_type)
+ ecus_for_addr = addr_to_ecu[(addr, sub_addr)]
+ ecu_strings = ", ".join([f'Ecu.{ECU_NAME[ecu]}' for ecu in ecus_for_addr])
+ self.assertLessEqual(len(ecus_for_addr), 1, f"{brand} has multiple ECUs that map to one address: {ecu_strings} -> ({hex(addr)}, {sub_addr})")
+
def test_data_collection_ecus(self):
# Asserts no extra ECUs are in the fingerprinting database
for brand, config in FW_QUERY_CONFIGS.items():
diff --git a/selfdrive/car/torque_data/override.yaml b/selfdrive/car/torque_data/override.yaml
index 13a0dae7a7..460b9a9097 100644
--- a/selfdrive/car/torque_data/override.yaml
+++ b/selfdrive/car/torque_data/override.yaml
@@ -21,7 +21,6 @@ FORD FOCUS 4TH GEN: [.nan, 1.5, .nan]
COMMA BODY: [.nan, 1000, .nan]
# Totally new cars
-KIA EV6 2022: [3.5, 3.0, 0.0]
RAM 1500 5TH GEN: [2.0, 2.0, 0.0]
RAM HD 5TH GEN: [1.4, 1.4, 0.0]
SUBARU OUTBACK 6TH GEN: [2.3, 2.3, 0.11]
diff --git a/selfdrive/car/torque_data/params.yaml b/selfdrive/car/torque_data/params.yaml
index 160f605488..5c828fa669 100644
--- a/selfdrive/car/torque_data/params.yaml
+++ b/selfdrive/car/torque_data/params.yaml
@@ -35,21 +35,22 @@ HYUNDAI SANTA FE 2019: [3.0787027729757632, 2.6173437483495565, 0.12070193418239
HYUNDAI SANTA FE HYBRID 2022: [3.501877602644835, 2.729064118456137, 0.10384068104538963]
HYUNDAI SANTA FE PlUG-IN HYBRID 2022: [1.6953050513611045, 1.5837614296206861, 0.12672855941458458]
HYUNDAI SONATA 2019: [2.2200457811703953, 1.2967330275895228, 0.14039920986586393]
-HYUNDAI SONATA 2020: [3.284505627881726, 2.1259108157250735, 0.08452048323586728]
+HYUNDAI SONATA 2020: [2.9638737459977467, 2.1259108157250735, 0.07813665616927593]
HYUNDAI SONATA HYBRID 2021: [2.8990264092395734, 2.061410192222139, 0.0899805488717382]
JEEP GRAND CHEROKEE 2019: [1.7321233388827006, 1.289689569171081, 0.15046331002097185]
JEEP GRAND CHEROKEE V6 2018: [1.8776598027756923, 1.4057367824262523, 0.11725947414922003]
+KIA EV6 2022: [3.2, 3.0, 0.05]
KIA K5 2021: [2.405339728085138, 1.460032270828705, 0.11650989850813716]
KIA NIRO EV 2020: [2.9215954981365337, 2.1500583840260044, 0.09236802474810267]
KIA SORENTO GT LINE 2018: [2.464854685101844, 1.5335274218367956, 0.12056170567599558]
KIA STINGER GT2 2018: [2.7499043387418967, 1.849652021986449, 0.12048334239559202]
-LEXUS ES 2019: [2.0203086922726112, 2.134803912579666, 0.12757526789308554]
-LEXUS ES HYBRID 2019: [2.392442298703042, 1.863360677810788, 0.17690002108856212]
+LEXUS ES 2019: [1.935835, 2.134803912579666, 0.093439]
+LEXUS ES HYBRID 2019: [2.135678, 1.863360677810788, 0.109627]
LEXUS NX 2018: [2.302625600642627, 2.1382378491466625, 0.14986840878892838]
LEXUS NX 2020: [2.4331999786982936, 2.1045680431705414, 0.14099899317761067]
LEXUS NX HYBRID 2018: [2.4025593501080955, 1.8080446063815507, 0.15349361249519017]
LEXUS RX 2016: [1.5876816543130423, 1.0427699298523752, 0.21334066732397142]
-LEXUS RX 2020: [1.5228812994274734, 1.431102486563665, 0.2093316728710659]
+LEXUS RX 2020: [1.5228812994274734, 1.431102486563665, 0.164117]
LEXUS RX HYBRID 2017: [1.6984261557042386, 1.3211501880159107, 0.1820354534928893]
LEXUS RX HYBRID 2020: [1.5522309889823778, 1.255230465866663, 0.2220954003055114]
MAZDA CX-9 2021: [1.7601682915983443, 1.0889677335154337, 0.17713792194297195]
@@ -62,31 +63,31 @@ TOYOTA AVALON 2019: [1.7036141952825095, 1.239619084240008, 0.08459830394899492]
TOYOTA AVALON 2022: [2.3154403649717357, 2.7777922854327124, 0.11453999639164605]
TOYOTA C-HR 2018: [1.5591084333664578, 1.271271459066948, 0.20259087058453193]
TOYOTA C-HR 2021: [1.7678810166088303, 1.3742176337919942, 0.2319674583741509]
-TOYOTA CAMRY 2018: [2.1172995371905015, 1.7156177222420887, 0.13519250664782062]
-TOYOTA CAMRY 2021: [2.6922769557433055, 2.3476510120007434, 0.1450430192989234]
-TOYOTA CAMRY HYBRID 2018: [2.0974120828287774, 1.7996193116697359, 0.13823613467632756]
-TOYOTA CAMRY HYBRID 2021: [2.6426668350384457, 2.3901492458927986, 0.16103875108816076]
+TOYOTA CAMRY 2018: [2.1172995371905015, 1.7156177222420887, 0.105192506]
+TOYOTA CAMRY 2021: [2.446083, 2.3476510120007434, 0.121615]
+TOYOTA CAMRY HYBRID 2018: [1.996333, 1.7996193116697359, 0.112565]
+TOYOTA CAMRY HYBRID 2021: [2.263582, 2.3901492458927986, 0.115257]
TOYOTA COROLLA 2017: [3.117154369115421, 1.8438132575043773, 0.12289685869250652]
-TOYOTA COROLLA HYBRID TSS2 2019: [2.3287672277252005, 1.8118712531729109, 0.2215868445753317]
-TOYOTA COROLLA TSS2 2019: [2.4204464833010175, 1.9258612322678952, 0.20670411068012526]
+TOYOTA COROLLA HYBRID TSS2 2019: [1.9079729107361805, 1.8118712531729109, 0.22251440891543514]
+TOYOTA COROLLA TSS2 2019: [2.0742917676766712, 1.9258612322678952, 0.16888685704519352]
TOYOTA HIGHLANDER 2017: [1.8696367437248915, 1.626293990451463, 0.17485372210240796]
TOYOTA HIGHLANDER 2020: [2.022340166827233, 1.6183134804881791, 0.14592306380054457]
-TOYOTA HIGHLANDER HYBRID 2018: [1.9421825202382728, 1.6433903296845025, 0.16928956792275918]
-TOYOTA HIGHLANDER HYBRID 2020: [2.103373061114133, 2.104015182965606, 0.14447040132184993]
+TOYOTA HIGHLANDER HYBRID 2018: [1.752033, 1.6433903296845025, 0.144600]
+TOYOTA HIGHLANDER HYBRID 2020: [1.901174, 2.104015182965606, 0.14447040132184993]
TOYOTA MIRAI 2021: [2.506899832157829, 1.7417213930750164, 0.20182618449440565]
-TOYOTA PRIUS 2017: [2.0183401513314294, 1.5023147650693636, 0.20856908464957724]
-TOYOTA PRIUS TSS2 2021: [2.327639738920072, 1.9104337425537743, 0.2030762265549664]
+TOYOTA PRIUS 2017: [1.746445, 1.5023147650693636, 0.151515]
+TOYOTA PRIUS TSS2 2021: [1.972600, 1.9104337425537743, 0.170968]
TOYOTA RAV4 2017: [2.085695074355425, 2.2142832316984733, 0.13339165270103975]
-TOYOTA RAV4 2019: [2.5038362866776835, 2.0993589721530252, 0.1552425356342368]
+TOYOTA RAV4 2019: [2.331293, 2.0993589721530252, 0.129822]
TOYOTA RAV4 2019 8965: [2.5084506298290377, 2.4216520504763475, 0.11992835265067918]
TOYOTA RAV4 2019 x02: [2.7209621987605024, 2.2148637653781593, 0.10862567142268198]
TOYOTA RAV4 HYBRID 2017: [1.9796257271652042, 1.7503987331707576, 0.14628860048885406]
TOYOTA RAV4 HYBRID 2019: [2.2271858492309153, 2.074844961405639, 0.14382216826893632]
TOYOTA RAV4 HYBRID 2019 8965: [2.1077397198131336, 1.8162215166877735, 0.13891369391200137]
TOYOTA RAV4 HYBRID 2019 x02: [2.803624333289342, 2.272367966572498, 0.11364569214387774]
-TOYOTA RAV4 HYBRID 2022: [2.241883248393209, 1.9304407208090029, 0.1565442715453653]
+TOYOTA RAV4 HYBRID 2022: [2.241883248393209, 1.9304407208090029, 0.112174]
TOYOTA RAV4 HYBRID 2022 x02: [3.044930631831037, 2.3979189796380918, 0.14023209146703736]
-TOYOTA SIENNA 2018: [1.8660896232147548, 1.3208264576110418, 0.18799149615227198]
+TOYOTA SIENNA 2018: [1.689726, 1.3208264576110418, 0.140456]
VOLKSWAGEN ARTEON 1ST GEN: [1.45136518053819, 1.3639364049316804, 0.23806361745695032]
VOLKSWAGEN ATLAS 1ST GEN: [1.4677006726964945, 1.6733266634075656, 0.12959584092073367]
VOLKSWAGEN GOLF 7TH GEN: [1.3750394140491293, 1.5814743077200641, 0.2018321939386586]
diff --git a/selfdrive/car/torque_data/substitute.yaml b/selfdrive/car/torque_data/substitute.yaml
index f5e3d1d61d..acd7526003 100644
--- a/selfdrive/car/torque_data/substitute.yaml
+++ b/selfdrive/car/torque_data/substitute.yaml
@@ -26,7 +26,6 @@ KIA SELTOS 2021: HYUNDAI SONATA 2020
KIA NIRO HYBRID 2019: KIA NIRO EV 2020
KIA NIRO HYBRID 2021: KIA NIRO EV 2020
HYUNDAI VELOSTER 2019: HYUNDAI SONATA 2019
-HYUNDAI I30 N LINE 2019 & GT 2018 DCT: HYUNDAI SONATA 2019
HYUNDAI KONA 2020: HYUNDAI KONA ELECTRIC 2019
HYUNDAI KONA HYBRID 2020: HYUNDAI KONA ELECTRIC 2019
HYUNDAI KONA ELECTRIC 2022: HYUNDAI KONA ELECTRIC 2019
diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py
index 28912645ac..0d5acbfff4 100644
--- a/selfdrive/car/toyota/interface.py
+++ b/selfdrive/car/toyota/interface.py
@@ -2,7 +2,6 @@
from cereal import car
from common.conversions import Conversions as CV
from panda import Panda
-from selfdrive.car.toyota.tunes import LatTunes, LongTunes, set_long_tune, set_lat_tune
from selfdrive.car.toyota.values import Ecu, CAR, ToyotaFlags, TSS2_CAR, RADAR_ACC_CAR, NO_DSU_CAR, MIN_ACC_SPEED, EPS_SCALE, EV_HYBRID_CAR, CarControllerParams
from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config
from selfdrive.car.interfaces import CarInterfaceBase
@@ -74,7 +73,6 @@ class CarInterface(CarInterfaceBase):
ret.wheelSpeedFactor = 1.035
tire_stiffness_factor = 0.5533
ret.mass = 4481. * CV.LB_TO_KG + STD_CARGO_KG # mean between min and max
- set_lat_tune(ret.lateralTuning, LatTunes.PID_C)
elif candidate in (CAR.CHR, CAR.CHRH):
stop_and_go = True
@@ -82,7 +80,6 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 13.6
tire_stiffness_factor = 0.7933
ret.mass = 3300. * CV.LB_TO_KG + STD_CARGO_KG
- set_lat_tune(ret.lateralTuning, LatTunes.PID_F)
elif candidate in (CAR.CAMRY, CAR.CAMRYH, CAR.CAMRY_TSS2, CAR.CAMRYH_TSS2):
stop_and_go = True
@@ -90,8 +87,6 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 13.7
tire_stiffness_factor = 0.7933
ret.mass = 3400. * CV.LB_TO_KG + STD_CARGO_KG # mean between normal and hybrid
- if candidate not in (CAR.CAMRY_TSS2, CAR.CAMRYH_TSS2):
- set_lat_tune(ret.lateralTuning, LatTunes.PID_C)
elif candidate in (CAR.HIGHLANDER, CAR.HIGHLANDERH, CAR.HIGHLANDER_TSS2, CAR.HIGHLANDERH_TSS2):
stop_and_go = True
@@ -99,7 +94,6 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 16.0
tire_stiffness_factor = 0.8
ret.mass = 4516. * CV.LB_TO_KG + STD_CARGO_KG # mean between normal and hybrid
- set_lat_tune(ret.lateralTuning, LatTunes.PID_G)
elif candidate in (CAR.AVALON, CAR.AVALON_2019, CAR.AVALONH_2019, CAR.AVALON_TSS2, CAR.AVALONH_TSS2):
# starting from 2019, all Avalon variants have stop and go
@@ -109,7 +103,6 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 14.8 # Found at https://pressroom.toyota.com/releases/2016+avalon+product+specs.download
tire_stiffness_factor = 0.7983
ret.mass = 3505. * CV.LB_TO_KG + STD_CARGO_KG # mean between normal and hybrid
- set_lat_tune(ret.lateralTuning, LatTunes.PID_H)
elif candidate in (CAR.RAV4_TSS2, CAR.RAV4_TSS2_2022, CAR.RAV4H_TSS2, CAR.RAV4H_TSS2_2022):
stop_and_go = True
@@ -117,14 +110,6 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 14.3
tire_stiffness_factor = 0.7933
ret.mass = 3585. * CV.LB_TO_KG + STD_CARGO_KG # Average between ICE and Hybrid
- set_lat_tune(ret.lateralTuning, LatTunes.PID_D)
-
- # 2019+ RAV4 TSS2 uses two different steering racks and specific tuning seems to be necessary.
- # See https://github.com/commaai/openpilot/pull/21429#issuecomment-873652891
- for fw in car_fw:
- if fw.ecu == "eps" and (fw.fwVersion.startswith(b'\x02') or fw.fwVersion in [b'8965B42181\x00\x00\x00\x00\x00\x00']):
- set_lat_tune(ret.lateralTuning, LatTunes.PID_I)
- break
elif candidate in (CAR.COROLLA_TSS2, CAR.COROLLAH_TSS2):
stop_and_go = True
@@ -139,7 +124,6 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 16.0 # not optimized
tire_stiffness_factor = 0.444 # not optimized yet
ret.mass = 3677. * CV.LB_TO_KG + STD_CARGO_KG # mean between min and max
- set_lat_tune(ret.lateralTuning, LatTunes.PID_D)
elif candidate == CAR.SIENNA:
stop_and_go = True
@@ -147,14 +131,12 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 15.5
tire_stiffness_factor = 0.444
ret.mass = 4590. * CV.LB_TO_KG + STD_CARGO_KG
- set_lat_tune(ret.lateralTuning, LatTunes.PID_J)
elif candidate in (CAR.LEXUS_IS, CAR.LEXUS_RC):
ret.wheelbase = 2.79908
ret.steerRatio = 13.3
tire_stiffness_factor = 0.444
ret.mass = 3736.8 * CV.LB_TO_KG + STD_CARGO_KG
- set_lat_tune(ret.lateralTuning, LatTunes.PID_L)
elif candidate == CAR.LEXUS_CTH:
stop_and_go = True
@@ -162,7 +144,6 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 18.6
tire_stiffness_factor = 0.517
ret.mass = 3108 * CV.LB_TO_KG + STD_CARGO_KG # mean between min and max
- set_lat_tune(ret.lateralTuning, LatTunes.PID_M)
elif candidate in (CAR.LEXUS_NX, CAR.LEXUS_NXH, CAR.LEXUS_NX_TSS2, CAR.LEXUS_NXH_TSS2):
stop_and_go = True
@@ -170,7 +151,6 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 14.7
tire_stiffness_factor = 0.444 # not optimized yet
ret.mass = 4070 * CV.LB_TO_KG + STD_CARGO_KG
- set_lat_tune(ret.lateralTuning, LatTunes.PID_C)
elif candidate == CAR.PRIUS_TSS2:
stop_and_go = True
@@ -178,7 +158,6 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 13.4 # True steerRatio from older prius
tire_stiffness_factor = 0.6371 # hand-tune
ret.mass = 3115. * CV.LB_TO_KG + STD_CARGO_KG
- set_lat_tune(ret.lateralTuning, LatTunes.PID_N)
elif candidate == CAR.MIRAI:
stop_and_go = True
@@ -186,7 +165,6 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 14.8
tire_stiffness_factor = 0.8
ret.mass = 4300. * CV.LB_TO_KG + STD_CARGO_KG
- set_lat_tune(ret.lateralTuning, LatTunes.PID_C)
elif candidate in (CAR.ALPHARD_TSS2, CAR.ALPHARDH_TSS2):
stop_and_go = True
@@ -194,7 +172,6 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 14.2
tire_stiffness_factor = 0.444
ret.mass = 4305. * CV.LB_TO_KG + STD_CARGO_KG
- set_lat_tune(ret.lateralTuning, LatTunes.PID_J)
ret.centerToFront = ret.wheelbase * 0.44
@@ -230,12 +207,23 @@ class CarInterface(CarInterfaceBase):
# to a negative value, so it won't matter.
ret.minEnableSpeed = -1. if (stop_and_go or ret.enableGasInterceptor) else MIN_ACC_SPEED
+ tune = ret.longitudinalTuning
if candidate in TSS2_CAR or ret.enableGasInterceptor:
- set_long_tune(ret.longitudinalTuning, LongTunes.TSS2)
+ tune.deadzoneBP = [0., 8.05]
+ tune.deadzoneV = [.0, .14]
+ tune.kpBP = [0., 5., 20.]
+ tune.kpV = [1.3, 1.0, 0.7]
+ tune.kiBP = [0., 5., 12., 20., 27.]
+ tune.kiV = [.35, .23, .20, .17, .1]
if candidate in TSS2_CAR:
ret.stoppingDecelRate = 0.3 # reach stopping target smoothly
else:
- set_long_tune(ret.longitudinalTuning, LongTunes.TSS)
+ tune.deadzoneBP = [0., 9.]
+ tune.deadzoneV = [.0, .15]
+ tune.kpBP = [0., 5., 35.]
+ tune.kiBP = [0., 35.]
+ tune.kpV = [3.6, 2.4, 1.5]
+ tune.kiV = [0.54, 0.36]
return ret
diff --git a/selfdrive/car/toyota/tunes.py b/selfdrive/car/toyota/tunes.py
deleted file mode 100644
index b73ab4c8c9..0000000000
--- a/selfdrive/car/toyota/tunes.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/usr/bin/env python3
-from enum import Enum
-
-class LongTunes(Enum):
- TSS2 = 0
- TSS = 1
-
-class LatTunes(Enum):
- INDI_PRIUS = 0
- LQR_RAV4 = 1
- PID_A = 2
- PID_B = 3
- PID_C = 4
- PID_D = 5
- PID_E = 6
- PID_F = 7
- PID_G = 8
- PID_I = 9
- PID_H = 10
- PID_J = 11
- PID_K = 12
- PID_L = 13
- PID_M = 14
- PID_N = 15
-
-
-###### LONG ######
-def set_long_tune(tune, name):
- # Improved longitudinal tune
- if name == LongTunes.TSS2:
- tune.deadzoneBP = [0., 8.05]
- tune.deadzoneV = [.0, .14]
- tune.kpBP = [0., 5., 20.]
- tune.kpV = [1.3, 1.0, 0.7]
- tune.kiBP = [0., 5., 12., 20., 27.]
- tune.kiV = [.35, .23, .20, .17, .1]
- # Default longitudinal tune
- elif name == LongTunes.TSS:
- tune.deadzoneBP = [0., 9.]
- tune.deadzoneV = [.0, .15]
- tune.kpBP = [0., 5., 35.]
- tune.kiBP = [0., 35.]
- tune.kpV = [3.6, 2.4, 1.5]
- tune.kiV = [0.54, 0.36]
- else:
- raise NotImplementedError('This longitudinal tune does not exist')
-
-
-###### LAT ######
-def set_lat_tune(tune, name, MAX_LAT_ACCEL=2.5, FRICTION=0.01, steering_angle_deadzone_deg=0.0, use_steering_angle=True):
- if 'PID' in str(name):
- tune.init('pid')
- tune.pid.kiBP = [0.0]
- tune.pid.kpBP = [0.0]
- if name == LatTunes.PID_A:
- tune.pid.kpV = [0.2]
- tune.pid.kiV = [0.05]
- tune.pid.kf = 0.00003
- elif name == LatTunes.PID_C:
- tune.pid.kpV = [0.6]
- tune.pid.kiV = [0.1]
- tune.pid.kf = 0.00006
- elif name == LatTunes.PID_D:
- tune.pid.kpV = [0.6]
- tune.pid.kiV = [0.1]
- tune.pid.kf = 0.00007818594
- elif name == LatTunes.PID_F:
- tune.pid.kpV = [0.723]
- tune.pid.kiV = [0.0428]
- tune.pid.kf = 0.00006
- elif name == LatTunes.PID_G:
- tune.pid.kpV = [0.18]
- tune.pid.kiV = [0.015]
- tune.pid.kf = 0.00012
- elif name == LatTunes.PID_H:
- tune.pid.kpV = [0.17]
- tune.pid.kiV = [0.03]
- tune.pid.kf = 0.00006
- elif name == LatTunes.PID_I:
- tune.pid.kpV = [0.15]
- tune.pid.kiV = [0.05]
- tune.pid.kf = 0.00004
- elif name == LatTunes.PID_J:
- tune.pid.kpV = [0.19]
- tune.pid.kiV = [0.02]
- tune.pid.kf = 0.00007818594
- elif name == LatTunes.PID_L:
- tune.pid.kpV = [0.3]
- tune.pid.kiV = [0.05]
- tune.pid.kf = 0.00006
- elif name == LatTunes.PID_M:
- tune.pid.kpV = [0.3]
- tune.pid.kiV = [0.05]
- tune.pid.kf = 0.00007
- elif name == LatTunes.PID_N:
- tune.pid.kpV = [0.35]
- tune.pid.kiV = [0.15]
- tune.pid.kf = 0.00007818594
- else:
- raise NotImplementedError('This PID tune does not exist')
- else:
- raise NotImplementedError('This lateral tune does not exist')
diff --git a/selfdrive/car/toyota/values.py b/selfdrive/car/toyota/values.py
index 819b85d759..07c33d0173 100644
--- a/selfdrive/car/toyota/values.py
+++ b/selfdrive/car/toyota/values.py
@@ -1367,6 +1367,7 @@ FW_VERSIONS = {
b'\x01896634AA1000\x00\x00\x00\x00',
b'\x01896634A88000\x00\x00\x00\x00',
b'\x01896634A89000\x00\x00\x00\x00',
+ b'\x01896634A89100\x00\x00\x00\x00',
],
(Ecu.fwdRadar, 0x750, 0xf): [
b'\x018821F0R01100\x00\x00\x00\x00',
diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py
index cbc54eadb8..1adbba4171 100755
--- a/selfdrive/controls/controlsd.py
+++ b/selfdrive/controls/controlsd.py
@@ -82,13 +82,13 @@ class Controls:
self.log_sock = messaging.sub_sock('androidLog')
- params = Params()
+ self.params = Params()
self.sm = sm
if self.sm is None:
ignore = ['testJoystick']
if SIMULATION:
ignore += ['driverCameraState', 'managerState']
- if params.get_bool('WideCameraOnly'):
+ if self.params.get_bool('WideCameraOnly'):
ignore += ['roadCameraState']
self.sm = messaging.SubMaster(['deviceState', 'pandaStates', 'peripheralState', 'modelV2', 'liveCalibration',
'driverMonitoringState', 'longitudinalPlan', 'lateralPlan', 'liveLocationKalman',
@@ -105,22 +105,22 @@ class Controls:
else:
self.CI, self.CP = CI, CI.CP
- self.joystick_mode = params.get_bool("JoystickDebugMode") or (self.CP.notCar and sm is None)
+ self.joystick_mode = self.params.get_bool("JoystickDebugMode") or (self.CP.notCar and sm is None)
# set alternative experiences from parameters
- self.disengage_on_accelerator = params.get_bool("DisengageOnAccelerator")
+ self.disengage_on_accelerator = self.params.get_bool("DisengageOnAccelerator")
self.CP.alternativeExperience = 0
if not self.disengage_on_accelerator:
self.CP.alternativeExperience |= ALTERNATIVE_EXPERIENCE.DISABLE_DISENGAGE_ON_GAS
- if self.CP.dashcamOnly and params.get_bool("DashcamOverride"):
+ if self.CP.dashcamOnly and self.params.get_bool("DashcamOverride"):
self.CP.dashcamOnly = False
# read params
- self.is_metric = params.get_bool("IsMetric")
- self.is_ldw_enabled = params.get_bool("IsLdwEnabled")
- openpilot_enabled_toggle = params.get_bool("OpenpilotEnabledToggle")
- passive = params.get_bool("Passive") or not openpilot_enabled_toggle
+ self.is_metric = self.params.get_bool("IsMetric")
+ self.is_ldw_enabled = self.params.get_bool("IsLdwEnabled")
+ openpilot_enabled_toggle = self.params.get_bool("OpenpilotEnabledToggle")
+ passive = self.params.get_bool("Passive") or not openpilot_enabled_toggle
# detect sound card presence and ensure successful init
sounds_available = HARDWARE.get_sound_card_online()
@@ -139,15 +139,15 @@ class Controls:
# Write CarParams for radard
cp_bytes = self.CP.to_bytes()
- params.put("CarParams", cp_bytes)
+ self.params.put("CarParams", cp_bytes)
put_nonblocking("CarParamsCache", cp_bytes)
put_nonblocking("CarParamsPersistent", cp_bytes)
# cleanup old params
if not self.CP.experimentalLongitudinalAvailable:
- params.remove("ExperimentalLongitudinalEnabled")
+ self.params.remove("ExperimentalLongitudinalEnabled")
if not self.CP.openpilotLongitudinalControl:
- params.remove("EndToEndLong")
+ self.params.remove("EndToEndLong")
self.CC = car.CarControl.new_message()
self.CS_prev = car.CarState.new_message()
@@ -254,8 +254,7 @@ class Controls:
self.events.add(EventName.pedalPressed)
if CS.gasPressed:
- self.events.add(EventName.pedalPressedPreEnable if self.disengage_on_accelerator else
- EventName.gasPressedOverride)
+ self.events.add(EventName.gasPressedOverride)
if not self.CP.notCar:
self.events.add_from_msg(self.sm['driverMonitoringState'].events)
@@ -583,9 +582,9 @@ class Controls:
"""Given the state, this function returns a CarControl packet"""
# Update VehicleModel
- params = self.sm['liveParameters']
- x = max(params.stiffnessFactor, 0.1)
- sr = max(params.steerRatio, 0.1)
+ lp = self.sm['liveParameters']
+ x = max(lp.stiffnessFactor, 0.1)
+ sr = max(lp.steerRatio, 0.1)
self.VM.update_params(x, sr)
# Update Torque Params
@@ -628,7 +627,7 @@ class Controls:
lat_plan.psis,
lat_plan.curvatures,
lat_plan.curvatureRates)
- actuators.steer, actuators.steeringAngleDeg, lac_log = self.LaC.update(CC.latActive, CS, self.VM, params,
+ actuators.steer, actuators.steeringAngleDeg, lac_log = self.LaC.update(CC.latActive, CS, self.VM, lp,
self.last_actuators, self.steer_limited, self.desired_curvature,
self.desired_curvature_rate, self.sm['liveLocationKalman'])
else:
@@ -768,10 +767,10 @@ class Controls:
(self.state == State.softDisabling)
# Curvature & Steering angle
- params = self.sm['liveParameters']
+ lp = self.sm['liveParameters']
- steer_angle_without_offset = math.radians(CS.steeringAngleDeg - params.angleOffsetDeg)
- curvature = -self.VM.calc_curvature(steer_angle_without_offset, CS.vEgo, params.roll)
+ steer_angle_without_offset = math.radians(CS.steeringAngleDeg - lp.angleOffsetDeg)
+ curvature = -self.VM.calc_curvature(steer_angle_without_offset, CS.vEgo, lp.roll)
# controlsState
dat = messaging.new_message('controlsState')
@@ -856,6 +855,8 @@ class Controls:
start_time = sec_since_boot()
self.prof.checkpoint("Ratekeeper", ignore=True)
+ self.is_metric = self.params.get_bool("IsMetric")
+
# Sample data from sockets and get a carState
CS = self.data_sample()
cloudlog.timestamp("Data sampled")
diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py
index 2aab4b71af..49eb5988e2 100644
--- a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py
+++ b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py
@@ -253,7 +253,8 @@ class LongitudinalMpc:
cost_weights = [X_EGO_OBSTACLE_COST, X_EGO_COST, V_EGO_COST, A_EGO_COST, a_change_cost, J_EGO_COST]
constraint_cost_weights = [LIMIT_COST, LIMIT_COST, LIMIT_COST, DANGER_ZONE_COST]
elif self.mode == 'blended':
- cost_weights = [0., 0.1, 0.2, 5.0, 0.0, 1.0]
+ a_change_cost = 40.0 if prev_accel_constraint else 0
+ cost_weights = [0., 0.1, 0.2, 5.0, a_change_cost, 1.0]
constraint_cost_weights = [LIMIT_COST, LIMIT_COST, LIMIT_COST, 50.0]
else:
raise NotImplementedError(f'Planner mode {self.mode} not recognized in planner cost set')
diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py
index 018136e6f2..457065d3b5 100755
--- a/selfdrive/controls/lib/longitudinal_planner.py
+++ b/selfdrive/controls/lib/longitudinal_planner.py
@@ -133,7 +133,7 @@ class LongitudinalPlanner:
# TODO counter is only needed because radar is glitchy, remove once radar is gone
# TODO write fcw in e2e_long mode
- self.fcw = self.mpc.mode == 'acc' and self.mpc.crash_cnt > 5
+ self.fcw = self.mpc.mode == 'acc' and self.mpc.crash_cnt > 5 and not sm['carState'].standstill
if self.fcw:
cloudlog.info("FCW triggered")
diff --git a/selfdrive/controls/lib/radar_helpers.py b/selfdrive/controls/lib/radar_helpers.py
index bf788190cd..4bb0179267 100644
--- a/selfdrive/controls/lib/radar_helpers.py
+++ b/selfdrive/controls/lib/radar_helpers.py
@@ -151,7 +151,8 @@ class Cluster():
def potential_low_speed_lead(self, v_ego):
# stop for stuff in front of you and low speed, even without model confirmation
- return abs(self.yRel) < 1.0 and (v_ego < v_ego_stationary) and self.dRel < 25
+ # Radar points closer than 0.75, are almost always glitches on toyota radars
+ return abs(self.yRel) < 1.0 and (v_ego < v_ego_stationary) and (0.75 < self.dRel < 25)
def is_potential_fcw(self, model_prob):
return model_prob > .9
diff --git a/selfdrive/locationd/calibrationd.py b/selfdrive/locationd/calibrationd.py
index 9e6536f9b5..1c68eb67bd 100755
--- a/selfdrive/locationd/calibrationd.py
+++ b/selfdrive/locationd/calibrationd.py
@@ -31,6 +31,7 @@ INPUTS_NEEDED = 5 # Minimum blocks needed for valid calibration
INPUTS_WANTED = 50 # We want a little bit more than we need for stability
MAX_ALLOWED_SPREAD = np.radians(2)
RPY_INIT = np.array([0.0,0.0,0.0])
+WIDE_FROM_DEVICE_EULER_INIT = np.array([0.0, 0.0, 0.0])
# These values are needed to accommodate biggest modelframe
PITCH_LIMITS = np.array([-0.09074112085129739, 0.14907572052989657])
@@ -65,8 +66,8 @@ class Calibrator:
# Read saved calibration
params = Params()
calibration_params = params.get("CalibrationParams")
- self.wide_camera = params.get_bool('WideCameraOnly')
rpy_init = RPY_INIT
+ wide_from_device_euler = WIDE_FROM_DEVICE_EULER_INIT
valid_blocks = 0
if param_put and calibration_params:
@@ -74,24 +75,34 @@ class Calibrator:
msg = log.Event.from_bytes(calibration_params)
rpy_init = np.array(msg.liveCalibration.rpyCalib)
valid_blocks = msg.liveCalibration.validBlocks
+ wide_from_device_euler = np.array(msg.liveCalibration.wideFromDeviceEuler)
except Exception:
cloudlog.exception("Error reading cached CalibrationParams")
- self.reset(rpy_init, valid_blocks)
+ self.reset(rpy_init, valid_blocks, wide_from_device_euler)
self.update_status()
- def reset(self, rpy_init: np.ndarray = RPY_INIT, valid_blocks: int = 0, smooth_from: Optional[np.ndarray] = None) -> None:
+ def reset(self, rpy_init: np.ndarray = RPY_INIT,
+ valid_blocks: int = 0,
+ wide_from_device_euler_init: np.ndarray = WIDE_FROM_DEVICE_EULER_INIT,
+ smooth_from: Optional[np.ndarray] = None) -> None:
if not np.isfinite(rpy_init).all():
self.rpy = RPY_INIT.copy()
else:
self.rpy = rpy_init.copy()
+ if not np.isfinite(wide_from_device_euler_init).all() or len(wide_from_device_euler_init) != 3:
+ self.wide_from_device_euler = WIDE_FROM_DEVICE_EULER_INIT.copy()
+ else:
+ self.wide_from_device_euler = wide_from_device_euler_init.copy()
+
if not np.isfinite(valid_blocks) or valid_blocks < 0:
self.valid_blocks = 0
else:
self.valid_blocks = valid_blocks
self.rpys = np.tile(self.rpy, (INPUTS_WANTED, 1))
+ self.wide_from_device_eulers = np.tile(self.wide_from_device_euler, (INPUTS_WANTED, 1))
self.idx = 0
self.block_idx = 0
@@ -113,6 +124,7 @@ class Calibrator:
def update_status(self) -> None:
valid_idxs = self.get_valid_idxs()
if valid_idxs:
+ self.wide_from_device_euler = np.mean(self.wide_from_device_eulers[valid_idxs], axis=0)
rpys = self.rpys[valid_idxs]
self.rpy = np.mean(rpys, axis=0)
max_rpy_calib = np.array(np.max(rpys, axis=0))
@@ -146,14 +158,14 @@ class Calibrator:
else:
return self.rpy
- def handle_cam_odom(self, trans: List[float], rot: List[float], trans_std: List[float]) -> Optional[np.ndarray]:
+ def handle_cam_odom(self, trans: List[float],
+ rot: List[float],
+ wide_from_device_euler: List[float],
+ trans_std: List[float]) -> Optional[np.ndarray]:
self.old_rpy_weight = min(0.0, self.old_rpy_weight - 1/SMOOTH_CYCLES)
straight_and_fast = ((self.v_ego > MIN_SPEED_FILTER) and (trans[0] > MIN_SPEED_FILTER) and (abs(rot[2]) < MAX_YAW_RATE_FILTER))
- if self.wide_camera:
- angle_std_threshold = 4*MAX_VEL_ANGLE_STD
- else:
- angle_std_threshold = MAX_VEL_ANGLE_STD
+ angle_std_threshold = MAX_VEL_ANGLE_STD
certain_if_calib = ((np.arctan2(trans_std[1], trans[0]) < angle_std_threshold) or
(self.valid_blocks < INPUTS_NEEDED))
if not (straight_and_fast and certain_if_calib):
@@ -165,7 +177,14 @@ class Calibrator:
new_rpy = euler_from_rot(rot_from_euler(self.get_smooth_rpy()).dot(rot_from_euler(observed_rpy)))
new_rpy = sanity_clip(new_rpy)
- self.rpys[self.block_idx] = (self.idx*self.rpys[self.block_idx] + (BLOCK_SIZE - self.idx) * new_rpy) / float(BLOCK_SIZE)
+ if len(wide_from_device_euler) == 3:
+ new_wide_from_device_euler = np.array(wide_from_device_euler)
+ else:
+ new_wide_from_device_euler = WIDE_FROM_DEVICE_EULER_INIT
+ self.rpys[self.block_idx] = (self.idx*self.rpys[self.block_idx] +
+ (BLOCK_SIZE - self.idx) * new_rpy) / float(BLOCK_SIZE)
+ self.wide_from_device_eulers[self.block_idx] = (self.idx*self.wide_from_device_eulers[self.block_idx] +
+ (BLOCK_SIZE - self.idx) * new_wide_from_device_euler) / float(BLOCK_SIZE)
self.idx = (self.idx + 1) % BLOCK_SIZE
if self.idx == 0:
self.block_idx += 1
@@ -187,6 +206,7 @@ class Calibrator:
liveCalibration.calPerc = min(100 * (self.valid_blocks * BLOCK_SIZE + self.idx) // (INPUTS_NEEDED * BLOCK_SIZE), 100)
liveCalibration.rpyCalib = smooth_rpy.tolist()
liveCalibration.rpyCalibSpread = self.calib_spread.tolist()
+ liveCalibration.wideFromDeviceEuler = self.wide_from_device_euler.tolist()
if self.not_car:
liveCalibration.validBlocks = INPUTS_NEEDED
@@ -223,6 +243,7 @@ def calibrationd_thread(sm: Optional[messaging.SubMaster] = None, pm: Optional[m
calibrator.handle_v_ego(sm['carState'].vEgo)
new_rpy = calibrator.handle_cam_odom(sm['cameraOdometry'].trans,
sm['cameraOdometry'].rot,
+ sm['cameraOdometry'].wideFromDeviceEuler,
sm['cameraOdometry'].transStd)
if DEBUG and new_rpy is not None:
diff --git a/selfdrive/locationd/torqued.py b/selfdrive/locationd/torqued.py
index 66af234590..42dff60087 100755
--- a/selfdrive/locationd/torqued.py
+++ b/selfdrive/locationd/torqued.py
@@ -16,7 +16,9 @@ from selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_GRAVITY
HISTORY = 5 # secs
POINTS_PER_BUCKET = 1500
MIN_POINTS_TOTAL = 4000
+MIN_POINTS_TOTAL_QLOG = 800
FIT_POINTS_TOTAL = 2000
+FIT_POINTS_TOTAL_QLOG = 800
MIN_VEL = 15 # m/s
FRICTION_FACTOR = 1.5 # ~85% of data coverage
FACTOR_SANITY = 0.3
@@ -26,7 +28,7 @@ MIN_FILTER_DECAY = 50
MAX_FILTER_DECAY = 250
LAT_ACC_THRESHOLD = 1
STEER_BUCKET_BOUNDS = [(-0.5, -0.3), (-0.3, -0.2), (-0.2, -0.1), (-0.1, 0), (0, 0.1), (0.1, 0.2), (0.2, 0.3), (0.3, 0.5)]
-MIN_BUCKET_POINTS = [100, 300, 500, 500, 500, 500, 300, 100]
+MIN_BUCKET_POINTS = np.array([100, 300, 500, 500, 500, 500, 300, 100])
MAX_RESETS = 5.0
MAX_INVALID_THRESHOLD = 10
MIN_ENGAGE_BUFFER = 2 # secs
@@ -58,10 +60,11 @@ class NPQueue:
class PointBuckets:
- def __init__(self, x_bounds, min_points):
+ def __init__(self, x_bounds, min_points, min_points_total):
self.x_bounds = x_bounds
self.buckets = {bounds: NPQueue(maxlen=POINTS_PER_BUCKET, rowsize=3) for bounds in x_bounds}
self.buckets_min_points = {bounds: min_point for bounds, min_point in zip(x_bounds, min_points)}
+ self.min_points_total = min_points_total
def bucket_lengths(self):
return [len(v) for v in self.buckets.values()]
@@ -70,7 +73,7 @@ class PointBuckets:
return sum(self.bucket_lengths())
def is_valid(self):
- return all(len(v) >= min_pts for v, min_pts in zip(self.buckets.values(), self.buckets_min_points.values())) and (self.__len__() >= MIN_POINTS_TOTAL)
+ return all(len(v) >= min_pts for v, min_pts in zip(self.buckets.values(), self.buckets_min_points.values())) and (self.__len__() >= self.min_points_total)
def add_point(self, x, y):
for bound_min, bound_max in self.x_bounds:
@@ -90,9 +93,17 @@ class PointBuckets:
class TorqueEstimator:
- def __init__(self, CP):
+ def __init__(self, CP, decimated=False):
self.hist_len = int(HISTORY / DT_MDL)
self.lag = CP.steerActuatorDelay + .2 # from controlsd
+ if decimated:
+ self.min_bucket_points = MIN_BUCKET_POINTS / 10
+ self.min_points_total = MIN_POINTS_TOTAL_QLOG
+ self.fit_points = FIT_POINTS_TOTAL_QLOG
+ else:
+ self.min_bucket_points = MIN_BUCKET_POINTS
+ self.min_points_total = MIN_POINTS_TOTAL
+ self.fit_points = FIT_POINTS_TOTAL
self.offline_friction = 0.0
self.offline_latAccelFactor = 0.0
@@ -157,10 +168,10 @@ class TorqueEstimator:
self.invalid_values_tracker = 0.0
self.decay = MIN_FILTER_DECAY
self.raw_points = defaultdict(lambda: deque(maxlen=self.hist_len))
- self.filtered_points = PointBuckets(x_bounds=STEER_BUCKET_BOUNDS, min_points=MIN_BUCKET_POINTS)
+ self.filtered_points = PointBuckets(x_bounds=STEER_BUCKET_BOUNDS, min_points=self.min_bucket_points, min_points_total=self.min_points_total)
def estimate_params(self):
- points = self.filtered_points.get_points(FIT_POINTS_TOTAL)
+ points = self.filtered_points.get_points(self.fit_points)
# total least square solution as both x and y are noisy observations
# this is empirically the slope of the hysteresis parallelogram as opposed to the line through the diagonals
try:
diff --git a/selfdrive/modeld/models/supercombo.onnx b/selfdrive/modeld/models/supercombo.onnx
index 21602ea70a..243223eabd 100644
--- a/selfdrive/modeld/models/supercombo.onnx
+++ b/selfdrive/modeld/models/supercombo.onnx
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9c119aa811a929b3a442dbe8e462a9d88e8bfb9f5809a4e737687fb7380d7e05
-size 45922882
+oid sha256:dcfad22cecf37275d01a339d96174800c109e9a70f853fdef3e4ef62ed3f4bbe
+size 45922983
diff --git a/selfdrive/sensord/rawgps/rawgpsd.py b/selfdrive/sensord/rawgps/rawgpsd.py
index 5a6827a759..1c65051665 100755
--- a/selfdrive/sensord/rawgps/rawgpsd.py
+++ b/selfdrive/sensord/rawgps/rawgpsd.py
@@ -87,16 +87,24 @@ def try_setup_logs(diag, log_types):
else:
raise Exception(f"setup logs failed, {log_types=}")
-def mmcli(cmd: str) -> None:
+def at_cmd(cmd: str) -> None:
for _ in range(5):
try:
- subprocess.check_call(f"mmcli -m any --timeout 30 {cmd}", shell=True)
+ subprocess.check_call(f"mmcli -m any --timeout 30 --command='{cmd}'", shell=True)
break
except subprocess.CalledProcessError:
cloudlog.exception("rawgps.mmcli_command_failed")
else:
raise Exception(f"failed to execute mmcli command {cmd=}")
+
+def gps_enabled() -> bool:
+ try:
+ p = subprocess.check_output("mmcli -m any --command=\"AT+QGPS?\"", shell=True)
+ return b"QGPS: 1" in p
+ except subprocess.CalledProcessError as exc:
+ raise Exception("failed to execute QGPS mmcli command") from exc
+
def setup_quectel(diag: ModemDiag):
# enable OEMDRE in the NV
# TODO: it has to reboot for this to take effect
@@ -108,11 +116,17 @@ def setup_quectel(diag: ModemDiag):
setup_logs(diag, LOG_TYPES)
+ if gps_enabled():
+ at_cmd("AT+QGPSEND")
+
# disable DPO power savings for more accuracy
- mmcli("--command='AT+QGPSCFG=\"dpoenable\",0'")
+ at_cmd("AT+QGPSCFG=\"dpoenable\",0")
# don't automatically turn on GNSS on powerup
- mmcli("--command='AT+QGPSCFG=\"autogps\",0'")
- mmcli("--location-enable-gps-raw --location-enable-gps-nmea")
+ at_cmd("AT+QGPSCFG=\"autogps\",0")
+
+ at_cmd("AT+QGPSSUPLURL=\"supl.google.com:7275\"")
+ at_cmd("AT+QGPSCFG=\"outport\",\"usbnmea\"")
+ at_cmd("AT+QGPS=1")
# enable OEMDRE mode
DIAG_SUBSYS_CMD_F = 75
@@ -134,7 +148,9 @@ def setup_quectel(diag: ModemDiag):
))
def teardown_quectel(diag):
- mmcli("--location-disable-gps-raw --location-disable-gps-nmea")
+ at_cmd("AT+QGPSCFG=\"outport\",\"none\"")
+ if gps_enabled():
+ at_cmd("AT+QGPSEND")
try_setup_logs(diag, [])
@@ -156,7 +172,7 @@ def main() -> NoReturn:
# wait for ModemManager to come up
cloudlog.warning("waiting for modem to come up")
while True:
- ret = subprocess.call("mmcli -m any --timeout 10 --location-status", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True)
+ ret = subprocess.call("mmcli -m any --timeout 10 --command=\"AT+QGPS?\"", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True)
if ret == 0:
break
time.sleep(0.1)
diff --git a/selfdrive/test/process_replay/model_replay_ref_commit b/selfdrive/test/process_replay/model_replay_ref_commit
index b5fd11fee8..d13ced3a53 100644
--- a/selfdrive/test/process_replay/model_replay_ref_commit
+++ b/selfdrive/test/process_replay/model_replay_ref_commit
@@ -1 +1 @@
-46cb9c522e942d8b25deac90ffdee89efff60ce9
+49ea844254883ac61caa2ac425f453799aeb28a6
diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py
index 9d37be4a56..bc55e33cbf 100755
--- a/selfdrive/test/process_replay/process_replay.py
+++ b/selfdrive/test/process_replay/process_replay.py
@@ -456,6 +456,9 @@ def setup_env(simulation=False, CP=None, cfg=None, controlsState=None):
os.environ['SKIP_FW_QUERY'] = "1"
os.environ['FINGERPRINT'] = CP.carFingerprint
+ if CP.openpilotLongitudinalControl:
+ params.put_bool("ExperimentalLongitudinalEnabled", True)
+
def python_replay_process(cfg, lr, fingerprint=None):
sub_sockets = [s for _, sub in cfg.pub_sub.items() for s in sub]
diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit
index 230e81d949..0e4ac94784 100644
--- a/selfdrive/test/process_replay/ref_commit
+++ b/selfdrive/test/process_replay/ref_commit
@@ -1 +1 @@
-f5a352666728344ca5065bb44c47c1f5650b4243
+fc3a044c567a8702ed1500d745170c365dd6b3d4
\ 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 cecabd8a3a..5c754d9312 100755
--- a/selfdrive/test/process_replay/test_processes.py
+++ b/selfdrive/test/process_replay/test_processes.py
@@ -24,10 +24,11 @@ source_segments = [
("TOYOTA3", "f7d7e3538cda1a2a|2021-08-16--08-55-34--6"), # TOYOTA.COROLLA_TSS2
("HONDA", "eb140f119469d9ab|2021-06-12--10-46-24--27"), # HONDA.CIVIC (NIDEC)
("HONDA2", "7d2244f34d1bbcda|2021-06-25--12-25-37--26"), # HONDA.ACCORD (BOSCH)
- ("CHRYSLER", "4deb27de11bee626|2021-02-20--11-28-55--8"), # CHRYSLER.PACIFICA
+ ("CHRYSLER", "4deb27de11bee626|2021-02-20--11-28-55--8"), # CHRYSLER.PACIFICA_2018_HYBRID
("RAM", "2f4452b03ccb98f0|2022-09-07--13-55-08--10"), # CHRYSLER.RAM_1500
("SUBARU", "341dccd5359e3c97|2022-09-12--10-35-33--3"), # SUBARU.OUTBACK
("GM", "0c58b6a25109da2b|2021-02-23--16-35-50--11"), # GM.VOLT
+ ("GM2", "376bf99325883932|2022-10-27--13-41-22--1"), # GM.BOLT_EUV
("NISSAN", "35336926920f3571|2021-02-12--18-38-48--46"), # NISSAN.XTRAIL
("VOLKSWAGEN", "de9592456ad7d144|2021-06-29--11-00-15--6"), # VOLKSWAGEN.GOLF
("MAZDA", "bd6a637565e91581|2021-10-30--15-14-53--4"), # MAZDA.CX9_2021
@@ -50,6 +51,7 @@ segments = [
("RAM", "regen20490083AE7|2022-09-27--15-53-15--0"),
("SUBARU", "regen1E72BBDCED5|2022-09-27--15-55-31--0"),
("GM", "regen45B05A80EF6|2022-09-27--15-57-22--0"),
+ ("GM2", "376bf99325883932|2022-10-27--13-41-22--1"),
("NISSAN", "regenC19D899B46D|2022-09-27--15-59-13--0"),
("VOLKSWAGEN", "regenD8F7AC4BD0D|2022-09-27--16-41-45--0"),
("MAZDA", "regenFC3F9ECBB64|2022-09-27--16-03-09--0"),
diff --git a/selfdrive/ui/qt/home.cc b/selfdrive/ui/qt/home.cc
index 78bc6aab40..3fe00e6ed9 100644
--- a/selfdrive/ui/qt/home.cc
+++ b/selfdrive/ui/qt/home.cc
@@ -1,11 +1,9 @@
#include "selfdrive/ui/qt/home.h"
-#include
#include
#include
#include
-#include "common/params.h"
#include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/widgets/drive_stats.h"
#include "selfdrive/ui/qt/widgets/prime.h"
@@ -109,22 +107,20 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) {
header_layout->setContentsMargins(15, 15, 15, 0);
header_layout->setSpacing(16);
- date = new QLabel();
- header_layout->addWidget(date, 1, Qt::AlignHCenter | Qt::AlignLeft);
-
update_notif = new QPushButton(tr("UPDATE"));
update_notif->setVisible(false);
update_notif->setStyleSheet("background-color: #364DEF;");
QObject::connect(update_notif, &QPushButton::clicked, [=]() { center_layout->setCurrentIndex(1); });
- header_layout->addWidget(update_notif, 0, Qt::AlignHCenter | Qt::AlignRight);
+ header_layout->addWidget(update_notif, 0, Qt::AlignHCenter | Qt::AlignLeft);
alert_notif = new QPushButton();
alert_notif->setVisible(false);
alert_notif->setStyleSheet("background-color: #E22C2C;");
QObject::connect(alert_notif, &QPushButton::clicked, [=] { center_layout->setCurrentIndex(2); });
- header_layout->addWidget(alert_notif, 0, Qt::AlignHCenter | Qt::AlignRight);
+ header_layout->addWidget(alert_notif, 0, Qt::AlignHCenter | Qt::AlignLeft);
- header_layout->addWidget(new QLabel(getBrandVersion()), 0, Qt::AlignHCenter | Qt::AlignRight);
+ version = new ElidedLabel();
+ header_layout->addWidget(version, 0, Qt::AlignHCenter | Qt::AlignRight);
main_layout->addLayout(header_layout);
@@ -184,9 +180,7 @@ void OffroadHome::hideEvent(QHideEvent *event) {
}
void OffroadHome::refresh() {
- QString locale_name = QString(uiState()->language).replace("main_", "");
- QString dateString = QLocale(locale_name).toString(QDateTime::currentDateTime(), "dddd, MMMM d");
- date->setText(dateString);
+ version->setText(getBrand() + " " + QString::fromStdString(params.get("UpdaterCurrentDescription")));
bool updateAvailable = update_widget->refresh();
int alerts = alerts_widget->refresh();
diff --git a/selfdrive/ui/qt/home.h b/selfdrive/ui/qt/home.h
index 94f1330109..6636da56ec 100644
--- a/selfdrive/ui/qt/home.h
+++ b/selfdrive/ui/qt/home.h
@@ -7,10 +7,12 @@
#include
#include
+#include "common/params.h"
#include "selfdrive/ui/qt/offroad/driverview.h"
#include "selfdrive/ui/qt/body.h"
#include "selfdrive/ui/qt/onroad.h"
#include "selfdrive/ui/qt/sidebar.h"
+#include "selfdrive/ui/qt/widgets/controls.h"
#include "selfdrive/ui/qt/widgets/offroad_alerts.h"
#include "selfdrive/ui/ui.h"
@@ -25,8 +27,10 @@ private:
void hideEvent(QHideEvent *event) override;
void refresh();
+ Params params;
+
QTimer* timer;
- QLabel* date;
+ ElidedLabel* version;
QStackedLayout* center_layout;
UpdateAlert *update_widget;
OffroadAlert* alerts_widget;
diff --git a/selfdrive/ui/qt/offroad/software_settings.cc b/selfdrive/ui/qt/offroad/software_settings.cc
index 4f048241c3..e08a02a4d6 100644
--- a/selfdrive/ui/qt/offroad/software_settings.cc
+++ b/selfdrive/ui/qt/offroad/software_settings.cc
@@ -145,11 +145,11 @@ void SoftwarePanel::updateLabels() {
targetBranchBtn->setValue(QString::fromStdString(params.get("UpdaterTargetBranch")));
// current + new versions
- versionLbl->setText(QString::fromStdString(params.get("UpdaterCurrentDescription")).left(40));
+ versionLbl->setText(QString::fromStdString(params.get("UpdaterCurrentDescription")));
versionLbl->setDescription(QString::fromStdString(params.get("UpdaterCurrentReleaseNotes")));
installBtn->setVisible(!is_onroad && params.getBool("UpdateAvailable"));
- installBtn->setValue(QString::fromStdString(params.get("UpdaterNewDescription")).left(35));
+ installBtn->setValue(QString::fromStdString(params.get("UpdaterNewDescription")));
installBtn->setDescription(QString::fromStdString(params.get("UpdaterNewReleaseNotes")));
update();
diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc
index 1f677fc92d..346cb3ab96 100644
--- a/selfdrive/ui/qt/onroad.cc
+++ b/selfdrive/ui/qt/onroad.cc
@@ -100,10 +100,6 @@ void OnroadWindow::offroadTransition(bool offroad) {
#endif
alerts->updateAlert({}, bg);
-
- // update stream type
- bool wide_cam = Params().getBool("WideCameraOnly");
- nvg->setStreamType(wide_cam ? VISION_STREAM_WIDE_ROAD : VISION_STREAM_ROAD);
}
void OnroadWindow::paintEvent(QPaintEvent *event) {
@@ -232,8 +228,10 @@ void AnnotatedCameraWidget::updateState(const UIState &s) {
setProperty("rightHandDM", sm["driverMonitoringState"].getDriverMonitoringState().getIsRHD());
}
+ setStreamType(s.scene.wide_cam ? VISION_STREAM_WIDE_ROAD : VISION_STREAM_ROAD);
if (s.scene.calibration_valid) {
- CameraWidget::updateCalibration(s.scene.view_from_calib);
+ auto calib = s.scene.wide_cam ? s.scene.view_from_wide_calib : s.scene.view_from_calib;
+ CameraWidget::updateCalibration(calib);
} else {
CameraWidget::updateCalibration(DEFAULT_CALIBRATION);
}
diff --git a/selfdrive/ui/qt/util.cc b/selfdrive/ui/qt/util.cc
index c5697c1045..59903e3376 100644
--- a/selfdrive/ui/qt/util.cc
+++ b/selfdrive/ui/qt/util.cc
@@ -21,10 +21,6 @@ QString getBrand() {
return Params().getBool("Passive") ? QObject::tr("dashcam") : QObject::tr("openpilot");
}
-QString getBrandVersion() {
- return getBrand() + " v" + getVersion().left(14).trimmed();
-}
-
QString getUserAgent() {
return "openpilot-" + getVersion();
}
diff --git a/selfdrive/ui/qt/util.h b/selfdrive/ui/qt/util.h
index 209f051963..61a27a8669 100644
--- a/selfdrive/ui/qt/util.h
+++ b/selfdrive/ui/qt/util.h
@@ -11,7 +11,6 @@
QString getVersion();
QString getBrand();
-QString getBrandVersion();
QString getUserAgent();
std::optional getDongleId();
QMap getSupportedLanguages();
diff --git a/selfdrive/ui/qt/widgets/cameraview.cc b/selfdrive/ui/qt/widgets/cameraview.cc
index 200257235d..d7591633c9 100644
--- a/selfdrive/ui/qt/widgets/cameraview.cc
+++ b/selfdrive/ui/qt/widgets/cameraview.cc
@@ -96,8 +96,8 @@ mat4 get_fit_view_transform(float widget_aspect_ratio, float frame_aspect_ratio)
CameraWidget::CameraWidget(std::string stream_name, VisionStreamType type, bool zoom, QWidget* parent) :
stream_name(stream_name), stream_type(type), zoomed_view(zoom), QOpenGLWidget(parent) {
setAttribute(Qt::WA_OpaquePaintEvent);
- connect(this, &CameraWidget::vipcThreadConnected, this, &CameraWidget::vipcConnected, Qt::BlockingQueuedConnection);
- connect(this, &CameraWidget::vipcThreadFrameReceived, this, &CameraWidget::vipcFrameReceived);
+ QObject::connect(this, &CameraWidget::vipcThreadConnected, this, &CameraWidget::vipcConnected, Qt::BlockingQueuedConnection);
+ QObject::connect(this, &CameraWidget::vipcThreadFrameReceived, this, &CameraWidget::vipcFrameReceived, Qt::QueuedConnection);
}
CameraWidget::~CameraWidget() {
@@ -162,13 +162,13 @@ void CameraWidget::initializeGL() {
}
void CameraWidget::showEvent(QShowEvent *event) {
- frames.clear();
if (!vipc_thread) {
vipc_thread = new QThread();
connect(vipc_thread, &QThread::started, [=]() { vipcThread(); });
connect(vipc_thread, &QThread::finished, vipc_thread, &QObject::deleteLater);
vipc_thread->start();
}
+ clearFrames();
}
void CameraWidget::hideEvent(QHideEvent *event) {
@@ -178,6 +178,7 @@ void CameraWidget::hideEvent(QHideEvent *event) {
vipc_thread->wait();
vipc_thread = nullptr;
}
+ clearFrames();
}
void CameraWidget::updateFrameMat() {
@@ -187,12 +188,17 @@ void CameraWidget::updateFrameMat() {
if (stream_type == VISION_STREAM_DRIVER) {
frame_mat = get_driver_view_transform(w, h, stream_width, stream_height);
} else {
- intrinsic_matrix = (stream_type == VISION_STREAM_WIDE_ROAD) ? ecam_intrinsic_matrix : fcam_intrinsic_matrix;
- zoom = (stream_type == VISION_STREAM_WIDE_ROAD) ? 2.5 : 1.1;
-
// Project point at "infinity" to compute x and y offsets
// to ensure this ends up in the middle of the screen
+ // for narrow come and a little lower for wide cam.
// TODO: use proper perspective transform?
+ if (stream_type == VISION_STREAM_WIDE_ROAD) {
+ intrinsic_matrix = ecam_intrinsic_matrix;
+ zoom = 2.0;
+ } else {
+ intrinsic_matrix = fcam_intrinsic_matrix;
+ zoom = 1.1;
+ }
const vec3 inf = {{1000., 0., 0.}};
const vec3 Ep = matvecmul3(calibration, inf);
const vec3 Kep = matvecmul3(intrinsic_matrix, Ep);
@@ -233,45 +239,37 @@ void CameraWidget::paintGL() {
glClearColor(bg.redF(), bg.greenF(), bg.blueF(), bg.alphaF());
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
- if (frames.empty()) return;
-
- int frame_idx = frames.size() - 1;
+ std::lock_guard lk(frame_lock);
- // Always draw latest frame until sync logic is more stable
- // for (frame_idx = 0; frame_idx < frames.size() - 1; frame_idx++) {
- // if (frames[frame_idx].first == draw_frame_id) break;
- // }
-
- // Log duplicate/dropped frames
- if (frames[frame_idx].first == prev_frame_id) {
- qDebug() << "Drawing same frame twice" << frames[frame_idx].first;
- } else if (frames[frame_idx].first != prev_frame_id + 1) {
- qDebug() << "Skipped frame" << frames[frame_idx].first;
+ // use previous texture if update() is called without new frame.
+ VisionBuf *frame = nullptr;
+ if (!frames.empty()) {
+ frame = frames.front().second;
+ frames.pop_front();
}
- prev_frame_id = frames[frame_idx].first;
glViewport(0, 0, width(), height());
glBindVertexArray(frame_vao);
glUseProgram(program->programId());
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- VisionBuf *frame = frames[frame_idx].second;
-
#ifdef QCOM2
glActiveTexture(GL_TEXTURE0);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_images[frame->idx]);
- assert(glGetError() == GL_NO_ERROR);
+ if (frame) {
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_images[frame->idx]);
+ assert(glGetError() == GL_NO_ERROR);
+ }
#else
glPixelStorei(GL_UNPACK_ROW_LENGTH, stream_stride);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, stream_width, stream_height, GL_RED, GL_UNSIGNED_BYTE, frame->y);
+ if (frame) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, stream_width, stream_height, GL_RED, GL_UNSIGNED_BYTE, frame->y);
assert(glGetError() == GL_NO_ERROR);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stream_stride/2);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, stream_width/2, stream_height/2, GL_RG, GL_UNSIGNED_BYTE, frame->uv);
+ if (frame) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, stream_width/2, stream_height/2, GL_RG, GL_UNSIGNED_BYTE, frame->uv);
assert(glGetError() == GL_NO_ERROR);
#endif
@@ -288,7 +286,6 @@ void CameraWidget::paintGL() {
void CameraWidget::vipcConnected(VisionIpcClient *vipc_client) {
makeCurrent();
- frames.clear();
stream_width = vipc_client->buffers[0].width;
stream_height = vipc_client->buffers[0].height;
stream_stride = vipc_client->buffers[0].stride;
@@ -339,11 +336,7 @@ void CameraWidget::vipcConnected(VisionIpcClient *vipc_client) {
updateFrameMat();
}
-void CameraWidget::vipcFrameReceived(VisionBuf *buf, uint32_t frame_id) {
- frames.push_back(std::make_pair(frame_id, buf));
- while (frames.size() > FRAME_BUFFER_SIZE) {
- frames.pop_front();
- }
+void CameraWidget::vipcFrameReceived() {
update();
}
@@ -354,11 +347,13 @@ void CameraWidget::vipcThread() {
while (!QThread::currentThread()->isInterruptionRequested()) {
if (!vipc_client || cur_stream_type != stream_type) {
+ clearFrames();
cur_stream_type = stream_type;
vipc_client.reset(new VisionIpcClient(stream_name, cur_stream_type, false));
}
if (!vipc_client->connected) {
+ clearFrames();
if (!vipc_client->connect(false)) {
QThread::msleep(100);
continue;
@@ -367,7 +362,15 @@ void CameraWidget::vipcThread() {
}
if (VisionBuf *buf = vipc_client->recv(&meta_main, 1000)) {
- emit vipcThreadFrameReceived(buf, meta_main.frame_id);
+ {
+ std::lock_guard lk(frame_lock);
+ frames.push_back(std::make_pair(meta_main.frame_id, buf));
+ while (frames.size() > FRAME_BUFFER_SIZE) {
+ qDebug() << "Skipped frame" << frames.front().first;
+ frames.pop_front();
+ }
+ }
+ emit vipcThreadFrameReceived();
}
}
@@ -378,3 +381,8 @@ void CameraWidget::vipcThread() {
egl_images.clear();
#endif
}
+
+void CameraWidget::clearFrames() {
+ std::lock_guard lk(frame_lock);
+ frames.clear();
+}
diff --git a/selfdrive/ui/qt/widgets/cameraview.h b/selfdrive/ui/qt/widgets/cameraview.h
index 9bcad935c0..aff3abc836 100644
--- a/selfdrive/ui/qt/widgets/cameraview.h
+++ b/selfdrive/ui/qt/widgets/cameraview.h
@@ -1,6 +1,7 @@
#pragma once
#include
+#include
#include
#include
@@ -37,7 +38,7 @@ public:
signals:
void clicked();
void vipcThreadConnected(VisionIpcClient *);
- void vipcThreadFrameReceived(VisionBuf *, quint32);
+ void vipcThreadFrameReceived();
protected:
void paintGL() override;
@@ -49,6 +50,7 @@ protected:
virtual void updateFrameMat();
void updateCalibration(const mat3 &calib);
void vipcThread();
+ void clearFrames();
bool zoomed_view;
GLuint frame_vao, frame_vbo, frame_ibo;
@@ -76,11 +78,11 @@ protected:
mat3 calibration = DEFAULT_CALIBRATION;
mat3 intrinsic_matrix = fcam_intrinsic_matrix;
+ std::mutex frame_lock;
std::deque> frames;
uint32_t draw_frame_id = 0;
- uint32_t prev_frame_id = 0;
protected slots:
void vipcConnected(VisionIpcClient *vipc_client);
- void vipcFrameReceived(VisionBuf *vipc_client, uint32_t frame_id);
+ void vipcFrameReceived();
};
diff --git a/selfdrive/ui/qt/widgets/controls.cc b/selfdrive/ui/qt/widgets/controls.cc
index a1ebf57b07..d3b77935df 100644
--- a/selfdrive/ui/qt/widgets/controls.cc
+++ b/selfdrive/ui/qt/widgets/controls.cc
@@ -41,7 +41,7 @@ AbstractControl::AbstractControl(const QString &title, const QString &desc, cons
hlayout->addWidget(title_label);
// value next to control button
- value = new QLabel();
+ value = new ElidedLabel();
value->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
value->setStyleSheet("color: #aaaaaa");
hlayout->addWidget(value);
@@ -70,7 +70,7 @@ AbstractControl::AbstractControl(const QString &title, const QString &desc, cons
}
void AbstractControl::hideEvent(QHideEvent *e) {
- if(description != nullptr) {
+ if (description != nullptr) {
description->hide();
}
}
diff --git a/selfdrive/ui/qt/widgets/controls.h b/selfdrive/ui/qt/widgets/controls.h
index c42716828f..f11f9baf59 100644
--- a/selfdrive/ui/qt/widgets/controls.h
+++ b/selfdrive/ui/qt/widgets/controls.h
@@ -65,7 +65,7 @@ protected:
QPushButton *title_label;
private:
- QLabel *value;
+ ElidedLabel *value;
QLabel *description = nullptr;
};
diff --git a/selfdrive/ui/qt/widgets/scrollview.cc b/selfdrive/ui/qt/widgets/scrollview.cc
index bd4309d8d0..5536593016 100644
--- a/selfdrive/ui/qt/widgets/scrollview.cc
+++ b/selfdrive/ui/qt/widgets/scrollview.cc
@@ -3,6 +3,8 @@
#include
#include
+// TODO: disable horizontal scrolling and resize
+
ScrollView::ScrollView(QWidget *w, QWidget *parent) : QScrollArea(parent) {
setWidget(w);
setWidgetResizable(true);
diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts
index 314a6b8338..a11333a54d 100644
--- a/selfdrive/ui/translations/main_ja.ts
+++ b/selfdrive/ui/translations/main_ja.ts
@@ -56,7 +56,7 @@
leave blank for automatic configuration
- 空白のままにして、自動設定にします
+ 自動で設定するには、空白のままにしてください。
Cellular Metered
@@ -136,7 +136,7 @@
PREVIEW
- 見る
+ プレビュー
Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off)
@@ -156,7 +156,7 @@
Review Training Guide
- 入門書を見る
+ 使い方の確認
REVIEW
@@ -168,7 +168,7 @@
Are you sure you want to review the training guide?
- 入門書を見てもよろしいですか?
+ 使い方の確認をしますか?
Regulatory
@@ -200,11 +200,11 @@
openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required.
- openpilot は、左または右の4°以内、上の5°または下の8°以内にデバイスを取付ける必要があります。キャリブレーションを引き続きます、リセットはほとんど必要ありません。
+ openpilotの本体は、左右4°以内、上5°、下8°以内の角度で取付ける必要があります。継続してキャリブレーションを続けているので、手動でリセットを行う必要はほぼありません。
Your device is pointed %1° %2 and %3° %4.
- このデバイスは%2の%1°、%4の%3°に向けます。
+ このデバイスは%2 %1°、%4 %3°の向きに設置されています。
down
@@ -309,7 +309,7 @@
MapETA
eta
- 予定到着時間
+ 到着予定時間
min
@@ -452,15 +452,15 @@ location set
Go to https://connect.comma.ai on your phone
- モバイルデバイスで「connect.comma.ai」にアクセスして
+ スマートフォンで「https://connect.comma.ai」にアクセスしてください。
Click "add new device" and scan the QR code on the right
- 「新しいデバイスを追加」を押すと、右側のQRコードをスキャンしてください
+ 「新しいデバイスを追加」を押し、右側のQRコードをスキャンしてください。
Bookmark connect.comma.ai to your home screen to use it like an app
- 「connect.comma.ai」をホーム画面に追加して、アプリのように使うことができます
+ 「connect.comma.ai」をホーム画面に追加して、アプリのように使うことができます。
@@ -608,7 +608,7 @@ location set
Toggles
- 切り替え
+ 機能設定
Software
@@ -627,7 +627,7 @@ location set
Power your device in a car with a harness or proceed at your own risk.
- 自己責任でハーネスから電源を供給してください。
+ 自己責任で実行を継続するか、ハーネスから電源を供給してください。
Power off
@@ -643,7 +643,7 @@ location set
Before we get on the road, let’s finish installation and cover some details.
- その前に、インストールを完了し、いくつかの詳細を説明します。
+ 道路に向かう前に、インストールを完了して使い方を確認しましょう。
Connect to Wi-Fi
@@ -655,7 +655,7 @@ location set
Continue without Wi-Fi
- Wi-Fi に未接続で続行
+ Wi-Fi に接続せずに続行
Waiting for internet
@@ -663,7 +663,7 @@ location set
Choose Software to Install
- インストールするソフトウェアを選びます
+ インストールするソフトウェアを選択してください
Dashcam
@@ -710,7 +710,7 @@ location set
Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer.
- デバイスを comma connect (connect.comma.ai)でペアリングし comma prime 特典を申請してください。
+ デバイスを comma connect (connect.comma.ai)でペアリングし、comma primeの特典を申請してください。
Pair device
@@ -836,7 +836,7 @@ location set
UNINSTALL
- アンインストール
+ 実行
Uninstall %1
@@ -859,7 +859,7 @@ location set
Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username.
- 警告: これは、GitHub の設定にあるすべての公開鍵への SSH アクセスを許可するものです。自分以外の GitHub のユーザー名を入力しないでください。コンマのスタッフが GitHub のユーザー名を追加するようお願いすることはありません。
+ 警告: これは、GitHub の設定にあるすべての公開鍵への SSH アクセスを許可するものです。自分以外の GitHub のユーザー名を入力しないでください。commaのスタッフが GitHub のユーザー名を追加するようお願いすることはありません。
ADD
@@ -871,7 +871,7 @@ location set
LOADING
- ローディング
+ 読み込み中
REMOVE
@@ -924,7 +924,7 @@ location set
Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off.
- アダプティブクルーズコントロールとレーンキーピングドライバーアシスト(openpilotシステム)。この機能を使用するには、常に注意が必要です。この設定を変更すると、車の電源が切れたときに有効になります。
+ openpilotによるアダプティブクルーズコントロールとレーンキーピングドライバーアシストを利用します。この機能を利用する際は、常に前方への注意が必要です。この設定を変更すると、車の電源が切れた時に反映されます。
Enable Lane Departure Warnings
@@ -932,11 +932,11 @@ location set
Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h).
- 時速31マイル(50km)を超えるスピードで走行中、ウインカーを作動させずに検出された車線ライン上に車両が触れた場合、車線に戻るアラートを受信します。
+ 時速31マイル(50km)を超えるスピードで走行中、ウインカーを作動させずに検出された車線ライン上に車両が触れた場合、手動で車線内に戻るように警告を行います。
Use Metric System
- メートル法を有効化
+ メートル法を使用
Display speed in km/h instead of mph.
@@ -952,7 +952,7 @@ location set
🌮 End-to-end longitudinal (extremely alpha) 🌮
- 🌮 エンドツーエンドのアクセル制御 (超アルファ版) 🌮
+ 🌮 エンドツーエンドのアクセル制御 (超α版) 🌮
Experimental openpilot longitudinal control
@@ -976,11 +976,11 @@ location set
Disengage On Accelerator Pedal
- アクセル踏むと openpilot をキャンセル
+ アクセルを踏むと openpilot を中断
When enabled, pressing the accelerator pedal will disengage openpilot.
- 有効な場合は、アクセルを踏むと openpilot をキャンセルします。
+ この機能を有効化すると、openpilotを利用中にアクセルを踏むとopenpilotによる運転サポートを中断します。
Show ETA in 24h Format
@@ -1003,11 +1003,11 @@ location set
Updater
Update Required
- 更新が必要です
+ アップデートが必要です
An operating system update is required. Connect your device to Wi-Fi for the fastest update experience. The download size is approximately 1GB.
- オペレーティングシステムのアップデートが必要です。Wi-Fi に接続することで、最速のアップデートを体験できます。ダウンロードサイズは約 1GB です。
+ オペレーティングシステムのアップデートが必要です。Wi-Fi に接続してアップデートする事をお勧めします。ダウンロードサイズは約 1GB です。
Connect to Wi-Fi
diff --git a/selfdrive/ui/translations/main_th.ts b/selfdrive/ui/translations/main_th.ts
index 5a8bf861df..95880e69c9 100644
--- a/selfdrive/ui/translations/main_th.ts
+++ b/selfdrive/ui/translations/main_th.ts
@@ -60,11 +60,11 @@
Cellular Metered
-
+ ลดการส่งข้อมูลผ่านเซลลูล่าร์
Prevent large data uploads when on a metered connection
-
+ ปิดการอัพโหลดข้อมูลขนาดใหญ่เมื่อเชื่อมต่อผ่านเซลลูล่าร์
@@ -802,54 +802,6 @@ location set
SoftwarePanel
-
- Git Branch
- Git Branch
-
-
- Git Commit
- Git Commit
-
-
- OS Version
- เวอร์ชันระบบปฏิบัติการ
-
-
- Version
- เวอร์ชั่น
-
-
- Last Update Check
- ตรวจสอบการอัปเดตล่าสุด
-
-
- The last time openpilot successfully checked for an update. The updater only runs while the car is off.
- ครั้งสุดท้ายที่ openpilot ตรวจสอบการอัปเดตสำเร็จ ตัวอัปเดตจะทำงานในขณะที่รถดับเครื่องอยู่เท่านั้น
-
-
- Check for Update
- ตรวจสอบการอัปเดต
-
-
- CHECKING
- กำลังตรวจสอบ
-
-
- Switch Branch
- เปลี่ยน Branch
-
-
- ENTER
- เปลี่ยน
-
-
- The new branch will be pulled the next time the updater runs.
- Branch ใหม่จะถูกติดตั้งในครั้งต่อไปที่ตัวอัปเดตทำงาน
-
-
- Enter branch name
- ใส่ชื่อ Branch
-
Uninstall %1
ถอนการติดตั้ง %1
@@ -862,45 +814,41 @@ location set
Are you sure you want to uninstall?
คุณแน่ใจหรือไม่ว่าต้องการถอนการติดตั้ง?
-
- failed to fetch update
- โหลดข้อมูลอัปเดตไม่สำเร็จ
-
CHECK
ตรวจสอบ
Updates are only downloaded while the car is off.
-
+ ตัวอัปเดตจะดำเนินการดาวน์โหลดเมื่อรถดับเครื่องยนต์อยู่เท่านั้น
Current Version
-
+ เวอร์ชั่นปัจจุบัน
Download
-
+ ดาวน์โหลด
Install Update
-
+ ติดตั้งตัวอัปเดต
INSTALL
-
+ ติดตั้ง
Target Branch
-
+ Branch ที่เลือก
SELECT
-
+ เลือก
Select a branch
-
+ เลือก Branch
@@ -1026,37 +974,29 @@ location set
Show map on left side when in split screen view.
แสดงแผนที่ด้านซ้ายของหน้าจอเมื่ออยู่ในโหมดแบ่งหน้าจอ
-
- openpilot Longitudinal Control
- openpilot การควบคุมการเร่งและลดความเร็ว
-
-
- openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB!
- openpilot จะปิดการใช้งานเรดาร์ของรถ และจะเข้าควบคุมการเร่งและเบรก คำเตือน: สิ่งนี้จะปิดระบบ AEB!
-
🌮 End-to-end longitudinal (extremely alpha) 🌮
-
+ 🌮 ควบคุมเร่ง/เบรคแบบ End-to-end (อยู่ขั้นพัฒนา) 🌮
Experimental openpilot longitudinal control
-
+ ทดลองใช้ระบบควบคุมการเร่ง/เบรคโดย openpilot
<b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b>
-
+ <b>คำเตือน: การควบคุมการเร่ง/เบรคโดย openpilot สำหรับรถคันนี้ยังอยู่ในขั้นทดลอง และระบบเบรคฉุกเฉินอัตโนมัติ (AEB) จะถูกปิด</b>
Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would. Super experimental.
-
+ ให้ openpilot ควบคุมการเร่ง/เบรคแบบ end-to-end โดย openpilot จะขับอย่างที่มนุษย์คิด ระบบยังอยู่ในขั้นทดลอง
openpilot longitudinal control is not currently available for this car.
-
+ ขณะนี้ยังไม่มีระบบควบคุมการเร่ง/เบรคโดย openpilot สำหรับรถคันนี้
Enable experimental longitudinal control to enable this.
-
+ เปิดใช้งานระบบควบคุมการเร่ง/เบรคขั้นทดลอง เพื่อเปิดใช้งานสิ่งนี้
diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc
index 1a6027bf7f..d1d72b4dad 100644
--- a/selfdrive/ui/ui.cc
+++ b/selfdrive/ui/ui.cc
@@ -23,8 +23,8 @@ static bool calib_frame_to_full_frame(const UIState *s, float in_x, float in_y,
const QRectF clip_region{-margin, -margin, s->fb_w + 2 * margin, s->fb_h + 2 * margin};
const vec3 pt = (vec3){{in_x, in_y, in_z}};
- const vec3 Ep = matvecmul3(s->scene.view_from_calib, pt);
- const vec3 KEp = matvecmul3(s->wide_camera ? ecam_intrinsic_matrix : fcam_intrinsic_matrix, Ep);
+ const vec3 Ep = matvecmul3(s->scene.wide_cam ? s->scene.view_from_wide_calib : s->scene.view_from_calib, pt);
+ const vec3 KEp = matvecmul3(s->scene.wide_cam ? ecam_intrinsic_matrix : fcam_intrinsic_matrix, Ep);
// Project.
QPointF point = s->car_space_transform.map(QPointF{KEp.v[0] / KEp.v[2], KEp.v[1] / KEp.v[2]});
@@ -121,17 +121,23 @@ static void update_state(UIState *s) {
if (sm.updated("liveCalibration")) {
auto rpy_list = sm["liveCalibration"].getLiveCalibration().getRpyCalib();
+ auto wfde_list = sm["liveCalibration"].getLiveCalibration().getWideFromDeviceEuler();
Eigen::Vector3d rpy;
- rpy << rpy_list[0], rpy_list[1], rpy_list[2];
+ Eigen::Vector3d wfde;
+ if (rpy_list.size() == 3) rpy << rpy_list[0], rpy_list[1], rpy_list[2];
+ if (wfde_list.size() == 3) wfde << wfde_list[0], wfde_list[1], wfde_list[2];
Eigen::Matrix3d device_from_calib = euler2rot(rpy);
+ Eigen::Matrix3d wide_from_device = euler2rot(wfde);
Eigen::Matrix3d view_from_device;
view_from_device << 0,1,0,
0,0,1,
1,0,0;
Eigen::Matrix3d view_from_calib = view_from_device * device_from_calib;
+ Eigen::Matrix3d view_from_wide_calib = view_from_device * wide_from_device * device_from_calib ;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
scene.view_from_calib.v[i*3 + j] = view_from_calib(i,j);
+ scene.view_from_wide_calib.v[i*3 + j] = view_from_wide_calib(i,j);
}
}
scene.calibration_valid = sm["liveCalibration"].getLiveCalibration().getCalStatus() == 1;
@@ -167,6 +173,17 @@ static void update_state(UIState *s) {
scene.light_sensor = std::max(100.0f - scale * sm["wideRoadCameraState"].getWideRoadCameraState().getExposureValPercent(), 0.0f);
}
scene.started = sm["deviceState"].getDeviceState().getStarted() && scene.ignition;
+
+ if (sm.updated("carState")) {
+ float v_ego = sm["carState"].getCarState().getVEgo();
+ // TODO: support replays without ecam by using fcam
+ // Wide or narrow cam dependent on speed
+ if ((v_ego < 10) || s->wide_cam_only) {
+ scene.wide_cam = true;
+ } else if (v_ego > 15) {
+ scene.wide_cam = false;
+ }
+ }
}
void ui_update_params(UIState *s) {
@@ -197,7 +214,7 @@ void UIState::updateStatus() {
if (scene.started) {
status = STATUS_DISENGAGED;
scene.started_frame = sm->frame;
- wide_camera = Params().getBool("WideCameraOnly");
+ wide_cam_only = Params().getBool("WideCameraOnly");
}
started_prev = scene.started;
emit offroadTransition(!scene.started);
@@ -219,7 +236,7 @@ UIState::UIState(QObject *parent) : QObject(parent) {
});
Params params;
- wide_camera = params.getBool("WideCameraOnly");
+ wide_cam_only = params.getBool("WideCameraOnly");
prime_type = std::atoi(params.get("PrimeType").c_str());
language = QString::fromStdString(params.get("LanguageSetting"));
diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h
index f60c26b59a..5a51dda8f8 100644
--- a/selfdrive/ui/ui.h
+++ b/selfdrive/ui/ui.h
@@ -87,7 +87,9 @@ const QColor bg_colors [] = {
typedef struct UIScene {
bool calibration_valid = false;
+ bool wide_cam = true;
mat3 view_from_calib = DEFAULT_CALIBRATION;
+ mat3 view_from_wide_calib = DEFAULT_CALIBRATION;
cereal::PandaState::PandaType pandaType;
// modelV2
@@ -130,7 +132,7 @@ public:
QString language;
QTransform car_space_transform;
- bool wide_camera;
+ bool wide_cam_only;
signals:
void uiUpdate(const UIState &s);
diff --git a/selfdrive/updated.py b/selfdrive/updated.py
index 57f957cfff..c261a92a84 100755
--- a/selfdrive/updated.py
+++ b/selfdrive/updated.py
@@ -280,17 +280,25 @@ class Updater:
# Write out current and new version info
def get_description(basedir: str) -> str:
+ if not os.path.exists(basedir):
+ return ""
+
version = ""
branch = ""
commit = ""
+ commit_date = ""
try:
branch = self.get_branch(basedir)
- commit = self.get_commit_hash(basedir)
+ commit = self.get_commit_hash(basedir)[:7]
with open(os.path.join(basedir, "common", "version.h")) as f:
version = f.read().split('"')[1]
+
+ commit_unix_ts = run(["git", "show", "-s", "--format=%ct", "HEAD"], basedir).rstrip()
+ dt = datetime.datetime.fromtimestamp(int(commit_unix_ts))
+ commit_date = dt.strftime("%b %d")
except Exception:
- pass
- return f"{version} / {branch} / {commit[:7]}"
+ cloudlog.exception("updater.get_description")
+ return f"{version} / {branch} / {commit} / {commit_date}"
self.params.put("UpdaterCurrentDescription", get_description(BASEDIR))
self.params.put("UpdaterCurrentReleaseNotes", parse_release_notes(BASEDIR))
self.params.put("UpdaterNewDescription", get_description(FINALIZED))
diff --git a/tools/cabana/.gitignore b/tools/cabana/.gitignore
index d7a552eabb..73879ab05d 100644
--- a/tools/cabana/.gitignore
+++ b/tools/cabana/.gitignore
@@ -4,4 +4,4 @@ moc_*
_cabana
settings
car_fingerprint_to_dbc.json
-
+tests/_test_cabana
diff --git a/tools/cabana/SConscript b/tools/cabana/SConscript
index 4e4e11dbd8..b7321e1f8d 100644
--- a/tools/cabana/SConscript
+++ b/tools/cabana/SConscript
@@ -18,5 +18,9 @@ cabana_env = qt_env.Clone()
prev_moc_path = cabana_env['QT_MOCHPREFIX']
cabana_env['QT_MOCHPREFIX'] = os.path.dirname(prev_moc_path) + '/cabana/moc_'
cabana_env.Execute('./generate_dbc_json.py --out car_fingerprint_to_dbc.json')
-cabana_env.Program('_cabana', ['cabana.cc', 'mainwin.cc', 'binaryview.cc', 'chartswidget.cc', 'historylog.cc', 'videowidget.cc', 'signaledit.cc', 'dbcmanager.cc',
+cabana_lib = cabana_env.Library("cabana_lib", ['mainwin.cc', 'binaryview.cc', 'chartswidget.cc', 'historylog.cc', 'videowidget.cc', 'signaledit.cc', 'dbcmanager.cc',
'canmessages.cc', 'messageswidget.cc', 'settings.cc', 'detailwidget.cc'], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
+cabana_env.Program('_cabana', ['cabana.cc', cabana_lib], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
+
+if GetOption('test'):
+ cabana_env.Program('tests/_test_cabana', ['tests/test_runner.cc', 'tests/test_cabana.cc', cabana_lib], LIBS=[cabana_libs])
diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc
index 26fecd8c38..91353e9726 100644
--- a/tools/cabana/binaryview.cc
+++ b/tools/cabana/binaryview.cc
@@ -20,13 +20,15 @@ BinaryView::BinaryView(QWidget *parent) : QTableView(parent) {
setItemDelegate(delegate);
horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
horizontalHeader()->hide();
- verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
+ verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setMouseTracking(true);
+ setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
+}
- QObject::connect(model, &QAbstractItemModel::modelReset, [this]() {
- setFixedHeight((CELL_HEIGHT + 1) * std::min(model->rowCount(), 8) + 2);
- });
+QSize BinaryView::sizeHint() const {
+ QSize sz = QTableView::sizeHint();
+ return {sz.width(), model->rowCount() <= 8 ? ((CELL_HEIGHT + 1) * model->rowCount() + 2) : sz.height()};
}
void BinaryView::highlight(const Signal *sig) {
@@ -108,9 +110,9 @@ void BinaryView::leaveEvent(QEvent *event) {
void BinaryView::setMessage(const QString &message_id) {
msg_id = message_id;
model->setMessage(message_id);
- resizeRowsToContents();
clearSelection();
updateState();
+ updateGeometry();
}
void BinaryView::updateState() {
diff --git a/tools/cabana/binaryview.h b/tools/cabana/binaryview.h
index 0f58e9ed20..060a2eef7f 100644
--- a/tools/cabana/binaryview.h
+++ b/tools/cabana/binaryview.h
@@ -61,6 +61,7 @@ public:
void highlight(const Signal *sig);
const Signal *hoveredSignal() const { return hovered_sig; }
QSet getOverlappingSignals() const;
+ QSize sizeHint() const override;
signals:
void signalHovered(const Signal *sig);
diff --git a/tools/cabana/canmessages.cc b/tools/cabana/canmessages.cc
index 1b46bd9da7..3ffc29916f 100644
--- a/tools/cabana/canmessages.cc
+++ b/tools/cabana/canmessages.cc
@@ -28,7 +28,7 @@ bool CANMessages::loadRoute(const QString &route, const QString &data_dir, bool
replay = new Replay(route, {"can", "roadEncodeIdx", "carParams"}, {}, nullptr, use_qcam ? REPLAY_FLAG_QCAMERA : 0, data_dir, this);
replay->setSegmentCacheLimit(settings.cached_segment_limit);
replay->installEventFilter(event_filter, this);
- QObject::connect(replay, &Replay::segmentsMerged, this, &CANMessages::segmentsMerged);
+ QObject::connect(replay, &Replay::segmentsMerged, this, &CANMessages::eventsMerged);
if (replay->load()) {
replay->start();
return true;
@@ -63,41 +63,26 @@ QList CANMessages::findSignalValues(const QString &id, const Signal *si
return ret;
}
-void CANMessages::process(QHash> *messages) {
+void CANMessages::process(QHash *messages) {
for (auto it = messages->begin(); it != messages->end(); ++it) {
- auto &msgs = can_msgs[it.key()];
- const auto &new_msgs = it.value();
- if (new_msgs.size() == settings.can_msg_log_size || msgs.empty()) {
- msgs = std::move(new_msgs);
- } else {
- msgs.insert(msgs.begin(), std::make_move_iterator(new_msgs.begin()), std::make_move_iterator(new_msgs.end()));
- if (msgs.size() > settings.can_msg_log_size) {
- msgs.resize(settings.can_msg_log_size);
- }
- }
+ can_msgs[it.key()] = it.value();
}
delete messages;
-
- if (current_sec < begin_sec || current_sec > end_sec) {
- // loop replay in selected range.
- seekTo(begin_sec);
- } else {
- emit updated();
- }
+ emit updated();
}
bool CANMessages::eventFilter(const Event *event) {
+ static std::unique_ptr> new_msgs;
static double prev_update_ts = 0;
- // drop packets when the GUI thread is calling seekTo. to make sure the current_sec is accurate.
- if (!seeking && event->which == cereal::Event::Which::CAN) {
- if (!received_msgs) {
- received_msgs.reset(new QHash>);
- received_msgs->reserve(1000);
+
+ if (event->which == cereal::Event::Which::CAN) {
+ if (!new_msgs) {
+ new_msgs.reset(new QHash);
+ new_msgs->reserve(1000);
}
- current_sec = (event->mono_time - replay->routeStartTime()) / (double)1e9;
- if (counters_begin_sec > current_sec) {
- // clear counters
+ double current_sec = replay->currentSeconds();
+ if (counters_begin_sec == 0) {
counters.clear();
counters_begin_sec = current_sec;
}
@@ -105,8 +90,10 @@ bool CANMessages::eventFilter(const Event *event) {
auto can_events = event->event.getCan();
for (const auto &c : can_events) {
QString id = QString("%1:%2").arg(c.getSrc()).arg(c.getAddress(), 1, 16);
- auto &list = (*received_msgs)[id];
- while (list.size() >= settings.can_msg_log_size) {
+
+ std::lock_guard lk(lock);
+ auto &list = received_msgs[id];
+ while (list.size() > settings.can_msg_log_size) {
list.pop_back();
}
CanData &data = list.emplace_front();
@@ -119,49 +106,27 @@ bool CANMessages::eventFilter(const Event *event) {
if (double delta = (current_sec - counters_begin_sec); delta > 0) {
data.freq = count / delta;
}
+ (*new_msgs)[id] = data;
}
double ts = millis_since_boot();
if ((ts - prev_update_ts) > (1000.0 / settings.fps)) {
prev_update_ts = ts;
// use pointer to avoid data copy in queued connection.
- emit received(received_msgs.release());
+ emit received(new_msgs.release());
}
}
return true;
}
-void CANMessages::seekTo(double ts) {
- seeking = true;
- replay->seekTo(ts, false);
- seeking = false;
+const std::deque CANMessages::messages(const QString &id) {
+ std::lock_guard lk(lock);
+ return received_msgs[id];
}
-void CANMessages::setRange(double min, double max) {
- if (begin_sec != min || end_sec != max) {
- begin_sec = min;
- end_sec = max;
- is_zoomed = begin_sec != event_begin_sec || end_sec != event_end_sec;
- emit rangeChanged(min, max);
- }
-}
-
-void CANMessages::segmentsMerged() {
- auto events = replay->events();
- if (!events || events->empty()) return;
-
- auto it = std::find_if(events->begin(), events->end(), [=](const Event *e) { return e->which == cereal::Event::Which::CAN; });
- event_begin_sec = it == events->end() ? 0 : ((*it)->mono_time - replay->routeStartTime()) / (double)1e9;
- event_end_sec = double(events->back()->mono_time - replay->routeStartTime()) / 1e9;
- if (!is_zoomed) {
- begin_sec = event_begin_sec;
- end_sec = event_end_sec;
- }
- emit eventsMerged();
-}
-
-void CANMessages::resetRange() {
- setRange(event_begin_sec, event_end_sec);
+void CANMessages::seekTo(double ts) {
+ replay->seekTo(ts, false);
+ counters_begin_sec = 0;
}
void CANMessages::settingChanged() {
diff --git a/tools/cabana/canmessages.h b/tools/cabana/canmessages.h
index d1bb1b73b6..5fbccdbe12 100644
--- a/tools/cabana/canmessages.h
+++ b/tools/cabana/canmessages.h
@@ -2,7 +2,7 @@
#include
#include
-#include