From ac7d86d292eccabbdf64f04821948060a128ada4 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 23 Sep 2023 01:26:09 -0400 Subject: [PATCH 01/35] navd: Auto detect custom Mapbox token (#285) * navd: Auto detect custom Mapbox token * cleanup --- common/params.cc | 1 - selfdrive/navd/navd.py | 4 ++-- selfdrive/ui/qt/home.cc | 8 +++---- selfdrive/ui/qt/maps/map_helpers.h | 2 +- .../ui/qt/offroad/sunnypilot_settings.cc | 21 ------------------- selfdrive/ui/qt/onroad.cc | 3 +-- 6 files changed, 8 insertions(+), 31 deletions(-) diff --git a/common/params.cc b/common/params.cc index 59f6ca1816..1c791fdf1a 100644 --- a/common/params.cc +++ b/common/params.cc @@ -224,7 +224,6 @@ std::unordered_map keys = { {"CarModelText", PERSISTENT}, {"ChevronInfo", PERSISTENT}, {"CustomBootScreen", PERSISTENT}, - {"CustomMapbox", PERSISTENT}, {"CustomMapboxTokenPk", PERSISTENT}, {"CustomMapboxTokenSk", PERSISTENT}, {"CustomOffsets", PERSISTENT}, diff --git a/selfdrive/navd/navd.py b/selfdrive/navd/navd.py index fb9f0a3ee0..0d6306745a 100755 --- a/selfdrive/navd/navd.py +++ b/selfdrive/navd/navd.py @@ -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 self.params.get("CustomMapboxTokenSk") is not None or "MAPBOX_TOKEN" in os.environ: + self.mapbox_token = self.params.get("CustomMapboxTokenSk") if self.params.get("CustomMapboxTokenSk") is not None else os.environ["MAPBOX_TOKEN"] self.mapbox_host = "https://api.mapbox.com" else: try: diff --git a/selfdrive/ui/qt/home.cc b/selfdrive/ui/qt/home.cc index 26fde649e7..fcb7626430 100644 --- a/selfdrive/ui/qt/home.cc +++ b/selfdrive/ui/qt/home.cc @@ -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); diff --git a/selfdrive/ui/qt/maps/map_helpers.h b/selfdrive/ui/qt/maps/map_helpers.h index d0dd65e7a6..b72c301f4f 100644 --- a/selfdrive/ui/qt/maps/map_helpers.h +++ b/selfdrive/ui/qt/maps/map_helpers.h @@ -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"; diff --git a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc index 6ce6c7fdf6..7b023c588d 100644 --- a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc +++ b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc @@ -635,19 +635,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
" - "%2
" - "%3
" - "

%4

") - .arg(tr("Enable built-in navigation on sunnypilot, powered by Mapbox.")) - .arg(tr("Access via the web interface: \"http://: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"), @@ -701,14 +688,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(); - } }); } diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index 82c0ed4f0b..ceb8057bbd 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -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; From c514823c94a38c2f74bbb6c8c52fc2518a4663af Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 23 Sep 2023 01:59:16 -0400 Subject: [PATCH 02/35] navd: Prioritize comma Prime Mapbox token (#286) --- selfdrive/navd/navd.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/selfdrive/navd/navd.py b/selfdrive/navd/navd.py index 0d6306745a..6318336699 100755 --- a/selfdrive/navd/navd.py +++ b/selfdrive/navd/navd.py @@ -48,8 +48,8 @@ class RouteEngine: self.reroute_counter = 0 - if self.params.get("CustomMapboxTokenSk") is not None or "MAPBOX_TOKEN" in os.environ: - self.mapbox_token = self.params.get("CustomMapboxTokenSk") if self.params.get("CustomMapboxTokenSk") is not None 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) From 9308c1682319722773e16917e6d73d3bd73314f9 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 23 Sep 2023 09:43:29 -0400 Subject: [PATCH 03/35] Core management (#232) * set core affinity and priority for gpxd and gpx_uploader * use higher cores * 4 is available offroad * sync them all * set for fleet manager * only upload gpx while offroad --- selfdrive/gpxd/gpx_uploader.py | 13 +++++++++++-- selfdrive/gpxd/gpxd.py | 6 +++++- selfdrive/manager/process_config.py | 2 +- selfdrive/mapd/mapd.py | 6 +++++- selfdrive/navd/otisserv.py | 6 ++++++ system/fleetmanager/fleet_manager.py | 6 ++++++ 6 files changed, 34 insertions(+), 5 deletions(-) diff --git a/selfdrive/gpxd/gpx_uploader.py b/selfdrive/gpxd/gpx_uploader.py index bb78c65d0b..d02889d512 100644 --- a/selfdrive/gpxd/gpx_uploader.py +++ b/selfdrive/gpxd/gpx_uploader.py @@ -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__": diff --git a/selfdrive/gpxd/gpxd.py b/selfdrive/gpxd/gpxd.py index 4c463c485a..0b69b4b65f 100644 --- a/selfdrive/gpxd/gpxd.py +++ b/selfdrive/gpxd/gpxd.py @@ -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() diff --git a/selfdrive/manager/process_config.py b/selfdrive/manager/process_config.py index bcc5ff4faf..fd1ba29868 100644 --- a/selfdrive/manager/process_config.py +++ b/selfdrive/manager/process_config.py @@ -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), diff --git a/selfdrive/mapd/mapd.py b/selfdrive/mapd/mapd.py index db40c16abb..42bcae50cd 100644 --- a/selfdrive/mapd/mapd.py +++ b/selfdrive/mapd/mapd.py @@ -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 diff --git a/selfdrive/navd/otisserv.py b/selfdrive/navd/otisserv.py index 1dbf2a5335..33e51b86e1 100644 --- a/selfdrive/navd/otisserv.py +++ b/selfdrive/navd/otisserv.py @@ -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: diff --git a/system/fleetmanager/fleet_manager.py b/system/fleetmanager/fleet_manager.py index bf1ed190a8..c48a4ac451 100755 --- a/system/fleetmanager/fleet_manager.py +++ b/system/fleetmanager/fleet_manager.py @@ -5,6 +5,8 @@ import secrets import threading import time from flask import Flask, render_template, Response, request, send_from_directory, session, redirect, url_for +from common.realtime import set_core_affinity +from system.swaglog import cloudlog import system.fleetmanager.helpers as fleet from system.loggerd.config import ROOT as REALDATA @@ -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) From d20dbdf12b04360580e5e72fb0f497ed822f78fd Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Fri, 22 Sep 2023 23:53:46 -0400 Subject: [PATCH 04/35] Update CHANGELOGS.md --- CHANGELOGS.md | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/CHANGELOGS.md b/CHANGELOGS.md index 787da4b9a1..4b804ef28d 100644 --- a/CHANGELOGS.md +++ b/CHANGELOGS.md @@ -1,10 +1,29 @@ -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❗: Wide camera view when the steering angle is more than 45° -* Custom Stock Longitudinal Control - * RE-ENABLED: Hyundai/Kia/Genesis CAN-FD platforms +* 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 sunnypilot - 0.9.4.1 (2023-08-11) ======================== From 3b776937fab7402e3eb38860cd2fa774635cc0aa Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 23 Sep 2023 01:31:38 -0400 Subject: [PATCH 05/35] Sync params --- common/params.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/params.cc b/common/params.cc index 986ed4474b..d5596a6b55 100644 --- a/common/params.cc +++ b/common/params.cc @@ -224,7 +224,6 @@ std::unordered_map keys = { {"CarModelText", PERSISTENT}, {"ChevronInfo", PERSISTENT}, {"CustomBootScreen", PERSISTENT}, - {"CustomMapbox", PERSISTENT}, {"CustomMapboxTokenPk", PERSISTENT}, {"CustomMapboxTokenSk", PERSISTENT}, {"CustomOffsets", PERSISTENT}, @@ -234,6 +233,8 @@ std::unordered_map keys = { {"DevUIInfo", PERSISTENT}, {"DisableOnroadUploads", PERSISTENT}, {"DisengageLateralOnBrake", PERSISTENT}, + {"DynamicExperimentalControl", PERSISTENT}, + {"DynamicExperimentalControlToggle", PERSISTENT}, {"DynamicLaneProfile", PERSISTENT}, {"DynamicLaneProfileToggle", PERSISTENT}, {"EnableAmap", PERSISTENT}, From 231f2331aa5aad93f9822088efbf15dd8fbfd7ef Mon Sep 17 00:00:00 2001 From: Yassine Date: Fri, 15 Sep 2023 16:40:42 -0400 Subject: [PATCH 06/35] Gap Adjust Cruise: Fix param typing --- selfdrive/car/interfaces.py | 2 +- selfdrive/car/toyota/interface.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 2e1156d849..b9af5afc83 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -474,7 +474,7 @@ class CarInterfaceBase(ABC): if not self.CP.openpilotLongitudinalControl: CS.gac_tr = 2 CS.gac_tr_cluster = gac_default - put_nonblocking("LongitudinalPersonality", 2) + put_nonblocking("LongitudinalPersonality", "2") return cs_out, CS if gac_button: self.gac_button_counter += 1 diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index 20ae720c1c..f8ce1598e7 100644 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -324,7 +324,7 @@ 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) + put_nonblocking("LongitudinalPersonality", "2") else: gap_dist_button = bool(self.CS.gap_dist_button) if gap_dist_button: From acdfbbb35951f0cb5e111ce0b3d712d0aef8ced5 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 23 Sep 2023 13:53:46 -0400 Subject: [PATCH 07/35] Gap Adjust Cruise: Fix unnecessary I/O (#287) --- selfdrive/car/interfaces.py | 5 +++-- selfdrive/car/toyota/interface.py | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index b9af5afc83..c71d08bb99 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -472,9 +472,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 diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index f8ce1598e7..3a24cdd623 100644 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -324,7 +324,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 CS.gac_tr != 2: + CS.gac_tr = 2 + put_nonblocking("LongitudinalPersonality", "2") else: gap_dist_button = bool(self.CS.gap_dist_button) if gap_dist_button: From c5a85ba83152e07a182534f86cdf385ea45db87f Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 23 Sep 2023 05:18:36 -0400 Subject: [PATCH 08/35] Gap Adjust Cruise: Fix object reference --- selfdrive/car/toyota/interface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index 3a24cdd623..54f6c7b206 100644 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -324,8 +324,8 @@ 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 - if CS.gac_tr != 2: - CS.gac_tr = 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) From 07e1b55df2baa7f6fa818afe78c842e1c13ae70a Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 23 Sep 2023 08:36:17 -0400 Subject: [PATCH 09/35] Update CHANGELOGS.md --- CHANGELOGS.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGELOGS.md b/CHANGELOGS.md index 4b804ef28d..2168dd22a8 100644 --- a/CHANGELOGS.md +++ b/CHANGELOGS.md @@ -3,24 +3,24 @@ sunnypilot - 0.9.5.1 (2023-09-27) * 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) + * 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 + * GAP - Driving Personality + * DLP - Dynamic Lane Profile + * SLC - Speed Limit Control * NEW❗: Wide camera view when the steering angle is more than 45° * 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: 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 + * RE-ENABLED: Hyundai/Kia/Genesis CAN-FD platforms * UPDATED: Auto-detect custom Mapbox token - * REMOVED: "Enable Mapbox Navigation" toggle + * 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 From da58d5114bcdea82b443614515442e986602bc6a Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 23 Sep 2023 10:33:33 -0400 Subject: [PATCH 10/35] Fleet Manager: paths cleanup (#216) --- system/fleetmanager/fleet_manager.py | 8 ++++---- system/fleetmanager/helpers.py | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/system/fleetmanager/fleet_manager.py b/system/fleetmanager/fleet_manager.py index 755f04d4c7..c1e4818fcf 100755 --- a/system/fleetmanager/fleet_manager.py +++ b/system/fleetmanager/fleet_manager.py @@ -3,8 +3,8 @@ import os import random import secrets 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 +import openpilot.system.fleetmanager.helpers as fleet +from openpilot.system.hardware.hw import Paths app = Flask(__name__) @@ -39,7 +39,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: @@ -53,7 +53,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') diff --git a/system/fleetmanager/helpers.py b/system/fleetmanager/helpers.py index 998dd8fe6c..de4172553d 100644 --- a/system/fleetmanager/helpers.py +++ b/system/fleetmanager/helpers.py @@ -3,9 +3,9 @@ import subprocess from flask import render_template, request, session from functools import wraps from pathlib import Path -from system.hardware import PC -from system.loggerd.config import ROOT as REALDATA -from system.loggerd.uploader import listdir_by_creation +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 @@ -36,7 +36,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 @@ -49,9 +49,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 From 3b1ad57ee2302aa56fc0041e59212d7aff680606 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 23 Sep 2023 14:12:49 -0400 Subject: [PATCH 11/35] sunnypilot: Fix upstream conflict --- selfdrive/car/hyundai/carstate.py | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/car/hyundai/carstate.py b/selfdrive/car/hyundai/carstate.py index 6f9f66a925..fc36ce27f8 100644 --- a/selfdrive/car/hyundai/carstate.py +++ b/selfdrive/car/hyundai/carstate.py @@ -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 From fb9a9901848642f37b1fc2eca807c5ad756d3a7a Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sun, 24 Sep 2023 00:09:50 -0400 Subject: [PATCH 12/35] FCR: sync with upstream supported car platforms --- selfdrive/car/sunnypilot_carname.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/selfdrive/car/sunnypilot_carname.json b/selfdrive/car/sunnypilot_carname.json index e22c2a13cf..7ef5e3c8af 100644 --- a/selfdrive/car/sunnypilot_carname.json +++ b/selfdrive/car/sunnypilot_carname.json @@ -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", From ab66732ee9d897ad65d0cf4ded1f7f7a87f9f841 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sun, 24 Sep 2023 11:33:19 -0400 Subject: [PATCH 13/35] ui: Some comments in sunnypilot settings (#291) --- selfdrive/ui/qt/offroad/sunnypilot_settings.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc index 7b023c588d..ae8c3b0281 100644 --- a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc +++ b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc @@ -276,7 +276,7 @@ SPControlsPanel::SPControlsPanel(QWidget *parent) : ListWidget(parent) { std::vector updateTogglesNamesAlert{ "CustomTorqueLateral", "LiveTorque" }; - // toggle names to trigger updateToggles() when toggleFlipped and display ConfirmationDialog::alert + // toggle for offroadTransition when going onroad/offroad std::vector toggleOffroad{ "EnableMads", "DisengageLateralOnBrake", "AccMadsCombo", "MadsCruiseMain", "BelowSpeedPause", "EnforceTorqueLateral", "CustomTorqueLateral", "LiveTorque" @@ -548,6 +548,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 +560,7 @@ SPVehiclesTogglesPanel::SPVehiclesTogglesPanel(SPVehiclesPanel *parent) : ListWi hkgSmoothStop->setConfirmation(true, false); addItem(hkgSmoothStop); + // Toyota/Lexus addItem(new LabelControl(tr("Toyota/Lexus"))); stockLongToyota = new ParamControl( "StockLongToyota", From 8d75ca9a7b39b73d14921afc0054822f007f1b34 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Mon, 25 Sep 2023 01:14:48 -0400 Subject: [PATCH 14/35] Retain hotspot/tether: Fix initialization (#293) * Retain hotspot/tether: Fix initialization * init before manager starts * simpler --- common/params.cc | 1 + selfdrive/manager/manager.py | 6 +++--- selfdrive/ui/qt/network/networking.cc | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/common/params.cc b/common/params.cc index 448170d1f5..f661f1e7c1 100644 --- a/common/params.cc +++ b/common/params.cc @@ -255,6 +255,7 @@ std::unordered_map keys = { {"HideVEgoUi", PERSISTENT}, {"HkgSmoothStop", PERSISTENT}, {"HotspotOnBoot", PERSISTENT}, + {"HotspotOnBootConfirmed", PERSISTENT}, {"LastCarModel", PERSISTENT}, {"LastSpeedLimitSignTap", PERSISTENT}, {"LiveTorque", PERSISTENT}, diff --git a/selfdrive/manager/manager.py b/selfdrive/manager/manager.py index 8f6f29d07a..471d3db828 100755 --- a/selfdrive/manager/manager.py +++ b/selfdrive/manager/manager.py @@ -267,6 +267,9 @@ def main() -> None: # SystemExit on sigterm signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit(1)) + if Params().get_bool("HotspotOnBoot") and Params().get_bool("HotspotOnBootConfirmed"): + os.system('nmcli con up Hotspot') + try: manager_thread() except Exception: @@ -286,9 +289,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() diff --git a/selfdrive/ui/qt/network/networking.cc b/selfdrive/ui/qt/network/networking.cc index e7865b11a7..6d81e78410 100644 --- a/selfdrive/ui/qt/network/networking.cc +++ b/selfdrive/ui/qt/network/networking.cc @@ -201,7 +201,7 @@ void AdvancedNetworking::refresh() { } void AdvancedNetworking::toggleTethering(bool enabled) { - params.putBool("HotspotOnBoot", enabled); + params.putBool("HotspotOnBootConfirmed", enabled); wifi->setTetheringEnabled(enabled); tetheringToggle->setEnabled(false); } From 7445c42b5de5eecdceda786da421dacea4020bdc Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Mon, 25 Sep 2023 10:48:39 -0400 Subject: [PATCH 15/35] Retain hotspot/tether: Initialize after modem is configured (#295) --- selfdrive/manager/manager.py | 3 --- selfdrive/thermald/thermald.py | 2 ++ selfdrive/ui/qt/network/networking.cc | 3 ++- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/selfdrive/manager/manager.py b/selfdrive/manager/manager.py index 471d3db828..031e7564e8 100755 --- a/selfdrive/manager/manager.py +++ b/selfdrive/manager/manager.py @@ -267,9 +267,6 @@ def main() -> None: # SystemExit on sigterm signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit(1)) - if Params().get_bool("HotspotOnBoot") and Params().get_bool("HotspotOnBootConfirmed"): - os.system('nmcli con up Hotspot') - try: manager_thread() except Exception: diff --git a/selfdrive/thermald/thermald.py b/selfdrive/thermald/thermald.py index 32cfe11c39..256db7d061 100755 --- a/selfdrive/thermald/thermald.py +++ b/selfdrive/thermald/thermald.py @@ -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: diff --git a/selfdrive/ui/qt/network/networking.cc b/selfdrive/ui/qt/network/networking.cc index 6d81e78410..de75027a13 100644 --- a/selfdrive/ui/qt/network/networking.cc +++ b/selfdrive/ui/qt/network/networking.cc @@ -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("HotspotOnBootConfirmed"); + tetheringToggle = new ToggleControl(tr("Enable Tethering"), "", "", wifi->isTetheringEnabled() || set_hotspot_on_boot); list->addItem(tetheringToggle); QObject::connect(tetheringToggle, &ToggleControl::toggleFlipped, this, &AdvancedNetworking::toggleTethering); From 172d629393e7907d69485bddd209f1f95e4ed7b5 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Mon, 25 Sep 2023 11:44:26 -0400 Subject: [PATCH 16/35] Retain hotspot/tether: Check `HotspotOnBoot` toggle (#296) --- selfdrive/ui/qt/network/networking.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/ui/qt/network/networking.cc b/selfdrive/ui/qt/network/networking.cc index de75027a13..57c9973add 100644 --- a/selfdrive/ui/qt/network/networking.cc +++ b/selfdrive/ui/qt/network/networking.cc @@ -125,7 +125,7 @@ AdvancedNetworking::AdvancedNetworking(QWidget* parent, WifiManager* wifi): QWid ListWidget *list = new ListWidget(this); // Enable tethering layout - const bool set_hotspot_on_boot = params.getBool("HotspotOnBootConfirmed"); + 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); From 99d64ed1b49bf1176f4b15c2feef6183ff41df44 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Mon, 25 Sep 2023 12:45:15 -0400 Subject: [PATCH 17/35] ui: Sync Onroad Settings buttons with Onroad Feature Status (#297) --- selfdrive/ui/qt/onroad_settings.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/selfdrive/ui/qt/onroad_settings.cc b/selfdrive/ui/qt/onroad_settings.cc index cc74a620ee..3e26cc235c 100644 --- a/selfdrive/ui/qt/onroad_settings.cc +++ b/selfdrive/ui/qt/onroad_settings.cc @@ -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); From dd98954ce3a2d8352803ce39a9283353f57f7844 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Mon, 25 Sep 2023 14:45:27 -0400 Subject: [PATCH 18/35] Toyota: ZSS support (#292) * Toyota: ZSS support * comment --- CHANGELOGS.md | 1 + selfdrive/car/toyota/carstate.py | 25 ++++++++++++++++++++++++- selfdrive/car/toyota/interface.py | 12 ++++++++---- selfdrive/car/toyota/values.py | 4 ++++ 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/CHANGELOGS.md b/CHANGELOGS.md index 2168dd22a8..021fafc597 100644 --- a/CHANGELOGS.md +++ b/CHANGELOGS.md @@ -12,6 +12,7 @@ sunnypilot - 0.9.5.1 (2023-09-27) * DLP - Dynamic Lane Profile * SLC - Speed Limit Control * NEW❗: Wide camera view when the steering angle is more than 45° +* 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 diff --git a/selfdrive/car/toyota/carstate.py b/selfdrive/car/toyota/carstate.py index c012ff0065..88c8123229 100644 --- a/selfdrive/car/toyota/carstate.py +++ b/selfdrive/car/toyota/carstate.py @@ -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 diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index 54f6c7b206..c6bf4c8bd1 100644 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -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 diff --git a/selfdrive/car/toyota/values.py b/selfdrive/car/toyota/values.py index fd0a54b349..07def65d37 100644 --- a/selfdrive/car/toyota/values.py +++ b/selfdrive/car/toyota/values.py @@ -46,6 +46,10 @@ class ToyotaFlags(IntFlag): DISABLE_RADAR = 4 +class ToyotaFlagsSP(IntFlag): + SP_ZSS = 1 + + class CAR: # Toyota ALPHARD_TSS2 = "TOYOTA ALPHARD 2020" From 65b74b45c474b5794db08b3e360686ae53539255 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Mon, 25 Sep 2023 14:46:50 -0400 Subject: [PATCH 19/35] Toyota: Stop and Go hack implementation (#290) --- CHANGELOGS.md | 3 +++ common/params.cc | 1 + selfdrive/car/toyota/carcontroller.py | 4 +++- selfdrive/ui/qt/offroad/sunnypilot_settings.cc | 10 ++++++++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOGS.md b/CHANGELOGS.md index 021fafc597..e6066f7545 100644 --- a/CHANGELOGS.md +++ b/CHANGELOGS.md @@ -11,6 +11,9 @@ sunnypilot - 0.9.5.1 (2023-09-27) * GAP - Driving Personality * DLP - Dynamic Lane Profile * SLC - Speed Limit Control +* 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° * NEW❗: Toyota: ZSS support thanks to dragonpilot-community and ErichMoraga! * openpilot Longitudianl Control capable cars only diff --git a/common/params.cc b/common/params.cc index f661f1e7c1..c3142f324a 100644 --- a/common/params.cc +++ b/common/params.cc @@ -292,6 +292,7 @@ std::unordered_map keys = { {"TorqueDeadzoneDeg", PERSISTENT}, {"TorqueFriction", PERSISTENT}, {"TorqueMaxLatAccel", PERSISTENT}, + {"ToyotaSnG", PERSISTENT}, {"ToyotaTSS2Long", PERSISTENT}, {"TrueVEgoUi", PERSISTENT}, {"TurnSpeedControl", PERSISTENT}, diff --git a/selfdrive/car/toyota/carcontroller.py b/selfdrive/car/toyota/carcontroller.py index 8ce4270be6..1dc7e3926a 100644 --- a/selfdrive/car/toyota/carcontroller.py +++ b/selfdrive/car/toyota/carcontroller.py @@ -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 diff --git a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc index ae8c3b0281..850e2303bb 100644 --- a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc +++ b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc @@ -592,10 +592,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); }); } From 5cf452acdd9799e1209e262d4f255ca5caa5f4b9 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 26 Sep 2023 10:00:41 -0400 Subject: [PATCH 20/35] Hyundai: radar interface cleanup (#298) --- selfdrive/car/hyundai/radar_interface.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/selfdrive/car/hyundai/radar_interface.py b/selfdrive/car/hyundai/radar_interface.py index bf08e2d130..d8d0f6c9b4 100644 --- a/selfdrive/car/hyundai/radar_interface.py +++ b/selfdrive/car/hyundai/radar_interface.py @@ -10,11 +10,11 @@ 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: + messages = ("ESCC", 50) + return CANParser(DBC[CP.carFingerprint]['pt'], messages, 0) + else: return None messages = [(f"RADAR_TRACK_{addr:x}", 50) for addr in range(RADAR_START_ADDR, RADAR_START_ADDR + RADAR_MSG_COUNT)] From 934aa7acd236023bdb084d900037ecc4e6966cc8 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 26 Sep 2023 21:46:31 -0400 Subject: [PATCH 21/35] ui: Controls Panel: slight cleanup (#301) --- selfdrive/ui/qt/offroad/sunnypilot_settings.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc index 850e2303bb..f803b1b475 100644 --- a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc +++ b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc @@ -267,19 +267,18 @@ SPControlsPanel::SPControlsPanel(QWidget *parent) : ListWidget(parent) { // toggle names to trigger updateToggles() when toggleFlipped std::vector updateTogglesNames{ - "EnableMads", "CustomOffsets", "EnforceTorqueLateral", - "SpeedLimitPercOffset", "SpeedLimitControl" + "EnableMads", "CustomOffsets", "EnforceTorqueLateral", "SpeedLimitPercOffset", "SpeedLimitControl", + "CustomTorqueLateral", "LiveTorque" }; connect(dynamic_lane_profile, &DynamicLaneProfile::updateExternalToggles, this, &SPControlsPanel::updateToggles); - // toggle names to trigger updateToggles() when toggleFlipped and display ConfirmationDialog::alert + // toggle names to display ConfirmationDialog::alert std::vector updateTogglesNamesAlert{ "CustomTorqueLateral", "LiveTorque" }; // toggle for offroadTransition when going onroad/offroad std::vector toggleOffroad{ - "EnableMads", "DisengageLateralOnBrake", "AccMadsCombo", "MadsCruiseMain", "BelowSpeedPause", "EnforceTorqueLateral", - "CustomTorqueLateral", "LiveTorque" + "EnableMads", "DisengageLateralOnBrake", "AccMadsCombo", "MadsCruiseMain", "BelowSpeedPause", "EnforceTorqueLateral" }; // Controls: Camera Offset (cm) @@ -362,7 +361,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); }); } From 67208ee3722bd1a2edd6229bb85f981d79b69980 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 26 Sep 2023 23:00:10 -0400 Subject: [PATCH 22/35] ui: sunnypilot settings panels params cleanup (#302) --- .../ui/qt/offroad/sunnypilot_settings.cc | 34 +++++++++++-------- selfdrive/ui/qt/widgets/controls.h | 2 ++ 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc index f803b1b475..6173f71cd4 100644 --- a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc +++ b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc @@ -392,7 +392,7 @@ void SPControlsPanel::updateToggles() { std::vector 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()); } } @@ -402,44 +402,48 @@ void SPControlsPanel::updateToggles() { // toggle names to update when CustomOffsets is flipped std::vector 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 speed_limit_control = toggles["SpeedLimitControl"]; + auto speed_limit_perc_offset = toggles["SpeedLimitPercOffset"]; + // toggle names to update when EnforceTorqueLateral is flipped std::vector enforceTorqueGroup{"CustomTorqueLateral", "LiveTorque"}; 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 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 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")) { + if (enforce_torque_lateral->isToggled()) { + if (custom_torque_lateral->isToggled()) { live_torque->setEnabled(false); params.putBool("LiveTorque", false); } else { live_torque->setEnabled(true); } - if (params.getBool("LiveTorque")) { + if (live_torque->isToggled()) { custom_torque_lateral->setEnabled(false); params.putBool("CustomTorqueLateral", false); for (const auto& customTorqueControl : customTorqueGroup) { @@ -459,8 +463,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 { @@ -475,7 +479,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()) { @@ -484,7 +488,7 @@ void SPControlsPanel::updateToggles() { cereal::CarParams::Reader CP = cmsg.getRoot(); if (CP.getSteerControlType() == cereal::CarParams::SteerControlType::ANGLE) { - toggles["EnforceTorqueLateral"]->setEnabled(false); + enforce_torque_lateral->setEnabled(false); params.remove("EnforceTorqueLateral"); } } @@ -707,7 +711,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) @@ -1033,7 +1037,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) { @@ -1080,7 +1084,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() { diff --git a/selfdrive/ui/qt/widgets/controls.h b/selfdrive/ui/qt/widgets/controls.h index fe4742722c..44d7f49300 100644 --- a/selfdrive/ui/qt/widgets/controls.h +++ b/selfdrive/ui/qt/widgets/controls.h @@ -183,6 +183,8 @@ public: refresh(); } + bool isToggled() { return params.getBool(key); } + private: void setIcon(bool state) { if (state && !active_icon_pixmap.isNull()) { From 5dbecc7d38038b0f84f4cf6fee7b8a0718bcadfc Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Wed, 27 Sep 2023 02:10:44 -0400 Subject: [PATCH 23/35] Hyundai: radar interface fixups (#303) --- selfdrive/car/hyundai/radar_interface.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/selfdrive/car/hyundai/radar_interface.py b/selfdrive/car/hyundai/radar_interface.py index d8d0f6c9b4..05d368b817 100644 --- a/selfdrive/car/hyundai/radar_interface.py +++ b/selfdrive/car/hyundai/radar_interface.py @@ -12,10 +12,11 @@ RADAR_MSG_COUNT = 32 def get_radar_can_parser(CP): if DBC[CP.carFingerprint]['radar'] is None: if CP.spFlags & HyundaiFlagsSP.SP_ENHANCED_SCC: - messages = ("ESCC", 50) - return CANParser(DBC[CP.carFingerprint]['pt'], messages, 0) + 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) From c8cb9b3b751e9e270af522082e631a6f4fb5c4df Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Wed, 27 Sep 2023 02:27:34 -0400 Subject: [PATCH 24/35] ESCC: Disable `radarUnavailable` when detected (#304) --- selfdrive/car/hyundai/interface.py | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py index 85b9f06d7d..5da5b0f1ea 100644 --- a/selfdrive/car/hyundai/interface.py +++ b/selfdrive/car/hyundai/interface.py @@ -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 From 5bf6368947ae87a5dd153719151e33d994986cc5 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Wed, 27 Sep 2023 11:17:16 -0400 Subject: [PATCH 25/35] ui: Clear road name cache when going onroad (#305) * ui: Clear road name cache at UI initiation * clear on offroad --- selfdrive/ui/qt/onroad.cc | 10 ++++++---- selfdrive/ui/qt/onroad.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index ceb8057bbd..7287ca62b7 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -479,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 @@ -641,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); diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h index 7c729c5189..8630aa2f3c 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -170,7 +170,7 @@ private: bool showDebugUI = false; - QString roadName; + QString roadName = ""; bool showSpeedLimit = false; float speedLimitSLC; From a612ee07d782a63a3bdf378b07a7d9c15d0a5b59 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Wed, 27 Sep 2023 12:27:02 -0400 Subject: [PATCH 26/35] ui: Fix blinker positions when in split view (#306) * ui: Fix blinker positions when in split view * Shorten name --- selfdrive/ui/qt/onroad.cc | 24 ++++++++++++------------ selfdrive/ui/qt/onroad.h | 5 +++-- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index 7287ca62b7..76a8434b3b 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -1418,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; @@ -1444,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); @@ -1475,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; @@ -1502,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); @@ -1967,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; diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h index 8630aa2f3c..d679a74efe 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -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(); From 5214a703d72ea8f8b1fe855a62483c7e5522933a Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Wed, 27 Sep 2023 21:59:13 -0400 Subject: [PATCH 27/35] Sentry: Cleanup unncessary inits (#307) * Sentry: cleanup unncessary inits * unnecessary * unused * cleanup --- selfdrive/sentry.py | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/selfdrive/sentry.py b/selfdrive/sentry.py index 12275983eb..2852afa455 100644 --- a/selfdrive/sentry.py +++ b/selfdrive/sentry.py @@ -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()) From c2c2be07bca07511c3064c6cbba669472e1ebc9e Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Thu, 28 Sep 2023 00:10:51 -0400 Subject: [PATCH 28/35] 3D Building on Map (#308) * ui: 3D buildings on map * add toggle * toggleable offroad only * fixes * Revert "toggleable offroad only" This reverts commit 7c0c8d99bca3bbec00921c2d438e68b5f9054393. --- common/params.cc | 1 + selfdrive/ui/qt/maps/map.cc | 43 +++++++++++++++++++ .../ui/qt/offroad/sunnypilot_settings.cc | 6 +++ selfdrive/ui/ui.cc | 1 + selfdrive/ui/ui.h | 2 + 5 files changed, 53 insertions(+) diff --git a/common/params.cc b/common/params.cc index c3142f324a..dcaf7fc2db 100644 --- a/common/params.cc +++ b/common/params.cc @@ -263,6 +263,7 @@ std::unordered_map keys = { {"MadsCruiseMain", PERSISTENT}, {"MadsIconToggle", PERSISTENT}, {"MapboxFullScreen", PERSISTENT}, + {"Map3DBuildings", PERSISTENT}, {"MaxTimeOffroad", PERSISTENT}, {"OnroadScreenOff", PERSISTENT}, {"OnroadScreenOffBrightness", PERSISTENT}, diff --git a/selfdrive/ui/qt/maps/map.cc b/selfdrive/ui/qt/maps/map.cc index db56fcdcfc..ab776ccd8b 100644 --- a/selfdrive/ui/qt/maps/map.cc +++ b/selfdrive/ui/qt/maps/map.cc @@ -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) { diff --git a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc index 6173f71cd4..a3ee8a376e 100644 --- a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc +++ b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc @@ -668,6 +668,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) diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 66c2d8ce1f..6f8cb69ae0 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -252,6 +252,7 @@ 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"); // Handle Onroad Screen Off params if (s->scene.onroadScreenOff > 0) { diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index e31602c782..966c1fa981 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -237,6 +237,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 { From 429f7307beb186a33cdc94155d424130b3ab36a4 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Fri, 29 Sep 2023 00:33:03 -0400 Subject: [PATCH 29/35] Subaru: Stop and Go autoresume (#289) * Subaru: Stop and Go autoresume * Update CHANGELOGS.md * Update CHANGELOGS.md * do this * sync with subaru-community * sync for manual parking brake * no slot machine pls * fix this too * flipped * fix panda * comments * Update CHANGELOGS.md * check every 2.5 second * move them to a function * more logical * frame-based frequency sends * type hinting * should be tuple * better grouping * for docs regeneration * same as upstream * move it down * cleanup * use int flag and safety param, only block message when sng is allowed * Do it here instead * gate everything * move comment * block tx if sng is not allowed on certain platforms * bump panda --- CHANGELOGS.md | 2 + common/params.cc | 1 + panda | 2 +- selfdrive/car/subaru/carcontroller.py | 93 ++++++++++++++++++- selfdrive/car/subaru/carstate.py | 10 +- selfdrive/car/subaru/interface.py | 7 +- selfdrive/car/subaru/subarucan.py | 64 +++++++++++++ selfdrive/car/subaru/values.py | 4 + .../ui/qt/offroad/sunnypilot_settings.cc | 11 +++ 9 files changed, 190 insertions(+), 4 deletions(-) diff --git a/CHANGELOGS.md b/CHANGELOGS.md index e6066f7545..1b3e254db6 100644 --- a/CHANGELOGS.md +++ b/CHANGELOGS.md @@ -11,6 +11,8 @@ sunnypilot - 0.9.5.1 (2023-09-27) * 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 diff --git a/common/params.cc b/common/params.cc index dcaf7fc2db..585e9c5c67 100644 --- a/common/params.cc +++ b/common/params.cc @@ -290,6 +290,7 @@ std::unordered_map keys = { {"SpeedLimitOffsetType", PERSISTENT}, {"StandStillTimer", PERSISTENT}, {"StockLongToyota", PERSISTENT}, + {"SubaruManualParkingBrakeSng", PERSISTENT}, {"TorqueDeadzoneDeg", PERSISTENT}, {"TorqueFriction", PERSISTENT}, {"TorqueMaxLatAccel", PERSISTENT}, diff --git a/panda b/panda index 235217badc..a83841a157 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit 235217badc8d88d6d21def19cd93ba8cc12ae8c0 +Subproject commit a83841a157e3c41765f6b8666a4e50c318d7a415 diff --git a/selfdrive/car/subaru/carcontroller.py b/selfdrive/car/subaru/carcontroller.py index 03a2d01235..6c22b75103 100644 --- a/selfdrive/car/subaru/carcontroller.py +++ b/selfdrive/car/subaru/carcontroller.py @@ -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 diff --git a/selfdrive/car/subaru/carstate.py b/selfdrive/car/subaru/carstate.py index ce352e9da6..aa4e8acc8f 100644 --- a/selfdrive/car/subaru/carstate.py +++ b/selfdrive/car/subaru/carstate.py @@ -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: diff --git a/selfdrive/car/subaru/interface.py b/selfdrive/car/subaru/interface.py index bc157589ff..0780ee4351 100644 --- a/selfdrive/car/subaru/interface.py +++ b/selfdrive/car/subaru/interface.py @@ -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 diff --git a/selfdrive/car/subaru/subarucan.py b/selfdrive/car/subaru/subarucan.py index f73c23420b..411b034323 100644 --- a/selfdrive/car/subaru/subarucan.py +++ b/selfdrive/car/subaru/subarucan.py @@ -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) diff --git a/selfdrive/car/subaru/values.py b/selfdrive/car/subaru/values.py index 1547876008..19c50fa8da 100644 --- a/selfdrive/car/subaru/values.py +++ b/selfdrive/car/subaru/values.py @@ -60,6 +60,10 @@ class SubaruFlags(IntFlag): SEND_INFOTAINMENT = 1 +class SubaruFlagsSP(IntFlag): + SP_SUBARU_SNG = 1 + + class CanBus: main = 0 alt = 1 diff --git a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc index a3ee8a376e..dc989452b8 100644 --- a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc +++ b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc @@ -562,6 +562,17 @@ 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( From c49b5c8e35396e458e7cd7fa32434285c8924121 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Fri, 29 Sep 2023 00:39:49 -0400 Subject: [PATCH 30/35] Lateral Planner: Fix Custom Offsets and Path Offset in all modes (#309) * Lateral Planner: Fix Custom Offsets and Path Offset in all modes * Update init values --- selfdrive/controls/lib/lane_planner.py | 32 +++++++++++++++---- selfdrive/controls/lib/lateral_planner.py | 5 ++- selfdrive/manager/manager.py | 2 +- .../ui/qt/offroad/sunnypilot_settings.cc | 6 ++-- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/selfdrive/controls/lib/lane_planner.py b/selfdrive/controls/lib/lane_planner.py index 5227757f0e..b32ccbd237 100644 --- a/selfdrive/controls/lib/lane_planner.py +++ b/selfdrive/controls/lib/lane_planner.py @@ -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 diff --git a/selfdrive/controls/lib/lateral_planner.py b/selfdrive/controls/lib/lateral_planner.py index 7a0f232aa7..e4aa6e328d 100644 --- a/selfdrive/controls/lib/lateral_planner.py +++ b/selfdrive/controls/lib/lateral_planner.py @@ -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, diff --git a/selfdrive/manager/manager.py b/selfdrive/manager/manager.py index 031e7564e8..111017e822 100755 --- a/selfdrive/manager/manager.py +++ b/selfdrive/manager/manager.py @@ -58,7 +58,7 @@ def manager_init() -> None: ("CustomTorqueLateral", "0"), ("CameraControl", "2"), ("CameraControlToggle", "0"), - ("CameraOffset", "0"), + ("CameraOffset", "4"), ("CarModel", ""), ("CarModelText", ""), ("ChevronInfo", "1"), diff --git a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc index dc989452b8..ff4708996b 100644 --- a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc +++ b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc @@ -846,10 +846,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(); } From c0f2e6bc0551bfe9b8d4caac424549f12f68e872 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Fri, 29 Sep 2023 00:54:15 -0400 Subject: [PATCH 31/35] ui: Allow `SPOptionControl` button group enabled state modifications (#310) --- selfdrive/ui/qt/offroad/sunnypilot_settings.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/selfdrive/ui/qt/offroad/sunnypilot_settings.h b/selfdrive/ui/qt/offroad/sunnypilot_settings.h index fb05095842..b7ff48d7f3 100644 --- a/selfdrive/ui/qt/offroad/sunnypilot_settings.h +++ b/selfdrive/ui/qt/offroad/sunnypilot_settings.h @@ -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(); From 71fc267606f035929fd5f2f28a33a609e2eb8781 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Fri, 29 Sep 2023 01:49:43 -0400 Subject: [PATCH 32/35] ui: Feature Status: Update only when param is changed (#311) * ui: Feature Status: Update only when param is changed * less calls --- selfdrive/ui/qt/onroad_settings.cc | 6 ++++++ selfdrive/ui/ui.cc | 9 --------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/selfdrive/ui/qt/onroad_settings.cc b/selfdrive/ui/qt/onroad_settings.cc index 3e26cc235c..988b49f8e8 100644 --- a/selfdrive/ui/qt/onroad_settings.cc +++ b/selfdrive/ui/qt/onroad_settings.cc @@ -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); diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 6f8cb69ae0..fbf2f40277 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -313,15 +313,6 @@ void UIState::updateStatus() { } 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) { From 613d5b4aba5cb32259302e628a2cd13edfbf0e58 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Fri, 29 Sep 2023 02:36:55 -0400 Subject: [PATCH 33/35] Torque Lateral Control: Refactor settings (#300) * Torque Lateral Control: Refactor settings * don't need this * only offroad allowed * Don't need this * allow when offroad * gate them * flipped * handle them better * cleaner * remove duplicate * toggle checks cleanup * 2.5 second check * trigger refresh when going offroad * cleanup * move toggle * update title and description * fix ampersand * update live torque toggle * live torqued every 2.5 second --- common/params.cc | 2 + selfdrive/car/interfaces.py | 12 ++- selfdrive/controls/controlsd.py | 7 +- selfdrive/controls/lib/latcontrol_torque.py | 12 ++- selfdrive/locationd/torqued.py | 11 ++- .../ui/qt/offroad/sunnypilot_settings.cc | 98 ++++++++++--------- selfdrive/ui/qt/onroad.cc | 2 +- selfdrive/ui/ui.cc | 3 +- selfdrive/ui/ui.h | 1 - 9 files changed, 91 insertions(+), 57 deletions(-) diff --git a/common/params.cc b/common/params.cc index 585e9c5c67..0c19b6dc76 100644 --- a/common/params.cc +++ b/common/params.cc @@ -259,6 +259,7 @@ std::unordered_map keys = { {"LastCarModel", PERSISTENT}, {"LastSpeedLimitSignTap", PERSISTENT}, {"LiveTorque", PERSISTENT}, + {"LiveTorqueRelaxed", PERSISTENT}, {"LkasToggle", PERSISTENT}, {"MadsCruiseMain", PERSISTENT}, {"MadsIconToggle", PERSISTENT}, @@ -294,6 +295,7 @@ std::unordered_map keys = { {"TorqueDeadzoneDeg", PERSISTENT}, {"TorqueFriction", PERSISTENT}, {"TorqueMaxLatAccel", PERSISTENT}, + {"TorquedOverride", PERSISTENT}, {"ToyotaSnG", PERSISTENT}, {"ToyotaTSS2Long", PERSISTENT}, {"TrueVEgoUi", PERSISTENT}, diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index c71d08bb99..0ebab681cf 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -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 diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 8789e930e0..8976ae468f 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -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") diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py index 914fea81f4..bde6989dcb 100644 --- a/selfdrive/controls/lib/latcontrol_torque.py +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -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() diff --git a/selfdrive/locationd/torqued.py b/selfdrive/locationd/torqued.py index ddb95e944c..b1eed3f9c6 100755 --- a/selfdrive/locationd/torqued.py +++ b/selfdrive/locationd/torqued.py @@ -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: diff --git a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc index ff4708996b..b12ae2474b 100644 --- a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc +++ b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc @@ -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", @@ -268,17 +280,14 @@ SPControlsPanel::SPControlsPanel(QWidget *parent) : ListWidget(parent) { // toggle names to trigger updateToggles() when toggleFlipped std::vector updateTogglesNames{ "EnableMads", "CustomOffsets", "EnforceTorqueLateral", "SpeedLimitPercOffset", "SpeedLimitControl", - "CustomTorqueLateral", "LiveTorque" + "CustomTorqueLateral", "LiveTorque", "TorquedOverride" }; connect(dynamic_lane_profile, &DynamicLaneProfile::updateExternalToggles, this, &SPControlsPanel::updateToggles); - // toggle names to display ConfirmationDialog::alert - std::vector updateTogglesNamesAlert{ - "CustomTorqueLateral", "LiveTorque" - }; // toggle for offroadTransition when going onroad/offroad std::vector toggleOffroad{ - "EnableMads", "DisengageLateralOnBrake", "AccMadsCombo", "MadsCruiseMain", "BelowSpeedPause", "EnforceTorqueLateral" + "EnableMads", "DisengageLateralOnBrake", "AccMadsCombo", "MadsCruiseMain", "BelowSpeedPause", "EnforceTorqueLateral", + "LiveTorqueRelaxed" }; // Controls: Camera Offset (cm) @@ -335,7 +344,7 @@ SPControlsPanel::SPControlsPanel(QWidget *parent) : ListWidget(parent) { addItem(auto_lane_change_timer); } - if (param == "CustomTorqueLateral") { + if (param == "TorquedOverride") { // Control: FRICTION addItem(friction); @@ -358,13 +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) { - 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) { @@ -381,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) { @@ -411,12 +434,14 @@ void SPControlsPanel::updateToggles() { 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 enforceTorqueGroup{"CustomTorqueLateral", "LiveTorque"}; + std::vector enforceTorqueGroup{"CustomTorqueLateral", "LiveTorque", "TorquedOverride"}; for (const auto& enforceTorqueToggle : enforceTorqueGroup) { if (toggles.find(enforceTorqueToggle) != toggles.end()) { toggles[enforceTorqueToggle]->setVisible(enforce_torque_lateral->isToggled()); @@ -436,25 +461,8 @@ void SPControlsPanel::updateToggles() { } if (enforce_torque_lateral->isToggled()) { - if (custom_torque_lateral->isToggled()) { - live_torque->setEnabled(false); - params.putBool("LiveTorque", false); - } else { - live_torque->setEnabled(true); - } - - if (live_torque->isToggled()) { - 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(); + live_torque_relaxed->setVisible(live_torque->isToggled()); + torqued_override->setVisible(custom_torque_lateral->isToggled()); } else { params.putBool("LiveTorque", false); params.putBool("CustomTorqueLateral", false); @@ -907,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. Live: Override self-tune values; Offline: Override self-tune offline values at car restart."), "../assets/offroad/icon_blank.png", {0, 50}) { @@ -917,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. Live: Override self-tune values; Offline: Override self-tune offline values at car restart."), "../assets/offroad/icon_blank.png", {1, 500}) { @@ -933,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)); } diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index 76a8434b3b..f05e9d89cf 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -587,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(); diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index fbf2f40277..62bd20f090 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -253,6 +253,7 @@ void ui_update_params(UIState *s) { 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) { @@ -305,8 +306,6 @@ 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); diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index 966c1fa981..76911b6211 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -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; From 44b0b11ff191766eb9005e100c7ec6b224109096 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Fri, 29 Sep 2023 08:56:50 -0400 Subject: [PATCH 34/35] HKG: add Kia Seltos 2023-24 Non-SCC platform (#215) * HKG: add Kia Seltos 2024 Non-SCC platform * 2023 MY also works * Update CHANGELOGS.md * add fw * fix * fix list --- CHANGELOGS.md | 1 + selfdrive/car/hyundai/interface.py | 2 +- selfdrive/car/hyundai/values.py | 30 +++++++++++++++++++++++++-- selfdrive/car/sunnypilot_carname.json | 1 + 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/CHANGELOGS.md b/CHANGELOGS.md index b8a3035779..ed5d9e5f84 100644 --- a/CHANGELOGS.md +++ b/CHANGELOGS.md @@ -1,5 +1,6 @@ sunnypilot - 0.9.5.1 (202x-xx-xx) ======================== +* Kia Seltos Non-SCC 2023-24 support thanks to Moodkiller and jeroid_! sunnypilot - 0.9.4.1 (2023-08-11) ======================== diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py index 1109c52277..561216aec4 100644 --- a/selfdrive/car/hyundai/interface.py +++ b/selfdrive/car/hyundai/interface.py @@ -158,7 +158,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 diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index e02e4561cd..9c9cc4e0b5 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -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), diff --git a/selfdrive/car/sunnypilot_carname.json b/selfdrive/car/sunnypilot_carname.json index 7ef5e3c8af..de48bc420d 100644 --- a/selfdrive/car/sunnypilot_carname.json +++ b/selfdrive/car/sunnypilot_carname.json @@ -130,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", From b982079429704c913b0fdb2817d35cc50c2d2c8e Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Fri, 29 Sep 2023 08:59:01 -0400 Subject: [PATCH 35/35] HKG: Car Port for Kia Seltos Non-SCC 2023-24 (#288) * HKG: add Kia Seltos 2024 Non-SCC platform * 2023 MY also works * finish port * Update CHANGELOGS.md * update name * add fw * fix * fix list --- selfdrive/car/hyundai/hyundaican.py | 3 ++- selfdrive/car/torque_data/substitute.yaml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/selfdrive/car/hyundai/hyundaican.py b/selfdrive/car/hyundai/hyundaican.py index 696f18150a..00f62df231 100644 --- a/selfdrive/car/hyundai/hyundaican.py +++ b/selfdrive/car/hyundai/hyundaican.py @@ -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 diff --git a/selfdrive/car/torque_data/substitute.yaml b/selfdrive/car/torque_data/substitute.yaml index e2ef4627e4..38fd35feb0 100644 --- a/selfdrive/car/torque_data/substitute.yaml +++ b/selfdrive/car/torque_data/substitute.yaml @@ -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