Compare commits

..

32 Commits

Author SHA1 Message Date
Jason Wen 33ad27f65b wrong offset 2026-06-09 00:14:15 -04:00
Jason Wen 35137acd50 bump 2026-06-09 00:03:43 -04:00
Jason Wen eb34e66ffb bump 2026-06-09 00:02:23 -04:00
Jason Wen 585e9989bc bump 2026-06-08 23:59:27 -04:00
Jason Wen 3812050328 Merge remote-tracking branch 'sunnypilot/sunnypilot/master' into hkg-angle-steering-2025-new-comma
# Conflicts:
#	opendbc_repo
2026-06-08 23:52:30 -04:00
Jason Wen 692f0ee187 Merge remote-tracking branch 'sunnypilot/sunnypilot/master' into hkg-angle-steering-2025-new-comma
# Conflicts:
#	opendbc_repo
2026-05-21 17:58:08 -04:00
Jason Wen c8f38bb6ea Merge remote-tracking branch 'sunnypilot/sunnypilot/master' into hkg-angle-steering-2025-new-comma 2026-05-09 11:47:52 -04:00
Jason Wen 1a40a45e8a Merge remote-tracking branch 'sunnypilot/sunnypilot/master' into hkg-angle-steering-2025-new-comma
# Conflicts:
#	opendbc_repo
2026-05-03 16:10:25 -04:00
Jason Wen 15176c08f1 Merge remote-tracking branch 'sunnypilot/sunnypilot/master' into hkg-angle-steering-2025-new-comma
# Conflicts:
#	opendbc_repo
2026-04-19 01:51:58 -04:00
Jason Wen 8faee8daad Merge remote-tracking branch 'sunnypilot/sunnypilot/master' into hkg-angle-steering-2025-new-comma
# Conflicts:
#	opendbc_repo
2026-04-12 16:29:52 -04:00
Jason Wen 955966924f Merge remote-tracking branch 'sunnypilot/sunnypilot/master' into hkg-angle-steering-2025-new-comma
# Conflicts:
#	opendbc_repo
2026-04-11 11:37:59 -04:00
DevTekVE f42e505f16 undisabling this for you jason 2026-04-10 12:12:33 +02:00
Jason Wen 7d0c81254d 2nd tune 2026-04-09 00:28:46 -04:00
Jason Wen bea1eb34aa gv80 2026-04-04 12:20:48 -04:00
Jason Wen aaa59fe155 new tune 2026-04-04 08:44:25 -04:00
Jason Wen 5b68479912 Merge remote-tracking branch 'sunnypilot/sunnypilot/master' into hkg-angle-steering-2025-new-comma
# Conflicts:
#	opendbc_repo
#	sunnypilot/models/tests/model_hash
2026-04-04 08:44:06 -04:00
Jason Wen 6290d24bf6 bump 2026-04-02 21:18:53 -04:00
DevTekVE 3b9cf0c162 quick fix for sunny max angle to 5 2026-04-03 01:18:33 +02:00
DevTekVE cfb0919596 clip: safeguard steering angle application in Hyundai CarController
- Added clipping logic to constrain `apply_angle_last` within `STEER_ANGLE_MAX` bounds.
- Prevents potential out-of-range errors for extreme steering angles.
2026-04-03 01:02:38 +02:00
DevTekVE ad1e72fb12 Adding ioniq 5 pe to test the new controls in isolation 2026-04-02 17:18:17 +02:00
Jason Wen 6354bb89ca signed 2026-04-02 06:07:15 -04:00
Jason Wen c431378ade brand new day 2026-04-02 04:15:29 -04:00
Jason Wen ae3ceaa32b use new name from harald 2026-04-02 02:54:31 -04:00
Jason Wen e3c48da79c v16 vroom 2026-04-02 02:49:19 -04:00
Jason Wen a5867d3998 Platform List: sync with latest 2026-04-02 02:38:06 -04:00
Jason Wen 0cea8ef65a fix tests 2026-04-02 02:37:44 -04:00
Jason Wen 50f5b0584f translations 2026-04-02 02:34:24 -04:00
Jason Wen 39867dea09 sunnypilot models: support for on-policy models 2026-04-02 02:03:29 -04:00
Jason Wen 999c54c149 new list 2026-04-02 00:06:14 -04:00
Jason Wen 500c235e64 new 2026-04-01 23:40:53 -04:00
Jason Wen 58e97698d2 fix 2026-04-01 23:40:43 -04:00
Jason Wen bff221f06a Merge branch 'upstream/openpilot/master' into sync-20260401
# Conflicts:
#	.github/workflows/auto_pr_review.yaml
#	.github/workflows/repo-maintenance.yaml
#	README.md
#	SConstruct
#	docs/CARS.md
#	opendbc_repo
#	panda
#	selfdrive/car/card.py
#	selfdrive/controls/controlsd.py
#	selfdrive/selfdrived/selfdrived.py
#	selfdrive/test/process_replay/migration.py
#	selfdrive/ui/translations/app_fr.po
2026-04-01 23:20:27 -04:00
5 changed files with 2 additions and 277 deletions
@@ -20,7 +20,6 @@ from openpilot.system.ui.widgets.list_view import button_item
from openpilot.system.ui.sunnypilot.widgets.html_render import HtmlModalSP
from openpilot.system.ui.sunnypilot.widgets.list_view import toggle_item_sp
from openpilot.selfdrive.ui.sunnypilot.layouts.settings.external_storage import external_storage_item
PREBUILT_PATH = os.path.join(Paths.comma_home(), "prebuilt") if PC else "/data/openpilot/prebuilt"
@@ -53,11 +52,7 @@ class DeveloperLayoutSP(DeveloperLayout):
self.error_log_btn = button_item(tr("Error Log"), tr("VIEW"), tr("View the error log for sunnypilot crashes."), callback=self._on_error_log_clicked)
self.external_storage = external_storage_item(tr("External Storage"), description=tr("Extend your comma device's storage by inserting a USB drive " +
"into the aux port."))
self.items: list = [self.show_advanced_controls, self.enable_github_runner_toggle, self.enable_copyparty_toggle, self.prebuilt_toggle,
self.external_storage, self.error_log_btn,]
self.items: list = [self.show_advanced_controls, self.enable_github_runner_toggle, self.enable_copyparty_toggle, self.prebuilt_toggle, self.error_log_btn,]
@staticmethod
def _on_prebuilt_toggled(state):
@@ -1,261 +0,0 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
import pyray as rl
import threading
import subprocess
import copy
from enum import Enum
from collections.abc import Callable
from openpilot.common.params import Params
from openpilot.system.hardware import PC
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.text_measure import measure_text_cached
from openpilot.system.ui.lib.multilang import tr, tr_noop
from openpilot.system.ui.widgets import DialogResult
from openpilot.system.ui.widgets.button import Button, ButtonStyle
from openpilot.system.ui.widgets.confirm_dialog import alert_dialog, ConfirmDialog
from openpilot.system.ui.widgets.list_view import (
ItemAction,
ListItem,
BUTTON_HEIGHT,
BUTTON_BORDER_RADIUS,
BUTTON_FONT_SIZE,
BUTTON_WIDTH,
)
VALUE_FONT_SIZE = 48
class ExternalStorageState(Enum):
DISABLED = tr_noop("DISABLED")
LOADING = tr_noop("LOADING")
CHECK = tr_noop("CHECK")
MOUNT = tr_noop("MOUNT")
UNMOUNT = tr_noop("UNMOUNT")
FORMAT = tr_noop("FORMAT")
class ExternalStorageAction(ItemAction):
MAX_WIDTH = 500
def __init__(self):
super().__init__(self.MAX_WIDTH, True)
self._params = Params()
self._error_message = ""
self._text_font = gui_app.font(FontWeight.NORMAL)
self._button = Button(
"",
click_callback=self._handle_button_click,
button_style=ButtonStyle.LIST_ACTION,
border_radius=BUTTON_BORDER_RADIUS,
font_size=BUTTON_FONT_SIZE,
)
self._value_text = ""
self._formatting = False
self._refresh_pending = False
self._state = ExternalStorageState.CHECK
self._refresh_state()
self.refresh()
def set_touch_valid_callback(self, callback):
def wrapped():
if self._state == ExternalStorageState.DISABLED:
return False
return callback()
super().set_touch_valid_callback(wrapped)
self._button.set_touch_valid_callback(wrapped)
def _run(self, cmd: str) -> bool:
return subprocess.call(["sh", "-c", cmd]) == 0
def _run_output(self, cmd: str) -> str:
try:
out = subprocess.check_output(["sh", "-c", cmd], universal_newlines=True)
return out.strip()
except Exception:
return ""
def _render(self, rect: rl.Rectangle) -> bool:
if self._error_message:
msg = copy.copy(self._error_message)
gui_app.set_modal_overlay(alert_dialog(msg))
self._error_message = ""
if self._value_text:
text_size = measure_text_cached(self._text_font, self._value_text, VALUE_FONT_SIZE)
rl.draw_text_ex(
self._text_font,
self._value_text,
(rect.x + rect.width - BUTTON_WIDTH - text_size.x - 30,
rect.y + (rect.height - text_size.y) / 2),
VALUE_FONT_SIZE,
1.0,
rl.Color(170, 170, 170, 255),
)
button_rect = rl.Rectangle(
rect.x + rect.width - BUTTON_WIDTH,
rect.y + (rect.height - BUTTON_HEIGHT) / 2,
BUTTON_WIDTH,
BUTTON_HEIGHT
)
self._button.set_rect(button_rect)
self._button.set_text(tr(self._state.value))
self._button.set_enabled(self._state not in (ExternalStorageState.LOADING,
ExternalStorageState.DISABLED))
self._button.render(button_rect)
return False
def _refresh_state(self):
if PC:
self._state = ExternalStorageState.DISABLED
self._button.set_enabled(False)
self._value_text = ""
def debounced_refresh(self):
if self._refresh_pending:
return
self._refresh_pending = True
def _timer():
import time
time.sleep(0.25)
self._refresh_pending = False
self.refresh()
threading.Thread(target=_timer, daemon=True).start()
def refresh(self):
def _work():
is_mounted = self._run("findmnt -n /mnt/external_realdata")
has_drive = self._run("lsblk -f /dev/sdg")
has_fs = self._run("lsblk -f /dev/sdg1 | grep -q ext4")
has_label = self._run("blkid /dev/sdg1 | grep -q 'LABEL=\"openpilot\"'")
info = ""
if is_mounted and has_label:
info = self._run_output(
"df -h /mnt/external_realdata | awk 'NR==2 {print $3 \"/\" $2}'"
)
def apply():
if self._formatting:
self._value_text = tr("formatting")
self._state = ExternalStorageState.FORMAT
return
if not has_drive:
self._value_text = tr("insert drive")
self._state = ExternalStorageState.CHECK
elif not has_fs or not has_label:
self._value_text = tr("needs format")
self._state = ExternalStorageState.FORMAT
elif is_mounted:
self._value_text = info
self._state = ExternalStorageState.UNMOUNT
else:
self._value_text = tr("drive detected")
self._state = ExternalStorageState.MOUNT
apply()
threading.Thread(target=_work, daemon=True).start()
def _handle_button_click(self):
st = self._state
if st == ExternalStorageState.DISABLED:
return
if st in (ExternalStorageState.CHECK, ExternalStorageState.MOUNT):
self.mount_storage()
elif st == ExternalStorageState.UNMOUNT:
self.unmount_storage()
elif st == ExternalStorageState.FORMAT:
dialog = ConfirmDialog(
tr("Are you sure you want to format this drive? This will erase all data."),
confirm_text=tr("Format"),
cancel_text=tr("Cancel"),
)
gui_app.set_modal_overlay(dialog, callback=self._confirm_format)
def _confirm_format(self, result: DialogResult):
if result == DialogResult.CONFIRM:
self.format_storage()
def mount_storage(self):
self._value_text = tr("mounting")
self._state = ExternalStorageState.LOADING
def _work():
cmd = """
sudo mount -o remount,rw / &&
sudo mkdir -p /mnt/external_realdata &&
(grep -q '/dev/sdg1 /mnt/external_realdata' /etc/fstab ||
echo '/dev/sdg1 /mnt/external_realdata ext4 defaults,nofail 0 2' >> /etc/fstab) &&
sudo systemctl daemon-reexec &&
sudo mount /mnt/external_realdata &&
sudo chown -R comma:comma /mnt/external_realdata &&
sudo chmod -R 775 /mnt/external_realdata &&
sudo mount -o remount,ro /
"""
subprocess.call(["sh", "-c", cmd])
self.debounced_refresh()
threading.Thread(target=_work, daemon=True).start()
def unmount_storage(self):
self._value_text = tr("unmounting")
self._state = ExternalStorageState.LOADING
def _work():
subprocess.call(["sh", "-c", "sudo umount /mnt/external_realdata"])
self.debounced_refresh()
threading.Thread(target=_work, daemon=True).start()
def format_storage(self):
self._formatting = True
self._value_text = tr("formatting")
self._state = ExternalStorageState.LOADING
def _work():
cmd = """
sudo wipefs -a /dev/sdg &&
sudo parted -s /dev/sdg mklabel gpt mkpart primary ext4 0% 100% &&
sudo mkfs.ext4 -F -L openpilot /dev/sdg1
"""
exitcode = subprocess.call(["sh", "-c", cmd])
def apply():
self._formatting = False
if exitcode == 0:
self.mount_storage()
else:
self._value_text = tr("needs format")
self._state = ExternalStorageState.FORMAT
apply()
threading.Thread(target=_work, daemon=True).start()
def external_storage_item(title: str | Callable[[], str], description: str | Callable[[], str]) -> ListItem:
return ListItem(
title=title,
description=description,
action_item=ExternalStorageAction()
)
@@ -134,11 +134,6 @@ class SteeringLayout(Widget):
enforce_torque_enabled = self._torque_control_toggle.action_item.get_state()
nnlc_enabled = self._nnlc_toggle.action_item.get_state()
if enforce_torque_enabled and nnlc_enabled:
self._torque_control_toggle.action_item.set_state(False)
self._nnlc_toggle.action_item.set_state(False)
enforce_torque_enabled = False
nnlc_enabled = False
self._nnlc_toggle.action_item.set_enabled(ui_state.is_offroad() and torque_allowed and not enforce_torque_enabled)
self._torque_control_toggle.action_item.set_enabled(ui_state.is_offroad() and torque_allowed and not nnlc_enabled)
self._torque_customization_button.action_item.set_enabled(self._torque_control_toggle.action_item.get_state())
-4
View File
@@ -179,10 +179,6 @@ class UIStateSP:
CP = self.CP
if CP is not None:
if self.params.get_bool("EnforceTorqueControl") and self.params.get_bool("NeuralNetworkLateralControl"):
self.params.put_bool("EnforceTorqueControl", False, block=True)
self.params.put_bool("NeuralNetworkLateralControl", False, block=True)
# Angle steering: no torque-based lateral controls
if CP.steerControlType == car.CarParams.SteerControlType.angle:
self.params.remove("EnforceTorqueControl")