mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-11-03 14:53:44 +08:00
Merge branch 'dev-priv/master' into subaru-gen2-torque-increase
# Conflicts: # panda
This commit is contained in:
+29
-3
@@ -1,10 +1,36 @@
|
||||
sunnypilot - 0.9.5.1 (202x-xx-xx)
|
||||
sunnypilot - 0.9.5.1 (2023-09-27)
|
||||
========================
|
||||
* UPDATED: Synced with commaai's master commit 338288d
|
||||
* UPDATED: Synced with commaai's 0.9.5 release
|
||||
* NEW❗: Non-Inflatable driving model
|
||||
* NEW❗: Onroad Settings Panel
|
||||
* Onroad buttons (i.e., DLP, GAC) moved to its dedicated panel
|
||||
* Driving Personality
|
||||
* Dynamic Lane Profile (DLP)
|
||||
* Speed Limit Control (SLC)
|
||||
* NEW❗: Display main feature status on onroad view in real-time
|
||||
* GAP - Driving Personality
|
||||
* DLP - Dynamic Lane Profile
|
||||
* SLC - Speed Limit Control
|
||||
* NEW❗: Subaru - Stop and Go auto-resume support thanks to martinl!
|
||||
* Global (excluding Gen 2 and Hybrid) and Pre-Global support
|
||||
* NEW❗: Toyota - Stop and Go hack
|
||||
* Allow some Toyota/Lexus cars to auto resume during stop and go traffic
|
||||
* Only applicable to certain models and model years
|
||||
* NEW❗: Wide camera view when the steering angle is more than 45°
|
||||
* Custom Stock Longitudinal Control
|
||||
* NEW❗: Toyota: ZSS support thanks to dragonpilot-community and ErichMoraga!
|
||||
* openpilot Longitudianl Control capable cars only
|
||||
* UPDATED: Gap Adjust Cruise is now a part of Driving Personality
|
||||
* [DISTANCE/FOLLOW DISTANCE/GAP DISTANCE] physical button on the steering wheel to select Driving Personality on by default
|
||||
* Status now viewable in onroad view or Onroad Settings Panel
|
||||
* REMOVED: Gap Adjust Cruise toggle
|
||||
* UPDATED: Custom Stock Longitudinal Control
|
||||
* RE-ENABLED: Hyundai/Kia/Genesis CAN-FD platforms
|
||||
* UPDATED: Auto-detect custom Mapbox token
|
||||
* REMOVED: "Enable Mapbox Navigation" toggle
|
||||
* UPDATED: Developer UI: Bottom row now hidden when there are active alerts
|
||||
* FIXED: Map stuck in "Map Loading" if comma Prime is active
|
||||
* FIXED: UI elements adjustments
|
||||
* Kia Seltos Non-SCC 2023-24 support thanks to Moodkiller and jeroid_!
|
||||
|
||||
sunnypilot - 0.9.4.1 (2023-08-11)
|
||||
========================
|
||||
|
||||
+8
-1
@@ -224,7 +224,6 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"CarModelText", PERSISTENT},
|
||||
{"ChevronInfo", PERSISTENT},
|
||||
{"CustomBootScreen", PERSISTENT},
|
||||
{"CustomMapbox", PERSISTENT},
|
||||
{"CustomMapboxTokenPk", PERSISTENT},
|
||||
{"CustomMapboxTokenSk", PERSISTENT},
|
||||
{"CustomOffsets", PERSISTENT},
|
||||
@@ -234,6 +233,8 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"DevUIInfo", PERSISTENT},
|
||||
{"DisableOnroadUploads", PERSISTENT},
|
||||
{"DisengageLateralOnBrake", PERSISTENT},
|
||||
{"DynamicExperimentalControl", PERSISTENT},
|
||||
{"DynamicExperimentalControlToggle", PERSISTENT},
|
||||
{"DynamicLaneProfile", PERSISTENT},
|
||||
{"DynamicLaneProfileToggle", PERSISTENT},
|
||||
{"EnableAmap", PERSISTENT},
|
||||
@@ -254,13 +255,16 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"HideVEgoUi", PERSISTENT},
|
||||
{"HkgSmoothStop", PERSISTENT},
|
||||
{"HotspotOnBoot", PERSISTENT},
|
||||
{"HotspotOnBootConfirmed", PERSISTENT},
|
||||
{"LastCarModel", PERSISTENT},
|
||||
{"LastSpeedLimitSignTap", PERSISTENT},
|
||||
{"LiveTorque", PERSISTENT},
|
||||
{"LiveTorqueRelaxed", PERSISTENT},
|
||||
{"LkasToggle", PERSISTENT},
|
||||
{"MadsCruiseMain", PERSISTENT},
|
||||
{"MadsIconToggle", PERSISTENT},
|
||||
{"MapboxFullScreen", PERSISTENT},
|
||||
{"Map3DBuildings", PERSISTENT},
|
||||
{"MaxTimeOffroad", PERSISTENT},
|
||||
{"OnroadScreenOff", PERSISTENT},
|
||||
{"OnroadScreenOffBrightness", PERSISTENT},
|
||||
@@ -287,9 +291,12 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"SpeedLimitOffsetType", PERSISTENT},
|
||||
{"StandStillTimer", PERSISTENT},
|
||||
{"StockLongToyota", PERSISTENT},
|
||||
{"SubaruManualParkingBrakeSng", PERSISTENT},
|
||||
{"TorqueDeadzoneDeg", PERSISTENT},
|
||||
{"TorqueFriction", PERSISTENT},
|
||||
{"TorqueMaxLatAccel", PERSISTENT},
|
||||
{"TorquedOverride", PERSISTENT},
|
||||
{"ToyotaSnG", PERSISTENT},
|
||||
{"ToyotaTSS2Long", PERSISTENT},
|
||||
{"TrueVEgoUi", PERSISTENT},
|
||||
{"TurnSpeedControl", PERSISTENT},
|
||||
|
||||
+1
-1
Submodule panda updated: cd1cc939b4...92aaeb38b0
@@ -115,6 +115,7 @@ class CarState(CarStateBase):
|
||||
ret.cruiseState.available = cp.vl["TCS13"]["ACCEnable"] == 0 and self.mainEnabled
|
||||
ret.cruiseState.enabled = cp.vl["TCS13"]["ACC_REQ"] == 1
|
||||
ret.cruiseState.standstill = False
|
||||
ret.cruiseState.nonAdaptive = False
|
||||
elif self.CP.carFingerprint in NON_SCC_CAR:
|
||||
ret.cruiseState.available = cp.vl['EMS16']['CRUISE_LAMP_M'] != 0
|
||||
ret.cruiseState.enabled = cp.vl["LVR12"]['CF_Lvr_CruiseSet'] != 0
|
||||
|
||||
@@ -39,7 +39,8 @@ def create_lkas11(packer, frame, car_fingerprint, apply_steer, steer_req,
|
||||
CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_EV, CAR.KONA_HEV, CAR.KONA_EV_2022,
|
||||
CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022,
|
||||
CAR.SANTA_FE_PHEV_2022, CAR.KIA_STINGER_2022, CAR.KIA_K5_HEV_2020, CAR.KIA_CEED,
|
||||
CAR.AZERA_6TH_GEN, CAR.ELANTRA_2022_NON_SCC, CAR.GENESIS_G70_2021_NON_SCC):
|
||||
CAR.AZERA_6TH_GEN, CAR.ELANTRA_2022_NON_SCC, CAR.GENESIS_G70_2021_NON_SCC,
|
||||
CAR.KIA_SELTOS_2023_NON_SCC):
|
||||
values["CF_Lkas_LdwsActivemode"] = int(left_lane) + (int(right_lane) << 1)
|
||||
values["CF_Lkas_LdwsOpt_USM"] = 2
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
if 0x2AB in fingerprint[0]:
|
||||
ret.spFlags |= HyundaiFlagsSP.SP_ENHANCED_SCC.value
|
||||
ret.radarUnavailable = False
|
||||
|
||||
ret.steerActuatorDelay = 0.1 # Default delay
|
||||
ret.steerLimitTimer = 0.4
|
||||
@@ -160,7 +161,7 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.tireStiffnessFactor = 0.385
|
||||
if candidate == CAR.KIA_NIRO_PHEV:
|
||||
ret.minSteerSpeed = 32 * CV.MPH_TO_MS
|
||||
elif candidate == CAR.KIA_SELTOS:
|
||||
elif candidate in (CAR.KIA_SELTOS, CAR.KIA_SELTOS_2023_NON_SCC):
|
||||
ret.mass = 1337.
|
||||
ret.wheelbase = 2.63
|
||||
ret.steerRatio = 14.56
|
||||
|
||||
@@ -10,12 +10,13 @@ RADAR_MSG_COUNT = 32
|
||||
|
||||
|
||||
def get_radar_can_parser(CP):
|
||||
if (CP.spFlags & HyundaiFlagsSP.SP_ENHANCED_SCC) and DBC[CP.carFingerprint]['radar'] is None:
|
||||
messages = ("ESCC", 50)
|
||||
return CANParser(DBC[CP.carFingerprint]['pt'], messages, 0)
|
||||
else:
|
||||
if DBC[CP.carFingerprint]['radar'] is None:
|
||||
if DBC[CP.carFingerprint]['radar'] is None:
|
||||
if CP.spFlags & HyundaiFlagsSP.SP_ENHANCED_SCC:
|
||||
lead_src, bus = "ESCC", 0
|
||||
else:
|
||||
return None
|
||||
messages = [(lead_src, 50)]
|
||||
return CANParser(DBC[CP.carFingerprint]['pt'], messages, bus)
|
||||
|
||||
messages = [(f"RADAR_TRACK_{addr:x}", 50) for addr in range(RADAR_START_ADDR, RADAR_START_ADDR + RADAR_MSG_COUNT)]
|
||||
return CANParser(DBC[CP.carFingerprint]['radar'], messages, 1)
|
||||
|
||||
@@ -124,6 +124,7 @@ class CAR:
|
||||
KIA_OPTIMA_G4_FL = "KIA OPTIMA 4TH GEN FACELIFT"
|
||||
KIA_OPTIMA_H = "KIA OPTIMA HYBRID 2017 & SPORTS 2019"
|
||||
KIA_SELTOS = "KIA SELTOS 2021"
|
||||
KIA_SELTOS_2023_NON_SCC = "KIA SELTOS 2023 NON-SCC"
|
||||
KIA_SPORTAGE_5TH_GEN = "KIA SPORTAGE 5TH GEN"
|
||||
KIA_SORENTO = "KIA SORENTO GT LINE 2018"
|
||||
KIA_SORENTO_4TH_GEN = "KIA SORENTO 4TH GEN"
|
||||
@@ -297,6 +298,7 @@ CAR_INFO: Dict[str, Optional[Union[HyundaiCarInfo, List[HyundaiCarInfo]]]] = {
|
||||
CAR.ELANTRA_2022_NON_SCC: HyundaiCarInfo("Hyundai Elantra Non-SCC 2022", "No Smart Cruise Control (SCC)", car_parts=CarParts.common([CarHarness.hyundai_k])),
|
||||
CAR.KIA_FORTE_2019_NON_SCC: HyundaiCarInfo("Kia Forte Non-SCC 2019", "No Smart Cruise Control (SCC)", car_parts=CarParts.common([CarHarness.hyundai_g])),
|
||||
CAR.KIA_FORTE_2021_NON_SCC: HyundaiCarInfo("Kia Forte Non-SCC 2021", "No Smart Cruise Control (SCC)", car_parts=CarParts.common([CarHarness.hyundai_g])),
|
||||
CAR.KIA_SELTOS_2023_NON_SCC: HyundaiCarInfo("Kia Seltos Non-SCC 2023-24", "No Smart Cruise Control (SCC)", car_parts=CarParts.common([CarHarness.hyundai_l])),
|
||||
CAR.GENESIS_G70_2021_NON_SCC: HyundaiCarInfo("Genesis G70 Non-SCC 2021", "No Smart Cruise Control (SCC)", car_parts=CarParts.common([CarHarness.hyundai_f])),
|
||||
}
|
||||
|
||||
@@ -1639,6 +1641,28 @@ FW_VERSIONS = {
|
||||
b'\xf1\x87954A22D200\xf1\x81T01950A1 \xf1\000T0190XBL T01950A1 DSP2T16X4X950NS8\r\xfe\x9c\x8b',
|
||||
],
|
||||
},
|
||||
CAR.KIA_SELTOS_2023_NON_SCC: {
|
||||
(Ecu.abs, 0x7d1, None): [
|
||||
b'\xf1\x00SP ESC \t 101"\t\x01 58910-Q5510',
|
||||
b'\xf1\x00SP ESC \r 100"\x04\x01 58910-Q5510',
|
||||
],
|
||||
(Ecu.engine, 0x7e0, None): [
|
||||
b'\xf1\x81616K0051\x00\x00\x00\x00\x00\x00\x00\x00',
|
||||
b'\xf1\x81616G2051\x00\x00\x00\x00\x00\x00\x00\x00',
|
||||
],
|
||||
(Ecu.eps, 0x7d4, None): [
|
||||
b'\xf1\x00SP2 MDPS C 1.00 1.04 56310Q5240 4SPSC104',
|
||||
b'\xf1\x00SP2 MDPS C 1.00 1.01 56300Q5920 ',
|
||||
],
|
||||
(Ecu.fwdCamera, 0x7c4, None): [
|
||||
b'\xf1\x00SP2 MFC AT USA LHD 1.00 1.03 99210-Q5500 230208',
|
||||
b'\xf1\x00SP2 MFC AT AUS RHD 1.00 1.02 99210-Q5500 220624',
|
||||
],
|
||||
(Ecu.transmission, 0x7e1, None): [
|
||||
b'\xf1\x006V2B0_C2\x00\x006V2D5051\x00\x00CSP2N20NL0\x00\x00\x00\x00',
|
||||
b'\xf1\x006V2B0_C2\x00\x006V2D4051\x00\x00CSP2N20KL1\x00\x00\x00\x00',
|
||||
],
|
||||
},
|
||||
CAR.KIA_OPTIMA_G4: {
|
||||
(Ecu.fwdRadar, 0x7d0, None): [
|
||||
b'\xf1\x00JF__ SCC F-CUP 1.00 1.00 96400-D4100 ',
|
||||
@@ -2055,7 +2079,7 @@ FW_VERSIONS = {
|
||||
CHECKSUM = {
|
||||
"crc8": [CAR.SANTA_FE, CAR.SONATA, CAR.PALISADE, CAR.KIA_SELTOS, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021,
|
||||
CAR.SONATA_HYBRID, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.KIA_K5_HEV_2020,
|
||||
CAR.ELANTRA_2022_NON_SCC, CAR.GENESIS_G70_2021_NON_SCC],
|
||||
CAR.ELANTRA_2022_NON_SCC, CAR.GENESIS_G70_2021_NON_SCC, CAR.KIA_SELTOS_2023_NON_SCC],
|
||||
"6B": [CAR.KIA_SORENTO, CAR.HYUNDAI_GENESIS],
|
||||
}
|
||||
|
||||
@@ -2098,7 +2122,8 @@ LEGACY_SAFETY_MODE_CAR = {CAR.HYUNDAI_GENESIS, CAR.IONIQ_EV_LTD, CAR.KIA_OPTIMA_
|
||||
# these cars have not been verified to work with longitudinal yet - radar disable, sending correct messages, etc.
|
||||
UNSUPPORTED_LONGITUDINAL_CAR = LEGACY_SAFETY_MODE_CAR | {CAR.KIA_NIRO_PHEV, CAR.KIA_SORENTO, CAR.SONATA_LF, CAR.KIA_OPTIMA_G4_FL}
|
||||
|
||||
NON_SCC_CAR = {CAR.KIA_FORTE_2021_NON_SCC, CAR.ELANTRA_2022_NON_SCC, CAR.KIA_FORTE_2019_NON_SCC, CAR.GENESIS_G70_2021_NON_SCC}
|
||||
NON_SCC_CAR = {CAR.KIA_FORTE_2021_NON_SCC, CAR.ELANTRA_2022_NON_SCC, CAR.KIA_FORTE_2019_NON_SCC, CAR.GENESIS_G70_2021_NON_SCC,
|
||||
CAR.KIA_SELTOS_2023_NON_SCC}
|
||||
NON_SCC_NO_FCA_CAR = {CAR.KIA_FORTE_2019_NON_SCC, }
|
||||
NON_SCC_RADAR_FCA_CAR = {CAR.GENESIS_G70_2021_NON_SCC, }
|
||||
|
||||
@@ -2134,6 +2159,7 @@ DBC = {
|
||||
CAR.KIA_OPTIMA_G4_FL: dbc_dict('hyundai_kia_generic', None),
|
||||
CAR.KIA_OPTIMA_H: dbc_dict('hyundai_kia_generic', None),
|
||||
CAR.KIA_SELTOS: dbc_dict('hyundai_kia_generic', None),
|
||||
CAR.KIA_SELTOS_2023_NON_SCC: dbc_dict('hyundai_kia_generic', None),
|
||||
CAR.KIA_SORENTO: dbc_dict('hyundai_kia_generic', None), # Has 0x5XX messages, but different format
|
||||
CAR.KIA_STINGER: dbc_dict('hyundai_kia_generic', None),
|
||||
CAR.KIA_STINGER_2022: dbc_dict('hyundai_kia_generic', None),
|
||||
|
||||
@@ -127,8 +127,12 @@ class CarInterfaceBase(ABC):
|
||||
def get_params(cls, candidate: str, fingerprint: Dict[int, Dict[int, int]], car_fw: List[car.CarParams.CarFw], experimental_long: bool, docs: bool):
|
||||
ret = CarInterfaceBase.get_std_params(candidate)
|
||||
ret = cls._get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs)
|
||||
if Params().get_bool("EnforceTorqueLateral") and ret.steerControlType != car.CarParams.SteerControlType.angle:
|
||||
|
||||
params = Params()
|
||||
if params.get_bool("EnforceTorqueLateral") and ret.steerControlType != car.CarParams.SteerControlType.angle:
|
||||
ret = CarInterfaceBase.sp_configure_torque_tune(candidate, ret)
|
||||
if params.get_bool("CustomTorqueLateral"):
|
||||
ret = CarInterfaceBase.sp_configure_custom_torque_tune(ret, params)
|
||||
|
||||
# Vehicle mass is published curb weight plus assumed payload such as a human driver; notCars have no assumed payload
|
||||
if not ret.notCar:
|
||||
@@ -226,6 +230,12 @@ class CarInterfaceBase(ABC):
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def sp_configure_custom_torque_tune(ret, params):
|
||||
ret.lateralTuning.torque.friction = float(params.get("TorqueFriction", encoding="utf8")) * 0.01
|
||||
ret.lateralTuning.torque.latAccelFactor = float(params.get("TorqueMaxLatAccel", encoding="utf8")) * 0.01
|
||||
return ret
|
||||
|
||||
@abstractmethod
|
||||
def _update(self, c: car.CarControl) -> car.CarState:
|
||||
pass
|
||||
@@ -472,9 +482,10 @@ class CarInterfaceBase(ABC):
|
||||
|
||||
def toggle_gac(self, cs_out, CS, gac_button, gac_min, gac_max, gac_default, inc_dec):
|
||||
if not self.CP.openpilotLongitudinalControl:
|
||||
CS.gac_tr = 2
|
||||
CS.gac_tr_cluster = gac_default
|
||||
put_nonblocking("LongitudinalPersonality", 2)
|
||||
if CS.gac_tr != 2:
|
||||
CS.gac_tr = 2
|
||||
put_nonblocking("LongitudinalPersonality", "2")
|
||||
return cs_out, CS
|
||||
if gac_button:
|
||||
self.gac_button_counter += 1
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
from cereal import car
|
||||
from typing import Tuple
|
||||
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 apply_driver_steer_torque_limits, common_fault_avoidance
|
||||
from openpilot.selfdrive.car.subaru import subarucan
|
||||
from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, STEER_RATE_LIMITED, CanBus, CarControllerParams, SubaruFlags
|
||||
from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, STEER_RATE_LIMITED, CanBus, CarControllerParams, SubaruFlags, SubaruFlagsSP
|
||||
|
||||
# FIXME: These limits aren't exact. The real limit is more than likely over a larger time period and
|
||||
# involves the total steering angle change rather than rate, but these limits work well for now
|
||||
MAX_STEER_RATE = 25 # deg/s
|
||||
MAX_STEER_RATE_FRAMES = 7 # tx control frames needed before torque can be cut
|
||||
|
||||
_SNG_ACC_MIN_DIST = 3
|
||||
_SNG_ACC_MAX_DIST = 4.5
|
||||
|
||||
|
||||
class CarController:
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
@@ -19,6 +25,21 @@ class CarController:
|
||||
self.cruise_button_prev = 0
|
||||
self.steer_rate_counter = 0
|
||||
|
||||
self.param_s = Params()
|
||||
|
||||
if CP.spFlags & SubaruFlagsSP.SP_SUBARU_SNG:
|
||||
self.subaru_sng = True
|
||||
self.manual_parking_brake = self.param_s.get_bool("SubaruManualParkingBrakeSng")
|
||||
self.throttle_cnt = -1
|
||||
self.brake_pedal_cnt = -1
|
||||
self.prev_close_distance = 0
|
||||
self.prev_standstill = False
|
||||
self.standstill_start = 0
|
||||
self.sng_acc_resume = False
|
||||
self.sng_acc_resume_cnt = -1
|
||||
self.manual_hold = False
|
||||
self.prev_cruise_state = 0
|
||||
|
||||
self.p = CarControllerParams(CP)
|
||||
self.packer = CANPacker(DBC[CP.carFingerprint]['pt'])
|
||||
|
||||
@@ -27,6 +48,9 @@ class CarController:
|
||||
hud_control = CC.hudControl
|
||||
pcm_cancel_cmd = CC.cruiseControl.cancel
|
||||
|
||||
if self.frame % 250 == 0 and self.subaru_sng:
|
||||
self.manual_parking_brake = self.param_s.get_bool("SubaruManualParkingBrakeSng")
|
||||
|
||||
can_sends = []
|
||||
|
||||
# *** steering ***
|
||||
@@ -56,6 +80,9 @@ class CarController:
|
||||
|
||||
self.apply_steer_last = apply_steer
|
||||
|
||||
# *** stop and go ***
|
||||
throttle_cmd, speed_cmd = self.stop_and_go(CC, CS)
|
||||
|
||||
# *** longitudinal ***
|
||||
|
||||
if CC.longActive:
|
||||
@@ -92,6 +119,9 @@ class CarController:
|
||||
|
||||
can_sends.append(subarucan.create_preglobal_es_distance(self.packer, cruise_button, CS.es_distance_msg))
|
||||
|
||||
if self.subaru_sng:
|
||||
can_sends.append(subarucan.create_preglobal_throttle(self.packer, CS.throttle_msg, throttle_cmd))
|
||||
|
||||
else:
|
||||
if self.frame % 10 == 0:
|
||||
can_sends.append(subarucan.create_es_dashstatus(self.packer, self.frame // 10, CS.es_dashstatus_msg, CC.enabled, self.CP.openpilotLongitudinalControl,
|
||||
@@ -104,6 +134,12 @@ class CarController:
|
||||
if self.CP.flags & SubaruFlags.SEND_INFOTAINMENT:
|
||||
can_sends.append(subarucan.create_es_infotainment(self.packer, self.frame // 10, CS.es_infotainment_msg, hud_control.visualAlert))
|
||||
|
||||
if self.subaru_sng:
|
||||
can_sends.append(subarucan.create_throttle(self.packer, CS.throttle_msg, throttle_cmd))
|
||||
|
||||
if self.frame % 2 == 0:
|
||||
can_sends.append(subarucan.create_brake_pedal(self.packer, CS.brake_pedal_msg, speed_cmd, pcm_cancel_cmd))
|
||||
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
if self.frame % 5 == 0:
|
||||
can_sends.append(subarucan.create_es_status(self.packer, self.frame // 5, CS.es_status_msg,
|
||||
@@ -125,3 +161,58 @@ class CarController:
|
||||
|
||||
self.frame += 1
|
||||
return new_actuators, can_sends
|
||||
|
||||
# Stop and Go auto-resume thanks to martinl from subaru-community
|
||||
def stop_and_go(self, CC: car.CarControl, CS: car.CarState, throttle_cmd: bool = False, speed_cmd: bool = False) -> Tuple[bool, bool]:
|
||||
if not self.subaru_sng:
|
||||
return throttle_cmd, speed_cmd
|
||||
if self.CP.carFingerprint in PREGLOBAL_CARS:
|
||||
# Initiate the ACC resume sequence if conditions are met
|
||||
if (CC.enabled # ACC active
|
||||
and CS.car_follow == 1 # lead car
|
||||
and CS.out.standstill # must be standing still
|
||||
and CS.close_distance > _SNG_ACC_MIN_DIST # acc resume trigger low threshold
|
||||
and CS.close_distance < _SNG_ACC_MAX_DIST # acc resume trigger high threshold
|
||||
and CS.close_distance > self.prev_close_distance): # distance with lead car is increasing
|
||||
self.sng_acc_resume = True
|
||||
elif self.CP.carFingerprint not in (GLOBAL_GEN2 | HYBRID_CARS):
|
||||
if self.manual_parking_brake:
|
||||
# Send brake message with non-zero speed in standstill to avoid non-EPB ACC disengage
|
||||
if (CC.enabled # ACC active
|
||||
and CS.car_follow == 1 # lead car
|
||||
and CS.out.standstill
|
||||
and self.frame > self.standstill_start + 50): # standstill for >0.5 second
|
||||
speed_cmd = True
|
||||
else:
|
||||
# Record manual hold set while in standstill and no car in front
|
||||
if CS.out.standstill and self.prev_cruise_state == 1 and CS.cruise_state == 3 and CS.car_follow == 0:
|
||||
self.manual_hold = True
|
||||
# Cancel manual hold when car starts moving
|
||||
if not CS.out.standstill:
|
||||
self.manual_hold = False
|
||||
# Initiate the ACC resume sequence if conditions are met
|
||||
if (CC.enabled # ACC active
|
||||
and not self.manual_hold
|
||||
and CS.car_follow == 1 # lead car
|
||||
and CS.cruise_state == 3 # ACC HOLD (only with EPB)
|
||||
and CS.close_distance > _SNG_ACC_MIN_DIST # acc resume trigger low threshold
|
||||
and CS.close_distance < _SNG_ACC_MAX_DIST # acc resume trigger high threshold
|
||||
and CS.close_distance > self.prev_close_distance): # distance with lead car is increasing
|
||||
self.sng_acc_resume = True
|
||||
|
||||
if CS.out.standstill and not self.prev_standstill:
|
||||
self.standstill_start = self.frame
|
||||
self.prev_standstill = CS.out.standstill
|
||||
self.prev_cruise_state = CS.cruise_state
|
||||
|
||||
if self.sng_acc_resume:
|
||||
if self.sng_acc_resume_cnt < 5:
|
||||
throttle_cmd = True
|
||||
self.sng_acc_resume_cnt += 1
|
||||
else:
|
||||
self.sng_acc_resume = False
|
||||
self.sng_acc_resume_cnt = -1
|
||||
|
||||
self.prev_close_distance = CS.close_distance
|
||||
|
||||
return throttle_cmd, speed_cmd
|
||||
|
||||
@@ -4,7 +4,7 @@ from opendbc.can.can_define import CANDefine
|
||||
from openpilot.common.conversions import Conversions as CV
|
||||
from openpilot.selfdrive.car.interfaces import CarStateBase
|
||||
from opendbc.can.parser import CANParser
|
||||
from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, CanBus, SubaruFlags
|
||||
from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, CanBus, SubaruFlags, SubaruFlagsSP
|
||||
from openpilot.selfdrive.car import CanSignalRateCalculator
|
||||
|
||||
|
||||
@@ -123,8 +123,16 @@ class CarState(CarStateBase):
|
||||
self.es_status_msg = copy.copy(cp_es_status.vl["ES_Status"])
|
||||
self.cruise_control_msg = copy.copy(cp_cruise.vl["CruiseControl"])
|
||||
|
||||
if self.CP.spFlags & SubaruFlagsSP.SP_SUBARU_SNG:
|
||||
self.cruise_state = cp_cam.vl["ES_DashStatus"]["Cruise_State"]
|
||||
self.brake_pedal_msg = copy.copy(cp.vl["Brake_Pedal"])
|
||||
|
||||
if self.car_fingerprint not in HYBRID_CARS:
|
||||
self.es_distance_msg = copy.copy(cp_es_distance.vl["ES_Distance"])
|
||||
if self.CP.spFlags & SubaruFlagsSP.SP_SUBARU_SNG:
|
||||
self.throttle_msg = copy.copy(cp.vl["Throttle"])
|
||||
self.car_follow = cp_es_distance.vl["ES_Distance"]["Car_Follow"]
|
||||
self.close_distance = cp_es_distance.vl["ES_Distance"]["Close_Distance"]
|
||||
|
||||
self.es_dashstatus_msg = copy.copy(cp_cam.vl["ES_DashStatus"])
|
||||
if self.CP.flags & SubaruFlags.SEND_INFOTAINMENT:
|
||||
|
||||
@@ -2,7 +2,7 @@ from cereal import car
|
||||
from panda import Panda
|
||||
from openpilot.selfdrive.car import get_safety_config, create_mads_event
|
||||
from openpilot.selfdrive.car.interfaces import CarInterfaceBase
|
||||
from openpilot.selfdrive.car.subaru.values import CAR, LKAS_ANGLE, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, SubaruFlags
|
||||
from openpilot.selfdrive.car.subaru.values import CAR, LKAS_ANGLE, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, SubaruFlags, SubaruFlagsSP
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
EventName = car.CarEvent.EventName
|
||||
@@ -35,6 +35,11 @@ class CarInterface(CarInterfaceBase):
|
||||
if candidate in GLOBAL_GEN2:
|
||||
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_SUBARU_GEN2
|
||||
|
||||
if candidate not in (GLOBAL_GEN2 | HYBRID_CARS):
|
||||
ret.autoResumeSng = True
|
||||
ret.spFlags |= SubaruFlagsSP.SP_SUBARU_SNG.value
|
||||
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_SUBARU_SNG
|
||||
|
||||
ret.steerLimitTimer = 0.4
|
||||
ret.steerActuatorDelay = 0.1
|
||||
|
||||
|
||||
@@ -291,3 +291,67 @@ def create_preglobal_es_distance(packer, cruise_button, es_distance_msg):
|
||||
values["Checksum"] = subaru_preglobal_checksum(packer, values, "ES_Distance")
|
||||
|
||||
return packer.make_can_msg("ES_Distance", CanBus.main, values)
|
||||
|
||||
|
||||
def create_brake_pedal(packer, brake_pedal_msg, speed_cmd, brake_cmd):
|
||||
values = {s: brake_pedal_msg[s] for s in [
|
||||
"COUNTER",
|
||||
"Signal1",
|
||||
"Speed",
|
||||
"Signal2",
|
||||
"Brake_Lights",
|
||||
"Signal3",
|
||||
"Brake_Pedal",
|
||||
"Signal4",
|
||||
]}
|
||||
|
||||
if speed_cmd:
|
||||
values["Speed"] = 3
|
||||
if brake_cmd:
|
||||
values["Brake_Pedal"] = 5
|
||||
values["Brake_Lights"] = 1
|
||||
|
||||
return packer.make_can_msg("Brake_Pedal", CanBus.camera, values)
|
||||
|
||||
|
||||
def create_throttle(packer, throttle_msg, throttle_cmd):
|
||||
values = {s: throttle_msg[s] for s in [
|
||||
"CHECKSUM",
|
||||
"COUNTER",
|
||||
"Signal1",
|
||||
"Engine_RPM",
|
||||
"Signal2",
|
||||
"Throttle_Pedal",
|
||||
"Throttle_Cruise",
|
||||
"Throttle_Combo",
|
||||
"Signal3",
|
||||
"Off_Accel",
|
||||
]}
|
||||
|
||||
if throttle_cmd:
|
||||
values["Throttle_Pedal"] = 5
|
||||
|
||||
return packer.make_can_msg("Throttle", 2, values)
|
||||
|
||||
|
||||
def create_preglobal_throttle(packer, throttle_msg, throttle_cmd):
|
||||
values = {s: throttle_msg[s] for s in [
|
||||
"Throttle_Pedal",
|
||||
"COUNTER",
|
||||
"Signal1",
|
||||
"Not_Full_Throttle",
|
||||
"Signal2",
|
||||
"Engine_RPM",
|
||||
"Off_Throttle",
|
||||
"Signal3",
|
||||
"Throttle_Cruise",
|
||||
"Throttle_Combo",
|
||||
"Throttle_Body",
|
||||
"Off_Throttle_2",
|
||||
"Signal4",
|
||||
]}
|
||||
|
||||
if throttle_cmd:
|
||||
values["Throttle_Pedal"] = 5
|
||||
|
||||
return packer.make_can_msg("Throttle", 2, values)
|
||||
|
||||
@@ -60,6 +60,10 @@ class SubaruFlags(IntFlag):
|
||||
SEND_INFOTAINMENT = 1
|
||||
|
||||
|
||||
class SubaruFlagsSP(IntFlag):
|
||||
SP_SUBARU_SNG = 1
|
||||
|
||||
|
||||
class CanBus:
|
||||
main = 0
|
||||
alt = 1
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
"Honda Passport 2019-23": "HONDA PILOT 2017",
|
||||
"Honda Pilot 2016-22": "HONDA PILOT 2017",
|
||||
"Honda Ridgeline 2017-23": "HONDA RIDGELINE 2017",
|
||||
"Hyundai Azera 2022": "HYUNDAI AZERA 6TH GEN",
|
||||
"Hyundai Elantra 2017-19": "HYUNDAI ELANTRA 2017",
|
||||
"Hyundai Elantra 2021-23": "HYUNDAI ELANTRA 2021",
|
||||
"Hyundai Elantra GT 2017-19": "HYUNDAI ELANTRA 2017",
|
||||
@@ -84,7 +85,7 @@
|
||||
"Hyundai Ioniq Plug-in Hybrid 2020-22": "HYUNDAI IONIQ PHEV 2020",
|
||||
"Hyundai Kona 2020": "HYUNDAI KONA 2020",
|
||||
"Hyundai Kona Electric 2018-21": "HYUNDAI KONA ELECTRIC 2019",
|
||||
"Hyundai Kona Electric 2022": "HYUNDAI KONA ELECTRIC 2022",
|
||||
"Hyundai Kona Electric 2022-23": "HYUNDAI KONA ELECTRIC 2022",
|
||||
"Hyundai Kona Electric (with HDA II, Korea only) 2023": "HYUNDAI KONA ELECTRIC 2ND GEN",
|
||||
"Hyundai Kona Hybrid 2020": "HYUNDAI KONA HYBRID 2020",
|
||||
"Hyundai Palisade 2020-22": "HYUNDAI PALISADE 2020",
|
||||
@@ -104,7 +105,7 @@
|
||||
"Hyundai Veloster 2019-20": "HYUNDAI VELOSTER 2019",
|
||||
"Jeep Grand Cherokee 2016-18": "JEEP GRAND CHEROKEE V6 2018",
|
||||
"Jeep Grand Cherokee 2019-21": "JEEP GRAND CHEROKEE 2019",
|
||||
"Kia Carnival 2023": "KIA CARNIVAL 4TH GEN",
|
||||
"Kia Carnival 2023-24": "KIA CARNIVAL 4TH GEN",
|
||||
"Kia Carnival (China only) 2023": "KIA CARNIVAL 4TH GEN",
|
||||
"Kia Ceed 2019": "KIA CEED INTRO ED 2019",
|
||||
"Kia EV6 (Southeast Asia only) 2022-23": "KIA EV6 2022",
|
||||
@@ -116,6 +117,7 @@
|
||||
"Kia Forte Non-SCC 2021": "KIA FORTE LXS 2021 NON-SCC",
|
||||
"Kia K5 2021-22": "KIA K5 2021",
|
||||
"Kia K5 Hybrid 2020": "KIA K5 HYBRID 2020",
|
||||
"Kia K8 Hybrid (with HDA II) 2023": "KIA K8 HYBRID 1ST GEN",
|
||||
"Kia Niro EV 2019": "KIA NIRO EV 2020",
|
||||
"Kia Niro EV 2020": "KIA NIRO EV 2020",
|
||||
"Kia Niro EV 2021": "KIA NIRO EV 2020",
|
||||
@@ -128,6 +130,7 @@
|
||||
"Kia Optima 2017": "KIA OPTIMA 4TH GEN",
|
||||
"Kia Optima 2019-20": "KIA OPTIMA 4TH GEN FACELIFT",
|
||||
"Kia Seltos 2021": "KIA SELTOS 2021",
|
||||
"Kia Seltos Non-SCC 2023-24": "KIA SELTOS 2023 NON-SCC",
|
||||
"Kia Sorento 2018": "KIA SORENTO GT LINE 2018",
|
||||
"Kia Sorento 2019": "KIA SORENTO GT LINE 2018",
|
||||
"Kia Sorento 2021-23": "KIA SORENTO 4TH GEN",
|
||||
|
||||
@@ -27,6 +27,7 @@ KIA FORTE 2019 NON-SCC: HYUNDAI SONATA 2020
|
||||
KIA FORTE LXS 2021 NON-SCC: HYUNDAI SONATA 2020
|
||||
KIA CEED INTRO ED 2019: HYUNDAI SONATA 2020
|
||||
KIA SELTOS 2021: HYUNDAI SONATA 2020
|
||||
KIA SELTOS 2023 NON-SCC: HYUNDAI SONATA 2020
|
||||
KIA NIRO HYBRID 2019: KIA NIRO EV 2020
|
||||
KIA NIRO HYBRID 2021: KIA NIRO EV 2020
|
||||
HYUNDAI VELOSTER 2019: HYUNDAI SONATA 2019
|
||||
|
||||
@@ -44,6 +44,7 @@ class CarController:
|
||||
|
||||
self.param_s = Params()
|
||||
self._reverse_acc_change = self.param_s.get_bool("ReverseAccChange")
|
||||
self._sng_hack = self.param_s.get_bool("ToyotaSnG")
|
||||
|
||||
def update(self, CC, CS, now_nanos):
|
||||
actuators = CC.actuators
|
||||
@@ -119,7 +120,8 @@ class CarController:
|
||||
pcm_cancel_cmd = 1
|
||||
|
||||
# on entering standstill, send standstill request
|
||||
if CS.out.standstill and not self.last_standstill and (self.CP.carFingerprint not in NO_STOP_TIMER_CAR or self.CP.enableGasInterceptor):
|
||||
if CS.out.standstill and not self.last_standstill and (self.CP.carFingerprint not in NO_STOP_TIMER_CAR or self.CP.enableGasInterceptor) and \
|
||||
not self._sng_hack:
|
||||
self.standstill_req = True
|
||||
if CS.pcm_acc_status != 8:
|
||||
# pcm entered standstill or it's disabled
|
||||
|
||||
@@ -8,7 +8,7 @@ from openpilot.common.realtime import DT_CTRL
|
||||
from opendbc.can.can_define import CANDefine
|
||||
from opendbc.can.parser import CANParser
|
||||
from openpilot.selfdrive.car.interfaces import CarStateBase
|
||||
from openpilot.selfdrive.car.toyota.values import ToyotaFlags, CAR, DBC, STEER_THRESHOLD, NO_STOP_TIMER_CAR, \
|
||||
from openpilot.selfdrive.car.toyota.values import ToyotaFlags, ToyotaFlagsSP, CAR, DBC, STEER_THRESHOLD, NO_STOP_TIMER_CAR, \
|
||||
TSS2_CAR, RADAR_ACC_CAR, EPS_SCALE, UNSUPPORTED_DSU_CAR
|
||||
|
||||
SteerControlType = car.CarParams.SteerControlType
|
||||
@@ -61,6 +61,11 @@ class CarState(CarStateBase):
|
||||
self.gac_send_counter = 0
|
||||
self.follow_distance = 0
|
||||
|
||||
if CP.spFlags & ToyotaFlagsSP.SP_ZSS:
|
||||
self.zss_compute = False
|
||||
self.zss_cruise_active_last = False
|
||||
self.zss_angle_offset = 0.
|
||||
|
||||
def update(self, cp, cp_cam):
|
||||
ret = car.CarState.new_message()
|
||||
|
||||
@@ -128,6 +133,21 @@ class CarState(CarStateBase):
|
||||
ret.steeringAngleOffsetDeg = self.angle_offset.x
|
||||
ret.steeringAngleDeg = torque_sensor_angle_deg - self.angle_offset.x
|
||||
|
||||
# ZSS support thanks to dragonpilot and ErichMoraga
|
||||
if self.CP.spFlags & ToyotaFlagsSP.SP_ZSS:
|
||||
zorro_steer = cp.vl["SECONDARY_STEER_ANGLE"]["ZORRO_STEER"]
|
||||
# Only compute ZSS offset when acc is active
|
||||
if bool(cp.vl["PCM_CRUISE"]["CRUISE_ACTIVE"]) and not self.zss_cruise_active_last:
|
||||
self.zss_compute = True # Cruise was just activated, so allow offset to be recomputed
|
||||
self.zss_cruise_active_last = bool(cp.vl["PCM_CRUISE"]["CRUISE_ACTIVE"])
|
||||
|
||||
# Compute ZSS offset
|
||||
if self.zss_compute:
|
||||
if abs(ret.steeringAngleDeg) > 1e-3 and abs(zorro_steer) > 1e-3:
|
||||
self.zss_angle_offset = zorro_steer - ret.steeringAngleDeg
|
||||
# Apply offset
|
||||
ret.steeringAngleDeg = zorro_steer - self.zss_angle_offset
|
||||
|
||||
ret.steeringRateDeg = cp.vl["STEER_ANGLE_SENSOR"]["STEER_RATE"]
|
||||
|
||||
can_gear = int(cp.vl["GEAR_PACKET"]["GEAR"])
|
||||
@@ -343,6 +363,9 @@ class CarState(CarStateBase):
|
||||
if CP.flags & ToyotaFlags.SMART_DSU:
|
||||
messages.append(("SDSU", 33))
|
||||
|
||||
if CP.spFlags & ToyotaFlagsSP.SP_ZSS:
|
||||
messages.apend(("SECONDARY_STEER_ANGLE", 0))
|
||||
|
||||
return CANParser(DBC[CP.carFingerprint]["pt"], messages, 0)
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -4,7 +4,7 @@ from openpilot.common.numpy_fast import clip
|
||||
from openpilot.common.params import Params, put_nonblocking
|
||||
from panda import Panda
|
||||
from panda.python import uds
|
||||
from openpilot.selfdrive.car.toyota.values import Ecu, CAR, DBC, ToyotaFlags, CarControllerParams, TSS2_CAR, RADAR_ACC_CAR, NO_DSU_CAR, \
|
||||
from openpilot.selfdrive.car.toyota.values import Ecu, CAR, DBC, ToyotaFlags, ToyotaFlagsSP, CarControllerParams, TSS2_CAR, RADAR_ACC_CAR, NO_DSU_CAR, \
|
||||
MIN_ACC_SPEED, EPS_SCALE, EV_HYBRID_CAR, UNSUPPORTED_DSU_CAR, NO_STOP_TIMER_CAR, ANGLE_CONTROL_CAR
|
||||
from openpilot.selfdrive.car import create_button_events, get_safety_config, create_mads_event
|
||||
from openpilot.selfdrive.car.disable_ecu import disable_ecu
|
||||
@@ -51,21 +51,25 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.steerActuatorDelay = 0.25
|
||||
ret.steerLimitTimer = 0.8
|
||||
|
||||
if 0x23 in fingerprint[0]: # Detect if ZSS is present
|
||||
ret.spFlags |= ToyotaFlagsSP.SP_ZSS.value
|
||||
|
||||
ret.stoppingControl = False # Toyota starts braking more when it thinks you want to stop
|
||||
|
||||
stop_and_go = candidate in TSS2_CAR
|
||||
|
||||
if candidate == CAR.PRIUS:
|
||||
zss = ret.spFlags & ToyotaFlagsSP.SP_ZSS
|
||||
stop_and_go = True
|
||||
ret.wheelbase = 2.70
|
||||
ret.steerRatio = 15.74 # unknown end-to-end spec
|
||||
ret.steerRatio = 15.0 if zss else 15.74 # unknown end-to-end spec
|
||||
ret.tireStiffnessFactor = 0.6371 # hand-tune
|
||||
ret.mass = 3045. * CV.LB_TO_KG
|
||||
ret.mass = (3370. if zss else 3045.) * CV.LB_TO_KG
|
||||
# Only give steer angle deadzone to for bad angle sensor prius
|
||||
for fw in car_fw:
|
||||
if fw.ecu == "eps" and not fw.fwVersion == b'8965B47060\x00\x00\x00\x00\x00\x00':
|
||||
ret.steerActuatorDelay = 0.25
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning, steering_angle_deadzone_deg=0.2)
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning, steering_angle_deadzone_deg=0.0 if zss else 0.2)
|
||||
|
||||
elif candidate == CAR.PRIUS_V:
|
||||
stop_and_go = True
|
||||
@@ -324,7 +328,9 @@ class CarInterface(CarInterfaceBase):
|
||||
self.CS.madsEnabled = self.get_acc_mads(ret.cruiseState.enabled, self.CS.accEnabled, self.CS.madsEnabled)
|
||||
if not self.CP.openpilotLongitudinalControl:
|
||||
self.CS.gac_tr_cluster = 3
|
||||
put_nonblocking("LongitudinalPersonality", 2)
|
||||
if self.CS.gac_tr != 2:
|
||||
self.CS.gac_tr = 2
|
||||
put_nonblocking("LongitudinalPersonality", "2")
|
||||
else:
|
||||
gap_dist_button = bool(self.CS.gap_dist_button)
|
||||
if gap_dist_button:
|
||||
|
||||
@@ -46,6 +46,10 @@ class ToyotaFlags(IntFlag):
|
||||
DISABLE_RADAR = 4
|
||||
|
||||
|
||||
class ToyotaFlagsSP(IntFlag):
|
||||
SP_ZSS = 1
|
||||
|
||||
|
||||
class CAR:
|
||||
# Toyota
|
||||
ALPHARD_TSS2 = "TOYOTA ALPHARD 2020"
|
||||
|
||||
@@ -205,7 +205,7 @@ class Controls:
|
||||
self.reverse_acc_change = False
|
||||
|
||||
self.live_torque = self.params.get_bool("LiveTorque")
|
||||
self.custom_torque = self.params.get_bool("CustomTorqueLateral")
|
||||
self.torqued_override = self.params.get_bool("TorquedOverride")
|
||||
|
||||
self.process_not_running = False
|
||||
|
||||
@@ -635,7 +635,7 @@ class Controls:
|
||||
# Update Torque Params
|
||||
if self.CP.lateralTuning.which() == 'torque':
|
||||
torque_params = self.sm['liveTorqueParameters']
|
||||
if self.sm.all_checks(['liveTorqueParameters']) and (torque_params.useParams or self.live_torque) and not self.custom_torque:
|
||||
if self.sm.all_checks(['liveTorqueParameters']) and (torque_params.useParams or self.live_torque) and not self.torqued_override:
|
||||
self.LaC.update_live_torque_params(torque_params.latAccelFactorFiltered, torque_params.latAccelOffsetFiltered,
|
||||
torque_params.frictionCoefficientFiltered)
|
||||
|
||||
@@ -918,6 +918,9 @@ class Controls:
|
||||
self.lane_change_set_timer = int(self.params.get("AutoLaneChangeTimer", encoding="utf8"))
|
||||
self.reverse_acc_change = self.params.get_bool("ReverseAccChange")
|
||||
|
||||
if self.sm.frame % int(2.5 / DT_CTRL) == 0:
|
||||
self.live_torque = self.params.get_bool("LiveTorque")
|
||||
|
||||
# Sample data from sockets and get a carState
|
||||
CS = self.data_sample()
|
||||
cloudlog.timestamp("Data sampled")
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import numpy as np
|
||||
from cereal import log
|
||||
from common.filter_simple import FirstOrderFilter
|
||||
from common.numpy_fast import interp
|
||||
from common.realtime import DT_MDL
|
||||
from system.swaglog import cloudlog
|
||||
from openpilot.common.filter_simple import FirstOrderFilter
|
||||
from openpilot.common.numpy_fast import interp
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.common.realtime import DT_MDL
|
||||
from openpilot.system.swaglog import cloudlog
|
||||
|
||||
|
||||
TRAJECTORY_SIZE = 33
|
||||
@@ -33,10 +34,29 @@ class LanePlanner:
|
||||
self.l_lane_change_prob = 0.
|
||||
self.r_lane_change_prob = 0.
|
||||
|
||||
self.camera_offset = -CAMERA_OFFSET
|
||||
self.path_offset = -PATH_OFFSET
|
||||
self.camera_offset = CAMERA_OFFSET
|
||||
self.path_offset = PATH_OFFSET
|
||||
|
||||
self.param_s = Params()
|
||||
self.custom_offsets = self.param_s.get_bool("CustomOffsets")
|
||||
self._frame = 0
|
||||
|
||||
def update_custom_offsets(self):
|
||||
self._frame += 1
|
||||
if self._frame % 50 == 0:
|
||||
self.custom_offsets = self.param_s.get_bool("CustomOffsets")
|
||||
if not self.custom_offsets:
|
||||
self._frame = 0
|
||||
self.camera_offset = CAMERA_OFFSET
|
||||
self.path_offset = PATH_OFFSET
|
||||
return
|
||||
|
||||
self.camera_offset = float(self.param_s.get("CameraOffset", encoding="utf8")) * 0.01
|
||||
self.path_offset = float(self.param_s.get("PathOffset", encoding="utf8")) * 0.01
|
||||
self._frame = 0
|
||||
|
||||
def parse_model(self, md):
|
||||
self.update_custom_offsets()
|
||||
lane_lines = md.laneLines
|
||||
if len(lane_lines) == 4 and len(lane_lines[0].t) == TRAJECTORY_SIZE:
|
||||
self.ll_t = (np.array(lane_lines[1].t) + np.array(lane_lines[2].t))/2
|
||||
|
||||
@@ -33,7 +33,7 @@ class LatControlTorque(LatControl):
|
||||
self.steering_angle_deadzone_deg = self.torque_params.steeringAngleDeadzoneDeg
|
||||
|
||||
self.param_s = Params()
|
||||
self.custom_torque = self.param_s.get_bool("CustomTorqueLateral")
|
||||
self.torqued_override = self.param_s.get_bool("TorquedOverride")
|
||||
self._frame = 0
|
||||
|
||||
def update_live_torque_params(self, latAccelFactor, latAccelOffset, friction):
|
||||
@@ -42,13 +42,15 @@ class LatControlTorque(LatControl):
|
||||
self.torque_params.friction = friction
|
||||
|
||||
def update_live_tune(self):
|
||||
if not self.custom_torque:
|
||||
return
|
||||
self._frame += 1
|
||||
if self._frame % 300 == 0:
|
||||
if self._frame % 250 == 0:
|
||||
self._frame = 0
|
||||
self.torqued_override = self.param_s.get_bool("TorquedOverride")
|
||||
if not self.torqued_override:
|
||||
return
|
||||
|
||||
self.torque_params.latAccelFactor = float(self.param_s.get("TorqueMaxLatAccel", encoding="utf8")) * 0.01
|
||||
self.torque_params.friction = float(self.param_s.get("TorqueFriction", encoding="utf8")) * 0.01
|
||||
self._frame = 0
|
||||
|
||||
def update(self, active, CS, VM, params, last_actuators, steer_limited, desired_curvature, desired_curvature_rate, llk):
|
||||
self.update_live_tune()
|
||||
|
||||
@@ -115,12 +115,11 @@ class LateralPlanner:
|
||||
low_speed = v_ego_car < 10 * CV.MPH_TO_MS
|
||||
|
||||
if not self.get_dynamic_lane_profile(sm['longitudinalPlan']) and not low_speed:
|
||||
d_path_xyz = self.LP.get_d_path(self.v_ego, self.t_idxs, self.path_xyz)
|
||||
self.path_xyz = self.LP.get_d_path(self.v_ego, self.t_idxs, self.path_xyz)
|
||||
self.dynamic_lane_profile_status = False
|
||||
else:
|
||||
d_path_xyz = self.path_xyz
|
||||
self.path_xyz[:, 1] += self.LP.path_offset
|
||||
self.dynamic_lane_profile_status = True
|
||||
self.path_xyz = d_path_xyz
|
||||
|
||||
self.lat_mpc.set_weights(PATH_COST, LATERAL_MOTION_COST,
|
||||
LATERAL_ACCEL_COST, LATERAL_JERK_COST,
|
||||
|
||||
@@ -24,8 +24,9 @@
|
||||
import os
|
||||
import time
|
||||
from common.params import Params
|
||||
from common.realtime import Ratekeeper
|
||||
from common.realtime import set_core_affinity, Ratekeeper
|
||||
from selfdrive.athena.registration import register
|
||||
from system.swaglog import cloudlog
|
||||
from system.version import get_version
|
||||
|
||||
# for uploader
|
||||
@@ -139,10 +140,18 @@ class GpxUploader():
|
||||
print(f'Upload error: {e}')
|
||||
return False
|
||||
|
||||
def gpx_uploader_thread(self):
|
||||
try:
|
||||
set_core_affinity([0, 1, 2, 3])
|
||||
except Exception:
|
||||
cloudlog.exception("gpx_uploader: failed to set core affinity")
|
||||
|
||||
self.update()
|
||||
|
||||
|
||||
def main():
|
||||
gpx_uploader = GpxUploader()
|
||||
gpx_uploader.update()
|
||||
gpx_uploader.gpx_uploader_thread()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -27,7 +27,7 @@ import datetime
|
||||
import signal
|
||||
import subprocess
|
||||
import threading
|
||||
from common.realtime import Ratekeeper
|
||||
from common.realtime import set_core_affinity, Ratekeeper
|
||||
from cereal import log
|
||||
from system.swaglog import cloudlog
|
||||
|
||||
@@ -164,6 +164,10 @@ class GpxD:
|
||||
return gpx_str
|
||||
|
||||
def gpxd_thread(self):
|
||||
try:
|
||||
set_core_affinity([0, 1, 2, 3])
|
||||
except Exception:
|
||||
cloudlog.exception("gpxd: failed to set core affinity")
|
||||
while True:
|
||||
self.sm.update(0)
|
||||
self.log()
|
||||
|
||||
@@ -120,6 +120,16 @@ class TorqueEstimator:
|
||||
self.offline_friction = CP.lateralTuning.torque.friction
|
||||
self.offline_latAccelFactor = CP.lateralTuning.torque.latAccelFactor
|
||||
|
||||
params = Params()
|
||||
if params.get_bool("EnforceTorqueLateral"):
|
||||
if params.get_bool("CustomTorqueLateral"):
|
||||
self.offline_friction = float(params.get("TorqueFriction", encoding="utf8")) * 0.01
|
||||
self.offline_latAccelFactor = float(params.get("TorqueMaxLatAccel", encoding="utf8")) * 0.01
|
||||
if params.get_bool("LiveTorqueRelaxed"):
|
||||
self.min_bucket_points = np.array([0, 200, 300, 500, 500, 300, 200, 0]) / (10 if decimated else 1)
|
||||
self.factor_sanity = FACTOR_SANITY_QLOG if decimated else 1.0
|
||||
self.friction_sanity = FRICTION_SANITY_QLOG if decimated else 1.0
|
||||
|
||||
self.reset()
|
||||
|
||||
initial_params = {
|
||||
@@ -135,7 +145,6 @@ class TorqueEstimator:
|
||||
self.max_friction = (1.0 + self.friction_sanity) * self.offline_friction
|
||||
|
||||
# try to restore cached params
|
||||
params = Params()
|
||||
params_cache = params.get("LiveTorqueCarParams")
|
||||
torque_cache = params.get("LiveTorqueParameters")
|
||||
if params_cache is not None and torque_cache is not None:
|
||||
|
||||
@@ -58,7 +58,7 @@ def manager_init() -> None:
|
||||
("CustomTorqueLateral", "0"),
|
||||
("CameraControl", "2"),
|
||||
("CameraControlToggle", "0"),
|
||||
("CameraOffset", "0"),
|
||||
("CameraOffset", "4"),
|
||||
("CarModel", ""),
|
||||
("CarModelText", ""),
|
||||
("ChevronInfo", "1"),
|
||||
@@ -286,9 +286,6 @@ def main() -> None:
|
||||
cloudlog.warning("shutdown")
|
||||
HARDWARE.shutdown()
|
||||
|
||||
if params.get_bool("HotspotOnBoot"):
|
||||
os.system('nmcli con up Hotspot')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unblock_stdout()
|
||||
|
||||
@@ -85,7 +85,7 @@ procs = [
|
||||
NativeProcess("ui", "selfdrive/ui", ["./ui"], always_run, watchdog_max_dt=(5 if not PC else None), always_watchdog=True),
|
||||
|
||||
PythonProcess("gpxd", "selfdrive.gpxd.gpxd", only_onroad),
|
||||
PythonProcess("gpxd_uploader", "selfdrive.gpxd.gpx_uploader", always_run),
|
||||
PythonProcess("gpxd_uploader", "selfdrive.gpxd.gpx_uploader", only_offroad),
|
||||
PythonProcess("mapd", "selfdrive.mapd.mapd", only_onroad),
|
||||
PythonProcess("otisserv", "selfdrive.navd.otisserv", always_run),
|
||||
PythonProcess("fleet_manager", "system.fleetmanager.fleet_manager", only_offroad),
|
||||
|
||||
@@ -7,7 +7,7 @@ from time import strftime, gmtime
|
||||
from cereal import log
|
||||
import cereal.messaging as messaging
|
||||
from common.params import Params
|
||||
from common.realtime import Ratekeeper
|
||||
from common.realtime import set_core_affinity, Ratekeeper
|
||||
from selfdrive.mapd.lib.osm import OSM
|
||||
from selfdrive.mapd.lib.geo import distance_to_points
|
||||
from selfdrive.mapd.lib.WayCollection import WayCollection
|
||||
@@ -260,6 +260,10 @@ class MapD():
|
||||
|
||||
# provides live map data information
|
||||
def mapd_thread(sm=None, pm=None):
|
||||
try:
|
||||
set_core_affinity([0, 1, 2, 3])
|
||||
except Exception:
|
||||
cloudlog.exception("mapd: failed to set core affinity")
|
||||
mapd = MapD()
|
||||
rk = Ratekeeper(1., print_delay_threshold=None) # Keeps rate at 1 hz
|
||||
|
||||
|
||||
@@ -48,8 +48,8 @@ class RouteEngine:
|
||||
|
||||
self.reroute_counter = 0
|
||||
|
||||
if self.params.get_bool("CustomMapbox") or "MAPBOX_TOKEN" in os.environ:
|
||||
self.mapbox_token = self.params.get("CustomMapboxTokenSk") if self.params.get_bool("CustomMapbox") else os.environ["MAPBOX_TOKEN"]
|
||||
if "MAPBOX_TOKEN" in os.environ:
|
||||
self.mapbox_token = os.environ["MAPBOX_TOKEN"]
|
||||
self.mapbox_host = "https://api.mapbox.com"
|
||||
else:
|
||||
try:
|
||||
@@ -59,6 +59,10 @@ class RouteEngine:
|
||||
self.mapbox_token = ""
|
||||
self.mapbox_host = "https://maps.comma.ai"
|
||||
|
||||
if self.mapbox_token != "" and self.params.get("CustomMapboxTokenSk") is not None:
|
||||
self.mapbox_token = self.params.get("CustomMapboxTokenSk")
|
||||
self.mapbox_host = "https://api.mapbox.com"
|
||||
|
||||
def update(self):
|
||||
self.sm.update(0)
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ import requests
|
||||
import math
|
||||
from common.basedir import BASEDIR
|
||||
from common.params import Params
|
||||
from common.realtime import set_core_affinity
|
||||
from system.swaglog import cloudlog
|
||||
params = Params()
|
||||
|
||||
hostName = ""
|
||||
@@ -407,6 +409,10 @@ class OtisServ(BaseHTTPRequestHandler):
|
||||
params.put("ApiCache_NavDestinations", json.dumps(dests).rstrip("\n\r"))
|
||||
|
||||
def main():
|
||||
try:
|
||||
set_core_affinity([0, 1, 2, 3])
|
||||
except Exception:
|
||||
cloudlog.exception("otisserv: failed to set core affinity")
|
||||
webServer = HTTPServer((hostName, serverPort), OtisServ)
|
||||
|
||||
try:
|
||||
|
||||
+2
-33
@@ -12,7 +12,6 @@ from openpilot.system.version import get_branch, get_commit, get_origin, get_ver
|
||||
|
||||
import os
|
||||
import traceback
|
||||
from cereal import car
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
@@ -24,27 +23,7 @@ class SentryProject(Enum):
|
||||
|
||||
|
||||
CRASHES_DIR = '/data/community/crashes/'
|
||||
ret = car.CarParams.new_message()
|
||||
candidate = ret.carFingerprint
|
||||
params = Params()
|
||||
#uniqueID = op_params.get('uniqueID')
|
||||
try:
|
||||
dongle_id = params.get("DongleId").decode('utf8')
|
||||
except AttributeError:
|
||||
dongle_id = "None"
|
||||
try:
|
||||
gitname = params.get("GithubUsername", encoding='utf-8')
|
||||
except Exception:
|
||||
gitname = ""
|
||||
error_tags = {
|
||||
'dirty': is_dirty(),
|
||||
'dongle_id': dongle_id,
|
||||
'branch': get_branch(),
|
||||
'remote': get_origin(),
|
||||
'fingerprintedAs': candidate,
|
||||
'gitname': gitname
|
||||
}
|
||||
ip = "{{auto}}"
|
||||
IP_ADDRESS = "{{auto}}"
|
||||
|
||||
|
||||
def report_tombstone(fn: str, message: str, contents: str) -> None:
|
||||
@@ -60,7 +39,6 @@ def report_tombstone(fn: str, message: str, contents: str) -> None:
|
||||
def capture_exception(*args, **kwargs) -> None:
|
||||
save_exception(traceback.format_exc())
|
||||
cloudlog.error("crash", exc_info=kwargs.get('exc_info', 1))
|
||||
bind_user(id=dongle_id, ip_address=ip, username=gitname)
|
||||
|
||||
try:
|
||||
sentry_sdk.capture_exception(*args, **kwargs)
|
||||
@@ -85,26 +63,18 @@ def save_exception(exc_text):
|
||||
print('Logged current crash to {}'.format(files))
|
||||
|
||||
|
||||
def bind_user(**kwargs) -> None:
|
||||
sentry_sdk.set_user(kwargs)
|
||||
sentry_sdk.flush()
|
||||
|
||||
|
||||
def capture_warning(warning_string):
|
||||
bind_user(id=dongle_id, ip_address=ip, name=gitname)
|
||||
sentry_sdk.capture_message(warning_string, level='warning')
|
||||
sentry_sdk.flush()
|
||||
|
||||
|
||||
def capture_info(info_string):
|
||||
bind_user(id=dongle_id, ip_address=ip, name=gitname)
|
||||
sentry_sdk.capture_message(info_string, level='info')
|
||||
sentry_sdk.flush()
|
||||
|
||||
|
||||
def set_tag(key: str, value: str) -> None:
|
||||
sentry_sdk.set_tag(key, value)
|
||||
sentry_sdk.flush()
|
||||
|
||||
|
||||
def init(project: SentryProject) -> None:
|
||||
@@ -116,7 +86,6 @@ def init(project: SentryProject) -> None:
|
||||
#env = "release" if is_tested_branch() else "master"
|
||||
env = get_branch_type()
|
||||
dongle_id = Params().get("DongleId", encoding='utf-8')
|
||||
ip = "{{auto}}"
|
||||
gitname = Params().get("GithubUsername", encoding='utf-8')
|
||||
|
||||
integrations = []
|
||||
@@ -134,7 +103,7 @@ def init(project: SentryProject) -> None:
|
||||
send_default_pii=True)
|
||||
|
||||
sentry_sdk.set_user({"id": dongle_id})
|
||||
sentry_sdk.set_user({"ip_address": ip})
|
||||
sentry_sdk.set_user({"ip_address": IP_ADDRESS})
|
||||
sentry_sdk.set_user({"username": gitname})
|
||||
sentry_sdk.set_tag("dirty", is_dirty())
|
||||
sentry_sdk.set_tag("origin", get_origin())
|
||||
|
||||
@@ -156,6 +156,8 @@ def hw_state_thread(end_event, hw_queue):
|
||||
cloudlog.warning("configuring modem")
|
||||
HARDWARE.configure_modem()
|
||||
modem_configured = True
|
||||
if Params().get_bool("HotspotOnBoot") and Params().get_bool("HotspotOnBootConfirmed"):
|
||||
os.system('nmcli con up Hotspot')
|
||||
|
||||
prev_hw_state = hw_state
|
||||
except Exception:
|
||||
|
||||
@@ -172,15 +172,15 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) {
|
||||
#else
|
||||
left_widget->addWidget(new DriveStats);
|
||||
#endif
|
||||
custom_mapbox = params.getBool("CustomMapbox") && QString::fromStdString(params.get("CustomMapboxTokenSk")) != "";
|
||||
custom_mapbox = QString::fromStdString(params.get("CustomMapboxTokenSk")) != "";
|
||||
if (!custom_mapbox) {
|
||||
left_widget->addWidget(new PrimeAdWidget);
|
||||
}
|
||||
left_widget->setStyleSheet("border-radius: 10px;");
|
||||
|
||||
left_widget->setCurrentIndex(!custom_mapbox ? uiState()->hasPrime() ? 0 : 1 : 0);
|
||||
connect(uiState(), &UIState::primeChanged, [=](int prime) {
|
||||
left_widget->setCurrentIndex(!custom_mapbox ? prime ? 0 : 1 : 0);
|
||||
left_widget->setCurrentIndex((uiState()->hasPrime() || custom_mapbox) ? 0 : 1);
|
||||
connect(uiState(), &UIState::primeChanged, [=](bool prime) {
|
||||
left_widget->setCurrentIndex((prime || custom_mapbox) ? 0 : 1);
|
||||
});
|
||||
|
||||
home_layout->addWidget(left_widget, 1);
|
||||
|
||||
@@ -112,6 +112,49 @@ void MapWindow::initLayers() {
|
||||
// TODO: remove, symbol-sort-key does not seem to matter outside of each layer
|
||||
m_map->setLayoutProperty("carPosLayer", "symbol-sort-key", 0);
|
||||
}
|
||||
if ((!m_map->layerExists("buildingsLayer")) && uiState()->scene.map_3d_buildings) { // Could put this behind the cellular metered toggle in case it increases data usage
|
||||
qDebug() << "Initializing buildingsLayer";
|
||||
QVariantMap buildings;
|
||||
buildings["id"] = "buildingsLayer";
|
||||
buildings["source"] = "composite";
|
||||
buildings["source-layer"] = "building";
|
||||
buildings["type"] = "fill-extrusion";
|
||||
buildings["minzoom"] = 15;
|
||||
m_map->addLayer(buildings);
|
||||
m_map->setFilter("buildingsLayer", QVariantList({"==", "extrude", "true"}));
|
||||
|
||||
QVariantList fillExtrusionHeight = { // scale buildings as you zoom in
|
||||
"interpolate",
|
||||
QVariantList{"linear"},
|
||||
QVariantList{"zoom"},
|
||||
15, 0,
|
||||
15.05, QVariantList{"get", "height"}
|
||||
};
|
||||
|
||||
QVariantList fillExtrusionBase = {
|
||||
"interpolate",
|
||||
QVariantList{"linear"},
|
||||
QVariantList{"zoom"},
|
||||
15, 0,
|
||||
15.05, QVariantList{"get", "min_height"}
|
||||
};
|
||||
|
||||
QVariantList fillExtrusionOpacity = {
|
||||
"interpolate",
|
||||
QVariantList{"linear"},
|
||||
QVariantList{"zoom"},
|
||||
15, 0, // transparent at zoom level 15
|
||||
15.5, .6, // fade in
|
||||
17, .6, // begin fading out
|
||||
20, 0 // fade out when zoomed in
|
||||
};
|
||||
|
||||
m_map->setPaintProperty("buildingsLayer", "fill-extrusion-color", QColor("grey"));
|
||||
m_map->setPaintProperty("buildingsLayer", "fill-extrusion-opacity", fillExtrusionOpacity);
|
||||
m_map->setPaintProperty("buildingsLayer", "fill-extrusion-height", fillExtrusionHeight);
|
||||
m_map->setPaintProperty("buildingsLayer", "fill-extrusion-base", fillExtrusionBase);
|
||||
m_map->setLayoutProperty("buildingsLayer", "visibility", "visible");
|
||||
}
|
||||
}
|
||||
|
||||
void MapWindow::updateState(const UIState &s) {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "cereal/messaging/messaging.h"
|
||||
#include "common/params.h"
|
||||
|
||||
const QString MAPBOX_TOKEN = Params().getBool("CustomMapbox") ? QString::fromStdString(Params().get("CustomMapboxTokenSk")) : util::getenv("MAPBOX_TOKEN").c_str();
|
||||
const QString MAPBOX_TOKEN = QString::fromStdString(Params().get("CustomMapboxTokenSk")) != "" ? QString::fromStdString(Params().get("CustomMapboxTokenSk")) : util::getenv("MAPBOX_TOKEN").c_str();
|
||||
const QString MAPS_HOST = util::getenv("MAPS_HOST", MAPBOX_TOKEN.isEmpty() ? "https://maps.comma.ai" : "https://api.mapbox.com").c_str();
|
||||
const QString MAPS_CACHE_PATH = "/data/mbgl-cache-navd.db";
|
||||
|
||||
|
||||
@@ -125,7 +125,8 @@ AdvancedNetworking::AdvancedNetworking(QWidget* parent, WifiManager* wifi): QWid
|
||||
|
||||
ListWidget *list = new ListWidget(this);
|
||||
// Enable tethering layout
|
||||
tetheringToggle = new ToggleControl(tr("Enable Tethering"), "", "", wifi->isTetheringEnabled());
|
||||
const bool set_hotspot_on_boot = params.getBool("HotspotOnBoot") && params.getBool("HotspotOnBootConfirmed");
|
||||
tetheringToggle = new ToggleControl(tr("Enable Tethering"), "", "", wifi->isTetheringEnabled() || set_hotspot_on_boot);
|
||||
list->addItem(tetheringToggle);
|
||||
QObject::connect(tetheringToggle, &ToggleControl::toggleFlipped, this, &AdvancedNetworking::toggleTethering);
|
||||
|
||||
@@ -201,7 +202,7 @@ void AdvancedNetworking::refresh() {
|
||||
}
|
||||
|
||||
void AdvancedNetworking::toggleTethering(bool enabled) {
|
||||
params.putBool("HotspotOnBoot", enabled);
|
||||
params.putBool("HotspotOnBootConfirmed", enabled);
|
||||
wifi->setTetheringEnabled(enabled);
|
||||
tetheringToggle->setEnabled(false);
|
||||
}
|
||||
|
||||
@@ -202,16 +202,28 @@ SPControlsPanel::SPControlsPanel(QWidget *parent) : ListWidget(parent) {
|
||||
"../assets/offroad/icon_calibration.png",
|
||||
},
|
||||
{
|
||||
"CustomTorqueLateral",
|
||||
tr("Torque Lateral Control Live Tune"),
|
||||
tr("Enables live tune for Torque lateral control."),
|
||||
"../assets/offroad/icon_calibration.png",
|
||||
"LiveTorque",
|
||||
tr("Enable Self-Tune"),
|
||||
tr("Enables self-tune for Torque lateral control for platforms that do not use Torque lateral control by default."),
|
||||
"../assets/offroad/icon_blank.png",
|
||||
},
|
||||
{
|
||||
"LiveTorque",
|
||||
tr("Torque Lateral Controller Self-Tune"),
|
||||
tr("Enables self-tune for Torque lateral control."),
|
||||
"../assets/offroad/icon_calibration.png",
|
||||
"LiveTorqueRelaxed",
|
||||
tr("Less Restrict Settings for Self-Tune (Beta)"),
|
||||
tr("Less strict settings when using Self-Tune. This allows torqued to be more forgiving when learning values."),
|
||||
"../assets/offroad/icon_blank.png",
|
||||
},
|
||||
{
|
||||
"CustomTorqueLateral",
|
||||
tr("Enable Custom Tuning"),
|
||||
tr("Enables custom tuning for Torque lateral control. Modifying FRICTION and LAT_ACCEL_FACTOR below will override the offline values indicated in the YAML files within \"selfdrive/torque_data\". The values will also be used live when \"Override Self-Tune\" toggle is enabled."),
|
||||
"../assets/offroad/icon_blank.png",
|
||||
},
|
||||
{
|
||||
"TorquedOverride",
|
||||
tr("Manual Real-Time Tuning"),
|
||||
tr("Enforces the torque lateral controller to use the fixed values instead of the learned values from Self-Tune. Enabling this toggle overrides Self-Tune values."),
|
||||
"../assets/offroad/icon_blank.png",
|
||||
},
|
||||
{
|
||||
"HandsOnWheelMonitoring",
|
||||
@@ -267,19 +279,15 @@ SPControlsPanel::SPControlsPanel(QWidget *parent) : ListWidget(parent) {
|
||||
|
||||
// toggle names to trigger updateToggles() when toggleFlipped
|
||||
std::vector<std::string> updateTogglesNames{
|
||||
"EnableMads", "CustomOffsets", "EnforceTorqueLateral",
|
||||
"SpeedLimitPercOffset", "SpeedLimitControl"
|
||||
"EnableMads", "CustomOffsets", "EnforceTorqueLateral", "SpeedLimitPercOffset", "SpeedLimitControl",
|
||||
"CustomTorqueLateral", "LiveTorque", "TorquedOverride"
|
||||
};
|
||||
connect(dynamic_lane_profile, &DynamicLaneProfile::updateExternalToggles, this, &SPControlsPanel::updateToggles);
|
||||
|
||||
// toggle names to trigger updateToggles() when toggleFlipped and display ConfirmationDialog::alert
|
||||
std::vector<std::string> updateTogglesNamesAlert{
|
||||
"CustomTorqueLateral", "LiveTorque"
|
||||
};
|
||||
// toggle names to trigger updateToggles() when toggleFlipped and display ConfirmationDialog::alert
|
||||
// toggle for offroadTransition when going onroad/offroad
|
||||
std::vector<std::string> toggleOffroad{
|
||||
"EnableMads", "DisengageLateralOnBrake", "AccMadsCombo", "MadsCruiseMain", "BelowSpeedPause", "EnforceTorqueLateral",
|
||||
"CustomTorqueLateral", "LiveTorque"
|
||||
"LiveTorqueRelaxed"
|
||||
};
|
||||
|
||||
// Controls: Camera Offset (cm)
|
||||
@@ -336,7 +344,7 @@ SPControlsPanel::SPControlsPanel(QWidget *parent) : ListWidget(parent) {
|
||||
addItem(auto_lane_change_timer);
|
||||
}
|
||||
|
||||
if (param == "CustomTorqueLateral") {
|
||||
if (param == "TorquedOverride") {
|
||||
// Control: FRICTION
|
||||
addItem(friction);
|
||||
|
||||
@@ -359,14 +367,6 @@ SPControlsPanel::SPControlsPanel(QWidget *parent) : ListWidget(parent) {
|
||||
});
|
||||
}
|
||||
|
||||
// trigger updateToggles() and display ConfirmationDialog::alert when toggleFlipped
|
||||
if (std::find(updateTogglesNamesAlert.begin(), updateTogglesNamesAlert.end(), param.toStdString()) != updateTogglesNamesAlert.end()) {
|
||||
connect(toggle, &ToggleControl:: toggleFlipped, [=](bool state) {
|
||||
updateToggles();
|
||||
ConfirmationDialog::alert(tr("You must restart your car or your device to apply these changes."), this);
|
||||
});
|
||||
}
|
||||
|
||||
// trigger offroadTransition when going onroad/offroad
|
||||
if (std::find(toggleOffroad.begin(), toggleOffroad.end(), param.toStdString()) != toggleOffroad.end()) {
|
||||
connect(uiState(), &UIState::offroadTransition, [=](bool offroad) {
|
||||
@@ -383,6 +383,27 @@ SPControlsPanel::SPControlsPanel(QWidget *parent) : ListWidget(parent) {
|
||||
params.remove("OsmLocalDb");
|
||||
}
|
||||
});
|
||||
|
||||
// update "FRICTION" and "LAT_ACCEL_FACTOR" titles when going onroad/offroad
|
||||
connect(uiState(), &UIState::offroadTransition, [=](bool offroad) {
|
||||
friction->setEnabled(offroad);
|
||||
lat_accel_factor->setEnabled(offroad);
|
||||
|
||||
friction->refresh();
|
||||
lat_accel_factor->refresh();
|
||||
});
|
||||
|
||||
// update "FRICTION" and "LAT_ACCEL_FACTOR" titles when TorquedOverride is flipped
|
||||
connect(toggles["TorquedOverride"], &ToggleControl::toggleFlipped, [=](bool state) {
|
||||
friction->setEnabled(params.getBool("IsOffroad") || state);
|
||||
lat_accel_factor->setEnabled(params.getBool("IsOffroad") || state);
|
||||
|
||||
friction->setTitle(state ? "FRICTION - Live && Offline" : "FRICTION - Offline Only");
|
||||
lat_accel_factor->setTitle(state ? "LAT_ACCEL_FACTOR - Live && Offline" : "LAT_ACCEL_FACTOR - Offline Only");
|
||||
|
||||
friction->refresh();
|
||||
lat_accel_factor->refresh();
|
||||
});
|
||||
}
|
||||
|
||||
void SPControlsPanel::showEvent(QShowEvent *event) {
|
||||
@@ -394,7 +415,7 @@ void SPControlsPanel::updateToggles() {
|
||||
std::vector<std::string> enableMadsGroup{"DisengageLateralOnBrake", "AccMadsCombo", "MadsCruiseMain"};
|
||||
for (const auto& enableMadstoggle : enableMadsGroup) {
|
||||
if (toggles.find(enableMadstoggle) != toggles.end()) {
|
||||
toggles[enableMadstoggle]->setVisible(params.getBool("EnableMads"));
|
||||
toggles[enableMadstoggle]->setVisible(toggles["EnableMads"]->isToggled());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,55 +425,44 @@ void SPControlsPanel::updateToggles() {
|
||||
// toggle names to update when CustomOffsets is flipped
|
||||
std::vector<AbstractControl*> customOffsetsGroup{camera_offset, path_offset};
|
||||
for (const auto& customOffsetsControl : customOffsetsGroup) {
|
||||
customOffsetsControl->setVisible(params.getBool("CustomOffsets"));
|
||||
customOffsetsControl->setVisible(toggles["CustomOffsets"]->isToggled());
|
||||
}
|
||||
|
||||
// toggle names to update when AutoLaneChangeTimer is not "Nudge"
|
||||
toggles["AutoLaneChangeBsmDelay"]->setVisible(QString::fromStdString(params.get("AutoLaneChangeTimer")) != "0");
|
||||
|
||||
auto enforce_torque_lateral = toggles["EnforceTorqueLateral"];
|
||||
auto custom_torque_lateral = toggles["CustomTorqueLateral"];
|
||||
auto live_torque = toggles["LiveTorque"];
|
||||
auto live_torque_relaxed = toggles["LiveTorqueRelaxed"];
|
||||
auto torqued_override = toggles["TorquedOverride"];
|
||||
|
||||
auto speed_limit_control = toggles["SpeedLimitControl"];
|
||||
auto speed_limit_perc_offset = toggles["SpeedLimitPercOffset"];
|
||||
|
||||
// toggle names to update when EnforceTorqueLateral is flipped
|
||||
std::vector<std::string> enforceTorqueGroup{"CustomTorqueLateral", "LiveTorque"};
|
||||
std::vector<std::string> enforceTorqueGroup{"CustomTorqueLateral", "LiveTorque", "TorquedOverride"};
|
||||
for (const auto& enforceTorqueToggle : enforceTorqueGroup) {
|
||||
if (toggles.find(enforceTorqueToggle) != toggles.end()) {
|
||||
toggles[enforceTorqueToggle]->setVisible(params.getBool("EnforceTorqueLateral"));
|
||||
toggles[enforceTorqueToggle]->setVisible(enforce_torque_lateral->isToggled());
|
||||
}
|
||||
}
|
||||
|
||||
// toggle names to update when CustomTorqueLateral is flipped
|
||||
std::vector<AbstractControl*> customTorqueGroup{friction, lat_accel_factor};
|
||||
for (const auto& customTorqueControl : customTorqueGroup) {
|
||||
customTorqueControl->setVisible(params.getBool("CustomTorqueLateral"));
|
||||
customTorqueControl->setVisible(custom_torque_lateral->isToggled());
|
||||
}
|
||||
|
||||
// toggle names to update when SpeedLimitControl is flipped
|
||||
std::vector<AbstractControl*> speedLimitControlGroup{slo_type, slvo};
|
||||
for (const auto& speedLimitControl : speedLimitControlGroup) {
|
||||
speedLimitControl->setVisible(params.getBool("SpeedLimitControl"));
|
||||
speedLimitControl->setVisible(speed_limit_control->isToggled());
|
||||
}
|
||||
|
||||
if (params.getBool("EnforceTorqueLateral")) {
|
||||
if (params.getBool("CustomTorqueLateral")) {
|
||||
live_torque->setEnabled(false);
|
||||
params.putBool("LiveTorque", false);
|
||||
} else {
|
||||
live_torque->setEnabled(true);
|
||||
}
|
||||
|
||||
if (params.getBool("LiveTorque")) {
|
||||
custom_torque_lateral->setEnabled(false);
|
||||
params.putBool("CustomTorqueLateral", false);
|
||||
for (const auto& customTorqueControl : customTorqueGroup) {
|
||||
customTorqueControl->setVisible(false);
|
||||
}
|
||||
} else {
|
||||
custom_torque_lateral->setEnabled(true);
|
||||
}
|
||||
|
||||
live_torque->refresh();
|
||||
custom_torque_lateral->refresh();
|
||||
if (enforce_torque_lateral->isToggled()) {
|
||||
live_torque_relaxed->setVisible(live_torque->isToggled());
|
||||
torqued_override->setVisible(custom_torque_lateral->isToggled());
|
||||
} else {
|
||||
params.putBool("LiveTorque", false);
|
||||
params.putBool("CustomTorqueLateral", false);
|
||||
@@ -461,8 +471,8 @@ void SPControlsPanel::updateToggles() {
|
||||
}
|
||||
}
|
||||
|
||||
if (params.getBool("SpeedLimitControl")) {
|
||||
if (params.getBool("SpeedLimitPercOffset")) {
|
||||
if (speed_limit_control->isToggled()) {
|
||||
if (speed_limit_perc_offset->isToggled()) {
|
||||
slvo->setVisible(QString::fromStdString(params.get("SpeedLimitOffsetType")) != "0");
|
||||
slo_type->setVisible(true);
|
||||
} else {
|
||||
@@ -477,7 +487,7 @@ void SPControlsPanel::updateToggles() {
|
||||
}
|
||||
|
||||
// toggle names to update when SpeedLimitControl is flipped
|
||||
toggles["SpeedLimitPercOffset"]->setVisible(params.getBool("SpeedLimitControl"));
|
||||
speed_limit_perc_offset->setVisible(speed_limit_control->isToggled());
|
||||
|
||||
auto cp_bytes = params.get("CarParamsPersistent");
|
||||
if (!cp_bytes.empty()) {
|
||||
@@ -486,7 +496,7 @@ void SPControlsPanel::updateToggles() {
|
||||
cereal::CarParams::Reader CP = cmsg.getRoot<cereal::CarParams>();
|
||||
|
||||
if (CP.getSteerControlType() == cereal::CarParams::SteerControlType::ANGLE) {
|
||||
toggles["EnforceTorqueLateral"]->setEnabled(false);
|
||||
enforce_torque_lateral->setEnabled(false);
|
||||
params.remove("EnforceTorqueLateral");
|
||||
}
|
||||
}
|
||||
@@ -548,6 +558,8 @@ SPVehiclesPanel::SPVehiclesPanel(QWidget *parent) : QWidget(parent) {
|
||||
|
||||
SPVehiclesTogglesPanel::SPVehiclesTogglesPanel(SPVehiclesPanel *parent) : ListWidget(parent) {
|
||||
setSpacing(50);
|
||||
|
||||
// Hyundai/Kia/Genesis
|
||||
addItem(new LabelControl(tr("Hyundai/Kia/Genesis")));
|
||||
auto hkgSmoothStop = new ParamControl(
|
||||
"HkgSmoothStop",
|
||||
@@ -558,6 +570,18 @@ SPVehiclesTogglesPanel::SPVehiclesTogglesPanel(SPVehiclesPanel *parent) : ListWi
|
||||
hkgSmoothStop->setConfirmation(true, false);
|
||||
addItem(hkgSmoothStop);
|
||||
|
||||
// Subaru
|
||||
addItem(new LabelControl(tr("Subaru")));
|
||||
auto subaruManualParkingBrakeSng = new ParamControl(
|
||||
"SubaruManualParkingBrakeSng",
|
||||
tr("Manual Parking Brake: Stop and Go (Beta)"),
|
||||
tr("Experimental feature to enable stop and go for Subaru Global models with manual handbrake. Models with electric parking brake should keep this disabled. Thanks to martinl for this implementation!"),
|
||||
"../assets/offroad/icon_blank.png"
|
||||
);
|
||||
subaruManualParkingBrakeSng->setConfirmation(true, false);
|
||||
addItem(subaruManualParkingBrakeSng);
|
||||
|
||||
// Toyota/Lexus
|
||||
addItem(new LabelControl(tr("Toyota/Lexus")));
|
||||
stockLongToyota = new ParamControl(
|
||||
"StockLongToyota",
|
||||
@@ -589,10 +613,20 @@ SPVehiclesTogglesPanel::SPVehiclesTogglesPanel(SPVehiclesPanel *parent) : ListWi
|
||||
toyotaTss2LongTune->setConfirmation(true, false);
|
||||
addItem(toyotaTss2LongTune);
|
||||
|
||||
auto toyotaSngHack = new ParamControl(
|
||||
"ToyotaSnG",
|
||||
"Enable Stop and Go Hack",
|
||||
"sunnypilot will allow some Toyota/Lexus cars to auto resume during stop and go traffic. This feature is only applicable to certain models. Use at your own risk.",
|
||||
"../assets/offroad/icon_blank.png"
|
||||
);
|
||||
toyotaSngHack->setConfirmation(true, false);
|
||||
addItem(toyotaSngHack);
|
||||
|
||||
// trigger offroadTransition when going onroad/offroad
|
||||
connect(uiState(), &UIState::offroadTransition, [=](bool offroad) {
|
||||
hkgSmoothStop->setEnabled(offroad);
|
||||
toyotaTss2LongTune->setEnabled(offroad);
|
||||
toyotaSngHack->setEnabled(offroad);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -635,19 +669,6 @@ SPVisualsPanel::SPVisualsPanel(QWidget *parent) : ListWidget(parent) {
|
||||
tr("OSM: Show UI elements that aid debugging."),
|
||||
"../assets/offroad/icon_calibration.png",
|
||||
},
|
||||
{
|
||||
"CustomMapbox",
|
||||
tr("Enable Mapbox Navigation*"),
|
||||
QString("%1<br>"
|
||||
"%2<br>"
|
||||
"%3<br>"
|
||||
"<h4>%4</h4>")
|
||||
.arg(tr("Enable built-in navigation on sunnypilot, powered by Mapbox."))
|
||||
.arg(tr("Access via the web interface: \"http://<device_ip>:8082\""))
|
||||
.arg(tr("If you do not have comma Prime, you will need to provide your own Mapbox token at https://mapbox.com/. Reach out to sunnyhaibin#0865 on Discord for more information."))
|
||||
.arg(tr("Huge thanks to the dragonpilot team for making this possible!")),
|
||||
"../assets/img_map.png",
|
||||
},
|
||||
{
|
||||
"TrueVEgoUi",
|
||||
tr("Speedometer: Display True Speed"),
|
||||
@@ -666,6 +687,12 @@ SPVisualsPanel::SPVisualsPanel(QWidget *parent) : ListWidget(parent) {
|
||||
tr("Enable this will display an icon that appears when the End-to-end model decides to start or stop."),
|
||||
"../assets/offroad/icon_road.png",
|
||||
},
|
||||
{
|
||||
"Map3DBuildings",
|
||||
tr("Map: Display 3D Buildings"),
|
||||
tr("Parse and display 3D buildings on map. Thanks to jakethesnake420 for this implementation."),
|
||||
"../assets/img_map.png",
|
||||
},
|
||||
};
|
||||
|
||||
// Visuals: Developer UI Info (Dev UI)
|
||||
@@ -701,14 +728,6 @@ SPVisualsPanel::SPVisualsPanel(QWidget *parent) : ListWidget(parent) {
|
||||
|
||||
// trigger offroadTransition when going onroad/offroad
|
||||
connect(uiState(), &UIState::offroadTransition, [=](bool offroad) {
|
||||
toggles["CustomMapbox"]->setEnabled(offroad);
|
||||
});
|
||||
|
||||
// trigger hardwrae reboot if user confirms the selection
|
||||
connect(toggles["CustomMapbox"], &ToggleControl::toggleFlipped, [=](bool state) {
|
||||
if (ConfirmationDialog::confirm(tr("\"Enable Mapbox Navigation\"\nYou must restart your car or your device to apply these changes.\nReboot now?"), "Reboot", parent)) {
|
||||
Hardware::reboot();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -717,7 +736,7 @@ void SPVisualsPanel::showEvent(QShowEvent *event) {
|
||||
}
|
||||
|
||||
void SPVisualsPanel::updateToggles() {
|
||||
dev_ui_info->setVisible(params.getBool("DevUI"));
|
||||
dev_ui_info->setVisible(toggles["DevUI"]->isToggled());
|
||||
}
|
||||
|
||||
// Max Time Offroad (Shutdown timer)
|
||||
@@ -835,10 +854,10 @@ void BrightnessControl::refresh() {
|
||||
// Camera Offset Value
|
||||
CameraOffset::CameraOffset() : SPOptionControl (
|
||||
"CameraOffset",
|
||||
tr("Camera Offset (cm)"),
|
||||
tr("Hack to trick vehicle to be left or right biased in its lane. Decreasing the value will make the car keep more left, increasing will make it keep more right. Changes take effect immediately."),
|
||||
tr("Camera Offset - Laneful Only (cm)"),
|
||||
tr("Hack to trick vehicle to be left or right biased in its lane. Decreasing the value will make the car keep more left, increasing will make it keep more right. Changes take effect immediately. Default: +4 cm"),
|
||||
"../assets/offroad/icon_blank.png",
|
||||
{-10, 10}) {
|
||||
{-20, 20}) {
|
||||
|
||||
refresh();
|
||||
}
|
||||
@@ -896,7 +915,7 @@ void AutoLaneChangeTimer::refresh() {
|
||||
TorqueFriction::TorqueFriction() : SPOptionControl (
|
||||
"TorqueFriction",
|
||||
tr("FRICTION"),
|
||||
tr("Adjust Friction for the Torque Lateral Controller"),
|
||||
tr("Adjust Friction for the Torque Lateral Controller. <b>Live</b>: Override self-tune values; <b>Offline</b>: Override self-tune offline values at car restart."),
|
||||
"../assets/offroad/icon_blank.png",
|
||||
{0, 50}) {
|
||||
|
||||
@@ -906,13 +925,14 @@ TorqueFriction::TorqueFriction() : SPOptionControl (
|
||||
void TorqueFriction::refresh() {
|
||||
QString torqueFrictionStr = QString::fromStdString(params.get("TorqueFriction"));
|
||||
float valuef = torqueFrictionStr.toInt() * 0.01;
|
||||
setTitle(params.getBool("TorquedOverride") ? "FRICTION - Live && Offline" : "FRICTION - Offline Only");
|
||||
setLabel(QString::number(valuef));
|
||||
}
|
||||
|
||||
TorqueMaxLatAccel::TorqueMaxLatAccel() : SPOptionControl (
|
||||
"TorqueMaxLatAccel",
|
||||
tr("LAT_ACCEL_FACTOR"),
|
||||
tr("Adjust Max Lateral Acceleration for the Torque Lateral Controller"),
|
||||
tr("Adjust Max Lateral Acceleration for the Torque Lateral Controller. <b>Live</b>: Override self-tune values; <b>Offline</b>: Override self-tune offline values at car restart."),
|
||||
"../assets/offroad/icon_blank.png",
|
||||
{1, 500}) {
|
||||
|
||||
@@ -922,6 +942,7 @@ TorqueMaxLatAccel::TorqueMaxLatAccel() : SPOptionControl (
|
||||
void TorqueMaxLatAccel::refresh() {
|
||||
QString torqueMaxLatAccelStr = QString::fromStdString(params.get("TorqueMaxLatAccel"));
|
||||
float valuef = torqueMaxLatAccelStr.toInt() * 0.01;
|
||||
setTitle(params.getBool("TorquedOverride") ? "LAT_ACCEL_FACTOR - Live && Offline" : "LAT_ACCEL_FACTOR - Offline Only");
|
||||
setLabel(QString::number(valuef));
|
||||
}
|
||||
|
||||
@@ -1043,7 +1064,7 @@ void SidebarTemp::showEvent(QShowEvent *event) {
|
||||
}
|
||||
|
||||
void SidebarTemp::updateToggles() {
|
||||
sidebar_temp_setting->setVisible(params.getBool("SidebarTemperature"));
|
||||
sidebar_temp_setting->setVisible(sidebarTemperature->isToggled());
|
||||
}
|
||||
|
||||
DynamicLaneProfile::DynamicLaneProfile(QWidget *parent) : QWidget(parent), outer_layout(this) {
|
||||
@@ -1090,7 +1111,7 @@ void DynamicLaneProfile::showEvent(QShowEvent *event) {
|
||||
|
||||
void DynamicLaneProfile::updateToggles() {
|
||||
// toggle names to update when DynamicLaneProfile is flipped
|
||||
dlp_settings->setVisible(params.getBool("DynamicLaneProfileToggle"));
|
||||
dlp_settings->setVisible(dynamicLaneProfile->isToggled());
|
||||
}
|
||||
|
||||
void DynamicLaneProfile::updateButtons() {
|
||||
|
||||
@@ -79,6 +79,12 @@ public:
|
||||
|
||||
inline void setLabel(const QString &text) { label.setText(text); }
|
||||
|
||||
void setEnabled(bool enabled) {
|
||||
for (auto btn : button_group->buttons()) {
|
||||
btn->setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
signals:
|
||||
void updateLabels();
|
||||
void updateOtherToggles();
|
||||
|
||||
+20
-19
@@ -235,8 +235,7 @@ void OnroadWindow::mousePressEvent(QMouseEvent* e) {
|
||||
void OnroadWindow::offroadTransition(bool offroad) {
|
||||
if (!offroad) {
|
||||
#ifdef ENABLE_MAPS
|
||||
bool custom_mapbox = params.getBool("CustomMapbox") && QString::fromStdString(params.get("CustomMapboxTokenSk")) != "";
|
||||
if (map == nullptr && (uiState()->hasPrime() || !MAPBOX_TOKEN.isEmpty() || custom_mapbox)) {
|
||||
if (map == nullptr && (uiState()->hasPrime() || !MAPBOX_TOKEN.isEmpty())) {
|
||||
auto m = new MapPanel(get_mapbox_settings());
|
||||
map = m;
|
||||
|
||||
@@ -480,8 +479,10 @@ AnnotatedCameraWidget::AnnotatedCameraWidget(VisionStreamType type, QWidget* par
|
||||
|
||||
#ifdef ENABLE_DASHCAM
|
||||
void AnnotatedCameraWidget::offroadTransition(bool offroad) {
|
||||
if (offroad && recorder) {
|
||||
recorder->stop();
|
||||
if (offroad) {
|
||||
if (recorder) recorder->stop();
|
||||
|
||||
roadName = "";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -586,7 +587,7 @@ void AnnotatedCameraWidget::updateState(const UIState &s) {
|
||||
steeringTorqueEps = car_state.getSteeringTorqueEps();
|
||||
bearingAccuracyDeg = gpsLocationExternal.getBearingAccuracyDeg();
|
||||
bearingDeg = gpsLocationExternal.getBearingDeg();
|
||||
torquedUseParams = s.scene.live_torque_toggle && !s.scene.custom_torque_toggle;
|
||||
torquedUseParams = ltp.getUseParams() || s.scene.live_torque_toggle;
|
||||
latAccelFactorFiltered = ltp.getLatAccelFactorFiltered();
|
||||
frictionCoefficientFiltered = ltp.getFrictionCoefficientFiltered();
|
||||
liveValid = ltp.getLiveValid();
|
||||
@@ -642,11 +643,11 @@ void AnnotatedCameraWidget::updateState(const UIState &s) {
|
||||
showDebugUI = s.scene.show_debug_ui;
|
||||
|
||||
const auto lmd = sm["liveMapData"].getLiveMapData();
|
||||
QString road_name = QString::fromStdString(lmd.getCurrentRoadName());
|
||||
|
||||
const auto data_type = int(lmd.getDataType());
|
||||
const QString data_type_draw(data_type == 2 ? "🌐 " : "");
|
||||
roadName = !road_name.isEmpty() ? data_type_draw + road_name : "";
|
||||
roadName = QString::fromStdString(lmd.getCurrentRoadName());
|
||||
roadName = !roadName.isEmpty() ? data_type_draw + roadName : "";
|
||||
|
||||
float speed_limit_slc = lp.getSpeedLimit() * (s.scene.is_metric ? MS_TO_KPH : MS_TO_MPH);
|
||||
const float speed_limit_offset = lp.getSpeedLimitOffset() * (s.scene.is_metric ? MS_TO_KPH : MS_TO_MPH);
|
||||
@@ -1417,7 +1418,7 @@ void AnnotatedCameraWidget::drawE2eStatus(QPainter &p, int x, int y, int w, int
|
||||
p.drawEllipse(e2eStatusIcon);
|
||||
}
|
||||
|
||||
void AnnotatedCameraWidget::drawLeftTurnSignal(QPainter &painter, int x, int y, int state) {
|
||||
void AnnotatedCameraWidget::drawLeftTurnSignal(QPainter &painter, int x, int y, int circle_size, int state) {
|
||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||
|
||||
QColor circle_color, circle_color_0, circle_color_1;
|
||||
@@ -1443,17 +1444,16 @@ void AnnotatedCameraWidget::drawLeftTurnSignal(QPainter &painter, int x, int y,
|
||||
}
|
||||
|
||||
// Draw the circle
|
||||
int circleSize = 120;
|
||||
int circleX = x;
|
||||
int circleY = y;
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(circle_color);
|
||||
painter.drawEllipse(circleX, circleY, circleSize, circleSize);
|
||||
painter.drawEllipse(circleX, circleY, circle_size, circle_size);
|
||||
|
||||
// Draw the arrow
|
||||
int arrowSize = 50;
|
||||
int arrowX = circleX + (circleSize - arrowSize) / 4;
|
||||
int arrowY = circleY + (circleSize - arrowSize) / 2;
|
||||
int arrowX = circleX + (circle_size - arrowSize) / 4;
|
||||
int arrowY = circleY + (circle_size - arrowSize) / 2;
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(arrow_color);
|
||||
|
||||
@@ -1474,7 +1474,7 @@ void AnnotatedCameraWidget::drawLeftTurnSignal(QPainter &painter, int x, int y,
|
||||
painter.fillRect(tailRect, arrow_color);
|
||||
}
|
||||
|
||||
void AnnotatedCameraWidget::drawRightTurnSignal(QPainter &painter, int x, int y, int state) {
|
||||
void AnnotatedCameraWidget::drawRightTurnSignal(QPainter &painter, int x, int y, int circle_size, int state) {
|
||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||
|
||||
QColor circle_color, circle_color_0, circle_color_1;
|
||||
@@ -1501,17 +1501,16 @@ void AnnotatedCameraWidget::drawRightTurnSignal(QPainter &painter, int x, int y,
|
||||
|
||||
|
||||
// Draw the circle
|
||||
int circleSize = 120;
|
||||
int circleX = x;
|
||||
int circleY = y;
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(circle_color);
|
||||
painter.drawEllipse(circleX, circleY, circleSize, circleSize);
|
||||
painter.drawEllipse(circleX, circleY, circle_size, circle_size);
|
||||
|
||||
// Draw the arrow
|
||||
int arrowSize = 50;
|
||||
int arrowX = circleX + (circleSize - arrowSize) / 2 + (arrowSize / 2.5) - 3;
|
||||
int arrowY = circleY + (circleSize - arrowSize) / 2;
|
||||
int arrowX = circleX + (circle_size - arrowSize) / 2 + (arrowSize / 2.5) - 3;
|
||||
int arrowY = circleY + (circle_size - arrowSize) / 2;
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(arrow_color);
|
||||
|
||||
@@ -1966,11 +1965,13 @@ void AnnotatedCameraWidget::paintEvent(QPaintEvent *event) {
|
||||
if (left_blinker || right_blinker) {
|
||||
blinker_frame++;
|
||||
int state = blinkerPulse(blinker_frame);
|
||||
int blinker_x = splitPanelVisible ? 150 : 180;
|
||||
int blinker_y = splitPanelVisible ? 220 : 90;
|
||||
if (left_blinker) {
|
||||
drawLeftTurnSignal(painter, rect().center().x() - 300, splitPanelVisible ? 210 : 90, state);
|
||||
drawLeftTurnSignal(painter, rect().center().x() - (blinker_x + blinker_size), blinker_y, blinker_size, state);
|
||||
}
|
||||
if (right_blinker) {
|
||||
drawRightTurnSignal(painter, rect().center().x() + 180, splitPanelVisible ? 210 : 90, state);
|
||||
drawRightTurnSignal(painter, rect().center().x() + blinker_x, blinker_y, blinker_size, state);
|
||||
}
|
||||
} else {
|
||||
blinker_frame = 0;
|
||||
|
||||
@@ -20,6 +20,7 @@ const int btn_size = 192;
|
||||
const int img_size = (btn_size / 4) * 3;
|
||||
const int subsign_img_size = 35;
|
||||
|
||||
const int blinker_size = 120;
|
||||
|
||||
// ***** onroad widgets *****
|
||||
class OnroadAlerts : public QWidget {
|
||||
@@ -117,8 +118,8 @@ private:
|
||||
|
||||
void drawE2eStatus(QPainter &p, int x, int y, int w, int h, int e2e_long_status);
|
||||
|
||||
void drawLeftTurnSignal(QPainter &painter, int x, int y, int state);
|
||||
void drawRightTurnSignal(QPainter &painter, int x, int y, int state);
|
||||
void drawLeftTurnSignal(QPainter &painter, int x, int y, int circle_size, int state);
|
||||
void drawRightTurnSignal(QPainter &painter, int x, int y, int circle_size, int state);
|
||||
int blinkerPulse(int frame);
|
||||
void updateButtonsLayout();
|
||||
|
||||
@@ -170,7 +171,7 @@ private:
|
||||
|
||||
bool showDebugUI = false;
|
||||
|
||||
QString roadName;
|
||||
QString roadName = "";
|
||||
|
||||
bool showSpeedLimit = false;
|
||||
float speedLimitSLC;
|
||||
|
||||
@@ -60,14 +60,14 @@ OnroadSettings::OnroadSettings(bool closeable, QWidget *parent) : QFrame(parent)
|
||||
options_layout->setContentsMargins(0, 32, 0, 32);
|
||||
options_layout->setSpacing(20);
|
||||
|
||||
// Dynamic Lane Profile
|
||||
options_layout->addWidget(dlp_widget = new OptionWidget(this));
|
||||
QObject::connect(dlp_widget, &OptionWidget::updateParam, this, &OnroadSettings::changeDynamicLaneProfile);
|
||||
|
||||
// Gap Adjust Cruise
|
||||
options_layout->addWidget(gac_widget = new OptionWidget(this));
|
||||
QObject::connect(gac_widget, &OptionWidget::updateParam, this, &OnroadSettings::changeGapAdjustCruise);
|
||||
|
||||
// Dynamic Lane Profile
|
||||
options_layout->addWidget(dlp_widget = new OptionWidget(this));
|
||||
QObject::connect(dlp_widget, &OptionWidget::updateParam, this, &OnroadSettings::changeDynamicLaneProfile);
|
||||
|
||||
// Speed Limit Control
|
||||
options_layout->addWidget(slc_widget = new OptionWidget(this));
|
||||
QObject::connect(slc_widget, &OptionWidget::updateParam, this, &OnroadSettings::changeSpeedLimitControl);
|
||||
@@ -147,6 +147,12 @@ void OnroadSettings::refresh() {
|
||||
param_watcher->addParam("LongitudinalPersonality");
|
||||
param_watcher->addParam("SpeedLimitControl");
|
||||
|
||||
UIScene &scene = uiState()->scene;
|
||||
// Update live params on Feature Status on camera view
|
||||
scene.dynamic_lane_profile = std::atoi(params.get("DynamicLaneProfile").c_str());
|
||||
scene.longitudinal_personality = std::atoi(params.get("LongitudinalPersonality").c_str());
|
||||
scene.speed_limit_control_enabled = params.getBool("SpeedLimitControl");
|
||||
|
||||
if (!isVisible()) return;
|
||||
|
||||
setUpdatesEnabled(false);
|
||||
|
||||
@@ -183,6 +183,8 @@ public:
|
||||
refresh();
|
||||
}
|
||||
|
||||
bool isToggled() { return params.getBool(key); }
|
||||
|
||||
private:
|
||||
void setIcon(bool state) {
|
||||
if (state && !active_icon_pixmap.isNull()) {
|
||||
|
||||
+2
-11
@@ -252,6 +252,8 @@ void ui_update_params(UIState *s) {
|
||||
s->scene.e2e_long_alert_light = params.getBool("EndToEndLongAlertLight");
|
||||
s->scene.e2e_long_alert_lead = params.getBool("EndToEndLongAlertLead");
|
||||
s->scene.e2e_long_alert_ui = params.getBool("EndToEndLongAlertUI");
|
||||
s->scene.map_3d_buildings = params.getBool("Map3DBuildings");
|
||||
s->scene.live_torque_toggle = params.getBool("LiveTorque");
|
||||
|
||||
// Handle Onroad Screen Off params
|
||||
if (s->scene.onroadScreenOff > 0) {
|
||||
@@ -304,23 +306,12 @@ void UIState::updateStatus() {
|
||||
if (scene.started) {
|
||||
status = STATUS_DISENGAGED;
|
||||
scene.started_frame = sm->frame;
|
||||
scene.live_torque_toggle = params.getBool("LiveTorque");
|
||||
scene.custom_torque_toggle = params.getBool("CustomTorqueLateral");
|
||||
}
|
||||
started_prev = scene.started;
|
||||
emit offroadTransition(!scene.started);
|
||||
}
|
||||
|
||||
if (scene.started) {
|
||||
// Update live params when the camera view is on
|
||||
{
|
||||
if (sm->frame % (UI_FREQ / 2) == 0) { // Update every 2 Hz
|
||||
scene.dynamic_lane_profile = std::atoi(params.get("DynamicLaneProfile").c_str());
|
||||
scene.longitudinal_personality = std::atoi(params.get("LongitudinalPersonality").c_str());
|
||||
scene.speed_limit_control_enabled = params.getBool("SpeedLimitControl");
|
||||
}
|
||||
}
|
||||
|
||||
// Auto hide UI button state machine
|
||||
{
|
||||
if (scene.button_auto_hide) {
|
||||
|
||||
+2
-1
@@ -217,7 +217,6 @@ typedef struct UIScene {
|
||||
int dev_ui_info;
|
||||
int rn_offset;
|
||||
bool live_torque_toggle;
|
||||
bool custom_torque_toggle;
|
||||
|
||||
bool touch_to_wake = false;
|
||||
int sleep_btn = -1;
|
||||
@@ -237,6 +236,8 @@ typedef struct UIScene {
|
||||
float mads_path_range = DRIVING_PATH_WIDE - DRIVING_PATH_NARROW; // 0.9 - 0.25 = 0.65
|
||||
|
||||
bool onroad_settings_visible;
|
||||
|
||||
bool map_3d_buildings;
|
||||
} UIScene;
|
||||
|
||||
class UIState : public QObject {
|
||||
|
||||
@@ -5,8 +5,10 @@ import secrets
|
||||
import threading
|
||||
import time
|
||||
from flask import Flask, render_template, Response, request, send_from_directory, session, redirect, url_for
|
||||
import system.fleetmanager.helpers as fleet
|
||||
from system.loggerd.config import ROOT as REALDATA
|
||||
from openpilot.common.realtime import set_core_affinity
|
||||
import openpilot.system.fleetmanager.helpers as fleet
|
||||
from openpilot.system.hardware.hw import Paths
|
||||
from openpilot.system.swaglog import cloudlog
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@@ -41,7 +43,7 @@ def login():
|
||||
def full(cameratype, route):
|
||||
chunk_size = 1024 * 512 # 5KiB
|
||||
file_name = cameratype + (".ts" if cameratype == "qcamera" else ".hevc")
|
||||
vidlist = "|".join(REALDATA + "/" + segment + "/" + file_name for segment in fleet.segments_in_route(route))
|
||||
vidlist = "|".join(Paths.log_root() + "/" + segment + "/" + file_name for segment in fleet.segments_in_route(route))
|
||||
|
||||
def generate_buffered_stream():
|
||||
with fleet.ffmpeg_mp4_concat_wrap_process_builder(vidlist, cameratype, chunk_size) as process:
|
||||
@@ -55,7 +57,7 @@ def full(cameratype, route):
|
||||
def fcamera(cameratype, segment):
|
||||
if not fleet.is_valid_segment(segment):
|
||||
return render_template("error.html", error="invalid segment")
|
||||
file_name = REALDATA + "/" + segment + "/" + cameratype + (".ts" if cameratype == "qcamera" else ".hevc")
|
||||
file_name = Paths.log_root() + "/" + segment + "/" + cameratype + (".ts" if cameratype == "qcamera" else ".hevc")
|
||||
return Response(fleet.ffmpeg_mp4_wrap_process_builder(file_name).stdout.read(), status=200, mimetype='video/mp4')
|
||||
|
||||
|
||||
@@ -153,6 +155,10 @@ def update_pin():
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
set_core_affinity([0, 1, 2, 3])
|
||||
except Exception:
|
||||
cloudlog.exception("fleet_manager: failed to set core affinity")
|
||||
app.secret_key = secrets.token_hex(32)
|
||||
schedule_pin_generate()
|
||||
app.run(host="0.0.0.0", port=5050)
|
||||
|
||||
@@ -3,10 +3,10 @@ import subprocess
|
||||
from flask import render_template, request, session
|
||||
from functools import wraps
|
||||
from pathlib import Path
|
||||
from common.params import Params
|
||||
from system.hardware import PC
|
||||
from system.loggerd.config import ROOT as REALDATA
|
||||
from system.loggerd.uploader import listdir_by_creation
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.system.hardware import PC
|
||||
from openpilot.system.hardware.hw import Paths
|
||||
from openpilot.system.loggerd.uploader import listdir_by_creation
|
||||
from tools.lib.route import SegmentName
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ def list_files(path):
|
||||
|
||||
def is_valid_segment(segment):
|
||||
try:
|
||||
segment_to_segment_name(REALDATA, segment)
|
||||
segment_to_segment_name(Paths.log_root(), segment)
|
||||
return True
|
||||
except AssertionError:
|
||||
return False
|
||||
@@ -50,9 +50,9 @@ def segment_to_segment_name(data_dir, segment):
|
||||
|
||||
def all_segment_names():
|
||||
segments = []
|
||||
for segment in listdir_by_creation(REALDATA):
|
||||
for segment in listdir_by_creation(Paths.log_root()):
|
||||
try:
|
||||
segments.append(segment_to_segment_name(REALDATA, segment))
|
||||
segments.append(segment_to_segment_name(Paths.log_root(), segment))
|
||||
except AssertionError:
|
||||
pass
|
||||
return segments
|
||||
|
||||
Reference in New Issue
Block a user