mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-08-03 10:49:25 +08:00
Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f24986ee7a | |||
| 45739d199c | |||
| 29c143e6ee | |||
| 6d51225a9a | |||
| 2d130b41c3 | |||
| cacdb08b05 | |||
| ed5dbc4dd2 | |||
| 028a468290 | |||
| 5b3acfbaf6 | |||
| d54bc4d0b4 | |||
| bb1ed2489c | |||
| aee0a96e02 | |||
| cc5a6b7fa4 | |||
| 4cb50eeb96 | |||
| 3014e01865 | |||
| fbde6d8d07 | |||
| 457c82a3b1 | |||
| e73c5dfc1d | |||
| 31accc75f9 | |||
| f34d61b9bd | |||
| b4b494e6e9 | |||
| deafc23ea3 | |||
| f113940993 | |||
| ddcabf9dea | |||
| 16354d4f63 | |||
| 73e620245a | |||
| 2a62ca2600 | |||
| 2d55dd0d12 | |||
| 61b9db6666 | |||
| 5135802760 | |||
| be46484b6e | |||
| 12f6278f96 | |||
| 53bed607bb | |||
| 6aaba7bda4 | |||
| 8879d158f8 | |||
| 3889accb5d | |||
| c8bef28d26 | |||
| 3798118a76 | |||
| 6e9a2eefeb | |||
| 6efef44bbe | |||
| 4488ad70dd | |||
| 9e3f15245e | |||
| 99b61454bd | |||
| cc720d2800 | |||
| 69b43269c1 | |||
| e2872e6f32 | |||
| a3a202fa87 | |||
| a5d6fe83ae | |||
| a70f9a642d | |||
| c63c7d8bfd | |||
| 931e79e801 | |||
| bc3f0fa6a4 | |||
| 121a863cbf | |||
| 7f146c5cce | |||
| 3b30419dee | |||
| ddad143b7f | |||
| efa292ca3f | |||
| 28c85087dc | |||
| ca0a00b546 | |||
| 6da758f53e | |||
| cb4ba22ac7 | |||
| 78d35cb24e | |||
| 3cc0656961 | |||
| 675e9957f9 | |||
| f2526cf0d1 | |||
| cc4ebe717b | |||
| b54d7d486e | |||
| 814b623bfe | |||
| 72b36d5482 | |||
| cc59dabc09 | |||
| e5f9885288 | |||
| 4e81036d6c | |||
| a0b09e7154 | |||
| 3097d451fe | |||
| f90cfc2d0a | |||
| cfc8878392 | |||
| da5a198bd0 | |||
| cecf82e951 | |||
| 43b87b53f5 | |||
| 9d84814aba | |||
| 30718cba8b | |||
| 48b7567e38 | |||
| ddb1c92b2e | |||
| af5ea57188 | |||
| 4be8029ead | |||
| 480da5f8b8 | |||
| 8d39d5045d | |||
| 455aa3d140 | |||
| 47bd75a1b1 | |||
| c1d08539e7 | |||
| e8b4d7c5a8 | |||
| 659c2ab446 | |||
| 8dff996b8b | |||
| 08ec79db30 | |||
| a88412f25a | |||
| 73075c8b5a | |||
| 859b2fb29e | |||
| 59a1122851 | |||
| 4a9894d843 | |||
| 385d8c20d2 | |||
| 43791061bb | |||
| 8eff79892c | |||
| b2cdfc09ae | |||
| 5b674d2231 | |||
| ddf69de7e0 | |||
| 69f88da9c5 | |||
| 117ad3b3ef | |||
| 6f3e44f76e | |||
| c70db1030c |
@@ -14,6 +14,9 @@ sunnypilot - 0.9.8.0 (2024-xx-xx)
|
||||
* Provides a more responsive and tailored driving experience compared to predefined settings
|
||||
* UPDATED: Driving Personality: Updated mode names
|
||||
* Aggressive, Moderate, Standard, Relaxed
|
||||
* NEW❗: Hyundai CAN: Enable Cruise Main by Default
|
||||
* Set CRUISE MAIN to ON by default when the car starts, without engaging MADS
|
||||
* This feature only applies when "openpilot Longitudinal Control (Alpha)" is enabled under the "Toggles" menu
|
||||
* NEW❗: Toyota - Enhanced Blind Spot Monitor (BSM) thanks to arne182, rav4kumar, and eFiniLan!
|
||||
* Enables Blind Spot Monitor (BSM) signals parsing in sunnypilot using the factory Blind Spot Monitor (BSM)
|
||||
* sunnypilot will use debugging CAN messages to receive unfiltered BSM signals, allowing detection of more objects
|
||||
@@ -37,6 +40,9 @@ sunnypilot - 0.9.8.0 (2024-xx-xx)
|
||||
* Auto Unlock by Shift to P: All doors are automatically unlocked when shifting the shift lever to P
|
||||
* FIXED: Driving Personality:
|
||||
* Maniac mode now correctly enforced when selected
|
||||
* FIXED: Experimental Model Distance Button Hold
|
||||
* Experimental Model toggle with distance button hold no longer changes Personality
|
||||
* Personality setting remains consistent when switching between Chill and Experimental Mode
|
||||
* UI Updates
|
||||
* Display Metrics Below Chevron
|
||||
* NEW❗: Time to Lead Car
|
||||
|
||||
+2
-1
@@ -137,6 +137,7 @@ struct CarEvent @0x9b1657f34caf3ad3 {
|
||||
speedLimitPreActive @139;
|
||||
speedLimitConfirmed @140;
|
||||
torqueNNLoad @141;
|
||||
hyundaiRadarTracksAvailable @142;
|
||||
|
||||
radarCanErrorDEPRECATED @15;
|
||||
communityFeatureDisallowedDEPRECATED @62;
|
||||
@@ -250,7 +251,7 @@ struct CarState {
|
||||
struct CustomStockLong {
|
||||
cruiseButton @0 :Int16;
|
||||
finalSpeedKph @1 :Float32;
|
||||
vCruiseKphPrev @2 :Float32;
|
||||
vCruiseKphPrevDEPRECATED @2 :Float32;
|
||||
targetSpeed @3 :Float32;
|
||||
vSetDis @4 :Float32;
|
||||
speedDiff @5 :Float32;
|
||||
|
||||
+18
-1
@@ -203,7 +203,24 @@ struct ModelDataV2SP @0xf98d843bfd7004a3 {
|
||||
modelCapabilities @4 :UInt32;
|
||||
}
|
||||
|
||||
struct CustomReserved7 @0xb86e6369214c01c8 {
|
||||
struct CarControlSP @0xb86e6369214c01c8 {
|
||||
customStockLongitudinalControl @0 :CustomStockLongitudinalControl;
|
||||
|
||||
struct CustomStockLongitudinalControl {
|
||||
state @0 :ButtonControlState;
|
||||
cruiseButton @1 :Int16;
|
||||
finalSpeedKphDEPRECATED @2 :Float32;
|
||||
vTarget @3 :Float32;
|
||||
vCruiseCluster @4 :Float32;
|
||||
|
||||
enum ButtonControlState {
|
||||
inactive @0; # No button press or default state
|
||||
loading @1; # Loading state before transitioning to accelerating or decelerating
|
||||
accelerating @2; # Increasing speed
|
||||
decelerating @3; # Decreasing speed
|
||||
holding @4; # Holding steady speed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CustomReserved8 @0xf416ec09499d9d19 {
|
||||
|
||||
+1
-1
@@ -2388,7 +2388,7 @@ struct Event {
|
||||
liveMapDataSP @111 :Custom.LiveMapDataSP;
|
||||
e2eLongStateSP @112 :Custom.E2eLongStateSP;
|
||||
modelV2SP @113 :Custom.ModelDataV2SP;
|
||||
customReserved7 @114 :Custom.CustomReserved7;
|
||||
carControlSP @114 :Custom.CarControlSP;
|
||||
customReserved8 @115 :Custom.CustomReserved8;
|
||||
customReserved9 @116 :Custom.CustomReserved9;
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ _services: dict[str, tuple] = {
|
||||
"liveMapDataSP": (True, 0.),
|
||||
"e2eLongStateSP": (True, 0.),
|
||||
"modelV2SP": (True, 20., 40),
|
||||
"carControlSP": (True, 100., 10),
|
||||
|
||||
# debug
|
||||
"uiDebug": (True, 0., 1),
|
||||
|
||||
@@ -261,9 +261,13 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"HandsOnWheelMonitoring", PERSISTENT | BACKUP},
|
||||
{"HasAcceptedTermsSP", PERSISTENT},
|
||||
{"HideVEgoUi", PERSISTENT | BACKUP},
|
||||
{"HyundaiCruiseMainDefault", PERSISTENT | BACKUP},
|
||||
{"HkgSmoothStop", PERSISTENT | BACKUP},
|
||||
{"HotspotOnBoot", PERSISTENT},
|
||||
{"HotspotOnBootConfirmed", PERSISTENT},
|
||||
{"HyundaiRadarTracksAvailable", PERSISTENT},
|
||||
{"HyundaiRadarTracksAvailableCache", PERSISTENT},
|
||||
{"HyundaiRadarTracksAvailablePersistent", PERSISTENT},
|
||||
{"LastCarModel", PERSISTENT | BACKUP},
|
||||
{"LastSpeedLimitSignTap", PERSISTENT},
|
||||
{"LastSunnylinkPingTime", CLEAR_ON_MANAGER_START},
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../sunnypilot/
|
||||
@@ -218,7 +218,7 @@ def create_gas_interceptor_command(packer, gas_amount, idx):
|
||||
values["GAS_COMMAND"] = gas_amount * 255.
|
||||
values["GAS_COMMAND2"] = gas_amount * 255.
|
||||
|
||||
dat = packer.make_can_msg("GAS_COMMAND", 0, values)[2]
|
||||
dat = packer.make_can_msg("GAS_COMMAND", 0, values)[1]
|
||||
|
||||
checksum = crc8_pedal(dat[:-1])
|
||||
values["CHECKSUM_PEDAL"] = checksum
|
||||
|
||||
+15
-1
@@ -31,7 +31,7 @@ class Car:
|
||||
def __init__(self, CI=None):
|
||||
self.can_sock = messaging.sub_sock('can', timeout=20)
|
||||
self.sm = messaging.SubMaster(['pandaStates', 'carControl', 'onroadEvents'])
|
||||
self.pm = messaging.PubMaster(['sendcan', 'carState', 'carParams', 'carOutput'])
|
||||
self.pm = messaging.PubMaster(['sendcan', 'carState', 'carParams', 'carOutput', 'carControlSP'])
|
||||
|
||||
self.can_rcv_cum_timeout_counter = 0
|
||||
|
||||
@@ -70,6 +70,12 @@ class Car:
|
||||
|
||||
if self.CP.customStockLongAvailable and self.CP.pcmCruise and self.params.get_bool("CustomStockLong"):
|
||||
self.CP.pcmCruiseSpeed = False
|
||||
services = self.sm.data.keys() | {'longitudinalPlanSP'}
|
||||
self.sm = messaging.SubMaster(list(services))
|
||||
|
||||
cslc_path = f'openpilot.sunnypilot.selfdrive.car.{self.CP.carName}.custom_stock_longitudinal_controller'
|
||||
CustomStockLongitudinalController = __import__(cslc_path + '.controller', fromlist=['CustomStockLongitudinalController']).CustomStockLongitudinalController
|
||||
self.custom_stock_longitudinal_controller = CustomStockLongitudinalController(self, self.CI.CC, self.CI.CS, self.CP)
|
||||
|
||||
openpilot_enabled_toggle = self.params.get_bool("OpenpilotEnabledToggle")
|
||||
|
||||
@@ -175,8 +181,16 @@ class Car:
|
||||
# send car controls over can
|
||||
now_nanos = self.can_log_mono_time if REPLAY else int(time.monotonic() * 1e9)
|
||||
self.last_actuators_output, can_sends = self.CI.apply(CC, now_nanos)
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
can_sends.extend(self.custom_stock_longitudinal_controller.update(CS, CC))
|
||||
self.pm.send('sendcan', can_list_to_can_capnp(can_sends, msgtype='sendcan', valid=CS.canValid))
|
||||
|
||||
cc_send_sp = messaging.new_message('carControlSP')
|
||||
cc_send_sp.valid = self.sm.all_checks(['carControl'])
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
cc_send_sp.carControlSP.customStockLongitudinalControl = self.custom_stock_longitudinal_controller.state_publish()
|
||||
self.pm.send('carControlSP', cc_send_sp)
|
||||
|
||||
self.CC_prev = CC
|
||||
|
||||
def step(self):
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
from cereal import car
|
||||
|
||||
import cereal.messaging as messaging
|
||||
from common.conversions import Conversions as CV
|
||||
from opendbc.can.packer import CANPacker
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.selfdrive.car import DT_CTRL, apply_meas_steer_torque_limits
|
||||
from openpilot.selfdrive.car import apply_meas_steer_torque_limits
|
||||
from openpilot.selfdrive.car.chrysler import chryslercan
|
||||
from openpilot.selfdrive.car.chrysler.values import RAM_CARS, RAM_DT, CarControllerParams, ChryslerFlags, ChryslerFlagsSP
|
||||
from openpilot.selfdrive.car.interfaces import CarControllerBase, FORWARD_GEARS
|
||||
from openpilot.selfdrive.controls.lib.drive_helpers import FCA_V_CRUISE_MIN
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
|
||||
@@ -26,64 +22,9 @@ class CarController(CarControllerBase):
|
||||
self.packer = CANPacker(dbc_name)
|
||||
self.params = CarControllerParams(CP)
|
||||
|
||||
self.sm = messaging.SubMaster(['longitudinalPlanSP'])
|
||||
self.param_s = Params()
|
||||
self.last_speed_limit_sign_tap_prev = False
|
||||
self.speed_limit = 0.
|
||||
self.speed_limit_offset = 0
|
||||
self.timer = 0
|
||||
self.final_speed_kph = 0
|
||||
self.init_speed = 0
|
||||
self.current_speed = 0
|
||||
self.v_set_dis = 0
|
||||
self.v_cruise_min = 0
|
||||
self.button_type = 0
|
||||
self.button_select = 0
|
||||
self.button_count = 0
|
||||
self.target_speed = 0
|
||||
self.t_interval = 7
|
||||
self.slc_active_stock = False
|
||||
self.sl_force_active_timer = 0
|
||||
self.v_tsc_state = 0
|
||||
self.slc_state = 0
|
||||
self.m_tsc_state = 0
|
||||
self.cruise_button = None
|
||||
self.speed_diff = 0
|
||||
self.v_tsc = 0
|
||||
self.m_tsc = 0
|
||||
self.steady_speed = 0
|
||||
self.button_frame = 0
|
||||
|
||||
def update(self, CC, CS, now_nanos):
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
self.sm.update(0)
|
||||
|
||||
if self.sm.updated['longitudinalPlanSP']:
|
||||
self.v_tsc_state = self.sm['longitudinalPlanSP'].visionTurnControllerState
|
||||
self.slc_state = self.sm['longitudinalPlanSP'].speedLimitControlState
|
||||
self.m_tsc_state = self.sm['longitudinalPlanSP'].turnSpeedControlState
|
||||
self.speed_limit = self.sm['longitudinalPlanSP'].speedLimit
|
||||
self.speed_limit_offset = self.sm['longitudinalPlanSP'].speedLimitOffset
|
||||
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
|
||||
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
|
||||
|
||||
self.v_cruise_min = FCA_V_CRUISE_MIN[CS.params_list.is_metric] * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1)
|
||||
|
||||
can_sends = []
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if not self.last_speed_limit_sign_tap_prev and CS.params_list.last_speed_limit_sign_tap:
|
||||
self.sl_force_active_timer = self.frame
|
||||
self.param_s.put_bool_nonblocking("LastSpeedLimitSignTap", False)
|
||||
self.last_speed_limit_sign_tap_prev = CS.params_list.last_speed_limit_sign_tap
|
||||
|
||||
sl_force_active = CS.params_list.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not CS.params_list.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (CS.params_list.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
slc_active = not sl_inactive and not sl_temp_inactive
|
||||
|
||||
self.slc_active_stock = slc_active
|
||||
|
||||
lkas_active = CC.latActive and CS.madsEnabled
|
||||
|
||||
if self.frame % 10 == 0 and self.CP.carFingerprint not in RAM_CARS:
|
||||
@@ -114,20 +55,6 @@ class CarController(CarControllerBase):
|
||||
self.last_button_frame = self.frame
|
||||
can_sends.append(chryslercan.create_cruise_buttons(self.packer, CS.button_counter + 1, das_bus, self.CP, resume=True))
|
||||
|
||||
if not (CC.cruiseControl.cancel or CC.cruiseControl.resume) and not self.CP.pcmCruiseSpeed and CS.out.cruiseState.enabled:
|
||||
self.button_frame += 1
|
||||
button_counter_offset = [1, 1, 0, None][self.button_frame % 4]
|
||||
if ram_cars:
|
||||
self.cruise_button = self.get_cruise_buttons(CS, CC.vCruise)
|
||||
elif button_counter_offset is not None:
|
||||
self.cruise_button = self.get_cruise_buttons(CS, CC.vCruise)
|
||||
|
||||
if self.cruise_button is not None:
|
||||
if ram_cars:
|
||||
can_sends.append(chryslercan.create_cruise_buttons(self.packer, CS.button_counter, das_bus, self.CP, buttons=self.cruise_button))
|
||||
elif button_counter_offset is not None:
|
||||
can_sends.append(chryslercan.create_cruise_buttons(self.packer, CS.button_counter + button_counter_offset, das_bus, self.CP, buttons=self.cruise_button))
|
||||
|
||||
# HUD alerts
|
||||
if self.frame % 25 == 0:
|
||||
if CS.lkas_car_model != -1:
|
||||
@@ -179,122 +106,3 @@ class CarController(CarControllerBase):
|
||||
new_actuators.steerOutputCan = self.apply_steer_last
|
||||
|
||||
return new_actuators, can_sends
|
||||
|
||||
# multikyd methods, sunnyhaibin logic
|
||||
def get_cruise_buttons_status(self, CS):
|
||||
if not CS.out.cruiseState.enabled:
|
||||
for be in CS.out.buttonEvents:
|
||||
if be.type in (ButtonType.accelCruise, ButtonType.decelCruise, ButtonType.resumeCruise) and be.pressed:
|
||||
self.timer = 40
|
||||
elif self.timer:
|
||||
self.timer -= 1
|
||||
else:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def get_target_speed(self, v_cruise_kph_prev):
|
||||
v_cruise_kph = v_cruise_kph_prev
|
||||
if self.slc_state > 1:
|
||||
v_cruise_kph = (self.speed_limit + self.speed_limit_offset) * CV.MS_TO_KPH
|
||||
if not self.slc_active_stock:
|
||||
v_cruise_kph = v_cruise_kph_prev
|
||||
return v_cruise_kph
|
||||
|
||||
def get_button_type(self, button_type):
|
||||
self.type_status = "type_" + str(button_type)
|
||||
self.button_picker = getattr(self, self.type_status, lambda: "default")
|
||||
return self.button_picker()
|
||||
|
||||
def reset_button(self):
|
||||
if self.button_type != 3:
|
||||
self.button_type = 0
|
||||
|
||||
def type_default(self):
|
||||
self.button_type = 0
|
||||
return None
|
||||
|
||||
def type_0(self):
|
||||
self.button_count = 0
|
||||
self.target_speed = self.init_speed
|
||||
self.speed_diff = self.target_speed - self.v_set_dis
|
||||
if self.target_speed > self.v_set_dis:
|
||||
self.button_type = 1
|
||||
elif self.target_speed < self.v_set_dis and self.v_set_dis > self.v_cruise_min:
|
||||
self.button_type = 2
|
||||
return None
|
||||
|
||||
def type_1(self):
|
||||
cruise_button = 1
|
||||
self.button_count += 1
|
||||
if self.target_speed <= self.v_set_dis:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
elif self.button_count > 5:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
return cruise_button
|
||||
|
||||
def type_2(self):
|
||||
cruise_button = 2
|
||||
self.button_count += 1
|
||||
if self.target_speed >= self.v_set_dis or self.v_set_dis <= self.v_cruise_min:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
elif self.button_count > 5:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
return cruise_button
|
||||
|
||||
def type_3(self):
|
||||
cruise_button = None
|
||||
self.button_count += 1
|
||||
if self.button_count > self.t_interval:
|
||||
self.button_type = 0
|
||||
return cruise_button
|
||||
|
||||
def get_curve_speed(self, target_speed_kph, v_cruise_kph_prev):
|
||||
if self.v_tsc_state != 0:
|
||||
vision_v_cruise_kph = self.v_tsc * CV.MS_TO_KPH
|
||||
if int(vision_v_cruise_kph) == int(v_cruise_kph_prev):
|
||||
vision_v_cruise_kph = 255
|
||||
else:
|
||||
vision_v_cruise_kph = 255
|
||||
if self.m_tsc_state > 1:
|
||||
map_v_cruise_kph = self.m_tsc * CV.MS_TO_KPH
|
||||
if int(map_v_cruise_kph) == 0.0:
|
||||
map_v_cruise_kph = 255
|
||||
else:
|
||||
map_v_cruise_kph = 255
|
||||
curve_speed = self.curve_speed_hysteresis(min(vision_v_cruise_kph, map_v_cruise_kph) + 2 * CV.MPH_TO_KPH)
|
||||
return min(target_speed_kph, curve_speed)
|
||||
|
||||
def get_button_control(self, CS, final_speed, v_cruise_kph_prev):
|
||||
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1))
|
||||
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not CS.params_list.is_metric else CV.MS_TO_KPH))
|
||||
cruise_button = self.get_button_type(self.button_type)
|
||||
return cruise_button
|
||||
|
||||
def curve_speed_hysteresis(self, cur_speed: float, hyst=(0.75 * CV.MPH_TO_KPH)):
|
||||
if cur_speed > self.steady_speed:
|
||||
self.steady_speed = cur_speed
|
||||
elif cur_speed < self.steady_speed - hyst:
|
||||
self.steady_speed = cur_speed
|
||||
return self.steady_speed
|
||||
|
||||
def get_cruise_buttons(self, CS, v_cruise_kph_prev):
|
||||
cruise_button = None
|
||||
if not self.get_cruise_buttons_status(CS):
|
||||
pass
|
||||
elif CS.out.cruiseState.enabled:
|
||||
set_speed_kph = self.get_target_speed(v_cruise_kph_prev)
|
||||
if self.slc_state > 1:
|
||||
target_speed_kph = set_speed_kph
|
||||
else:
|
||||
target_speed_kph = min(v_cruise_kph_prev, set_speed_kph)
|
||||
if self.v_tsc_state != 0 or self.m_tsc_state > 1:
|
||||
self.final_speed_kph = self.get_curve_speed(target_speed_kph, v_cruise_kph_prev)
|
||||
else:
|
||||
self.final_speed_kph = target_speed_kph
|
||||
|
||||
cruise_button = self.get_button_control(CS, self.final_speed_kph, v_cruise_kph_prev) # MPH/KPH based button presses
|
||||
return cruise_button
|
||||
|
||||
@@ -65,14 +65,9 @@ def create_lkas_command(packer, CP, apply_steer, lkas_control_bit):
|
||||
|
||||
def create_cruise_buttons(packer, frame, bus, CP, cruise_buttons_msg=None, buttons=0, cancel=False, resume=False):
|
||||
|
||||
acc_accel = 1 if buttons == 1 else 0
|
||||
acc_decel = 1 if buttons == 2 else 0
|
||||
|
||||
values = {
|
||||
"ACC_Cancel": cancel,
|
||||
"ACC_Resume": resume,
|
||||
"ACC_Accel": acc_accel,
|
||||
"ACC_Decel": acc_decel,
|
||||
"COUNTER": frame % 0x10,
|
||||
}
|
||||
|
||||
|
||||
@@ -98,10 +98,9 @@ class CarInterface(CarInterfaceBase):
|
||||
*create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}),
|
||||
]
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret)
|
||||
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
|
||||
self.CS.button_events, c.vCruise,
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, c.vCruise, self.CS.accEnabled,
|
||||
enable_buttons=(ButtonType.accelCruise, ButtonType.decelCruise, ButtonType.resumeCruise) if not self.CP.pcmCruiseSpeed else
|
||||
(ButtonType.accelCruise, ButtonType.decelCruise),
|
||||
resume_button=(ButtonType.resumeCruise,) if not self.CP.pcmCruiseSpeed else
|
||||
@@ -114,16 +113,16 @@ class CarInterface(CarInterfaceBase):
|
||||
if any(b.type == ButtonType.altButton1 and b.pressed for b in self.CS.button_events):
|
||||
self.CS.madsEnabled = not self.CS.madsEnabled
|
||||
self.CS.lkas_disabled = not self.CS.lkas_disabled
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret, self.CS.madsEnabled)
|
||||
else:
|
||||
self.CS.madsEnabled = False
|
||||
self.CS.madsEnabled = self.get_sp_started_mads(ret, self.CS)
|
||||
self.CS.madsEnabled = self.get_sp_started_mads(ret, self.CS.madsEnabled)
|
||||
|
||||
if not self.CP.pcmCruise or (self.CP.pcmCruise and self.CP.minEnableSpeed > 0) or not self.CP.pcmCruiseSpeed:
|
||||
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
ret.cruiseState.enabled = ret.cruiseState.enabled if not self.enable_mads else False if self.CP.pcmCruise else self.CS.accEnabled
|
||||
|
||||
if self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed:
|
||||
@@ -136,7 +135,7 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.accEnabled = False
|
||||
self.CS.accEnabled = ret.cruiseState.enabled or self.CS.accEnabled
|
||||
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=bool(self.CS.distance_button))
|
||||
ret = self.get_sp_common_state(ret)
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -146,7 +145,7 @@ class CarInterface(CarInterfaceBase):
|
||||
# events
|
||||
events = self.create_common_events(ret, c, extra_gears=[car.CarState.GearShifter.low], pcm_enable=False)
|
||||
|
||||
events, ret = self.create_sp_events(self.CS, ret, events)
|
||||
events, ret = self.create_sp_events(ret, events)
|
||||
|
||||
# Low speed steer alert hysteresis logic
|
||||
if self.CP.carFingerprint in RAM_DT:
|
||||
@@ -162,10 +161,6 @@ class CarInterface(CarInterfaceBase):
|
||||
if self.low_speed_alert:
|
||||
events.add(car.CarEvent.EventName.belowSteerSpeed)
|
||||
|
||||
ret.customStockLong = self.CS.update_custom_stock_long(self.CC.cruise_button, self.CC.final_speed_kph,
|
||||
self.CC.target_speed, self.CC.v_set_dis,
|
||||
self.CC.speed_diff, self.CC.button_type)
|
||||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
return ret
|
||||
|
||||
@@ -79,10 +79,9 @@ class CarInterface(CarInterfaceBase):
|
||||
*create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}),
|
||||
]
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret)
|
||||
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
|
||||
self.CS.button_events, c.vCruise)
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, c.vCruise, self.CS.accEnabled)
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if self.enable_mads:
|
||||
@@ -90,15 +89,15 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.madsEnabled = True
|
||||
if any(b.type == ButtonType.altButton1 and b.pressed for b in self.CS.button_events):
|
||||
self.CS.madsEnabled = not self.CS.madsEnabled
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret, self.CS.madsEnabled)
|
||||
else:
|
||||
self.CS.madsEnabled = False
|
||||
|
||||
if not self.CP.pcmCruise or (self.CP.pcmCruise and self.CP.minEnableSpeed > 0):
|
||||
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
ret.cruiseState.enabled = ret.cruiseState.enabled if not self.enable_mads else False if self.CP.pcmCruise else self.CS.accEnabled
|
||||
|
||||
if self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed:
|
||||
@@ -106,7 +105,7 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.accEnabled = False
|
||||
self.CS.accEnabled = ret.cruiseState.enabled or self.CS.accEnabled
|
||||
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=bool(self.CS.distance_button))
|
||||
ret = self.get_sp_common_state(ret)
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -115,7 +114,7 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
events = self.create_common_events(ret, c, extra_gears=[GearShifter.manumatic], pcm_enable=False)
|
||||
|
||||
events, ret = self.create_sp_events(self.CS, ret, events)
|
||||
events, ret = self.create_sp_events(ret, events)
|
||||
|
||||
if not self.CS.vehicle_sensors_valid:
|
||||
events.add(car.CarEvent.EventName.vehicleSensorsInvalid)
|
||||
|
||||
@@ -204,8 +204,6 @@ class CarInterface(CarInterfaceBase):
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_loopback)
|
||||
|
||||
distance_button = 0
|
||||
|
||||
# Don't add event if transitioning from INIT, unless it's to an actual button
|
||||
if self.CS.cruise_buttons != CruiseButtons.UNPRESS or self.CS.prev_cruise_buttons != CruiseButtons.INIT:
|
||||
self.CS.button_events = [
|
||||
@@ -214,21 +212,19 @@ class CarInterface(CarInterfaceBase):
|
||||
*create_button_events(self.CS.distance_button, self.CS.prev_distance_button,
|
||||
{1: ButtonType.gapAdjustCruise})
|
||||
]
|
||||
distance_button = self.CS.distance_button
|
||||
|
||||
self.CS.button_events = [
|
||||
*self.CS.button_events,
|
||||
*create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}),
|
||||
]
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret)
|
||||
|
||||
if not self.CP.pcmCruise:
|
||||
if any(b.type == ButtonType.accelCruise and b.pressed for b in self.CS.button_events):
|
||||
self.CS.accEnabled = True
|
||||
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
|
||||
self.CS.button_events, c.vCruise)
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, c.vCruise, self.CS.accEnabled)
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if self.enable_mads:
|
||||
@@ -236,15 +232,15 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.madsEnabled = True
|
||||
if any(b.type == ButtonType.altButton1 and b.pressed for b in self.CS.button_events):
|
||||
self.CS.madsEnabled = not self.CS.madsEnabled
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret, self.CS.madsEnabled)
|
||||
else:
|
||||
self.CS.madsEnabled = False
|
||||
|
||||
if not self.CP.pcmCruise or (self.CP.pcmCruise and self.CP.minEnableSpeed > 0):
|
||||
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
ret.cruiseState.enabled = ret.cruiseState.enabled if not self.enable_mads else False if self.CP.pcmCruise else self.CS.accEnabled
|
||||
|
||||
if self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed:
|
||||
@@ -252,7 +248,7 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.accEnabled = False
|
||||
self.CS.accEnabled = ret.cruiseState.enabled or self.CS.accEnabled
|
||||
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=bool(distance_button))
|
||||
ret = self.get_sp_common_state(ret)
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -267,7 +263,7 @@ class CarInterface(CarInterfaceBase):
|
||||
# if any(b.type == ButtonType.accelCruise and b.pressed for b in ret.buttonEvents):
|
||||
# events.add(EventName.buttonEnable)
|
||||
|
||||
events, ret = self.create_sp_events(self.CS, ret, events, enable_pressed=self.CS.accEnabled,
|
||||
events, ret = self.create_sp_events(ret, events, enable_pressed=self.CS.accEnabled,
|
||||
enable_buttons=(ButtonType.decelCruise,))
|
||||
|
||||
# Enabling at a standstill with brake is allowed
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
from collections import namedtuple
|
||||
|
||||
from cereal import car
|
||||
import cereal.messaging as messaging
|
||||
from openpilot.common.conversions import Conversions as CV
|
||||
from openpilot.common.numpy_fast import clip, interp
|
||||
from openpilot.common.params import Params
|
||||
from opendbc.can.packer import CANPacker
|
||||
from openpilot.selfdrive.car import DT_CTRL, rate_limit, make_tester_present_msg, create_gas_interceptor_command
|
||||
from openpilot.selfdrive.car.honda import hondacan
|
||||
from openpilot.selfdrive.car.honda.values import CruiseButtons, VISUAL_HUD, HONDA_BOSCH, HONDA_BOSCH_RADARLESS, HONDA_NIDEC_ALT_PCM_ACCEL, CarControllerParams
|
||||
from openpilot.selfdrive.car.interfaces import CarControllerBase
|
||||
from openpilot.selfdrive.controls.lib.drive_helpers import HONDA_V_CRUISE_MIN
|
||||
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
LongCtrlState = car.CarControl.Actuators.LongControlState
|
||||
@@ -128,48 +124,7 @@ class CarController(CarControllerBase):
|
||||
self.last_steer = 0.0
|
||||
self.last_button_frame = 0
|
||||
|
||||
self.sm = messaging.SubMaster(['longitudinalPlanSP'])
|
||||
self.param_s = Params()
|
||||
self.last_speed_limit_sign_tap_prev = False
|
||||
self.speed_limit = 0.
|
||||
self.speed_limit_offset = 0
|
||||
self.timer = 0
|
||||
self.final_speed_kph = 0
|
||||
self.init_speed = 0
|
||||
self.current_speed = 0
|
||||
self.v_set_dis = 0
|
||||
self.v_cruise_min = 0
|
||||
self.button_type = 0
|
||||
self.button_select = 0
|
||||
self.button_count = 0
|
||||
self.target_speed = 0
|
||||
self.t_interval = 7
|
||||
self.slc_active_stock = False
|
||||
self.sl_force_active_timer = 0
|
||||
self.v_tsc_state = 0
|
||||
self.slc_state = 0
|
||||
self.m_tsc_state = 0
|
||||
self.cruise_button = None
|
||||
self.speed_diff = 0
|
||||
self.v_tsc = 0
|
||||
self.m_tsc = 0
|
||||
self.steady_speed = 0
|
||||
|
||||
def update(self, CC, CS, now_nanos):
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
self.sm.update(0)
|
||||
|
||||
if self.sm.updated['longitudinalPlanSP']:
|
||||
self.v_tsc_state = self.sm['longitudinalPlanSP'].visionTurnControllerState
|
||||
self.slc_state = self.sm['longitudinalPlanSP'].speedLimitControlState
|
||||
self.m_tsc_state = self.sm['longitudinalPlanSP'].turnSpeedControlState
|
||||
self.speed_limit = self.sm['longitudinalPlanSP'].speedLimit
|
||||
self.speed_limit_offset = self.sm['longitudinalPlanSP'].speedLimitOffset
|
||||
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
|
||||
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
|
||||
|
||||
self.v_cruise_min = HONDA_V_CRUISE_MIN[CS.params_list.is_metric] * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1)
|
||||
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
conversion = hondacan.get_cruise_speed_conversion(self.CP.carFingerprint, CS.is_metric)
|
||||
@@ -203,19 +158,6 @@ class CarController(CarControllerBase):
|
||||
apply_steer = int(interp(-limited_steer * self.params.STEER_MAX,
|
||||
self.params.STEER_LOOKUP_BP, self.params.STEER_LOOKUP_V))
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if not self.last_speed_limit_sign_tap_prev and CS.params_list.last_speed_limit_sign_tap:
|
||||
self.sl_force_active_timer = self.frame
|
||||
self.param_s.put_bool_nonblocking("LastSpeedLimitSignTap", False)
|
||||
self.last_speed_limit_sign_tap_prev = CS.params_list.last_speed_limit_sign_tap
|
||||
|
||||
sl_force_active = CS.params_list.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not CS.params_list.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (CS.params_list.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
slc_active = not sl_inactive and not sl_temp_inactive
|
||||
|
||||
self.slc_active_stock = slc_active
|
||||
|
||||
# Send CAN commands
|
||||
can_sends = []
|
||||
|
||||
@@ -265,15 +207,6 @@ class CarController(CarControllerBase):
|
||||
can_sends.append(hondacan.spam_buttons_command(self.packer, self.CAN, CruiseButtons.CANCEL, self.CP.carFingerprint))
|
||||
elif CC.cruiseControl.resume:
|
||||
can_sends.append(hondacan.spam_buttons_command(self.packer, self.CAN, CruiseButtons.RES_ACCEL, self.CP.carFingerprint))
|
||||
elif CS.out.cruiseState.enabled and not self.CP.pcmCruiseSpeed:
|
||||
self.cruise_button = self.get_cruise_buttons(CS, CC.vCruise)
|
||||
if self.cruise_button is not None:
|
||||
send_freq = 1
|
||||
if not (self.v_tsc_state != 0 or self.m_tsc_state > 1) and abs(self.target_speed - self.v_set_dis) <= 2:
|
||||
send_freq = 3
|
||||
if (self.frame - self.last_button_frame) * DT_CTRL > 0.01 * send_freq:
|
||||
can_sends.append(hondacan.spam_buttons_command(self.packer, self.CAN, self.cruise_button, self.CP.carFingerprint))
|
||||
self.last_button_frame = self.frame
|
||||
|
||||
else:
|
||||
# Send gas and brake commands.
|
||||
@@ -335,120 +268,3 @@ class CarController(CarControllerBase):
|
||||
|
||||
self.frame += 1
|
||||
return new_actuators, can_sends
|
||||
|
||||
# multikyd methods, sunnyhaibin logic
|
||||
def get_cruise_buttons_status(self, CS):
|
||||
if not CS.out.cruiseState.enabled or CS.cruise_buttons != 0:
|
||||
self.timer = 40
|
||||
elif self.timer:
|
||||
self.timer -= 1
|
||||
else:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def get_target_speed(self, v_cruise_kph_prev):
|
||||
v_cruise_kph = v_cruise_kph_prev
|
||||
if self.slc_state > 1:
|
||||
v_cruise_kph = (self.speed_limit + self.speed_limit_offset) * CV.MS_TO_KPH
|
||||
if not self.slc_active_stock:
|
||||
v_cruise_kph = v_cruise_kph_prev
|
||||
return v_cruise_kph
|
||||
|
||||
def get_button_type(self, button_type):
|
||||
self.type_status = "type_" + str(button_type)
|
||||
self.button_picker = getattr(self, self.type_status, lambda: "default")
|
||||
return self.button_picker()
|
||||
|
||||
def reset_button(self):
|
||||
if self.button_type != 3:
|
||||
self.button_type = 0
|
||||
|
||||
def type_default(self):
|
||||
self.button_type = 0
|
||||
return None
|
||||
|
||||
def type_0(self):
|
||||
self.button_count = 0
|
||||
self.target_speed = self.init_speed
|
||||
self.speed_diff = self.target_speed - self.v_set_dis
|
||||
if self.target_speed > self.v_set_dis:
|
||||
self.button_type = 1
|
||||
elif self.target_speed < self.v_set_dis and self.v_set_dis > self.v_cruise_min:
|
||||
self.button_type = 2
|
||||
return None
|
||||
|
||||
def type_1(self):
|
||||
cruise_button = CruiseButtons.RES_ACCEL
|
||||
self.button_count += 1
|
||||
if self.target_speed <= self.v_set_dis:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
elif self.button_count > 5:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
return cruise_button
|
||||
|
||||
def type_2(self):
|
||||
cruise_button = CruiseButtons.DECEL_SET
|
||||
self.button_count += 1
|
||||
if self.target_speed >= self.v_set_dis or self.v_set_dis <= self.v_cruise_min:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
elif self.button_count > 5:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
return cruise_button
|
||||
|
||||
def type_3(self):
|
||||
cruise_button = None
|
||||
self.button_count += 1
|
||||
if self.button_count > self.t_interval:
|
||||
self.button_type = 0
|
||||
return cruise_button
|
||||
|
||||
def get_curve_speed(self, target_speed_kph, v_cruise_kph_prev):
|
||||
if self.v_tsc_state != 0:
|
||||
vision_v_cruise_kph = self.v_tsc * CV.MS_TO_KPH
|
||||
if int(vision_v_cruise_kph) == int(v_cruise_kph_prev):
|
||||
vision_v_cruise_kph = 255
|
||||
else:
|
||||
vision_v_cruise_kph = 255
|
||||
if self.m_tsc_state > 1:
|
||||
map_v_cruise_kph = self.m_tsc * CV.MS_TO_KPH
|
||||
if int(map_v_cruise_kph) == 0.0:
|
||||
map_v_cruise_kph = 255
|
||||
else:
|
||||
map_v_cruise_kph = 255
|
||||
curve_speed = self.curve_speed_hysteresis(min(vision_v_cruise_kph, map_v_cruise_kph) + 2 * CV.MPH_TO_KPH)
|
||||
return min(target_speed_kph, curve_speed)
|
||||
|
||||
def get_button_control(self, CS, final_speed, v_cruise_kph_prev):
|
||||
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1))
|
||||
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not CS.params_list.is_metric else CV.MS_TO_KPH))
|
||||
cruise_button = self.get_button_type(self.button_type)
|
||||
return cruise_button
|
||||
|
||||
def curve_speed_hysteresis(self, cur_speed: float, hyst=(0.75 * CV.MPH_TO_KPH)):
|
||||
if cur_speed > self.steady_speed:
|
||||
self.steady_speed = cur_speed
|
||||
elif cur_speed < self.steady_speed - hyst:
|
||||
self.steady_speed = cur_speed
|
||||
return self.steady_speed
|
||||
|
||||
def get_cruise_buttons(self, CS, v_cruise_kph_prev):
|
||||
cruise_button = None
|
||||
if not self.get_cruise_buttons_status(CS):
|
||||
pass
|
||||
elif CS.out.cruiseState.enabled:
|
||||
set_speed_kph = self.get_target_speed(v_cruise_kph_prev)
|
||||
if self.slc_state > 1:
|
||||
target_speed_kph = set_speed_kph
|
||||
else:
|
||||
target_speed_kph = min(v_cruise_kph_prev, set_speed_kph)
|
||||
if self.v_tsc_state != 0 or self.m_tsc_state > 1:
|
||||
self.final_speed_kph = self.get_curve_speed(target_speed_kph, v_cruise_kph_prev)
|
||||
else:
|
||||
self.final_speed_kph = target_speed_kph
|
||||
|
||||
cruise_button = self.get_button_control(CS, self.final_speed_kph, v_cruise_kph_prev) # MPH/KPH based button presses
|
||||
return cruise_button
|
||||
|
||||
@@ -267,10 +267,9 @@ class CarInterface(CarInterfaceBase):
|
||||
*create_button_events(self.CS.cruise_setting, self.CS.prev_cruise_setting, SETTINGS_BUTTONS_DICT),
|
||||
]
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret)
|
||||
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
|
||||
self.CS.button_events, c.vCruise)
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, c.vCruise, self.CS.accEnabled)
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if self.enable_mads:
|
||||
@@ -278,7 +277,7 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.madsEnabled = True
|
||||
if any(b.type == ButtonType.altButton1 and b.pressed for b in self.CS.button_events):
|
||||
self.CS.madsEnabled = not self.CS.madsEnabled
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret, self.CS.madsEnabled)
|
||||
else:
|
||||
self.CS.madsEnabled = False
|
||||
|
||||
@@ -286,9 +285,9 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
if not self.CP.pcmCruise or min_enable_speed_pcm or not self.CP.pcmCruiseSpeed:
|
||||
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
ret.cruiseState.enabled = ret.cruiseState.enabled if not self.enable_mads or min_enable_speed_pcm \
|
||||
else False if self.CP.pcmCruise \
|
||||
else self.CS.accEnabled
|
||||
@@ -301,7 +300,7 @@ class CarInterface(CarInterfaceBase):
|
||||
elif not ret.cruiseState.enabled:
|
||||
self.CS.accEnabled = False
|
||||
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=(self.CS.cruise_setting == 3))
|
||||
ret = self.get_sp_common_state(ret)
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -313,7 +312,7 @@ class CarInterface(CarInterfaceBase):
|
||||
if self.CP.pcmCruise and ret.vEgo < self.CP.minEnableSpeed and not self.CS.madsEnabled:
|
||||
events.add(EventName.belowEngageSpeed)
|
||||
|
||||
events, ret = self.create_sp_events(self.CS, ret, events)
|
||||
events, ret = self.create_sp_events(ret, events)
|
||||
|
||||
#if self.CP.pcmCruise:
|
||||
# # we engage when pcm is active (rising edge)
|
||||
@@ -330,10 +329,6 @@ class CarInterface(CarInterfaceBase):
|
||||
if self.CS.CP.minEnableSpeed > 0 and ret.vEgo < 0.001:
|
||||
events.add(EventName.manualRestart)
|
||||
|
||||
ret.customStockLong = self.CS.update_custom_stock_long(self.CC.cruise_button, self.CC.final_speed_kph,
|
||||
self.CC.target_speed, self.CC.v_set_dis,
|
||||
self.CC.speed_diff, self.CC.button_type)
|
||||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
return ret
|
||||
|
||||
@@ -7,9 +7,8 @@ from opendbc.can.packer import CANPacker
|
||||
from openpilot.selfdrive.car import DT_CTRL, apply_driver_steer_torque_limits, common_fault_avoidance, make_tester_present_msg
|
||||
from openpilot.selfdrive.car.hyundai import hyundaicanfd, hyundaican
|
||||
from openpilot.selfdrive.car.hyundai.hyundaicanfd import CanBus
|
||||
from openpilot.selfdrive.car.hyundai.values import HyundaiFlags, HyundaiFlagsSP, Buttons, CarControllerParams, CANFD_CAR, CAR, CAMERA_SCC_CAR, LEGACY_SAFETY_MODE_CAR
|
||||
from openpilot.selfdrive.car.hyundai.values import HyundaiFlags, HyundaiFlagsSP, Buttons, CarControllerParams, CANFD_CAR, CAR, CAMERA_SCC_CAR
|
||||
from openpilot.selfdrive.car.interfaces import CarControllerBase
|
||||
from openpilot.selfdrive.controls.lib.drive_helpers import HYUNDAI_V_CRUISE_MIN
|
||||
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
LongCtrlState = car.CarControl.Actuators.LongControlState
|
||||
@@ -62,38 +61,10 @@ class CarController(CarControllerBase):
|
||||
self.lat_disengage_init = False
|
||||
self.lat_active_last = False
|
||||
|
||||
sub_services = ['longitudinalPlanSP']
|
||||
if CP.openpilotLongitudinalControl:
|
||||
sub_services.append('radarState')
|
||||
# TODO: Always true, prep for future conditional refactoring
|
||||
if sub_services:
|
||||
self.sm = messaging.SubMaster(sub_services)
|
||||
self.sm = messaging.SubMaster(['radarState'])
|
||||
|
||||
self.param_s = Params()
|
||||
self.last_speed_limit_sign_tap_prev = False
|
||||
self.speed_limit = 0.
|
||||
self.speed_limit_offset = 0
|
||||
self.timer = 0
|
||||
self.final_speed_kph = 0
|
||||
self.init_speed = 0
|
||||
self.current_speed = 0
|
||||
self.v_set_dis = 0
|
||||
self.v_cruise_min = 0
|
||||
self.button_type = 0
|
||||
self.button_select = 0
|
||||
self.button_count = 0
|
||||
self.target_speed = 0
|
||||
self.t_interval = 7
|
||||
self.slc_active_stock = False
|
||||
self.sl_force_active_timer = 0
|
||||
self.v_tsc_state = 0
|
||||
self.slc_state = 0
|
||||
self.m_tsc_state = 0
|
||||
self.cruise_button = None
|
||||
self.speed_diff = 0
|
||||
self.v_tsc = 0
|
||||
self.m_tsc = 0
|
||||
self.steady_speed = 0
|
||||
self.hkg_can_smooth_stop = self.param_s.get_bool("HkgSmoothStop")
|
||||
self.lead_distance = 0
|
||||
|
||||
@@ -109,21 +80,9 @@ class CarController(CarControllerBase):
|
||||
return 19 if hud_control.leadVisible else 0
|
||||
|
||||
def update(self, CC, CS, now_nanos):
|
||||
if not self.CP.pcmCruiseSpeed or (self.CP.openpilotLongitudinalControl and self.frame % 5 == 0):
|
||||
if self.CP.openpilotLongitudinalControl and self.frame % 5 == 0:
|
||||
self.sm.update(0)
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if self.sm.updated['longitudinalPlanSP']:
|
||||
self.v_tsc_state = self.sm['longitudinalPlanSP'].visionTurnControllerState
|
||||
self.slc_state = self.sm['longitudinalPlanSP'].speedLimitControlState
|
||||
self.m_tsc_state = self.sm['longitudinalPlanSP'].turnSpeedControlState
|
||||
self.speed_limit = self.sm['longitudinalPlanSP'].speedLimit
|
||||
self.speed_limit_offset = self.sm['longitudinalPlanSP'].speedLimitOffset
|
||||
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
|
||||
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
|
||||
|
||||
self.v_cruise_min = HYUNDAI_V_CRUISE_MIN[CS.params_list.is_metric] * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1)
|
||||
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
|
||||
@@ -165,19 +124,6 @@ class CarController(CarControllerBase):
|
||||
|
||||
blinking_icon = (self.frame - self.disengage_blink) * DT_CTRL < 1.0 if self.lat_disengage_init else False
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if not self.last_speed_limit_sign_tap_prev and CS.params_list.last_speed_limit_sign_tap:
|
||||
self.sl_force_active_timer = self.frame
|
||||
self.param_s.put_bool_nonblocking("LastSpeedLimitSignTap", False)
|
||||
self.last_speed_limit_sign_tap_prev = CS.params_list.last_speed_limit_sign_tap
|
||||
|
||||
sl_force_active = CS.params_list.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not CS.params_list.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (CS.params_list.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
slc_active = not sl_inactive and not sl_temp_inactive
|
||||
|
||||
self.slc_active_stock = slc_active
|
||||
|
||||
self.lat_active_last = CC.latActive
|
||||
|
||||
escc = self.CP.spFlags & HyundaiFlagsSP.SP_ENHANCED_SCC.value
|
||||
@@ -232,15 +178,6 @@ class CarController(CarControllerBase):
|
||||
else:
|
||||
# button presses
|
||||
can_sends.extend(self.create_button_messages(CC, CS, use_clu11=False))
|
||||
if not (CC.cruiseControl.cancel or CC.cruiseControl.resume) and CS.out.cruiseState.enabled and not self.CP.pcmCruiseSpeed:
|
||||
if self.CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS:
|
||||
# TODO: resume for alt button cars
|
||||
pass
|
||||
else:
|
||||
self.cruise_button = self.get_cruise_buttons(CS, CC.vCruise)
|
||||
if self.cruise_button is not None:
|
||||
if self.frame % 2 == 0:
|
||||
can_sends.append(hyundaicanfd.create_buttons(self.packer, self.CP, self.CAN, ((self.frame // 2) + 1) % 0x10, self.cruise_button))
|
||||
else:
|
||||
can_sends.append(hyundaican.create_lkas11(self.packer, self.frame, self.CP, apply_steer, apply_steer_req,
|
||||
torque_fault, CS.lkas11, sys_warning, sys_state, CC.enabled,
|
||||
@@ -250,21 +187,6 @@ class CarController(CarControllerBase):
|
||||
|
||||
if not self.CP.openpilotLongitudinalControl:
|
||||
can_sends.extend(self.create_button_messages(CC, CS, use_clu11=True))
|
||||
if not (CC.cruiseControl.cancel or CC.cruiseControl.resume) and CS.out.cruiseState.enabled and not self.CP.pcmCruiseSpeed:
|
||||
self.cruise_button = self.get_cruise_buttons(CS, CC.vCruise)
|
||||
if self.cruise_button is not None:
|
||||
if self.CP.carFingerprint in LEGACY_SAFETY_MODE_CAR:
|
||||
send_freq = 1
|
||||
if not (self.v_tsc_state != 0 or self.m_tsc_state > 1) and abs(self.target_speed - self.v_set_dis) <= 2:
|
||||
send_freq = 5
|
||||
# send resume at a max freq of 10Hz
|
||||
if (self.frame - self.last_button_frame) * DT_CTRL > 0.1 * send_freq:
|
||||
# send 25 messages at a time to increases the likelihood of cruise buttons being accepted
|
||||
can_sends.extend([hyundaican.create_clu11(self.packer, self.frame, CS.clu11, self.cruise_button, self.CP)] * 25)
|
||||
if (self.frame - self.last_button_frame) * DT_CTRL >= 0.15 * send_freq:
|
||||
self.last_button_frame = self.frame
|
||||
elif self.frame % 2 == 0:
|
||||
can_sends.extend([hyundaican.create_clu11(self.packer, (self.frame // 2) + 1, CS.clu11, self.cruise_button, self.CP)] * 25)
|
||||
|
||||
# Parse lead distance from radarState and display the corresponding distance in the car's cluster
|
||||
if self.CP.openpilotLongitudinalControl and self.sm.updated['radarState'] and self.frame % 5 == 0:
|
||||
@@ -336,120 +258,3 @@ class CarController(CarControllerBase):
|
||||
self.last_button_frame = self.frame
|
||||
|
||||
return can_sends
|
||||
|
||||
# multikyd methods, sunnyhaibin logic
|
||||
def get_cruise_buttons_status(self, CS):
|
||||
if not CS.out.cruiseState.enabled or CS.cruise_buttons[-1] != Buttons.NONE:
|
||||
self.timer = 40
|
||||
elif self.timer:
|
||||
self.timer -= 1
|
||||
else:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def get_target_speed(self, v_cruise_kph_prev):
|
||||
v_cruise_kph = v_cruise_kph_prev
|
||||
if self.slc_state > 1:
|
||||
v_cruise_kph = (self.speed_limit + self.speed_limit_offset) * CV.MS_TO_KPH
|
||||
if not self.slc_active_stock:
|
||||
v_cruise_kph = v_cruise_kph_prev
|
||||
return v_cruise_kph
|
||||
|
||||
def get_button_type(self, button_type):
|
||||
self.type_status = "type_" + str(button_type)
|
||||
self.button_picker = getattr(self, self.type_status, lambda: "default")
|
||||
return self.button_picker()
|
||||
|
||||
def reset_button(self):
|
||||
if self.button_type != 3:
|
||||
self.button_type = 0
|
||||
|
||||
def type_default(self):
|
||||
self.button_type = 0
|
||||
return None
|
||||
|
||||
def type_0(self):
|
||||
self.button_count = 0
|
||||
self.target_speed = self.init_speed
|
||||
self.speed_diff = self.target_speed - self.v_set_dis
|
||||
if self.target_speed > self.v_set_dis:
|
||||
self.button_type = 1
|
||||
elif self.target_speed < self.v_set_dis and self.v_set_dis > self.v_cruise_min:
|
||||
self.button_type = 2
|
||||
return None
|
||||
|
||||
def type_1(self):
|
||||
cruise_button = Buttons.RES_ACCEL
|
||||
self.button_count += 1
|
||||
if self.target_speed <= self.v_set_dis:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
elif self.button_count > 5:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
return cruise_button
|
||||
|
||||
def type_2(self):
|
||||
cruise_button = Buttons.SET_DECEL
|
||||
self.button_count += 1
|
||||
if self.target_speed >= self.v_set_dis or self.v_set_dis <= self.v_cruise_min:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
elif self.button_count > 5:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
return cruise_button
|
||||
|
||||
def type_3(self):
|
||||
cruise_button = None
|
||||
self.button_count += 1
|
||||
if self.button_count > self.t_interval:
|
||||
self.button_type = 0
|
||||
return cruise_button
|
||||
|
||||
def get_curve_speed(self, target_speed_kph, v_cruise_kph_prev):
|
||||
if self.v_tsc_state != 0:
|
||||
vision_v_cruise_kph = self.v_tsc * CV.MS_TO_KPH
|
||||
if int(vision_v_cruise_kph) == int(v_cruise_kph_prev):
|
||||
vision_v_cruise_kph = 255
|
||||
else:
|
||||
vision_v_cruise_kph = 255
|
||||
if self.m_tsc_state > 1:
|
||||
map_v_cruise_kph = self.m_tsc * CV.MS_TO_KPH
|
||||
if int(map_v_cruise_kph) == 0.0:
|
||||
map_v_cruise_kph = 255
|
||||
else:
|
||||
map_v_cruise_kph = 255
|
||||
curve_speed = self.curve_speed_hysteresis(min(vision_v_cruise_kph, map_v_cruise_kph) + 2 * CV.MPH_TO_KPH)
|
||||
return min(target_speed_kph, curve_speed)
|
||||
|
||||
def get_button_control(self, CS, final_speed, v_cruise_kph_prev):
|
||||
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1))
|
||||
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not CS.params_list.is_metric else CV.MS_TO_KPH))
|
||||
cruise_button = self.get_button_type(self.button_type)
|
||||
return cruise_button
|
||||
|
||||
def curve_speed_hysteresis(self, cur_speed: float, hyst=(0.75 * CV.MPH_TO_KPH)):
|
||||
if cur_speed > self.steady_speed:
|
||||
self.steady_speed = cur_speed
|
||||
elif cur_speed < self.steady_speed - hyst:
|
||||
self.steady_speed = cur_speed
|
||||
return self.steady_speed
|
||||
|
||||
def get_cruise_buttons(self, CS, v_cruise_kph_prev):
|
||||
cruise_button = None
|
||||
if not self.get_cruise_buttons_status(CS):
|
||||
pass
|
||||
elif CS.out.cruiseState.enabled:
|
||||
set_speed_kph = self.get_target_speed(v_cruise_kph_prev)
|
||||
if self.slc_state > 1:
|
||||
target_speed_kph = set_speed_kph
|
||||
else:
|
||||
target_speed_kph = min(v_cruise_kph_prev, set_speed_kph)
|
||||
if self.v_tsc_state != 0 or self.m_tsc_state > 1:
|
||||
self.final_speed_kph = self.get_curve_speed(target_speed_kph, v_cruise_kph_prev)
|
||||
else:
|
||||
self.final_speed_kph = target_speed_kph
|
||||
|
||||
cruise_button = self.get_button_control(CS, self.final_speed_kph, v_cruise_kph_prev) # MPH/KPH based button presses
|
||||
return cruise_button
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import cereal.messaging as messaging
|
||||
from cereal import car
|
||||
from panda import Panda
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.selfdrive.car.sunnypilot.fingerprinting import can_fingerprint, get_one_can
|
||||
from openpilot.selfdrive.car.hyundai.enable_radar_tracks import enable_radar_tracks
|
||||
from openpilot.selfdrive.car.hyundai.hyundaicanfd import CanBus
|
||||
from openpilot.selfdrive.car.hyundai.values import HyundaiFlags, HyundaiFlagsSP, CAR, DBC, CANFD_CAR, CAMERA_SCC_CAR, CANFD_RADAR_SCC_CAR, \
|
||||
@@ -109,6 +111,7 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
if DBC[ret.carFingerprint]["radar"] is None:
|
||||
if ret.spFlags & (HyundaiFlagsSP.SP_ENHANCED_SCC | HyundaiFlagsSP.SP_CAMERA_SCC_LEAD):
|
||||
ret.radarTimeStep = 0.02
|
||||
ret.radarUnavailable = False
|
||||
|
||||
# *** feature detection ***
|
||||
@@ -125,7 +128,8 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
if ret.flags & HyundaiFlags.MANDO_RADAR and ret.radarUnavailable:
|
||||
ret.spFlags |= HyundaiFlagsSP.SP_RADAR_TRACKS.value
|
||||
ret.radarUnavailable = False
|
||||
if Params().get_bool("HyundaiRadarTracksAvailable"):
|
||||
ret.radarUnavailable = False
|
||||
|
||||
# *** panda safety config ***
|
||||
if candidate in CANFD_CAR:
|
||||
@@ -201,7 +205,23 @@ class CarInterface(CarInterfaceBase):
|
||||
if CP.spFlags & HyundaiFlagsSP.SP_RADAR_TRACKS:
|
||||
enable_radar_tracks(logcan, sendcan, bus=0, addr=0x7d0, config_data_id=b'\x01\x42')
|
||||
|
||||
params = Params()
|
||||
rt_avail = params.get_bool("HyundaiRadarTracksAvailable")
|
||||
rt_avail_persist = params.get_bool("HyundaiRadarTracksAvailablePersistent")
|
||||
params.put_bool_nonblocking("HyundaiRadarTracksAvailableCache", rt_avail)
|
||||
if not rt_avail_persist:
|
||||
messaging.drain_sock_raw(logcan)
|
||||
fingerprint = can_fingerprint(lambda: get_one_can(logcan))
|
||||
radar_unavailable = RADAR_START_ADDR not in fingerprint[1] or DBC[CP.carFingerprint]["radar"] is None
|
||||
params.put_bool_nonblocking("HyundaiRadarTracksAvailable", not radar_unavailable)
|
||||
params.put_bool_nonblocking("HyundaiRadarTracksAvailablePersistent", True)
|
||||
|
||||
def _update(self, c):
|
||||
if not self.CS.control_initialized and not self.CP.pcmCruise:
|
||||
can_cruise_main_default = self.CP.spFlags & HyundaiFlagsSP.SP_CAN_LFA_BTN and not self.CP.flags & HyundaiFlags.CANFD and \
|
||||
self.CS.params_list.hyundai_cruise_main_default
|
||||
self.CS.mainEnabled = True if can_cruise_main_default or self.CP.carFingerprint in CANFD_CAR else False
|
||||
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
|
||||
self.CS.button_events = [
|
||||
@@ -210,10 +230,9 @@ class CarInterface(CarInterfaceBase):
|
||||
*create_button_events(self.CS.main_buttons[-1], self.CS.prev_main_buttons, {1: ButtonType.altButton3}),
|
||||
]
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret)
|
||||
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
|
||||
self.CS.button_events, c.vCruise)
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, c.vCruise, self.CS.accEnabled)
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
@@ -221,12 +240,12 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.accEnabled = True
|
||||
|
||||
if self.enable_mads:
|
||||
if not self.CS.prev_mads_enabled and self.CS.mads_enabled and \
|
||||
any(b.type == ButtonType.altButton3 for b in self.CS.button_events):
|
||||
if not self.CS.prev_mads_enabled and self.CS.mads_enabled and (self.CP.pcmCruise or
|
||||
(any(b.type == ButtonType.altButton3 for b in self.CS.button_events) and not self.CP.pcmCruise)):
|
||||
self.CS.madsEnabled = True
|
||||
if any(b.type == ButtonType.altButton1 and b.pressed for b in self.CS.button_events):
|
||||
self.CS.madsEnabled = not self.CS.madsEnabled
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret, self.CS.madsEnabled)
|
||||
|
||||
if not ret.cruiseState.available and self.CS.out.cruiseState.available:
|
||||
self.CS.madsEnabled = False
|
||||
@@ -234,15 +253,15 @@ class CarInterface(CarInterfaceBase):
|
||||
if not self.CP.pcmCruise or not self.CP.pcmCruiseSpeed:
|
||||
if not self.CP.pcmCruise:
|
||||
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if not ret.cruiseState.enabled:
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
ret.cruiseState.enabled = ret.cruiseState.enabled if not self.enable_mads else False if self.CP.pcmCruise else self.CS.accEnabled
|
||||
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=(self.CS.cruise_buttons[-1] == 3))
|
||||
ret = self.get_sp_common_state(ret)
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -256,7 +275,7 @@ class CarInterface(CarInterfaceBase):
|
||||
events = self.create_common_events(ret, c, extra_gears=[GearShifter.sport, GearShifter.low, GearShifter.manumatic],
|
||||
pcm_enable=False, allow_enable=allow_enable)
|
||||
|
||||
events, ret = self.create_sp_events(self.CS, ret, events, main_enabled=True, allow_enable=allow_enable)
|
||||
events, ret = self.create_sp_events(ret, events, main_enabled=True, allow_enable=allow_enable)
|
||||
|
||||
# low speed steer alert hysteresis logic (only for cars with steer cut off above 10 m/s)
|
||||
if ret.vEgo < (self.CP.minSteerSpeed + 2.) and self.CP.minSteerSpeed > 10.:
|
||||
@@ -266,9 +285,8 @@ class CarInterface(CarInterfaceBase):
|
||||
if self.low_speed_alert and self.CS.madsEnabled:
|
||||
events.add(car.CarEvent.EventName.belowSteerSpeed)
|
||||
|
||||
ret.customStockLong = self.CS.update_custom_stock_long(self.CC.cruise_button, self.CC.final_speed_kph,
|
||||
self.CC.target_speed, self.CC.v_set_dis,
|
||||
self.CC.speed_diff, self.CC.button_type)
|
||||
if self.CS.params_list.hyundai_radar_tracks_available and not self.CS.params_list.hyundai_radar_tracks_available_cache:
|
||||
events.add(car.CarEvent.EventName.hyundaiRadarTracksAvailable)
|
||||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
|
||||
+53
-66
@@ -244,8 +244,6 @@ class CarInterfaceBase(ABC):
|
||||
self.cruise_cancelled_btn = True
|
||||
self.prev_acc_mads_combo = False
|
||||
self.mads_event_lock = True
|
||||
self.gap_button_counter = 0
|
||||
self.experimental_mode_hold = False
|
||||
self.last_mads_init = 0.
|
||||
self.madsEnabledInit = False
|
||||
self.madsEnabledInitPrev = False
|
||||
@@ -550,20 +548,20 @@ class CarInterfaceBase(ABC):
|
||||
def sp_v_cruise_initialized(v_cruise):
|
||||
return v_cruise != V_CRUISE_UNSET
|
||||
|
||||
def get_acc_mads(self, cruiseState_enabled, acc_enabled, mads_enabled):
|
||||
def get_acc_mads(self, cs_out, mads_enabled):
|
||||
if self.CS.params_list.acc_mads_combo:
|
||||
if not self.prev_acc_mads_combo and (cruiseState_enabled or acc_enabled):
|
||||
if not self.prev_acc_mads_combo and (cs_out.cruiseState.enabled or self.CS.accEnabled):
|
||||
mads_enabled = True
|
||||
self.prev_acc_mads_combo = (cruiseState_enabled or acc_enabled)
|
||||
self.prev_acc_mads_combo = (cs_out.cruiseState.enabled or self.CS.accEnabled)
|
||||
|
||||
return mads_enabled
|
||||
|
||||
def get_sp_v_cruise_non_pcm_state(self, cs_out, acc_enabled, button_events, vCruise,
|
||||
def get_sp_v_cruise_non_pcm_state(self, cs_out, vCruise, acc_enabled,
|
||||
enable_buttons=(ButtonType.accelCruise, ButtonType.decelCruise),
|
||||
resume_button=(ButtonType.accelCruise, ButtonType.resumeCruise)):
|
||||
|
||||
if cs_out.cruiseState.available:
|
||||
for b in button_events:
|
||||
for b in self.CS.button_events:
|
||||
if not self.CP.pcmCruise or not self.CP.pcmCruiseSpeed:
|
||||
if b.type in enable_buttons and not b.pressed:
|
||||
acc_enabled = True
|
||||
@@ -578,9 +576,9 @@ class CarInterfaceBase(ABC):
|
||||
|
||||
return acc_enabled
|
||||
|
||||
def get_sp_cancel_cruise_state(self, mads_enabled, acc_enabled=False):
|
||||
mads_enabled = False if not self.enable_mads or self.disengage_on_accelerator else mads_enabled
|
||||
return mads_enabled, acc_enabled
|
||||
def get_sp_cancel_cruise_state(self):
|
||||
self.CS.madsEnabled = False if not self.enable_mads or self.disengage_on_accelerator else self.CS.madsEnabled
|
||||
self.CS.accEnabled = False
|
||||
|
||||
def get_sp_pedal_disengage(self, cs_out):
|
||||
accel_pedal = cs_out.gasPressed and not self.CS.out.gasPressed and self.disengage_on_accelerator
|
||||
@@ -588,24 +586,22 @@ class CarInterfaceBase(ABC):
|
||||
regen = cs_out.regenBraking and (not self.CS.out.regenBraking or not cs_out.standstill)
|
||||
return accel_pedal or brake or regen
|
||||
|
||||
def get_sp_cruise_main_state(self, cs_out, CS):
|
||||
if not CS.control_initialized:
|
||||
mads_enabled = False
|
||||
def get_sp_cruise_main_state(self, cs_out):
|
||||
if not self.CS.control_initialized:
|
||||
return False
|
||||
elif not self.CS.params_list.mads_main_toggle:
|
||||
mads_enabled = False
|
||||
return False
|
||||
else:
|
||||
mads_enabled = cs_out.cruiseState.available
|
||||
return cs_out.cruiseState.available
|
||||
|
||||
return mads_enabled
|
||||
|
||||
def get_sp_started_mads(self, cs_out, CS):
|
||||
if not cs_out.cruiseState.available and CS.out.cruiseState.available:
|
||||
def get_sp_started_mads(self, cs_out, mads_enabled):
|
||||
if not cs_out.cruiseState.available and self.CS.out.cruiseState.available:
|
||||
self.madsEnabledInit = False
|
||||
self.madsEnabledInitPrev = False
|
||||
return False
|
||||
if not self.CS.params_list.mads_main_toggle or self.prev_acc_mads_combo:
|
||||
return CS.madsEnabled
|
||||
if not self.madsEnabledInit and CS.madsEnabled:
|
||||
return mads_enabled
|
||||
if not self.madsEnabledInit and self.CS.madsEnabled:
|
||||
self.madsEnabledInit = True
|
||||
self.last_mads_init = time.monotonic()
|
||||
if cs_out.gearShifter not in FORWARD_GEARS:
|
||||
@@ -616,19 +612,16 @@ class CarInterfaceBase(ABC):
|
||||
self.madsEnabledInitPrev = True
|
||||
return cs_out.cruiseState.available
|
||||
else:
|
||||
return CS.madsEnabled
|
||||
return mads_enabled
|
||||
|
||||
def get_sp_common_state(self, cs_out, CS, gear_allowed=True, gap_button=False):
|
||||
cs_out.cruiseState.enabled = CS.accEnabled if not self.CP.pcmCruise or not self.CP.pcmCruiseSpeed else cs_out.cruiseState.enabled
|
||||
def get_sp_common_state(self, cs_out, gear_allowed=True):
|
||||
cs_out.cruiseState.enabled = self.CS.accEnabled if not self.CP.pcmCruise or not self.CP.pcmCruiseSpeed else cs_out.cruiseState.enabled
|
||||
|
||||
if not self.enable_mads:
|
||||
if cs_out.cruiseState.enabled and not CS.out.cruiseState.enabled:
|
||||
CS.madsEnabled = True
|
||||
elif not cs_out.cruiseState.enabled and CS.out.cruiseState.enabled:
|
||||
CS.madsEnabled = False
|
||||
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
self.toggle_exp_mode(gap_button)
|
||||
if cs_out.cruiseState.enabled and not self.CS.out.cruiseState.enabled:
|
||||
self.CS.madsEnabled = True
|
||||
elif not cs_out.cruiseState.enabled and self.CS.out.cruiseState.enabled:
|
||||
self.CS.madsEnabled = False
|
||||
|
||||
lane_change_speed_min = get_min_lateral_speed(self.CS.params_list.pause_lateral_speed, self.CS.params_list.is_metric)
|
||||
|
||||
@@ -640,37 +633,24 @@ class CarInterfaceBase(ABC):
|
||||
|
||||
cs_out.latActive = gear_allowed
|
||||
|
||||
if not CS.control_initialized:
|
||||
CS.control_initialized = True
|
||||
if not self.CS.control_initialized:
|
||||
self.CS.control_initialized = True
|
||||
|
||||
# Disable on rising edge of gas or brake. Also disable on brake when speed > 0.
|
||||
if (cs_out.gasPressed and not self.CS.out.gasPressed and self.disengage_on_accelerator) or \
|
||||
(cs_out.brakePressed and (not self.CS.out.brakePressed or not cs_out.standstill)) or \
|
||||
(cs_out.regenBraking and (not self.CS.out.regenBraking or not cs_out.standstill)):
|
||||
if CS.madsEnabled:
|
||||
CS.disengageByBrake = True
|
||||
if self.CS.madsEnabled:
|
||||
self.CS.disengageByBrake = True
|
||||
|
||||
cs_out.madsEnabled = CS.madsEnabled
|
||||
cs_out.accEnabled = CS.accEnabled
|
||||
cs_out.disengageByBrake = CS.disengageByBrake
|
||||
cs_out.madsEnabled = self.CS.madsEnabled
|
||||
cs_out.accEnabled = self.CS.accEnabled
|
||||
cs_out.disengageByBrake = self.CS.disengageByBrake
|
||||
cs_out.brakeLightsDEPRECATED |= cs_out.brakePressed or cs_out.brakeHoldActive or cs_out.parkingBrake or cs_out.regenBraking
|
||||
|
||||
return cs_out, CS
|
||||
return cs_out
|
||||
|
||||
# TODO: SP: use upstream's buttonEvents counter checks from controlsd
|
||||
def toggle_exp_mode(self, gap_pressed):
|
||||
if gap_pressed:
|
||||
if not self.experimental_mode_hold:
|
||||
self.gap_button_counter += 1
|
||||
if self.gap_button_counter > 50:
|
||||
self.gap_button_counter = 0
|
||||
self.experimental_mode_hold = True
|
||||
self.param_s.put_bool_nonblocking("ExperimentalMode", not self.CS.params_list.experimental_mode)
|
||||
else:
|
||||
self.gap_button_counter = 0
|
||||
self.experimental_mode_hold = False
|
||||
|
||||
def create_sp_events(self, CS, cs_out, events, main_enabled=False, allow_enable=True, enable_pressed=False,
|
||||
def create_sp_events(self, cs_out, events, main_enabled=False, allow_enable=True, enable_pressed=False,
|
||||
enable_from_brake=False, enable_pressed_long=False,
|
||||
enable_buttons=(ButtonType.accelCruise, ButtonType.decelCruise)):
|
||||
|
||||
@@ -678,7 +658,7 @@ class CarInterfaceBase(ABC):
|
||||
if cs_out.disengageByBrake and cs_out.madsEnabled:
|
||||
enable_pressed = True
|
||||
enable_from_brake = True
|
||||
CS.disengageByBrake = False
|
||||
self.CS.disengageByBrake = False
|
||||
cs_out.disengageByBrake = False
|
||||
|
||||
for b in cs_out.buttonEvents:
|
||||
@@ -707,11 +687,11 @@ class CarInterfaceBase(ABC):
|
||||
if self.CP.pcmCruise:
|
||||
# do disable on button down
|
||||
if main_enabled:
|
||||
if any(CS.main_buttons) and not cs_out.cruiseState.enabled:
|
||||
if any(self.CS.main_buttons) and not cs_out.cruiseState.enabled:
|
||||
if not cs_out.madsEnabled:
|
||||
events.add(EventName.buttonCancel)
|
||||
# do enable on both accel and decel buttons
|
||||
if cs_out.cruiseState.enabled and not CS.out.cruiseState.enabled and allow_enable:
|
||||
if cs_out.cruiseState.enabled and not self.CS.out.cruiseState.enabled and allow_enable:
|
||||
enable_pressed = True
|
||||
enable_pressed_long = True
|
||||
elif not cs_out.cruiseState.enabled:
|
||||
@@ -731,6 +711,16 @@ class CarInterfaceBase(ABC):
|
||||
|
||||
return events, cs_out
|
||||
|
||||
def update_custom_stock_long(self):
|
||||
customStockLong = car.CarState.CustomStockLong.new_message()
|
||||
customStockLong.cruiseButton = 0 if self.CC.cruise_button is None else int(self.CC.cruise_button)
|
||||
customStockLong.finalSpeedKph = float(self.CC.final_speed_kph)
|
||||
customStockLong.targetSpeed = float(self.CC.target_speed)
|
||||
customStockLong.vSetDis = float(self.CC.v_set_dis)
|
||||
customStockLong.speedDiff = float(self.CC.speed_diff)
|
||||
customStockLong.buttonType = int(self.CC.button_type)
|
||||
return customStockLong
|
||||
|
||||
class RadarInterfaceBase(ABC):
|
||||
def __init__(self, CP):
|
||||
self.CP = CP
|
||||
@@ -834,16 +824,6 @@ class CarStateBase(ABC):
|
||||
|
||||
return bool(left_blinker_stalk or self.left_blinker_cnt > 0), bool(right_blinker_stalk or self.right_blinker_cnt > 0)
|
||||
|
||||
def update_custom_stock_long(self, cruise_button, final_speed_kph, target_speed, v_set_dis, speed_diff, button_type):
|
||||
customStockLong = car.CarState.CustomStockLong.new_message()
|
||||
customStockLong.cruiseButton = 0 if cruise_button is None else cruise_button
|
||||
customStockLong.finalSpeedKph = final_speed_kph
|
||||
customStockLong.targetSpeed = target_speed
|
||||
customStockLong.vSetDis = v_set_dis
|
||||
customStockLong.speedDiff = speed_diff
|
||||
customStockLong.buttonType = button_type
|
||||
return customStockLong
|
||||
|
||||
@staticmethod
|
||||
def parse_gear_shifter(gear: str | None) -> car.CarState.GearShifter:
|
||||
if gear is None:
|
||||
@@ -876,6 +856,13 @@ class CarControllerBase(ABC):
|
||||
self.CP = CP
|
||||
self.frame = 0
|
||||
|
||||
self.cruise_button = 0
|
||||
self.final_speed_kph = 0.0
|
||||
self.target_speed = 0.0
|
||||
self.v_set_dis = 0.0
|
||||
self.speed_diff = 0.0
|
||||
self.button_type = 0
|
||||
|
||||
@abstractmethod
|
||||
def update(self, CC: car.CarControl.Actuators, CS: car.CarState, now_nanos: int) -> tuple[car.CarControl.Actuators, list[SendCan]]:
|
||||
pass
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
from cereal import car
|
||||
import cereal.messaging as messaging
|
||||
from openpilot.common.conversions import Conversions as CV
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.common.realtime import DT_CTRL
|
||||
from opendbc.can.packer import CANPacker
|
||||
from openpilot.selfdrive.car import apply_driver_steer_torque_limits
|
||||
from openpilot.selfdrive.car.interfaces import CarControllerBase
|
||||
from openpilot.selfdrive.car.mazda import mazdacan
|
||||
from openpilot.selfdrive.car.mazda.values import CarControllerParams, Buttons
|
||||
from openpilot.selfdrive.controls.lib.drive_helpers import MAZDA_V_CRUISE_MIN
|
||||
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
@@ -21,63 +16,9 @@ class CarController(CarControllerBase):
|
||||
self.packer = CANPacker(dbc_name)
|
||||
self.brake_counter = 0
|
||||
|
||||
self.sm = messaging.SubMaster(['longitudinalPlanSP'])
|
||||
self.param_s = Params()
|
||||
self.last_speed_limit_sign_tap_prev = False
|
||||
self.speed_limit = 0.
|
||||
self.speed_limit_offset = 0
|
||||
self.timer = 0
|
||||
self.final_speed_kph = 0
|
||||
self.init_speed = 0
|
||||
self.current_speed = 0
|
||||
self.v_set_dis = 0
|
||||
self.v_cruise_min = 0
|
||||
self.button_type = 0
|
||||
self.button_select = 0
|
||||
self.button_count = 0
|
||||
self.target_speed = 0
|
||||
self.t_interval = 7
|
||||
self.slc_active_stock = False
|
||||
self.sl_force_active_timer = 0
|
||||
self.v_tsc_state = 0
|
||||
self.slc_state = 0
|
||||
self.m_tsc_state = 0
|
||||
self.cruise_button = None
|
||||
self.speed_diff = 0
|
||||
self.v_tsc = 0
|
||||
self.m_tsc = 0
|
||||
self.steady_speed = 0
|
||||
|
||||
def update(self, CC, CS, now_nanos):
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
self.sm.update(0)
|
||||
|
||||
if self.sm.updated['longitudinalPlanSP']:
|
||||
self.v_tsc_state = self.sm['longitudinalPlanSP'].visionTurnControllerState
|
||||
self.slc_state = self.sm['longitudinalPlanSP'].speedLimitControlState
|
||||
self.m_tsc_state = self.sm['longitudinalPlanSP'].turnSpeedControlState
|
||||
self.speed_limit = self.sm['longitudinalPlanSP'].speedLimit
|
||||
self.speed_limit_offset = self.sm['longitudinalPlanSP'].speedLimitOffset
|
||||
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
|
||||
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
|
||||
|
||||
self.v_cruise_min = MAZDA_V_CRUISE_MIN[CS.params_list.is_metric] * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1)
|
||||
|
||||
can_sends = []
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if not self.last_speed_limit_sign_tap_prev and CS.params_list.last_speed_limit_sign_tap:
|
||||
self.sl_force_active_timer = self.frame
|
||||
self.param_s.put_bool_nonblocking("LastSpeedLimitSignTap", False)
|
||||
self.last_speed_limit_sign_tap_prev = CS.params_list.last_speed_limit_sign_tap
|
||||
|
||||
sl_force_active = CS.params_list.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not CS.params_list.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (CS.params_list.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
slc_active = not sl_inactive and not sl_temp_inactive
|
||||
|
||||
self.slc_active_stock = slc_active
|
||||
|
||||
apply_steer = 0
|
||||
|
||||
if CC.latActive:
|
||||
@@ -102,11 +43,6 @@ class CarController(CarControllerBase):
|
||||
# Mazda Stop and Go requires a RES button (or gas) press if the car stops more than 3 seconds
|
||||
# Send Resume button when planner wants car to move
|
||||
can_sends.append(mazdacan.create_button_cmd(self.packer, self.CP, CS.crz_btns_counter, Buttons.RESUME))
|
||||
elif CS.out.cruiseState.enabled and not self.CP.pcmCruiseSpeed:
|
||||
self.cruise_button = self.get_cruise_buttons(CS, CC.vCruise)
|
||||
if self.cruise_button is not None:
|
||||
if self.frame % 10 == 0:
|
||||
can_sends.append(mazdacan.create_button_cmd(self.packer, self.CP, self.frame // 10, self.cruise_button))
|
||||
|
||||
self.apply_steer_last = apply_steer
|
||||
|
||||
@@ -128,125 +64,3 @@ class CarController(CarControllerBase):
|
||||
|
||||
self.frame += 1
|
||||
return new_actuators, can_sends
|
||||
|
||||
# multikyd methods, sunnyhaibin logic
|
||||
def get_cruise_buttons_status(self, CS):
|
||||
if not CS.out.cruiseState.enabled:
|
||||
for be in CS.out.buttonEvents:
|
||||
if be.type in (ButtonType.accelCruise, ButtonType.resumeCruise,
|
||||
ButtonType.decelCruise, ButtonType.setCruise) and be.pressed:
|
||||
self.timer = 40
|
||||
elif self.timer:
|
||||
self.timer -= 1
|
||||
else:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def get_target_speed(self, v_cruise_kph_prev):
|
||||
v_cruise_kph = v_cruise_kph_prev
|
||||
if self.slc_state > 1:
|
||||
v_cruise_kph = (self.speed_limit + self.speed_limit_offset) * CV.MS_TO_KPH
|
||||
if not self.slc_active_stock:
|
||||
v_cruise_kph = v_cruise_kph_prev
|
||||
return v_cruise_kph
|
||||
|
||||
def get_button_type(self, button_type):
|
||||
self.type_status = "type_" + str(button_type)
|
||||
self.button_picker = getattr(self, self.type_status, lambda: "default")
|
||||
return self.button_picker()
|
||||
|
||||
def reset_button(self):
|
||||
if self.button_type != 3:
|
||||
self.button_type = 0
|
||||
|
||||
def type_default(self):
|
||||
self.button_type = 0
|
||||
return None
|
||||
|
||||
def type_0(self):
|
||||
self.button_count = 0
|
||||
self.target_speed = self.init_speed
|
||||
self.speed_diff = self.target_speed - self.v_set_dis
|
||||
if self.target_speed > self.v_set_dis:
|
||||
return Buttons.SET_PLUS
|
||||
self.button_type = 1
|
||||
elif self.target_speed < self.v_set_dis and self.v_set_dis > self.v_cruise_min:
|
||||
return Buttons.SET_MINUS
|
||||
self.button_type = 2
|
||||
return None
|
||||
|
||||
def type_1(self):
|
||||
cruise_button = Buttons.SET_PLUS
|
||||
self.button_count += 1
|
||||
if self.target_speed <= self.v_set_dis:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
elif self.button_count > 5:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
return cruise_button
|
||||
|
||||
def type_2(self):
|
||||
cruise_button = Buttons.SET_MINUS
|
||||
self.button_count += 1
|
||||
if self.target_speed >= self.v_set_dis or self.v_set_dis <= self.v_cruise_min:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
elif self.button_count > 5:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
return cruise_button
|
||||
|
||||
def type_3(self):
|
||||
cruise_button = None
|
||||
self.button_count += 1
|
||||
if self.button_count > self.t_interval:
|
||||
self.button_type = 0
|
||||
return cruise_button
|
||||
|
||||
def get_curve_speed(self, target_speed_kph, v_cruise_kph_prev):
|
||||
if self.v_tsc_state != 0:
|
||||
vision_v_cruise_kph = self.v_tsc * CV.MS_TO_KPH
|
||||
if int(vision_v_cruise_kph) == int(v_cruise_kph_prev):
|
||||
vision_v_cruise_kph = 255
|
||||
else:
|
||||
vision_v_cruise_kph = 255
|
||||
if self.m_tsc_state > 1:
|
||||
map_v_cruise_kph = self.m_tsc * CV.MS_TO_KPH
|
||||
if int(map_v_cruise_kph) == 0.0:
|
||||
map_v_cruise_kph = 255
|
||||
else:
|
||||
map_v_cruise_kph = 255
|
||||
curve_speed = self.curve_speed_hysteresis(min(vision_v_cruise_kph, map_v_cruise_kph) + 2 * CV.MPH_TO_KPH)
|
||||
return min(target_speed_kph, curve_speed)
|
||||
|
||||
def get_button_control(self, CS, final_speed, v_cruise_kph_prev):
|
||||
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1))
|
||||
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not CS.params_list.is_metric else CV.MS_TO_KPH))
|
||||
cruise_button = self.get_button_type(self.button_type)
|
||||
return cruise_button
|
||||
|
||||
def curve_speed_hysteresis(self, cur_speed: float, hyst=(0.75 * CV.MPH_TO_KPH)):
|
||||
if cur_speed > self.steady_speed:
|
||||
self.steady_speed = cur_speed
|
||||
elif cur_speed < self.steady_speed - hyst:
|
||||
self.steady_speed = cur_speed
|
||||
return self.steady_speed
|
||||
|
||||
def get_cruise_buttons(self, CS, v_cruise_kph_prev):
|
||||
cruise_button = None
|
||||
if not self.get_cruise_buttons_status(CS):
|
||||
pass
|
||||
elif CS.out.cruiseState.enabled:
|
||||
set_speed_kph = self.get_target_speed(v_cruise_kph_prev)
|
||||
if self.slc_state > 1:
|
||||
target_speed_kph = set_speed_kph
|
||||
else:
|
||||
target_speed_kph = min(v_cruise_kph_prev, set_speed_kph)
|
||||
if self.v_tsc_state != 0 or self.m_tsc_state > 1:
|
||||
self.final_speed_kph = self.get_curve_speed(target_speed_kph, v_cruise_kph_prev)
|
||||
else:
|
||||
self.final_speed_kph = target_speed_kph
|
||||
|
||||
cruise_button = self.get_button_control(CS, self.final_speed_kph, v_cruise_kph_prev) # MPH/KPH based button presses
|
||||
return cruise_button
|
||||
|
||||
@@ -45,10 +45,9 @@ class CarInterface(CarInterfaceBase):
|
||||
*create_button_events(self.CS.lkas_enabled, self.CS.prev_lkas_enabled, {1: ButtonType.altButton1}),
|
||||
]
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret)
|
||||
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
|
||||
self.CS.button_events, c.vCruise)
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, c.vCruise, self.CS.accEnabled)
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if self.enable_mads:
|
||||
@@ -56,15 +55,15 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.madsEnabled = True
|
||||
if any(b.type == ButtonType.altButton1 and b.pressed for b in self.CS.button_events):
|
||||
self.CS.madsEnabled = not self.CS.madsEnabled
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret, self.CS.madsEnabled)
|
||||
else:
|
||||
self.CS.madsEnabled = False
|
||||
|
||||
if not self.CP.pcmCruise or (self.CP.pcmCruise and self.CP.minEnableSpeed > 0) or not self.CP.pcmCruiseSpeed:
|
||||
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
ret.cruiseState.enabled = ret.cruiseState.enabled if not self.enable_mads else False if self.CP.pcmCruise else self.CS.accEnabled
|
||||
|
||||
if self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed:
|
||||
@@ -72,7 +71,7 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.accEnabled = False
|
||||
self.CS.accEnabled = ret.cruiseState.enabled or self.CS.accEnabled
|
||||
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=bool(self.CS.distance_button))
|
||||
ret = self.get_sp_common_state(ret)
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -83,17 +82,13 @@ class CarInterface(CarInterfaceBase):
|
||||
events = self.create_common_events(ret, c, extra_gears=[GearShifter.sport, GearShifter.low, GearShifter.brake],
|
||||
pcm_enable=False)
|
||||
|
||||
events, ret = self.create_sp_events(self.CS, ret, events)
|
||||
events, ret = self.create_sp_events(ret, events)
|
||||
|
||||
#if self.CS.lkas_disabled:
|
||||
# events.add(EventName.lkasDisabled)
|
||||
if self.CS.low_speed_alert:
|
||||
events.add(EventName.belowSteerSpeed)
|
||||
|
||||
ret.customStockLong = self.CS.update_custom_stock_long(self.CC.cruise_button, self.CC.final_speed_kph,
|
||||
self.CC.target_speed, self.CC.v_set_dis,
|
||||
self.CC.speed_diff, self.CC.button_type)
|
||||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
return ret
|
||||
|
||||
@@ -92,22 +92,20 @@ def create_button_cmd(packer, CP, counter, button):
|
||||
|
||||
can = int(button == Buttons.CANCEL)
|
||||
res = int(button == Buttons.RESUME)
|
||||
inc = int(button == Buttons.SET_PLUS)
|
||||
dec = int(button == Buttons.SET_MINUS)
|
||||
|
||||
if CP.flags & MazdaFlags.GEN1:
|
||||
values = {
|
||||
"CAN_OFF": can,
|
||||
"CAN_OFF_INV": (can + 1) % 2,
|
||||
|
||||
"SET_P": inc,
|
||||
"SET_P_INV": (inc + 1) % 2,
|
||||
"SET_P": 0,
|
||||
"SET_P_INV": 1,
|
||||
|
||||
"RES": res,
|
||||
"RES_INV": (res + 1) % 2,
|
||||
|
||||
"SET_M": dec,
|
||||
"SET_M_INV": (dec + 1) % 2,
|
||||
"SET_M": 0,
|
||||
"SET_M_INV": 1,
|
||||
|
||||
"DISTANCE_LESS": 0,
|
||||
"DISTANCE_LESS_INV": 1,
|
||||
|
||||
@@ -35,22 +35,22 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
self.CS.button_events = create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise})
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret)
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if self.enable_mads:
|
||||
if not self.CS.prev_mads_enabled and self.CS.mads_enabled:
|
||||
self.CS.madsEnabled = True
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret, self.CS.madsEnabled)
|
||||
else:
|
||||
self.CS.madsEnabled = False
|
||||
|
||||
if (not ret.cruiseState.enabled and self.CS.out.cruiseState.enabled) or \
|
||||
self.get_sp_pedal_disengage(ret):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
ret.cruiseState.enabled = ret.cruiseState.enabled if not self.enable_mads else False if self.CP.pcmCruise else self.CS.accEnabled
|
||||
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=bool(self.CS.distance_button))
|
||||
ret = self.get_sp_common_state(ret)
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -61,7 +61,7 @@ class CarInterface(CarInterfaceBase):
|
||||
events = self.create_common_events(ret, c, extra_gears=[GearShifter.sport, GearShifter.low, GearShifter.brake],
|
||||
pcm_enable=False)
|
||||
|
||||
events, ret = self.create_sp_events(self.CS, ret, events)
|
||||
events, ret = self.create_sp_events(ret, events)
|
||||
|
||||
if self.CS.lkas_enabled:
|
||||
events.add(car.CarEvent.EventName.invalidLkasSetting)
|
||||
|
||||
@@ -9,8 +9,11 @@ class ParamManager:
|
||||
"acc_mads_combo": False,
|
||||
"below_speed_pause": False,
|
||||
"experimental_mode": False,
|
||||
"hyundai_radar_tracks_available": False,
|
||||
"hyundai_radar_tracks_available_cache": False,
|
||||
"is_metric": False,
|
||||
"last_speed_limit_sign_tap": False,
|
||||
"hyundai_cruise_main_default": False,
|
||||
"mads_main_toggle": False,
|
||||
"pause_lateral_speed": 0,
|
||||
"reverse_acc_change": False,
|
||||
@@ -35,8 +38,11 @@ class ParamManager:
|
||||
"acc_mads_combo": params.get_bool("AccMadsCombo"),
|
||||
"below_speed_pause": params.get_bool("BelowSpeedPause"),
|
||||
"experimental_mode": params.get_bool("ExperimentalMode"),
|
||||
"hyundai_radar_tracks_available": params.get_bool("HyundaiRadarTracksAvailable"),
|
||||
"hyundai_radar_tracks_available_cache": params.get_bool("HyundaiRadarTracksAvailableCache"),
|
||||
"is_metric": params.get_bool("IsMetric"),
|
||||
"last_speed_limit_sign_tap": params.get_bool("LastSpeedLimitSignTap"),
|
||||
"hyundai_cruise_main_default": params.get_bool("HyundaiCruiseMainDefault"),
|
||||
"mads_main_toggle": params.get_bool("MadsCruiseMain"),
|
||||
"pause_lateral_speed": int(params.get("PauseLateralSpeed", encoding="utf8")),
|
||||
"reverse_acc_change": params.get_bool("ReverseAccChange"),
|
||||
|
||||
@@ -117,7 +117,7 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_body)
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret)
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if self.enable_mads:
|
||||
@@ -128,7 +128,7 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.madsEnabled = not self.CS.madsEnabled
|
||||
elif self.CS.prev_lkas_enabled != self.CS.lkas_enabled and self.CS.prev_lkas_enabled == 2 and self.CS.lkas_enabled != 1:
|
||||
self.CS.madsEnabled = not self.CS.madsEnabled
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret, self.CS.madsEnabled)
|
||||
else:
|
||||
self.CS.madsEnabled = False
|
||||
|
||||
@@ -137,10 +137,10 @@ class CarInterface(CarInterfaceBase):
|
||||
if not self.enable_mads:
|
||||
self.CS.madsEnabled = False
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
ret.cruiseState.enabled = ret.cruiseState.enabled if not self.enable_mads else False if self.CP.pcmCruise else self.CS.accEnabled
|
||||
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS)
|
||||
ret = self.get_sp_common_state(ret)
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -150,7 +150,7 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
events = self.create_common_events(ret, c, extra_gears=[GearShifter.sport, GearShifter.low], pcm_enable=False)
|
||||
|
||||
events, ret = self.create_sp_events(self.CS, ret, events)
|
||||
events, ret = self.create_sp_events(ret, events)
|
||||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
from collections.abc import Callable
|
||||
|
||||
import cereal.messaging as messaging
|
||||
from openpilot.selfdrive.car import gen_empty_fingerprint
|
||||
|
||||
FRAME_FINGERPRINT = 25 # 0.25s
|
||||
|
||||
|
||||
def get_one_can(logcan):
|
||||
while True:
|
||||
can = messaging.recv_one_retry(logcan)
|
||||
if len(can.can) > 0:
|
||||
return can
|
||||
|
||||
|
||||
def can_fingerprint(next_can: Callable) -> tuple[str | None, dict[int, dict]]:
|
||||
finger = gen_empty_fingerprint()
|
||||
frame = 0
|
||||
done = False
|
||||
|
||||
while not done:
|
||||
a = next_can()
|
||||
|
||||
for can in a.can:
|
||||
# The fingerprint dict is generated for all buses, this way the car interface
|
||||
# can use it to detect a (valid) multipanda setup and initialize accordingly
|
||||
if can.src < 128:
|
||||
if can.src not in finger:
|
||||
finger[can.src] = {}
|
||||
finger[can.src][can.address] = len(can.dat)
|
||||
|
||||
# bail if we've been waiting for more than 2s
|
||||
done = frame > 100
|
||||
|
||||
frame += 1
|
||||
|
||||
return finger
|
||||
@@ -208,13 +208,10 @@ class CarInterface(CarInterfaceBase):
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
|
||||
distance_button = 0
|
||||
|
||||
if self.CP.carFingerprint in (TSS2_CAR - RADAR_ACC_CAR) or (self.CP.flags & ToyotaFlags.SMART_DSU and not self.CP.flags & ToyotaFlags.RADAR_CAN_FILTER):
|
||||
self.CS.button_events = create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise})
|
||||
distance_button = self.CS.distance_button
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret)
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if self.enable_mads:
|
||||
@@ -229,16 +226,16 @@ class CarInterface(CarInterfaceBase):
|
||||
if (not self.CS.prev_lkas_enabled and self.CS.lkas_enabled) or \
|
||||
(self.CS.prev_lkas_enabled == 1 and not self.CS.lkas_enabled):
|
||||
self.CS.madsEnabled = not self.CS.madsEnabled
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret, self.CS.madsEnabled)
|
||||
else:
|
||||
self.CS.madsEnabled = False
|
||||
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
if not self.CP.pcmCruise:
|
||||
ret.cruiseState.enabled = self.CS.accEnabled
|
||||
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS, gap_button=bool(distance_button))
|
||||
ret = self.get_sp_common_state(ret)
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -250,7 +247,7 @@ class CarInterface(CarInterfaceBase):
|
||||
events = self.create_common_events(ret, c, extra_gears=[GearShifter.sport, GearShifter.low, GearShifter.brake],
|
||||
pcm_enable=False)
|
||||
|
||||
events, ret = self.create_sp_events(self.CS, ret, events)
|
||||
events, ret = self.create_sp_events(ret, events)
|
||||
|
||||
# Lane Tracing Assist control is unavailable (EPS_STATUS->LTA_STATE=0) until
|
||||
# the more accurate angle sensor signal is initialized
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
from cereal import car
|
||||
import cereal.messaging as messaging
|
||||
from opendbc.can.packer import CANPacker
|
||||
from openpilot.common.numpy_fast import clip
|
||||
from openpilot.common.conversions import Conversions as CV
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.selfdrive.car import DT_CTRL, apply_driver_steer_torque_limits
|
||||
from openpilot.selfdrive.car.interfaces import CarControllerBase
|
||||
from openpilot.selfdrive.car.volkswagen import mqbcan, pqcan
|
||||
from openpilot.selfdrive.car.volkswagen.values import CANBUS, CarControllerParams, VolkswagenFlags
|
||||
from openpilot.selfdrive.controls.lib.drive_helpers import VOLKSWAGEN_V_CRUISE_MIN
|
||||
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
LongCtrlState = car.CarControl.Actuators.LongControlState
|
||||
@@ -28,70 +25,12 @@ class CarController(CarControllerBase):
|
||||
self.eps_timer_soft_disable_alert = False
|
||||
self.hca_frame_timer_running = 0
|
||||
self.hca_frame_same_torque = 0
|
||||
self.last_button_frame = 0
|
||||
|
||||
self.sm = messaging.SubMaster(['longitudinalPlanSP'])
|
||||
self.param_s = Params()
|
||||
self.last_speed_limit_sign_tap_prev = False
|
||||
self.speed_limit = 0.
|
||||
self.speed_limit_offset = 0
|
||||
self.timer = 0
|
||||
self.final_speed_kph = 0
|
||||
self.init_speed = 0
|
||||
self.current_speed = 0
|
||||
self.v_set_dis = 0
|
||||
self.v_set_dis_prev = 0
|
||||
self.v_cruise_min = 0
|
||||
self.button_type = 0
|
||||
self.button_select = 0
|
||||
self.button_count = 0
|
||||
self.target_speed = 0
|
||||
self.t_interval = 7
|
||||
self.slc_active_stock = False
|
||||
self.sl_force_active_timer = 0
|
||||
self.v_tsc_state = 0
|
||||
self.slc_state = 0
|
||||
self.m_tsc_state = 0
|
||||
self.cruise_button = None
|
||||
self.last_cruise_button = None
|
||||
self.speed_diff = 0
|
||||
self.v_tsc = 0
|
||||
self.m_tsc = 0
|
||||
self.steady_speed = 0
|
||||
self.acc_type = -1
|
||||
self.send_count = 0
|
||||
|
||||
def update(self, CC, CS, now_nanos):
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
self.sm.update(0)
|
||||
|
||||
if self.sm.updated['longitudinalPlanSP']:
|
||||
self.v_tsc_state = self.sm['longitudinalPlanSP'].visionTurnControllerState
|
||||
self.slc_state = self.sm['longitudinalPlanSP'].speedLimitControlState
|
||||
self.m_tsc_state = self.sm['longitudinalPlanSP'].turnSpeedControlState
|
||||
self.speed_limit = self.sm['longitudinalPlanSP'].speedLimit
|
||||
self.speed_limit_offset = self.sm['longitudinalPlanSP'].speedLimitOffset
|
||||
self.v_tsc = self.sm['longitudinalPlanSP'].visionTurnSpeed
|
||||
self.m_tsc = self.sm['longitudinalPlanSP'].turnSpeed
|
||||
|
||||
self.v_cruise_min = VOLKSWAGEN_V_CRUISE_MIN[CS.params_list.is_metric] * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1)
|
||||
actuators = CC.actuators
|
||||
hud_control = CC.hudControl
|
||||
can_sends = []
|
||||
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
if not self.last_speed_limit_sign_tap_prev and CS.params_list.last_speed_limit_sign_tap:
|
||||
self.sl_force_active_timer = self.frame
|
||||
self.param_s.put_bool_nonblocking("LastSpeedLimitSignTap", False)
|
||||
self.last_speed_limit_sign_tap_prev = CS.params_list.last_speed_limit_sign_tap
|
||||
|
||||
sl_force_active = CS.params_list.speed_limit_control_enabled and (self.frame < (self.sl_force_active_timer * DT_CTRL + 2.0))
|
||||
sl_inactive = not sl_force_active and (not CS.params_list.speed_limit_control_enabled or (True if self.slc_state == 0 else False))
|
||||
sl_temp_inactive = not sl_force_active and (CS.params_list.speed_limit_control_enabled and (True if self.slc_state == 1 else False))
|
||||
slc_active = not sl_inactive and not sl_temp_inactive
|
||||
|
||||
self.slc_active_stock = slc_active
|
||||
|
||||
# **** Steering Controls ************************************************ #
|
||||
|
||||
if self.frame % self.CCP.STEER_STEP == 0:
|
||||
@@ -171,155 +110,11 @@ class CarController(CarControllerBase):
|
||||
if gra_send_ready and (CC.cruiseControl.cancel or CC.cruiseControl.resume):
|
||||
can_sends.append(self.CCS.create_acc_buttons_control(self.packer_pt, self.ext_bus, CS.gra_stock_values,
|
||||
cancel=CC.cruiseControl.cancel, resume=CC.cruiseControl.resume))
|
||||
if not (CC.cruiseControl.cancel or CC.cruiseControl.resume) and CS.out.cruiseState.enabled:
|
||||
if not self.CP.pcmCruiseSpeed:
|
||||
self.cruise_button = self.get_cruise_buttons(CS, CC.vCruise)
|
||||
if self.cruise_button is not None:
|
||||
if self.acc_type == -1:
|
||||
if self.button_count >= 2 and self.v_set_dis_prev != self.v_set_dis:
|
||||
self.acc_type = 1 if abs(self.v_set_dis - self.v_set_dis_prev) >= 10 and self.last_cruise_button in (1, 2) else \
|
||||
0 if abs(self.v_set_dis - self.v_set_dis_prev) < 10 and self.last_cruise_button not in (1, 2) else 1
|
||||
if self.send_count >= 10 and self.v_set_dis_prev == self.v_set_dis:
|
||||
self.cruise_button = 3 if self.cruise_button == 1 else 4
|
||||
if self.acc_type == 0:
|
||||
self.cruise_button = 1 if self.cruise_button == 1 else 2 # accel, decel
|
||||
elif self.acc_type == 1:
|
||||
self.cruise_button = 3 if self.cruise_button == 1 else 4 # resume, set
|
||||
if self.frame % self.CCP.BTN_STEP == 0:
|
||||
can_sends.append(self.CCS.create_acc_buttons_control(self.packer_pt, CS.gra_stock_values, frame=(self.frame // self.CCP.BTN_STEP),
|
||||
buttons=self.cruise_button, custom_stock_long=True))
|
||||
self.send_count += 1
|
||||
else:
|
||||
self.send_count = 0
|
||||
self.last_cruise_button = self.cruise_button
|
||||
|
||||
new_actuators = actuators.as_builder()
|
||||
new_actuators.steer = self.apply_steer_last / self.CCP.STEER_MAX
|
||||
new_actuators.steerOutputCan = self.apply_steer_last
|
||||
|
||||
self.gra_acc_counter_last = CS.gra_stock_values["COUNTER"]
|
||||
self.v_set_dis_prev = self.v_set_dis
|
||||
self.frame += 1
|
||||
return new_actuators, can_sends
|
||||
|
||||
# multikyd methods, sunnyhaibin logic
|
||||
def get_cruise_buttons_status(self, CS):
|
||||
if not CS.out.cruiseState.enabled:
|
||||
for be in CS.out.buttonEvents:
|
||||
if be.type in (ButtonType.accelCruise, ButtonType.resumeCruise,
|
||||
ButtonType.decelCruise, ButtonType.setCruise) and be.pressed:
|
||||
self.timer = 40
|
||||
elif be.type == ButtonType.gapAdjustCruise and be.pressed:
|
||||
self.timer = 300
|
||||
elif self.timer:
|
||||
self.timer -= 1
|
||||
else:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def get_target_speed(self, v_cruise_kph_prev):
|
||||
v_cruise_kph = v_cruise_kph_prev
|
||||
if self.slc_state > 1:
|
||||
v_cruise_kph = (self.speed_limit + self.speed_limit_offset) * CV.MS_TO_KPH
|
||||
if not self.slc_active_stock:
|
||||
v_cruise_kph = v_cruise_kph_prev
|
||||
return v_cruise_kph
|
||||
|
||||
def get_button_type(self, button_type):
|
||||
self.type_status = "type_" + str(button_type)
|
||||
self.button_picker = getattr(self, self.type_status, lambda: "default")
|
||||
return self.button_picker()
|
||||
|
||||
def reset_button(self):
|
||||
if self.button_type != 3:
|
||||
self.button_type = 0
|
||||
|
||||
def type_default(self):
|
||||
self.button_type = 0
|
||||
return None
|
||||
|
||||
def type_0(self):
|
||||
self.button_count = 0
|
||||
self.target_speed = self.init_speed
|
||||
self.speed_diff = self.target_speed - self.v_set_dis
|
||||
if self.target_speed > self.v_set_dis:
|
||||
self.button_type = 1
|
||||
elif self.target_speed < self.v_set_dis and self.v_set_dis > self.v_cruise_min:
|
||||
self.button_type = 2
|
||||
return None
|
||||
|
||||
def type_1(self):
|
||||
cruise_button = 1
|
||||
self.button_count += 1
|
||||
if self.target_speed <= self.v_set_dis:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
elif self.button_count > 5:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
return cruise_button
|
||||
|
||||
def type_2(self):
|
||||
cruise_button = 2
|
||||
self.button_count += 1
|
||||
if self.target_speed >= self.v_set_dis or self.v_set_dis <= self.v_cruise_min:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
elif self.button_count > 5:
|
||||
self.button_count = 0
|
||||
self.button_type = 3
|
||||
return cruise_button
|
||||
|
||||
def type_3(self):
|
||||
cruise_button = None
|
||||
self.button_count += 1
|
||||
if self.button_count > self.t_interval:
|
||||
self.button_type = 0
|
||||
return cruise_button
|
||||
|
||||
def get_curve_speed(self, target_speed_kph, v_cruise_kph_prev):
|
||||
if self.v_tsc_state != 0:
|
||||
vision_v_cruise_kph = self.v_tsc * CV.MS_TO_KPH
|
||||
if int(vision_v_cruise_kph) == int(v_cruise_kph_prev):
|
||||
vision_v_cruise_kph = 255
|
||||
else:
|
||||
vision_v_cruise_kph = 255
|
||||
if self.m_tsc_state > 1:
|
||||
map_v_cruise_kph = self.m_tsc * CV.MS_TO_KPH
|
||||
if int(map_v_cruise_kph) == 0.0:
|
||||
map_v_cruise_kph = 255
|
||||
else:
|
||||
map_v_cruise_kph = 255
|
||||
curve_speed = self.curve_speed_hysteresis(min(vision_v_cruise_kph, map_v_cruise_kph) + 2 * CV.MPH_TO_KPH)
|
||||
return min(target_speed_kph, curve_speed)
|
||||
|
||||
def get_button_control(self, CS, final_speed, v_cruise_kph_prev):
|
||||
self.init_speed = round(min(final_speed, v_cruise_kph_prev) * (CV.KPH_TO_MPH if not CS.params_list.is_metric else 1))
|
||||
self.v_set_dis = round(CS.out.cruiseState.speed * (CV.MS_TO_MPH if not CS.params_list.is_metric else CV.MS_TO_KPH))
|
||||
cruise_button = self.get_button_type(self.button_type)
|
||||
return cruise_button
|
||||
|
||||
def curve_speed_hysteresis(self, cur_speed: float, hyst=(0.75 * CV.MPH_TO_KPH)):
|
||||
if cur_speed > self.steady_speed:
|
||||
self.steady_speed = cur_speed
|
||||
elif cur_speed < self.steady_speed - hyst:
|
||||
self.steady_speed = cur_speed
|
||||
return self.steady_speed
|
||||
|
||||
def get_cruise_buttons(self, CS, v_cruise_kph_prev):
|
||||
cruise_button = None
|
||||
if not self.get_cruise_buttons_status(CS):
|
||||
pass
|
||||
elif CS.out.cruiseState.enabled:
|
||||
set_speed_kph = self.get_target_speed(v_cruise_kph_prev)
|
||||
if self.slc_state > 1:
|
||||
target_speed_kph = set_speed_kph
|
||||
else:
|
||||
target_speed_kph = min(v_cruise_kph_prev, set_speed_kph)
|
||||
if self.v_tsc_state != 0 or self.m_tsc_state > 1:
|
||||
self.final_speed_kph = self.get_curve_speed(target_speed_kph, v_cruise_kph_prev)
|
||||
else:
|
||||
self.final_speed_kph = target_speed_kph
|
||||
|
||||
cruise_button = self.get_button_control(CS, self.final_speed_kph, v_cruise_kph_prev) # MPH/KPH based button presses
|
||||
return cruise_button
|
||||
|
||||
@@ -114,26 +114,25 @@ class CarInterface(CarInterfaceBase):
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_ext, self.CP.transmissionType)
|
||||
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret, self.CS)
|
||||
self.CS.mads_enabled = self.get_sp_cruise_main_state(ret)
|
||||
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, self.CS.accEnabled,
|
||||
self.CS.button_events, c.vCruise,
|
||||
self.CS.accEnabled = self.get_sp_v_cruise_non_pcm_state(ret, c.vCruise, self.CS.accEnabled,
|
||||
enable_buttons=(ButtonType.setCruise, ButtonType.resumeCruise))
|
||||
|
||||
if ret.cruiseState.available:
|
||||
if self.enable_mads:
|
||||
if not self.CS.prev_mads_enabled and self.CS.mads_enabled:
|
||||
self.CS.madsEnabled = True
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret, self.CS.madsEnabled)
|
||||
else:
|
||||
self.CS.madsEnabled = False
|
||||
self.CS.madsEnabled = self.get_sp_started_mads(ret, self.CS)
|
||||
self.CS.madsEnabled = self.get_sp_started_mads(ret, self.CS.madsEnabled)
|
||||
|
||||
if not self.CP.pcmCruise or (self.CP.pcmCruise and self.CP.minEnableSpeed > 0) or not self.CP.pcmCruiseSpeed:
|
||||
if any(b.type == ButtonType.cancel for b in self.CS.button_events):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
if self.get_sp_pedal_disengage(ret):
|
||||
self.CS.madsEnabled, self.CS.accEnabled = self.get_sp_cancel_cruise_state(self.CS.madsEnabled)
|
||||
self.get_sp_cancel_cruise_state()
|
||||
ret.cruiseState.enabled = ret.cruiseState.enabled if not self.enable_mads else False if self.CP.pcmCruise else self.CS.accEnabled
|
||||
|
||||
if self.CP.pcmCruise and self.CP.minEnableSpeed > 0 and self.CP.pcmCruiseSpeed:
|
||||
@@ -141,8 +140,7 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.accEnabled = False
|
||||
self.CS.accEnabled = ret.cruiseState.enabled or self.CS.accEnabled
|
||||
|
||||
ret, self.CS = self.get_sp_common_state(ret, self.CS,
|
||||
gap_button=any(b.type == ButtonType.gapAdjustCruise and b.pressed for b in self.CS.button_events))
|
||||
ret = self.get_sp_common_state(ret)
|
||||
|
||||
ret.buttonEvents = [
|
||||
*self.CS.button_events,
|
||||
@@ -153,7 +151,7 @@ class CarInterface(CarInterfaceBase):
|
||||
pcm_enable=False,
|
||||
enable_buttons=(ButtonType.setCruise, ButtonType.resumeCruise))
|
||||
|
||||
events, ret = self.create_sp_events(self.CS, ret, events,
|
||||
events, ret = self.create_sp_events(ret, events,
|
||||
enable_buttons=(ButtonType.setCruise, ButtonType.resumeCruise))
|
||||
|
||||
# Low speed steer alert hysteresis logic
|
||||
@@ -173,10 +171,6 @@ class CarInterface(CarInterfaceBase):
|
||||
if self.CC.eps_timer_soft_disable_alert:
|
||||
events.add(EventName.steerTimeLimit)
|
||||
|
||||
ret.customStockLong = self.CS.update_custom_stock_long(self.CC.cruise_button, self.CC.final_speed_kph,
|
||||
self.CC.target_speed, self.CC.v_set_dis,
|
||||
self.CC.speed_diff, self.CC.button_type)
|
||||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
return ret
|
||||
|
||||
@@ -49,7 +49,7 @@ def create_lka_hud_control(packer, bus, ldw_stock_values, lat_active, steering_p
|
||||
return packer.make_can_msg("LDW_02", bus, values)
|
||||
|
||||
|
||||
def create_acc_buttons_control(packer, bus, gra_stock_values, frame=0, buttons=0, cancel=False, resume=False, custom_stock_long=False):
|
||||
def create_acc_buttons_control(packer, bus, gra_stock_values, cancel=False, resume=False):
|
||||
values = {s: gra_stock_values[s] for s in [
|
||||
"GRA_Hauptschalter", # ACC button, on/off
|
||||
"GRA_Typ_Hauptschalter", # ACC main button type
|
||||
@@ -58,18 +58,10 @@ def create_acc_buttons_control(packer, bus, gra_stock_values, frame=0, buttons=0
|
||||
"GRA_ButtonTypeInfo", # unknown related to stalk type
|
||||
]}
|
||||
|
||||
accel_cruise = 1 if buttons == 1 else 0
|
||||
decel_cruise = 1 if buttons == 2 else 0
|
||||
resume_cruise = 1 if buttons == 3 else 0
|
||||
set_cruise = 1 if buttons == 4 else 0
|
||||
|
||||
values.update({
|
||||
"COUNTER": (frame + 1) % 0x10 if custom_stock_long else (gra_stock_values["COUNTER"] + 1) % 16,
|
||||
"COUNTER": (gra_stock_values["COUNTER"] + 1) % 16,
|
||||
"GRA_Abbrechen": cancel,
|
||||
"GRA_Tip_Wiederaufnahme": resume or resume_cruise,
|
||||
"GRA_Tip_Setzen": set_cruise,
|
||||
"GRA_Tip_Runter": decel_cruise,
|
||||
"GRA_Tip_Hoch": accel_cruise,
|
||||
"GRA_Tip_Wiederaufnahme": resume,
|
||||
})
|
||||
|
||||
return packer.make_can_msg("GRA_ACC_01", bus, values)
|
||||
|
||||
@@ -31,7 +31,7 @@ def create_lka_hud_control(packer, bus, ldw_stock_values, lat_active, steering_p
|
||||
return packer.make_can_msg("LDW_Status", bus, values)
|
||||
|
||||
|
||||
def create_acc_buttons_control(packer, bus, gra_stock_values, frame=0, buttons=0, cancel=False, resume=False, custom_stock_long=False):
|
||||
def create_acc_buttons_control(packer, bus, gra_stock_values, cancel=False, resume=False):
|
||||
values = {s: gra_stock_values[s] for s in [
|
||||
"GRA_Hauptschalt", # ACC button, on/off
|
||||
"GRA_Typ_Hauptschalt", # ACC button, momentary vs latching
|
||||
@@ -39,18 +39,10 @@ def create_acc_buttons_control(packer, bus, gra_stock_values, frame=0, buttons=0
|
||||
"GRA_Sender", # ACC button, CAN message originator
|
||||
]}
|
||||
|
||||
accel_cruise = 1 if buttons == 1 else 0
|
||||
decel_cruise = 1 if buttons == 2 else 0
|
||||
resume_cruise = 1 if buttons == 3 else 0
|
||||
set_cruise = 1 if buttons == 4 else 0
|
||||
|
||||
values.update({
|
||||
"COUNTER": (frame + 1) % 0x10 if custom_stock_long else (gra_stock_values["COUNTER"] + 1) % 16,
|
||||
"COUNTER": (gra_stock_values["COUNTER"] + 1) % 16,
|
||||
"GRA_Abbrechen": cancel,
|
||||
"GRA_Recall": resume or resume_cruise,
|
||||
"GRA_Neu_Setzen": set_cruise,
|
||||
"GRA_Down_kurz": decel_cruise,
|
||||
"GRA_Up_kurz": accel_cruise,
|
||||
"GRA_Recall": resume,
|
||||
})
|
||||
|
||||
return packer.make_can_msg("GRA_Neu", bus, values)
|
||||
|
||||
@@ -20,7 +20,7 @@ from openpilot.common.swaglog import cloudlog
|
||||
|
||||
from openpilot.selfdrive.car.car_helpers import get_car_interface, get_startup_event
|
||||
from openpilot.selfdrive.controls.lib.alertmanager import AlertManager, set_offroad_alert
|
||||
from openpilot.selfdrive.controls.lib.drive_helpers import VCruiseHelper, clip_curvature, get_lag_adjusted_curvature
|
||||
from openpilot.selfdrive.controls.lib.drive_helpers import VCruiseHelper, clip_curvature, get_lag_adjusted_curvature, CRUISE_LONG_PRESS
|
||||
from openpilot.selfdrive.controls.lib.events import Events, ET
|
||||
from openpilot.selfdrive.controls.lib.latcontrol import LatControl, MIN_LATERAL_CONTROL_SPEED
|
||||
from openpilot.selfdrive.controls.lib.latcontrol_pid import LatControlPID
|
||||
@@ -179,6 +179,7 @@ class Controls:
|
||||
self.mads_disengage_lateral_on_brake = self.params.get_bool("DisengageLateralOnBrake")
|
||||
self.mads_ndlob = self.enable_mads and not self.mads_disengage_lateral_on_brake
|
||||
self.process_not_running = False
|
||||
self.experimental_mode_update = False
|
||||
|
||||
self.custom_model_metadata = CustomModelMetadata(params=self.params, init_only=True)
|
||||
self.model_use_lateral_planner = self.custom_model_metadata.valid and \
|
||||
@@ -717,11 +718,21 @@ class Controls:
|
||||
cloudlog.error(f"actuators.{p} not finite {actuators.to_dict()}")
|
||||
setattr(actuators, p, 0.0)
|
||||
|
||||
# toggle experimental mode once on distance button hold
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
if self.v_cruise_helper.button_timers[ButtonType.gapAdjustCruise] == CRUISE_LONG_PRESS and \
|
||||
not self.experimental_mode_update:
|
||||
self.experimental_mode = not self.experimental_mode
|
||||
self.params.put_bool_nonblocking("ExperimentalMode", self.experimental_mode)
|
||||
self.experimental_mode_update = True
|
||||
|
||||
# decrement personality on distance button press
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
if any(not be.pressed and be.type == ButtonType.gapAdjustCruise for be in CS.buttonEvents):
|
||||
self.personality = (self.personality - 1) % 3
|
||||
self.params.put_nonblocking('LongitudinalPersonality', str(self.personality))
|
||||
if not self.experimental_mode_update:
|
||||
self.personality = (self.personality - 1) % 3
|
||||
self.params.put_nonblocking('LongitudinalPersonality', str(self.personality))
|
||||
self.experimental_mode_update = False
|
||||
|
||||
return CC, lac_log
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ class VCruiseHelper:
|
||||
self.v_cruise_kph = V_CRUISE_UNSET
|
||||
self.v_cruise_cluster_kph = V_CRUISE_UNSET
|
||||
self.v_cruise_kph_last = 0
|
||||
self.button_timers = {ButtonType.decelCruise: 0, ButtonType.accelCruise: 0}
|
||||
self.button_timers = {ButtonType.decelCruise: 0, ButtonType.accelCruise: 0, ButtonType.gapAdjustCruise: 0}
|
||||
self.button_change_states = {btn: {"standstill": False, "enabled": False} for btn in self.button_timers}
|
||||
|
||||
self.is_metric_prev = None
|
||||
@@ -101,10 +101,10 @@ class VCruiseHelper:
|
||||
self._update_v_cruise_non_pcm(CS, enabled, is_metric, reverse_acc)
|
||||
self._update_v_cruise_slc(long_plan_sp)
|
||||
self.v_cruise_cluster_kph = self.v_cruise_kph
|
||||
self.update_button_timers(CS, enabled)
|
||||
else:
|
||||
self.v_cruise_kph = CS.cruiseState.speed * CV.MS_TO_KPH
|
||||
self.v_cruise_cluster_kph = CS.cruiseState.speedCluster * CV.MS_TO_KPH
|
||||
self.update_button_timers(CS, enabled)
|
||||
else:
|
||||
self.v_cruise_kph = V_CRUISE_UNSET
|
||||
self.v_cruise_cluster_kph = V_CRUISE_UNSET
|
||||
@@ -137,7 +137,7 @@ class VCruiseHelper:
|
||||
long_press = True
|
||||
break
|
||||
|
||||
if button_type is None:
|
||||
if button_type is None or button_type == ButtonType.gapAdjustCruise:
|
||||
return
|
||||
|
||||
resume_button = ButtonType.accelCruise
|
||||
|
||||
@@ -1141,6 +1141,9 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = {
|
||||
ET.PERMANENT: torque_nn_load_alert,
|
||||
},
|
||||
|
||||
EventName.hyundaiRadarTracksAvailable: {
|
||||
ET.PERMANENT: NormalPermanentAlert("Radar tracks available. Restart the car to initialize")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -109,6 +109,16 @@ SPVehiclesTogglesPanel::SPVehiclesTogglesPanel(VehiclePanel *parent) : ListWidge
|
||||
hkgSmoothStop->setConfirmation(true, false);
|
||||
addItem(hkgSmoothStop);
|
||||
|
||||
hyundaiCruiseMainDefault = new ParamControlSP(
|
||||
"HyundaiCruiseMainDefault",
|
||||
tr("HKG CAN: Enable Cruise Main by Default"),
|
||||
QString("<b>%1</b><br><br>%2")
|
||||
.arg(tr("WARNING: This feature only applies when \"openpilot Longitudinal Control (Alpha)\" is enabled under \"Toggles\""))
|
||||
.arg(tr("Enabling this toggle sets CRUISE MAIN to ON by default when the car starts, without engaging MADS. The user still needs to manually engage MADS.")),
|
||||
"../assets/offroad/icon_blank.png");
|
||||
hyundaiCruiseMainDefault->setConfirmation(true, false);
|
||||
addItem(hyundaiCruiseMainDefault);
|
||||
|
||||
// Subaru
|
||||
addItem(new LabelControlSP(tr("Subaru")));
|
||||
auto subaruManualParkingBrakeSng = new ParamControlSP(
|
||||
@@ -194,6 +204,7 @@ SPVehiclesTogglesPanel::SPVehiclesTogglesPanel(VehiclePanel *parent) : ListWidge
|
||||
connect(uiStateSP(), &UIStateSP::offroadTransition, [=](bool offroad) {
|
||||
is_onroad = !offroad;
|
||||
hkgSmoothStop->setEnabled(offroad);
|
||||
hyundaiCruiseMainDefault->setEnabled(offroad);
|
||||
toyotaTss2LongTune->setEnabled(offroad);
|
||||
toyotaEnhancedBsm->setEnabled(offroad);
|
||||
toyotaSngHack->setEnabled(offroad);
|
||||
@@ -223,6 +234,17 @@ void SPVehiclesTogglesPanel::updateToggles() {
|
||||
capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size()));
|
||||
cereal::CarParams::Reader CP = cmsg.getRoot<cereal::CarParams>();
|
||||
|
||||
// Hyundai/Kia/Genesis
|
||||
{
|
||||
if (CP.getCarName() == "hyundai") {
|
||||
if ((CP.getSpFlags() & 2) and !(CP.getFlags() & 8192)) {
|
||||
hyundaiCruiseMainDefault->setEnabled(true);
|
||||
} else {
|
||||
hyundaiCruiseMainDefault->setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Toyota: Enhanced Blind Spot Monitor
|
||||
{
|
||||
if (CP.getCarName() == "toyota") {
|
||||
|
||||
@@ -67,6 +67,7 @@ private:
|
||||
Params params;
|
||||
bool is_onroad = false;
|
||||
|
||||
ParamControlSP *hyundaiCruiseMainDefault;
|
||||
ParamControlSP *stockLongToyota;
|
||||
ParamControlSP *toyotaEnhancedBsm;
|
||||
|
||||
|
||||
@@ -1583,6 +1583,18 @@ Reboot Required.</source>
|
||||
<source>Tested on RAV4 TSS1, Lexus LSS1, Toyota TSS1/1.5, and Prius TSS2.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>HKG CAN: Enable Cruise Main by Default</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WARNING: This feature only applies when "openpilot Longitudinal Control (Alpha)" is enabled under "Toggles"</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling this toggle sets CRUISE MAIN to ON by default when the car starts, without engaging MADS. The user still needs to manually engage MADS.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsWindow</name>
|
||||
|
||||
@@ -1565,6 +1565,18 @@ Reboot Required.</source>
|
||||
<source>Tested on RAV4 TSS1, Lexus LSS1, Toyota TSS1/1.5, and Prius TSS2.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>HKG CAN: Enable Cruise Main by Default</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WARNING: This feature only applies when "openpilot Longitudinal Control (Alpha)" is enabled under "Toggles"</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling this toggle sets CRUISE MAIN to ON by default when the car starts, without engaging MADS. The user still needs to manually engage MADS.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsWindow</name>
|
||||
|
||||
@@ -1563,6 +1563,18 @@ Reboot Required.</source>
|
||||
<source>Tested on RAV4 TSS1, Lexus LSS1, Toyota TSS1/1.5, and Prius TSS2.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>HKG CAN: Enable Cruise Main by Default</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WARNING: This feature only applies when "openpilot Longitudinal Control (Alpha)" is enabled under "Toggles"</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling this toggle sets CRUISE MAIN to ON by default when the car starts, without engaging MADS. The user still needs to manually engage MADS.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsWindow</name>
|
||||
|
||||
@@ -1567,6 +1567,18 @@ Reboot Required.</source>
|
||||
<source>Tested on RAV4 TSS1, Lexus LSS1, Toyota TSS1/1.5, and Prius TSS2.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>HKG CAN: Enable Cruise Main by Default</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WARNING: This feature only applies when "openpilot Longitudinal Control (Alpha)" is enabled under "Toggles"</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling this toggle sets CRUISE MAIN to ON by default when the car starts, without engaging MADS. The user still needs to manually engage MADS.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsWindow</name>
|
||||
|
||||
@@ -1561,6 +1561,18 @@ Reboot Required.</source>
|
||||
<source>Tested on RAV4 TSS1, Lexus LSS1, Toyota TSS1/1.5, and Prius TSS2.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>HKG CAN: Enable Cruise Main by Default</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WARNING: This feature only applies when "openpilot Longitudinal Control (Alpha)" is enabled under "Toggles"</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling this toggle sets CRUISE MAIN to ON by default when the car starts, without engaging MADS. The user still needs to manually engage MADS.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsWindow</name>
|
||||
|
||||
@@ -1563,6 +1563,18 @@ Reboot Required.</source>
|
||||
<source>Tested on RAV4 TSS1, Lexus LSS1, Toyota TSS1/1.5, and Prius TSS2.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>HKG CAN: Enable Cruise Main by Default</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WARNING: This feature only applies when "openpilot Longitudinal Control (Alpha)" is enabled under "Toggles"</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling this toggle sets CRUISE MAIN to ON by default when the car starts, without engaging MADS. The user still needs to manually engage MADS.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsWindow</name>
|
||||
|
||||
@@ -1567,6 +1567,18 @@ Reboot Required.</source>
|
||||
<source>Tested on RAV4 TSS1, Lexus LSS1, Toyota TSS1/1.5, and Prius TSS2.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>HKG CAN: Enable Cruise Main by Default</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WARNING: This feature only applies when "openpilot Longitudinal Control (Alpha)" is enabled under "Toggles"</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling this toggle sets CRUISE MAIN to ON by default when the car starts, without engaging MADS. The user still needs to manually engage MADS.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsWindow</name>
|
||||
|
||||
@@ -1563,6 +1563,18 @@ Reboot Required.</source>
|
||||
<source>Tested on RAV4 TSS1, Lexus LSS1, Toyota TSS1/1.5, and Prius TSS2.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>HKG CAN: Enable Cruise Main by Default</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WARNING: This feature only applies when "openpilot Longitudinal Control (Alpha)" is enabled under "Toggles"</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling this toggle sets CRUISE MAIN to ON by default when the car starts, without engaging MADS. The user still needs to manually engage MADS.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsWindow</name>
|
||||
|
||||
@@ -1561,6 +1561,18 @@ Reboot Required.</source>
|
||||
<source>Tested on RAV4 TSS1, Lexus LSS1, Toyota TSS1/1.5, and Prius TSS2.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>HKG CAN: Enable Cruise Main by Default</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WARNING: This feature only applies when "openpilot Longitudinal Control (Alpha)" is enabled under "Toggles"</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling this toggle sets CRUISE MAIN to ON by default when the car starts, without engaging MADS. The user still needs to manually engage MADS.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsWindow</name>
|
||||
|
||||
@@ -1563,6 +1563,18 @@ Reboot Required.</source>
|
||||
<source>Tested on RAV4 TSS1, Lexus LSS1, Toyota TSS1/1.5, and Prius TSS2.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>HKG CAN: Enable Cruise Main by Default</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WARNING: This feature only applies when "openpilot Longitudinal Control (Alpha)" is enabled under "Toggles"</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling this toggle sets CRUISE MAIN to ON by default when the car starts, without engaging MADS. The user still needs to manually engage MADS.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsWindow</name>
|
||||
|
||||
@@ -1563,6 +1563,18 @@ Reboot Required.</source>
|
||||
<source>Tested on RAV4 TSS1, Lexus LSS1, Toyota TSS1/1.5, and Prius TSS2.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>HKG CAN: Enable Cruise Main by Default</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WARNING: This feature only applies when "openpilot Longitudinal Control (Alpha)" is enabled under "Toggles"</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabling this toggle sets CRUISE MAIN to ON by default when the car starts, without engaging MADS. The user still needs to manually engage MADS.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsWindow</name>
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
from abc import abstractmethod, ABC
|
||||
|
||||
from cereal import car, custom
|
||||
from openpilot.common.conversions import Conversions as CV
|
||||
from openpilot.selfdrive.controls.lib.sunnypilot.speed_limit_controller import ACTIVE_STATES
|
||||
from openpilot.sunnypilot.controls.lib.custom_stock_longitudinal_controller.states import InactiveState, \
|
||||
LoadingState, AcceleratingState, DeceleratingState, HoldingState
|
||||
from openpilot.sunnypilot.controls.lib.custom_stock_longitudinal_controller.helpers import get_set_point, \
|
||||
speed_hysteresis, update_manual_button_timers
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
ButtonControlState = custom.CarControlSP.CustomStockLongitudinalControl.ButtonControlState
|
||||
SpeedLimitControlState = custom.LongitudinalPlanSP.SpeedLimitControlState
|
||||
TurnSpeedControlState = custom.LongitudinalPlanSP.SpeedLimitControlState
|
||||
VisionTurnControllerState = custom.LongitudinalPlanSP.VisionTurnControllerState
|
||||
|
||||
SendCan = tuple[int, bytes, int]
|
||||
|
||||
|
||||
class CustomStockLongitudinalControllerBase(ABC):
|
||||
def __init__(self, car, car_controller, car_state, CP):
|
||||
self.car = car
|
||||
self.car_controller = car_controller
|
||||
self.car_state = car_state
|
||||
self.CP = CP
|
||||
|
||||
self.v_target = 0
|
||||
self.v_cruise_cluster = 0
|
||||
self.v_cruise_min = 0
|
||||
self.cruise_button = None
|
||||
self.button_state = ButtonControlState.inactive
|
||||
|
||||
self.v_tsc_state = VisionTurnControllerState.disabled
|
||||
self.slc_state = SpeedLimitControlState.inactive
|
||||
self.m_tsc_state = TurnSpeedControlState.inactive
|
||||
self.v_tsc = 0
|
||||
self.speed_limit_offseted = 0
|
||||
self.m_tsc = 0
|
||||
|
||||
self.is_ready = False
|
||||
self.is_ready_prev = False
|
||||
self.speed_steady = 0
|
||||
|
||||
self.accel_button = None
|
||||
self.decel_button = None
|
||||
self.cruise_buttons = {ButtonType.decelCruise: 0, ButtonType.accelCruise: 0}
|
||||
|
||||
self.button_states = {
|
||||
ButtonControlState.inactive: InactiveState(self),
|
||||
ButtonControlState.loading: LoadingState(self),
|
||||
ButtonControlState.accelerating: AcceleratingState(self),
|
||||
ButtonControlState.decelerating: DeceleratingState(self),
|
||||
ButtonControlState.holding: HoldingState(self),
|
||||
}
|
||||
|
||||
@abstractmethod
|
||||
def create_mock_button_messages(self) -> list[SendCan]:
|
||||
pass
|
||||
|
||||
def state_publish(self) -> custom.CarControlSP.CustomStockLongitudinalControl:
|
||||
customStockLongitudinalControl = custom.CarControlSP.CustomStockLongitudinalControl.new_message()
|
||||
customStockLongitudinalControl.state = self.button_state
|
||||
customStockLongitudinalControl.cruiseButton = 0 if self.cruise_button is None else int(self.cruise_button)
|
||||
customStockLongitudinalControl.vTarget = float(self.v_target)
|
||||
customStockLongitudinalControl.vCruiseCluster = float(self.v_cruise_cluster)
|
||||
return customStockLongitudinalControl
|
||||
|
||||
def update_msgs(self) -> None:
|
||||
if self.car.sm.updated['longitudinalPlanSP']:
|
||||
self.v_tsc_state = self.car.sm['longitudinalPlanSP'].visionTurnControllerState
|
||||
self.slc_state = self.car.sm['longitudinalPlanSP'].speedLimitControlState
|
||||
self.m_tsc_state = self.car.sm['longitudinalPlanSP'].turnSpeedControlState
|
||||
self.v_tsc = self.car.sm['longitudinalPlanSP'].visionTurnSpeed
|
||||
|
||||
speed_limit = self.car.sm['longitudinalPlanSP'].speedLimit
|
||||
speed_limit_offset = self.car.sm['longitudinalPlanSP'].speedLimitOffset
|
||||
self.speed_limit_offseted = speed_limit + speed_limit_offset
|
||||
|
||||
self.m_tsc = self.car.sm['longitudinalPlanSP'].turnSpeed
|
||||
|
||||
def update_calculations(self, CS: car.CarState, CC: car.CarControl) -> None:
|
||||
is_metric = self.car_state.params_list.is_metric
|
||||
v_cruise_kph = CC.vCruise
|
||||
v_cruise = v_cruise_kph * CV.KPH_TO_MS
|
||||
self.v_cruise_min = get_set_point(is_metric)
|
||||
self.v_cruise_cluster = round(CS.cruiseState.speed * (CV.MS_TO_KPH if is_metric else CV.MS_TO_MPH))
|
||||
|
||||
v_targets = {'cruise': CC.vCruise}
|
||||
|
||||
if self.v_tsc_state != VisionTurnControllerState.disabled:
|
||||
v_targets['v_tsc'] = self.v_tsc
|
||||
|
||||
if self.slc_state in ACTIVE_STATES:
|
||||
v_targets['slc'] = self.speed_limit_offseted
|
||||
|
||||
if self.m_tsc_state > TurnSpeedControlState.tempInactive:
|
||||
v_targets['m_tsc'] = self.m_tsc
|
||||
|
||||
source = min(v_targets, key=v_targets.get)
|
||||
|
||||
v_target = speed_hysteresis(self, v_targets[source], self.speed_steady, 1.5 * (CV.KPH_TO_MS if is_metric else CV.MPH_TO_MS))
|
||||
v_target = min(v_target, v_cruise)
|
||||
v_target = round(v_target * (CV.MS_TO_KPH if is_metric else CV.MS_TO_MPH))
|
||||
|
||||
self.v_target = v_target
|
||||
|
||||
def update_state(self, CS: car.CarState, CC: car.CarControl) -> None:
|
||||
update_manual_button_timers(CS, self.cruise_buttons)
|
||||
|
||||
ready = CS.cruiseState.enabled and not CC.cruiseControl.cancel and not CC.cruiseControl.resume
|
||||
button_pressed = any(self.cruise_buttons[k] > 0 for k in self.cruise_buttons)
|
||||
self.is_ready = ready and not button_pressed
|
||||
|
||||
self.cruise_button = self.button_states[self.button_state]()
|
||||
|
||||
self.is_ready_prev = self.is_ready
|
||||
|
||||
def update(self, CS: car.CarState, CC: car.CarControl) -> list[SendCan]:
|
||||
self.update_msgs()
|
||||
|
||||
self.update_calculations(CS, CC)
|
||||
|
||||
self.update_state(CS, CC)
|
||||
|
||||
can_sends = self.create_mock_button_messages()
|
||||
|
||||
return can_sends
|
||||
@@ -0,0 +1,30 @@
|
||||
from cereal import car
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
|
||||
|
||||
def get_set_point(is_metric: bool) -> float:
|
||||
return 30 if is_metric else 20
|
||||
|
||||
|
||||
def speed_hysteresis(controller, speed: float, speed_steady: float, hyst: float) -> float:
|
||||
if speed > speed_steady + hyst:
|
||||
speed_steady = speed - hyst
|
||||
elif speed < speed_steady - hyst:
|
||||
speed_steady = speed + hyst
|
||||
|
||||
controller.speed_steady = speed
|
||||
|
||||
return speed_steady
|
||||
|
||||
|
||||
def update_manual_button_timers(CS: car.CarState, button_timers: dict[ButtonType, int]) -> None:
|
||||
# increment timer for buttons still pressed
|
||||
for k in button_timers:
|
||||
if button_timers[k] > 0:
|
||||
button_timers[k] += 1
|
||||
|
||||
for b in CS.buttonEvents:
|
||||
if b.type.raw in button_timers:
|
||||
# Start/end timer and store current state on change of button pressed
|
||||
button_timers[b.type.raw] = 1 if b.pressed else 0
|
||||
@@ -0,0 +1,85 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from random import randint
|
||||
|
||||
from cereal import custom
|
||||
|
||||
ButtonControlState = custom.CarControlSP.CustomStockLongitudinalControl.ButtonControlState
|
||||
|
||||
INACTIVE_TIMER = 40
|
||||
RESET_COUNT = 5
|
||||
HOLD_TIME = 7
|
||||
|
||||
|
||||
class ButtonStateBase(ABC):
|
||||
def __init__(self, controller):
|
||||
self.controller = controller
|
||||
self.button_count = 0
|
||||
self.timer = INACTIVE_TIMER
|
||||
|
||||
def __call__(self) -> int | None:
|
||||
if self.controller.is_ready:
|
||||
# TODO-SP: Validate different hold time intervals for different platforms to prevent temporary cruise fault
|
||||
pass
|
||||
else:
|
||||
if self.controller.is_ready_prev:
|
||||
self.controller.button_state = ButtonControlState.inactive
|
||||
return None
|
||||
|
||||
return self.handle()
|
||||
|
||||
@abstractmethod
|
||||
def handle(self) -> int | None:
|
||||
pass
|
||||
|
||||
|
||||
class InactiveState(ButtonStateBase):
|
||||
def handle(self) -> None:
|
||||
self.button_count = 0
|
||||
|
||||
if not self.controller.is_ready:
|
||||
self.timer = INACTIVE_TIMER
|
||||
elif self.timer > 0:
|
||||
self.timer -= 1
|
||||
else:
|
||||
self.controller.button_state = ButtonControlState.loading
|
||||
return None
|
||||
|
||||
|
||||
class LoadingState(ButtonStateBase):
|
||||
def handle(self) -> None:
|
||||
if self.controller.v_target > self.controller.v_cruise_cluster:
|
||||
self.controller.button_state = ButtonControlState.accelerating
|
||||
elif self.controller.v_target < self.controller.v_cruise_cluster and self.controller.v_cruise_cluster > self.controller.v_cruise_min:
|
||||
self.controller.button_state = ButtonControlState.decelerating
|
||||
else:
|
||||
self.controller.button_state = ButtonControlState.holding
|
||||
return None
|
||||
|
||||
|
||||
class AcceleratingState(ButtonStateBase):
|
||||
def handle(self) -> int | None:
|
||||
self.button_count += 1
|
||||
if self.controller.v_target <= self.controller.v_cruise_cluster or self.button_count > RESET_COUNT:
|
||||
self.button_count = 0
|
||||
self.controller.button_state = ButtonControlState.holding
|
||||
return None
|
||||
return self.controller.accel_button
|
||||
|
||||
|
||||
class DeceleratingState(ButtonStateBase):
|
||||
def handle(self) -> int | None:
|
||||
self.button_count += 1
|
||||
if self.controller.v_target >= self.controller.v_cruise_cluster or self.controller.v_cruise_cluster <= self.controller.v_cruise_min or self.button_count > RESET_COUNT:
|
||||
self.button_count = 0
|
||||
self.controller.button_state = ButtonControlState.holding
|
||||
return None
|
||||
return self.controller.decel_button
|
||||
|
||||
|
||||
class HoldingState(ButtonStateBase):
|
||||
def handle(self) -> None:
|
||||
self.button_count += 1
|
||||
if self.button_count > HOLD_TIME:
|
||||
self.button_count = 0
|
||||
self.controller.button_state = ButtonControlState.loading
|
||||
return None
|
||||
@@ -0,0 +1,32 @@
|
||||
from cereal import car
|
||||
from openpilot.selfdrive.car.chrysler.values import RAM_CARS
|
||||
from openpilot.sunnypilot.controls.lib.custom_stock_longitudinal_controller.controllers import CustomStockLongitudinalControllerBase, \
|
||||
SendCan
|
||||
from openpilot.sunnypilot.selfdrive.car.chrysler.custom_stock_longitudinal_controller import helpers
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
# TODO-SP: Handle this better in the base class
|
||||
ACCEL_BUTTON = 1
|
||||
DECEL_BUTTON = 2
|
||||
|
||||
|
||||
class CustomStockLongitudinalController(CustomStockLongitudinalControllerBase):
|
||||
def __init__(self, car, car_controller, car_state, CP):
|
||||
super().__init__(car, car_controller, car_state, CP)
|
||||
self.accel_button = ACCEL_BUTTON
|
||||
self.decel_button = DECEL_BUTTON
|
||||
self.cruise_buttons = {ButtonType.decelCruise: 0, ButtonType.accelCruise: 0, ButtonType.resumeCruise: 0}
|
||||
|
||||
def create_mock_button_messages(self) -> list[SendCan]:
|
||||
can_sends = []
|
||||
ram_cars = self.CP.carFingerprint in RAM_CARS
|
||||
das_bus = 2 if self.CP.carFingerprint in RAM_CARS else 0
|
||||
button_counter_offset = [1, 1, 0, None][self.car_controller.frame % 4]
|
||||
|
||||
if self.cruise_button is not None:
|
||||
if ram_cars:
|
||||
can_sends.append(helpers.create_cruise_buttons(self.car_controller.packer, self.car_state.button_counter, das_bus, self.cruise_button))
|
||||
elif button_counter_offset is not None:
|
||||
can_sends.append(helpers.create_cruise_buttons(self.car_controller.packer, self.car_state.button_counter + button_counter_offset, das_bus, self.cruise_button))
|
||||
|
||||
return can_sends
|
||||
@@ -0,0 +1,9 @@
|
||||
def create_cruise_buttons(packer, frame, bus, buttons=0):
|
||||
|
||||
values = {
|
||||
"ACC_Accel": 1 if buttons == 1 else 0,
|
||||
"ACC_Decel": 1 if buttons == 2 else 0,
|
||||
"COUNTER": frame % 0x10,
|
||||
}
|
||||
|
||||
return packer.make_can_msg("CRUISE_BUTTONS", bus, values)
|
||||
@@ -0,0 +1,25 @@
|
||||
from cereal import car
|
||||
from openpilot.selfdrive.car.honda import hondacan
|
||||
from openpilot.selfdrive.car.honda.values import CruiseButtons
|
||||
from openpilot.sunnypilot.controls.lib.custom_stock_longitudinal_controller.controllers import CustomStockLongitudinalControllerBase, \
|
||||
SendCan
|
||||
from openpilot.sunnypilot.selfdrive.car.honda.custom_stock_longitudinal_controller import helpers
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
|
||||
|
||||
class CustomStockLongitudinalController(CustomStockLongitudinalControllerBase):
|
||||
def __init__(self, car, car_controller, car_state, CP):
|
||||
super().__init__(car, car_controller, car_state, CP)
|
||||
self.accel_button = CruiseButtons.RES_ACCEL
|
||||
self.decel_button = CruiseButtons.DECEL_SET
|
||||
self.cruise_buttons = {ButtonType.decelCruise: 0, ButtonType.accelCruise: 0,
|
||||
ButtonType.altButton3: 0, ButtonType.cancel: 0}
|
||||
|
||||
def create_mock_button_messages(self) -> list[SendCan]:
|
||||
can_sends = []
|
||||
|
||||
if self.cruise_button is not None:
|
||||
can_sends.append(hondacan.spam_buttons_command(self.car_controller.packer, self.car_controller.CAN, self.cruise_button, self.CP.carFingerprint))
|
||||
|
||||
return can_sends
|
||||
@@ -0,0 +1,58 @@
|
||||
from random import choices
|
||||
|
||||
from cereal import car
|
||||
from openpilot.common.numpy_fast import interp
|
||||
from openpilot.selfdrive.car.hyundai import hyundaicanfd
|
||||
from openpilot.selfdrive.car.hyundai.values import HyundaiFlags, Buttons, CANFD_CAR
|
||||
from openpilot.sunnypilot.controls.lib.custom_stock_longitudinal_controller.controllers import CustomStockLongitudinalControllerBase, \
|
||||
SendCan
|
||||
from openpilot.sunnypilot.selfdrive.car.hyundai.custom_stock_longitudinal_controller import helpers
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
|
||||
BUTTON_COPIES = 2
|
||||
BUTTON_COPIES_TIME = 7
|
||||
BUTTON_COPIES_TIME_IMPERIAL = [BUTTON_COPIES_TIME + 3, 70]
|
||||
BUTTON_COPIES_TIME_METRIC = [BUTTON_COPIES_TIME, 40]
|
||||
POPULATION = [0, 1]
|
||||
WEIGHTS = [0.51, 0.49]
|
||||
|
||||
|
||||
class CustomStockLongitudinalController(CustomStockLongitudinalControllerBase):
|
||||
def __init__(self, car, car_controller, car_state, CP):
|
||||
super().__init__(car, car_controller, car_state, CP)
|
||||
self.accel_button = Buttons.RES_ACCEL
|
||||
self.decel_button = Buttons.SET_DECEL
|
||||
self.cruise_buttons = {ButtonType.decelCruise: 0, ButtonType.accelCruise: 0, ButtonType.gapAdjustCruise: 0}
|
||||
|
||||
def create_can_mock_button_messages(self) -> list[SendCan]:
|
||||
can_sends = []
|
||||
if self.cruise_button is not None:
|
||||
copies_xp = BUTTON_COPIES_TIME_METRIC if self.car_state.params_list.is_metric else BUTTON_COPIES_TIME_IMPERIAL
|
||||
copies = int(interp(BUTTON_COPIES_TIME, copies_xp, [1, BUTTON_COPIES]))
|
||||
can_sends.extend([helpers.create_clu11(self.car_controller.packer, self.car_state.clu11, self.cruise_button, self.CP)] * copies)
|
||||
|
||||
return can_sends
|
||||
|
||||
def create_canfd_mock_button_messages(self) -> list[SendCan]:
|
||||
can_sends = []
|
||||
if self.CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS:
|
||||
# TODO: resume for alt button cars
|
||||
pass
|
||||
else:
|
||||
if self.cruise_button is not None:
|
||||
for _ in range(BUTTON_COPIES):
|
||||
can_sends.append(hyundaicanfd.create_buttons(self.car_controller.packer, self.CP, self.car_controller.CAN,
|
||||
self.car_state.buttons_counter + choices(POPULATION, WEIGHTS)[0],
|
||||
self.cruise_button))
|
||||
|
||||
return can_sends
|
||||
|
||||
def create_mock_button_messages(self) -> list[SendCan]:
|
||||
can_sends = []
|
||||
if self.CP.carFingerprint in CANFD_CAR:
|
||||
can_sends.extend(self.create_canfd_mock_button_messages())
|
||||
else:
|
||||
can_sends.extend(self.create_can_mock_button_messages())
|
||||
|
||||
return can_sends
|
||||
@@ -0,0 +1,22 @@
|
||||
from openpilot.selfdrive.car.hyundai.values import HyundaiFlags
|
||||
|
||||
def create_clu11(packer, clu11, button, CP):
|
||||
values = {s: clu11[s] for s in [
|
||||
"CF_Clu_CruiseSwState",
|
||||
"CF_Clu_CruiseSwMain",
|
||||
"CF_Clu_SldMainSW",
|
||||
"CF_Clu_ParityBit1",
|
||||
"CF_Clu_VanzDecimal",
|
||||
"CF_Clu_Vanz",
|
||||
"CF_Clu_SPEED_UNIT",
|
||||
"CF_Clu_DetentOut",
|
||||
"CF_Clu_RheostatLevel",
|
||||
"CF_Clu_CluInfo",
|
||||
"CF_Clu_AmpInfo",
|
||||
"CF_Clu_AliveCnt1",
|
||||
]}
|
||||
values["CF_Clu_CruiseSwState"] = button
|
||||
values["CF_Clu_AliveCnt1"] = (values["CF_Clu_AliveCnt1"] + 1) % 0x10
|
||||
# send buttons to camera on camera-scc based cars
|
||||
bus = 2 if CP.flags & HyundaiFlags.CAMERA_SCC else 0
|
||||
return packer.make_can_msg("CLU11", bus, values)
|
||||
@@ -0,0 +1,25 @@
|
||||
from cereal import car
|
||||
from openpilot.selfdrive.car.mazda.values import Buttons
|
||||
from openpilot.sunnypilot.controls.lib.custom_stock_longitudinal_controller.controllers import CustomStockLongitudinalControllerBase, \
|
||||
SendCan
|
||||
from openpilot.sunnypilot.selfdrive.car.mazda.custom_stock_longitudinal_controller import helpers
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
|
||||
|
||||
class CustomStockLongitudinalController(CustomStockLongitudinalControllerBase):
|
||||
def __init__(self, car, car_controller, car_state, CP):
|
||||
super().__init__(car, car_controller, car_state, CP)
|
||||
self.accel_button = Buttons.SET_PLUS
|
||||
self.decel_button = Buttons.SET_MINUS
|
||||
self.cruise_buttons = {ButtonType.decelCruise: 0, ButtonType.accelCruise: 0,
|
||||
ButtonType.resumeCruise: 0, ButtonType.setCruise: 0}
|
||||
|
||||
def create_mock_button_messages(self) -> list[SendCan]:
|
||||
can_sends = []
|
||||
|
||||
if self.cruise_button is not None:
|
||||
if self.car_controller.frame % 10 == 0:
|
||||
can_sends.append(helpers.create_button_cmd(self.car_controller.packer, self.CP, self.car_controller.frame // 10, self.cruise_button))
|
||||
|
||||
return can_sends
|
||||
@@ -0,0 +1,40 @@
|
||||
def create_button_cmd(packer, CP, counter, button):
|
||||
|
||||
can = int(button == Buttons.CANCEL)
|
||||
res = int(button == Buttons.RESUME)
|
||||
inc = int(button == Buttons.SET_PLUS)
|
||||
dec = int(button == Buttons.SET_MINUS)
|
||||
|
||||
if CP.flags & MazdaFlags.GEN1:
|
||||
values = {
|
||||
"CAN_OFF": can,
|
||||
"CAN_OFF_INV": (can + 1) % 2,
|
||||
|
||||
"SET_P": inc,
|
||||
"SET_P_INV": (inc + 1) % 2,
|
||||
|
||||
"RES": res,
|
||||
"RES_INV": (res + 1) % 2,
|
||||
|
||||
"SET_M": dec,
|
||||
"SET_M_INV": (dec + 1) % 2,
|
||||
|
||||
"DISTANCE_LESS": 0,
|
||||
"DISTANCE_LESS_INV": 1,
|
||||
|
||||
"DISTANCE_MORE": 0,
|
||||
"DISTANCE_MORE_INV": 1,
|
||||
|
||||
"MODE_X": 0,
|
||||
"MODE_X_INV": 1,
|
||||
|
||||
"MODE_Y": 0,
|
||||
"MODE_Y_INV": 1,
|
||||
|
||||
"BIT1": 1,
|
||||
"BIT2": 1,
|
||||
"BIT3": 1,
|
||||
"CTR": (counter + 1) % 16,
|
||||
}
|
||||
|
||||
return packer.make_can_msg("CRZ_BTNS", 0, values)
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
from cereal import car, custom
|
||||
from openpilot.sunnypilot.controls.lib.custom_stock_longitudinal_controller.controllers import CustomStockLongitudinalControllerBase, \
|
||||
SendCan
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
ButtonControlState = custom.CarControlSP.CustomStockLongitudinalControl.ButtonControlState
|
||||
# TODO-SP: Handle this better in the base class
|
||||
ACCEL_BUTTON = 1
|
||||
DECEL_BUTTON = 2
|
||||
RESUME_CRUISE = 3
|
||||
SET_CRUISE = 4
|
||||
|
||||
ACC_TYPE_BUTTONS = {
|
||||
0: {1: ACCEL_BUTTON, 2: DECEL_BUTTON}, # accel, decel
|
||||
1: {1: RESUME_CRUISE, 2: SET_CRUISE} # resume, set
|
||||
}
|
||||
|
||||
|
||||
class CustomStockLongitudinalController(CustomStockLongitudinalControllerBase):
|
||||
def __init__(self, car, car_controller, car_state, CP):
|
||||
super().__init__(car, car_controller, car_state, CP)
|
||||
self.accel_button = ACCEL_BUTTON
|
||||
self.decel_button = DECEL_BUTTON
|
||||
self.cruise_buttons = {ButtonType.decelCruise: 0, ButtonType.accelCruise: 0,
|
||||
ButtonType.resumeCruise: 0, ButtonType.setCruise: 0}
|
||||
|
||||
self.last_v_cruise_cluster = 0
|
||||
self.last_cruise_button = False
|
||||
|
||||
self.acc_type = -1
|
||||
self.button_frame = 0
|
||||
|
||||
self.initial_v_target = 0
|
||||
self.initial_v_cruise_cluster = 0
|
||||
|
||||
def update_checks(self) -> None:
|
||||
if self.button_state > ButtonControlState.inactive:
|
||||
self.button_frame += 1
|
||||
if self.button_frame == 1:
|
||||
self.initial_v_target = self.v_target
|
||||
self.initial_v_cruise_cluster = self.v_cruise_cluster
|
||||
|
||||
self.set_acc_type()
|
||||
else:
|
||||
self.button_frame = 0
|
||||
self.initial_v_target = 0
|
||||
self.initial_v_cruise_cluster = 0
|
||||
|
||||
def set_acc_type(self):
|
||||
current_v_cruise_diff = abs(self.v_target - self.v_cruise_cluster)
|
||||
initial_v_cruise_diff = abs(self.initial_v_target - self.initial_v_cruise_cluster)
|
||||
|
||||
if self.last_v_cruise_cluster != self.v_cruise_cluster and current_v_cruise_diff != initial_v_cruise_diff:
|
||||
if self.acc_type == -1:
|
||||
v_cruise_diff = abs(self.v_cruise_cluster - self.last_v_cruise_cluster)
|
||||
|
||||
if v_cruise_diff >= 10 and self.last_cruise_button in (ACCEL_BUTTON, DECEL_BUTTON):
|
||||
self.acc_type = 1
|
||||
else:
|
||||
self.acc_type = 0
|
||||
|
||||
if self.cruise_button is not None:
|
||||
self.cruise_button = ACC_TYPE_BUTTONS.get(self.acc_type, {}).get(self.cruise_button, self.cruise_button)
|
||||
|
||||
def create_mock_button_messages(self) -> list[SendCan]:
|
||||
can_sends = []
|
||||
|
||||
self.update_checks()
|
||||
|
||||
if self.cruise_button is not None:
|
||||
if self.car_state.gra_stock_values["COUNTER"] != self.car_controller.gra_acc_counter_last:
|
||||
can_sends.append(self.car_controller.CCS.create_acc_buttons_control(self.car_controller.packer_pt, self.car_controller.ext_bus, self.car_state.gra_stock_values, buttons=self.cruise_button))
|
||||
|
||||
self.last_cruise_button = self.cruise_button
|
||||
self.last_v_cruise_cluster = self.v_cruise_cluster
|
||||
|
||||
return can_sends
|
||||
@@ -0,0 +1,18 @@
|
||||
def create_acc_buttons_control(packer, bus, gra_stock_values, buttons=0):
|
||||
values = {s: gra_stock_values[s] for s in [
|
||||
"GRA_Hauptschalter", # ACC button, on/off
|
||||
"GRA_Typ_Hauptschalter", # ACC main button type
|
||||
"GRA_Codierung", # ACC button configuration/coding
|
||||
"GRA_Tip_Stufe_2", # unknown related to stalk type
|
||||
"GRA_ButtonTypeInfo", # unknown related to stalk type
|
||||
]}
|
||||
|
||||
values.update({
|
||||
"COUNTER": (gra_stock_values["COUNTER"] + 1) % 16,
|
||||
"GRA_Tip_Wiederaufnahme": 1 if buttons == 3 else 0,
|
||||
"GRA_Tip_Setzen": 1 if buttons == 4 else 0,
|
||||
"GRA_Tip_Runter": 1 if buttons == 2 else 0,
|
||||
"GRA_Tip_Hoch": 1 if buttons == 1 else 0,
|
||||
})
|
||||
|
||||
return packer.make_can_msg("GRA_ACC_01", bus, values)
|
||||
@@ -0,0 +1,17 @@
|
||||
def create_acc_buttons_control(packer, bus, gra_stock_values, buttons=0):
|
||||
values = {s: gra_stock_values[s] for s in [
|
||||
"GRA_Hauptschalt", # ACC button, on/off
|
||||
"GRA_Typ_Hauptschalt", # ACC button, momentary vs latching
|
||||
"GRA_Kodierinfo", # ACC button, configuration
|
||||
"GRA_Sender", # ACC button, CAN message originator
|
||||
]}
|
||||
|
||||
values.update({
|
||||
"COUNTER": (gra_stock_values["COUNTER"] + 1) % 16,
|
||||
"GRA_Recall": 1 if buttons == 3 else 0,
|
||||
"GRA_Neu_Setzen": 1 if buttons == 4 else 0,
|
||||
"GRA_Down_kurz": 1 if buttons == 2 else 0,
|
||||
"GRA_Up_kurz": 1 if buttons == 1 else 0,
|
||||
})
|
||||
|
||||
return packer.make_can_msg("GRA_Neu", bus, values)
|
||||
@@ -72,6 +72,7 @@ def manager_init() -> None:
|
||||
("HandsOnWheelMonitoring", "0"),
|
||||
("HasAcceptedTermsSP", "0"),
|
||||
("HideVEgoUi", "0"),
|
||||
("HyundaiCruiseMainDefault", "0"),
|
||||
("LastSpeedLimitSignTap", "0"),
|
||||
("LkasToggle", "0"),
|
||||
("MadsIconToggle", "1"),
|
||||
|
||||
Reference in New Issue
Block a user