Merge branch 'dev-priv/master' into subaru-gen2-torque-increase

# Conflicts:
#	panda
This commit is contained in:
Jason Wen
2023-09-29 11:01:05 -04:00
48 changed files with 622 additions and 230 deletions
+29 -3
View File
@@ -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
View File
@@ -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
+1
View File
@@ -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
+2 -1
View File
@@ -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
+2 -1
View File
@@ -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
+6 -5
View File
@@ -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)
+28 -2
View File
@@ -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),
+14 -3
View File
@@ -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
+92 -1
View File
@@ -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
+9 -1
View File
@@ -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:
+6 -1
View File
@@ -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
+64
View File
@@ -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)
+4
View File
@@ -60,6 +60,10 @@ class SubaruFlags(IntFlag):
SEND_INFOTAINMENT = 1
class SubaruFlagsSP(IntFlag):
SP_SUBARU_SNG = 1
class CanBus:
main = 0
alt = 1
+5 -2
View File
@@ -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
+3 -1
View File
@@ -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
+24 -1
View File
@@ -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
+11 -5
View File
@@ -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:
+4
View File
@@ -46,6 +46,10 @@ class ToyotaFlags(IntFlag):
DISABLE_RADAR = 4
class ToyotaFlagsSP(IntFlag):
SP_ZSS = 1
class CAR:
# Toyota
ALPHARD_TSS2 = "TOYOTA ALPHARD 2020"
+5 -2
View File
@@ -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")
+26 -6
View File
@@ -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
+7 -5
View File
@@ -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()
+2 -3
View File
@@ -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,
+11 -2
View File
@@ -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__":
+5 -1
View File
@@ -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()
+10 -1
View File
@@ -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:
+1 -4
View File
@@ -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()
+1 -1
View File
@@ -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),
+5 -1
View File
@@ -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
+6 -2
View File
@@ -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)
+6
View File
@@ -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
View File
@@ -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())
+2
View File
@@ -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:
+4 -4
View File
@@ -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);
+43
View File
@@ -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) {
+1 -1
View File
@@ -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";
+3 -2
View File
@@ -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);
}
+105 -84
View File
@@ -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
View File
@@ -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;
+4 -3
View File
@@ -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;
+10 -4
View File
@@ -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);
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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 {
+10 -4
View File
@@ -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)
+7 -7
View File
@@ -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