Merge remote-tracking branch 'sunnypilot/sunnypilot/master' into hkg-angle-steering-2025-new-comma

This commit is contained in:
Jason Wen
2026-05-09 11:47:52 -04:00
17 changed files with 173 additions and 115 deletions
+86 -1
View File
@@ -1,4 +1,4 @@
sunnypilot Version 2026.001.000 (2026-03-xx)
sunnypilot Version 2026.001.000 (2026-05-06)
========================
* What's Changed (sunnypilot/sunnypilot)
* Complete rewrite of the user interface from Qt C++ to Raylib Python
@@ -66,6 +66,64 @@ sunnypilot Version 2026.001.000 (2026-03-xx)
* Pause Lateral Control with Blinker: Post-Blinker Delay by @CHaucke89
* SCC-V: Use p97 for predicted lateral accel by @yasu-oh
* Controls: Support for Torque Lateral Control v0 Tune by @sunnyhaibin
* [TIZI/TICI] ui: ensure null checks for `CarParams` and `CarParamsSP` by @sunnyhaibin
* [TIZI/TICI] ui: use `vCruiseCluster` and `vEgoCluster` for SLA `preActive` by @sunnyhaibin
* Fix display of values when using use_float_scaling by @CHaucke89
* models: fix default & index "0" by @nayan8teen
* [TIZI/TICI] visuals: Improved speed limit by @angaz
* ICBM: ensure button timers update on disable to clear stale presses by @jamesmikesell
* [TIZI/TICI] ui: simplify Smart Cruise Control text rendering by @sunnyhaibin
* controlsd: fix steer_limited_by_safety not updating under MADS by @zephleggett
* soundd: trigger timeout warning during MADS lateral-only by @zephleggett
* pandad: flasher for Rivian long upgrade module by @lukasloetkolben
* modeld_v2: tinygrad transformation warp by @Discountchubbs
* tools: block `manage_sunnylinkd` in sim startup script by @sunnyhaibin
* [MICI] ui: need superclass `_render` in `HudRendererSP` by @sunnyhaibin
* [TIZI/TICI] ui: Speed Limit Assist active status by @sunnyhaibin
* ui: reimplement "Screen Off" option to Onroad Brightness by @sunnyhaibin
* ui: don't hide steering wheel when blindspot disabled by @royjr
* ui: Speed Limit Assist `preActive` improvements by @sunnyhaibin
* ui: consolidate Speed Limit Assist `preActive` status rendering by @sunnyhaibin
* [MICI] ui: Speed Limit Assist `preActive` status by @sunnyhaibin
* sunnypilot modeld: remove thneed modeld by @Discountchubbs
* modeld_v2: decouple planplus scaling from accel by @Discountchubbs
* sunnylink: Handle exceptions in `getParamsAllKeysV1` to log crashes by @devtekve
* [TIZI/TICI] ui: Developer UI cleanup by @sunnyhaibin
* [TIZI/TICI] ui: dynamic alert size by @nayan8teen
* i18n(fr): Add French translations by @didlawowo
* Toyota: Stop and Go Hack (Alpha) by @sunnyhaibin
* ui: `AlertFadeAnimator` for longitudinal-related statuses by @sunnyhaibin
* pandad: gate unsupported pandas before flashing by @sunnyhaibin
* Rivian: Flash xnor's Longitudinal Upgrade Kit prior supported panda check by @lukasloetkolben
* [TIZI/TICI] ui: add back gate steering arc behind toggle by @sunnyhaibin
* ui: gate Onroad Brightness Delay on readiness by @sunnyhaibin
* ui: add new timer options for Onroad Brightness Delay by @sunnyhaibin
* [TIZI/TICI] ui: branch switcher is always available by @sunnyhaibin
* pandad: always prioritize internal panda by @sunnyhaibin
* sunnylinkd: fetch compressed params schema by @sunnyhaibin
* sunnypilot locationd: remove unused car_ekf filter by @sunnyhaibin
* modeld_v2: update deprecated temporalPose ref by @sunnyhaibin
* NNLC: restore pre-v1 PID gains in torque extension by @mmmorks
* MADS safety: enable heartbeat and lateral controls mismatch checks by @sunnyhaibin
* [MICI] ui: models panel enhancements by @nayan8teen
* [TIZI/TICI] ui: fix unintended selection while scrolling in TreeOptionDialog by @TheSecurityDev
* tools: script for video concatenation by @Discountchubbs
* tools: profile memory usage by @Discountchubbs
* [TIZI/TICI] ui: remove per-frame param sync by @sunnyhaibin
* [MICI] ui: always offroad by @nayan8teen
* controls: always default Torque Lateral Control to v0 Tune by @sunnyhaibin
* Revert "controls: always default Torque Lateral Control to v0 Tune" by @sunnyhaibin
* Reapply "controls: always default Torque Lateral Control to v0 Tune" (#1806) by @sunnyhaibin
* [MICI] ui: add sunnylink info & connectivity check by @nayan8teen
* sunnylink: Remove unused API endpoint by @devtekve
* DM: wheel touch enforcement in MADS by @sunnyhaibin
* torque: show static override values in Dev UI & gate `useParams` on custom torque tune by @sunnyhaibin
* MADS: suppress espActive event when long is not engaged by @sunnyhaibin
* sunnylink: SDUI by @sunnyhaibin
* [MICI] ui: align upstream changes with sunnypilot settings buttons by @nayan8teen
* ui: fix cellular toggles by @AmyJeanes
* sunnylink: switch athena domain by @devtekve
* Platform List: dynamically migrate CarPlatformBundle by @sunnyhaibin
* What's Changed (sunnypilot/opendbc)
* Honda: DBC for Accord 9th Generation by @mvl-boston
* FCA: update tire stiffness values for `RAM_HD` by @dparring
@@ -84,12 +142,25 @@ sunnypilot Version 2026.001.000 (2026-03-xx)
* Honda: add missing `GasInterceptor` messages to Taiwan Odyssey DBC by @mvl-boston
* GM: remove `CHEVROLET_EQUINOX_NON_ACC_3RD_GEN` from `dashcamOnly` by @sunnyhaibin
* GM: remove `CHEVROLET_BOLT_NON_ACC_2ND_GEN` from `dashcamOnly` by @sunnyhaibin
* Hyundai Longitudinal: deprecate ramp update for dynamic tune by @Discountchubbs
* Rivian: long upgrade messages on bus 1 by @lukasloetkolben
* Toyota: Stop and Go Hack (Alpha) by @sunnyhaibin
* Toyota: gate Smart DSU behind Alpha Longitudinal by @sunnyhaibin
* Toyota: Gas Interceptor always set `standstill_req` by @sunnyhaibin
* MADS safety: dedicated `controls_allowed_lateral` by @sunnyhaibin
* Platform List: include community supported platforms by @sunnyhaibin
* New Contributors (sunnypilot/sunnypilot)
* @TheSecurityDev made their first contribution in "ui: fix sidebar scroll in UI screenshots"
* @zikeji made their first contribution in "sunnylink: block remote modification of SSH key parameters"
* @Candy0707 made their first contribution in "[TIZI/TICI] ui: Fix misaligned turn signals and blindspot indicators with sidebar"
* @CHaucke89 made their first contribution in "Pause Lateral Control with Blinker: Post-Blinker Delay"
* @yasu-oh made their first contribution in "SCC-V: Use p97 for predicted lateral accel"
* @angaz made their first contribution in "[TIZI/TICI] visuals: Improved speed limit"
* @jamesmikesell made their first contribution in "ICBM: ensure button timers update on disable to clear stale presses"
* @zephleggett made their first contribution in "controlsd: fix steer_limited_by_safety not updating under MADS"
* @lukasloetkolben made their first contribution in "pandad: flasher for Rivian long upgrade module"
* @didlawowo made their first contribution in "i18n(fr): Add French translations"
* @mmmorks made their first contribution in "NNLC: restore pre-v1 PID gains in torque extension"
* New Contributors (sunnypilot/opendbc)
* @AmyJeanes made their first contribution in "Tesla: Fix stock LKAS being blocked when MADS is enabled"
* @mvl-boston made their first contribution in "Honda: Update Clarity brake to renamed DBC message name"
@@ -99,6 +170,20 @@ sunnypilot Version 2026.001.000 (2026-03-xx)
* @royjr made their first contribution in "HKG: add KIA_FORTE_2019_NON_SCC fingerprint"
* @ssysm made their first contribution in "Tesla: remove `TESLA_MODEL_X` from `dashcamOnly`"
* Full Changelog: https://github.com/sunnypilot/sunnypilot/compare/v2025.002.000...v2026.001.000
************************
* Synced with commaai's openpilot (v0.11.1)
* master commit c001f3c9b490a80e69539f0af6022f6e07ceb721 (April 16, 2026)
* New driver monitoring model
* Improved image processing pipeline for driver camera
* Rivian R1S and R1T 2025 support thanks to lukasloetkolben!
* New driving model #36798
* Fully trained using a learned simulator
* Improved longitudinal performance in Experimental mode
* Reduce comma four standby power usage by 77% to 52 mW
* Kia K7 2017 support thanks to royjr!
* Lexus LS 2018 support thanks to Hacheoy!
* Improved inter-process communication memory efficiency
* comma four support
sunnypilot Version 2025.002.000 (2025-11-06)
========================
+1 -1
View File
@@ -86,7 +86,7 @@ class Car:
self.can_callbacks = can_comm_callbacks(self.can_sock, self.pm.sock['sendcan'])
is_release = self.params.get_bool("IsReleaseBranch")
is_release = False # self.params.get_bool("IsReleaseBranch")
is_release_sp = self.params.get_bool("IsReleaseSpBranch")
if CI is None:
+1 -1
View File
@@ -36,7 +36,7 @@ class DeveloperLayout(Widget):
def __init__(self):
super().__init__()
self._params = Params()
self._is_release = self._params.get_bool("IsReleaseBranch")
self._is_release = False # self._params.get_bool("IsReleaseBranch")
# Build items and keep references for callbacks/state updates
self._adb_toggle = toggle_item(
+1 -1
View File
@@ -42,7 +42,7 @@ class TogglesLayout(Widget):
def __init__(self):
super().__init__()
self._params = Params()
self._is_release = self._params.get_bool("IsReleaseBranch")
self._is_release = False # self._params.get_bool("IsReleaseBranch")
# param, title, desc, icon, needs_restart
self._toggle_defs = {
+7 -6
View File
@@ -159,7 +159,6 @@ class UIStateSP:
def _enforce_constraints(self) -> None:
has_long = self.has_longitudinal_control
has_icbm = self.has_icbm
CP = self.CP
if CP is not None:
@@ -168,8 +167,8 @@ class UIStateSP:
self.params.remove("EnforceTorqueControl")
self.params.remove("NeuralNetworkLateralControl")
# Alpha longitudinal: clear if not available or on release branch
if not CP.alphaLongitudinalAvailable or self.params.get_bool("IsReleaseBranch"):
# Alpha longitudinal: clear if not available
if not CP.alphaLongitudinalAvailable:
self.params.remove("AlphaLongitudinalEnabled")
# BSM not available: clear BSM-dependent settings
@@ -181,21 +180,23 @@ class UIStateSP:
self.params.remove("NeuralNetworkLateralControl")
self.params.remove("AlphaLongitudinalEnabled")
# No longitudinal control: no experimental mode
# No longitudinal control: no experimental mode or DEC
if not has_long:
self.params.remove("ExperimentalMode")
self.params.remove("DynamicExperimentalControl")
# ICBM: clear if not available or if full longitudinal control is active
if self.CP_SP is not None:
if not self.CP_SP.intelligentCruiseButtonManagementAvailable or has_long:
self.params.remove("IntelligentCruiseButtonManagement")
self.has_icbm = False
else:
self.params.remove("IntelligentCruiseButtonManagement")
self.has_icbm = False
# Cruise features requiring longitudinal or ICBM
if not (has_long or has_icbm):
if not (has_long or self.has_icbm):
self.params.remove("CustomAccIncrementsEnabled")
self.params.remove("DynamicExperimentalControl")
self.params.remove("SmartCruiseControlVision")
self.params.remove("SmartCruiseControlMap")
+1 -1
View File
@@ -74,7 +74,7 @@ class UIState(UIStateSP):
# Core state variables
self.is_metric: bool = self.params.get_bool("IsMetric")
self.is_release = self.params.get_bool("IsReleaseBranch")
self.is_release = False # self.params.get_bool("IsReleaseBranch")
self.always_on_dm: bool = self.params.get_bool("AlwaysOnDM")
self.started: bool = False
self.ignition: bool = False
+1 -1
View File
@@ -34,7 +34,7 @@ from openpilot.sunnypilot.sunnylink.utils import sunnylink_need_register, sunnyl
from openpilot.sunnypilot.sunnylink.capabilities import generate_capabilities, CAPABILITY_LABELS
from openpilot.sunnypilot.sunnylink.tools.generate_settings_schema import generate_schema
SUNNYLINK_ATHENA_HOST = os.getenv('SUNNYLINK_ATHENA_HOST', 'wss://ws.stg.api.sunnypilot.ai')
SUNNYLINK_ATHENA_HOST = os.getenv('SUNNYLINK_ATHENA_HOST', 'wss://athena.sunnylink.ai')
HANDLER_THREADS = int(os.getenv('HANDLER_THREADS', "4"))
LOCAL_PORT_WHITELIST = {8022}
SUNNYLINK_LOG_ATTR_NAME = "user.sunny.upload"
+1 -1
View File
@@ -94,7 +94,7 @@ def generate_capabilities(params: Params | None = None) -> dict:
# Hardware + boolean params (no CarParams dependency)
caps["device_type"] = HARDWARE.get_device_type()
caps["is_release"] = params.get_bool("IsReleaseBranch")
caps["is_release"] = False # params.get_bool("IsReleaseBranch")
caps["is_sp_release"] = params.get_bool("IsReleaseSpBranch")
caps["is_development"] = params.get_bool("IsDevelopmentBranch")
caps["stock_longitudinal"] = params.get_bool("ToyotaEnforceStockLongitudinal")
-2
View File
@@ -2,8 +2,6 @@
> One YAML file per page. Edit, run the compiler, commit. The sunnylink frontend updates automatically.
For detailed architecture, capability fields, parity analysis, and dialog mappings, see [REFERENCE.md](REFERENCE.md).
## What you edit (and what's generated)
| File | What | When to edit |
+9 -64
View File
@@ -574,19 +574,9 @@
"description": "Let the model decide when to use sunnypilot ACC or sunnypilot End to End Longitudinal.",
"visibility": [
{
"type": "any",
"conditions": [
{
"type": "capability",
"field": "has_longitudinal_control",
"equals": true
},
{
"type": "capability",
"field": "has_icbm",
"equals": true
}
]
"type": "capability",
"field": "has_longitudinal_control",
"equals": true
}
],
"enablement": [
@@ -1731,26 +1721,6 @@
"key": "JoystickDebugMode",
"widget": "toggle",
"title": "Joystick Debug Mode",
"visibility": [
{
"type": "not",
"condition": {
"type": "any",
"conditions": [
{
"type": "capability",
"field": "is_release",
"equals": true
},
{
"type": "capability",
"field": "is_sp_release",
"equals": true
}
]
}
}
],
"enablement": [
{
"type": "offroad_only"
@@ -1775,19 +1745,9 @@
{
"type": "not",
"condition": {
"type": "any",
"conditions": [
{
"type": "capability",
"field": "is_release",
"equals": true
},
{
"type": "capability",
"field": "is_sp_release",
"equals": true
}
]
"type": "capability",
"field": "has_icbm",
"equals": true
}
}
]
@@ -1900,19 +1860,9 @@
{
"type": "not",
"condition": {
"type": "any",
"conditions": [
{
"type": "capability",
"field": "is_release",
"equals": true
},
{
"type": "capability",
"field": "is_sp_release",
"equals": true
}
]
"type": "capability",
"field": "is_sp_release",
"equals": true
}
}
],
@@ -1947,11 +1897,6 @@
"condition": {
"type": "any",
"conditions": [
{
"type": "capability",
"field": "is_release",
"equals": true
},
{
"type": "capability",
"field": "is_sp_release",
@@ -59,12 +59,7 @@ macros:
- type: not
condition: {type: capability, field: tesla_has_vehicle_bus, equals: true}
# Hide everything but a clearly-marked release branch (matches Raylib
# _is_release_branch = is_release OR is_sp_release).
# Hide on sunnypilot release branches (is_release is hardcoded False everywhere; is_sp_release is the active gate).
release_branches_hide:
- type: not
condition:
type: any
conditions:
- {type: capability, field: is_release, equals: true}
- {type: capability, field: is_sp_release, equals: true}
condition: {type: capability, field: is_sp_release, equals: true}
@@ -21,14 +21,7 @@ sections:
title: Dynamic Experimental Control
description: Let the model decide when to use sunnypilot ACC or sunnypilot End to End Longitudinal.
visibility:
- type: any
conditions:
- type: capability
field: has_longitudinal_control
equals: true
- type: capability
field: has_icbm
equals: true
- $ref: '#/macros/longitudinal'
enablement:
- $ref: '#/macros/longitudinal'
- key: DisengageOnAccelerator
@@ -26,8 +26,6 @@ sections:
- key: JoystickDebugMode
widget: toggle
title: Joystick Debug Mode
visibility:
- $ref: '#/macros/release_branches_hide'
enablement:
- $ref: '#/macros/offroad'
- key: AlphaLongitudinalEnabled
@@ -46,14 +44,9 @@ sections:
equals: true
- type: not
condition:
type: any
conditions:
- type: capability
field: is_release
equals: true
- type: capability
field: is_sp_release
equals: true
type: capability
field: has_icbm
equals: true
enablement:
- $ref: '#/macros/not_engaged'
- key: ShowDebugInfo
@@ -131,9 +124,6 @@ sections:
condition:
type: any
conditions:
- type: capability
field: is_release
equals: true
- type: capability
field: is_sp_release
equals: true
@@ -15,6 +15,7 @@ compiled output once the compiler has produced it.
"""
from __future__ import annotations
import difflib
import json
import os
@@ -44,7 +45,16 @@ def committed() -> dict:
class TestRoundtrip:
def test_compiled_matches_committed(self, compiled, committed):
"""Compiled output must match the checked-in JSON."""
assert compiled == committed
if compiled == committed:
return
diff = "\n".join(difflib.unified_diff(
json.dumps(committed, indent=2).splitlines(),
json.dumps(compiled, indent=2).splitlines(),
fromfile="settings_ui.json (committed)",
tofile="settings_ui.json (freshly compiled)",
lineterm="",
))
pytest.fail(f"settings_ui.json schema mismatch — run compile_settings_ui.py\n\n{diff}")
def test_committed_file_is_canonical(self):
"""Compiled output must byte-match the checked-in file (including trailing newline).
@@ -53,7 +63,16 @@ class TestRoundtrip:
rendered = json.dumps(schema, indent=2) + "\n"
with open(DEFAULT_OUT) as f:
current = f.read()
assert current == rendered, "settings_ui.json out of sync — run compile_settings_ui.py"
if current == rendered:
return
diff = "\n".join(difflib.unified_diff(
current.splitlines(),
rendered.splitlines(),
fromfile="settings_ui.json (on disk)",
tofile="settings_ui.json (freshly compiled)",
lineterm="",
))
pytest.fail(f"settings_ui.json out of sync — run compile_settings_ui.py\n\n{diff}")
class TestRefResolution:
@@ -181,17 +181,14 @@ class TestTorqueOptionGeneration:
class TestReleaseBranchGates:
@pytest.mark.parametrize("key", [
"JoystickDebugMode",
"AlphaLongitudinalEnabled",
"EnableGithubRunner",
"QuickBootToggle",
])
def test_sp_dev_items_gate_on_is_sp_release(self, schema, key):
"""SP dev items must hide on either release branch (is_release OR is_sp_release)."""
"""sunnypilot dev items must hide on sunnypilot release branches (is_sp_release gate)."""
item = _find_item(schema, key)
assert item is not None, f"{key} not found in schema"
rules = (item.get("visibility") or []) + (item.get("enablement") or [])
assert _references_capability_field(rules, "is_release"), f"{key} missing is_release gate"
assert _references_capability_field(rules, "is_sp_release"), f"{key} missing is_sp_release gate"
+35
View File
@@ -4,7 +4,10 @@ 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 json
from openpilot.common.swaglog import cloudlog
from openpilot.sunnypilot.selfdrive.car.sync_car_list_param import CAR_LIST_JSON_OUT
ONROAD_BRIGHTNESS_MIGRATION_VERSION: str = "1.0"
ONROAD_BRIGHTNESS_TIMER_MIGRATION_VERSION: str = "1.0"
@@ -14,6 +17,36 @@ ONROAD_BRIGHTNESS_TIMER_VALUES = {0: 3, 1: 5, 2: 7, 3: 10, 4: 15, 5: 30, **{i: (
VALID_TIMER_VALUES = set(ONROAD_BRIGHTNESS_TIMER_VALUES.values())
def _migrate_car_platform_bundle(_params):
bundle = _params.get("CarPlatformBundle")
if bundle is None:
return
old_platform = bundle.get("platform")
if not old_platform:
return
from opendbc.car.fingerprints import MIGRATION # lazy: avoids heavy import at module level
if old_platform not in MIGRATION:
return
new_platform = str(MIGRATION[old_platform])
with open(CAR_LIST_JSON_OUT) as f:
car_list = json.load(f)
candidates = [(k, v) for k, v in car_list.items() if v.get("platform") == new_platform]
if candidates:
old_model = bundle.get("model")
key, data = next(((k, v) for k, v in candidates if v.get("model") == old_model), candidates[0])
bundle = {**data, "name": key}
else:
bundle["platform"] = new_platform
_params.put("CarPlatformBundle", bundle)
cloudlog.info(f"params_migration: CarPlatformBundle migrated {old_platform!r} -> {new_platform!r}")
def run_migration(_params):
# migrate OnroadScreenOffBrightness
if _params.get("OnroadScreenOffBrightnessMigrated") != ONROAD_BRIGHTNESS_MIGRATION_VERSION:
@@ -45,3 +78,5 @@ def run_migration(_params):
cloudlog.info(log_str + f" Setting OnroadScreenOffTimerMigrated to {ONROAD_BRIGHTNESS_TIMER_MIGRATION_VERSION}")
except Exception as e:
cloudlog.exception(f"Error migrating OnroadScreenOffTimer: {e}")
_migrate_car_platform_bundle(_params)
+2 -2
View File
@@ -35,8 +35,8 @@ def manager_init() -> None:
params.clear_all(ParamKeyFlag.CLEAR_ON_ONROAD_TRANSITION)
params.clear_all(ParamKeyFlag.CLEAR_ON_OFFROAD_TRANSITION)
params.clear_all(ParamKeyFlag.CLEAR_ON_IGNITION_ON)
if build_metadata.release_channel:
params.clear_all(ParamKeyFlag.DEVELOPMENT_ONLY)
# if build_metadata.release_channel:
# params.clear_all(ParamKeyFlag.DEVELOPMENT_ONLY)
# device boot mode
if params.get("DeviceBootMode") == 1: # start in Always Offroad mode