From 30907c3cf9ca69416f92bce1dce3e8423f28390f Mon Sep 17 00:00:00 2001 From: discountchubbs Date: Sun, 13 Jul 2025 20:21:33 -0700 Subject: [PATCH] Affix to generation, while allowing older models to use this IF param is set. --- common/params_keys.h | 1 + .../qt/offroad/settings/models_panel.cc | 8 ++++ .../qt/offroad/settings/models_panel.h | 1 + .../modeld_v2/parse_model_outputs_split.py | 41 +++++++++++++------ system/manager/manager.py | 1 + 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/common/params_keys.h b/common/params_keys.h index e7c4e11745..baa19f3fa1 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -150,6 +150,7 @@ inline static std::unordered_map keys = { {"MadsUnifiedEngagementMode", PERSISTENT | BACKUP}, // Model Manager params + {"DynamicModeldOutputs", PERSISTENT | BACKUP}, {"ModelManager_ActiveBundle", PERSISTENT}, {"ModelManager_DownloadIndex", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION}, {"ModelManager_LastSyncTime", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION}, diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/models_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/models_panel.cc index 1a2e86622a..3f3790389c 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/models_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/models_panel.cc @@ -89,6 +89,14 @@ ModelsPanel::ModelsPanel(QWidget *parent) : QWidget(parent) { list->addItem(horizontal_line()); + // Dynamic Modeld Outputs toggle + dynamicModeldOutputs = new ParamControlSP("DynamicModeldOutputs", tr("Allow Dynamic Model Outputs"), + tr("Enable this to allow dynamic model output parsing on all models produced " + "after September, 2024. The affects of this toggle have been noted to make " + "Gas and Brake controls noticeably smoother."), + "../assets/offroad/icon_shell.png"); + list->addItem(dynamicModeldOutputs); + // LiveDelay toggle lagd_toggle_control = new ParamControlSP("LagdToggle", tr("Live Learning Steer Delay"), "", "../assets/offroad/icon_shell.png"); lagd_toggle_control->showDescription(); diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/models_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/models_panel.h index 61f15e6d3c..e0458c6f96 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/models_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/models_panel.h @@ -64,6 +64,7 @@ private: bool is_onroad = false; ButtonControlSP *currentModelLblBtn; + ParamControlSP *dynamicModeldOutputs; ParamControlSP *lagd_toggle_control; OptionControlSP *delay_control; QProgressBar *supercomboProgressBar; diff --git a/sunnypilot/modeld_v2/parse_model_outputs_split.py b/sunnypilot/modeld_v2/parse_model_outputs_split.py index 56d3235de2..fa3167af83 100644 --- a/sunnypilot/modeld_v2/parse_model_outputs_split.py +++ b/sunnypilot/modeld_v2/parse_model_outputs_split.py @@ -1,5 +1,7 @@ import numpy as np +from openpilot.common.params import Params from openpilot.sunnypilot.models.split_model_constants import SplitModelConstants +from openpilot.sunnypilot.models.helpers import get_active_bundle def safe_exp(x, out=None): @@ -24,6 +26,9 @@ def softmax(x, axis=-1): class Parser: def __init__(self, ignore_missing=False): self.ignore_missing = ignore_missing + self._params = Params() + model_bundle = get_active_bundle() + self.generation = model_bundle.generation if model_bundle is not None else None def check_missing(self, outs, name): if name not in outs and not self.ignore_missing: @@ -88,21 +93,31 @@ class Parser: outs[name] = pred_mu_final.reshape(final_shape) outs[name + '_stds'] = pred_std_final.reshape(final_shape) - def split_outputs(self, outs: dict[str, np.ndarray]) -> None: - if 'lead' in outs: - if outs['lead'].shape[1] == 2 * SplitModelConstants.LEAD_MHP_SELECTION *SplitModelConstants.LEAD_TRAJ_LEN * SplitModelConstants.LEAD_WIDTH: - self.parse_mdn('lead', outs, in_N=0, out_N=0, - out_shape=(SplitModelConstants.LEAD_MHP_SELECTION, SplitModelConstants.LEAD_TRAJ_LEN,SplitModelConstants.LEAD_WIDTH)) - else: + def parse_dynamic_outputs(self, outs: dict[str, np.ndarray]) -> None: + if self._params.get_bool("DynamicModeldOutputs") or (self.generation >= 12): + if 'lead' in outs: + if outs['lead'].shape[1] == 2 * SplitModelConstants.LEAD_MHP_SELECTION *SplitModelConstants.LEAD_TRAJ_LEN * SplitModelConstants.LEAD_WIDTH: + self.parse_mdn('lead', outs, in_N=0, out_N=0, + out_shape=(SplitModelConstants.LEAD_MHP_SELECTION, SplitModelConstants.LEAD_TRAJ_LEN,SplitModelConstants.LEAD_WIDTH)) + else: + self.parse_mdn('lead', outs, in_N=SplitModelConstants.LEAD_MHP_N, out_N=SplitModelConstants.LEAD_MHP_SELECTION, + out_shape=(SplitModelConstants.LEAD_TRAJ_LEN,SplitModelConstants.LEAD_WIDTH)) + if 'plan' in outs: + if outs['plan'].shape[1] > 2 * SplitModelConstants.PLAN_WIDTH * SplitModelConstants.IDX_N: + self.parse_mdn('plan', outs, in_N=SplitModelConstants.PLAN_MHP_N, out_N=SplitModelConstants.PLAN_MHP_SELECTION, + out_shape=(SplitModelConstants.IDX_N,SplitModelConstants.PLAN_WIDTH)) + else: + self.parse_mdn('plan', outs, in_N=0, out_N=0, + out_shape=(SplitModelConstants.IDX_N,SplitModelConstants.PLAN_WIDTH)) + else: + if 'lead' in outs: self.parse_mdn('lead', outs, in_N=SplitModelConstants.LEAD_MHP_N, out_N=SplitModelConstants.LEAD_MHP_SELECTION, - out_shape=(SplitModelConstants.LEAD_TRAJ_LEN,SplitModelConstants.LEAD_WIDTH)) - if 'plan' in outs: - if outs['plan'].shape[1] > 2 * SplitModelConstants.PLAN_WIDTH * SplitModelConstants.IDX_N: + out_shape=(SplitModelConstants.LEAD_TRAJ_LEN,SplitModelConstants.LEAD_WIDTH)) + if 'plan' in outs: self.parse_mdn('plan', outs, in_N=SplitModelConstants.PLAN_MHP_N, out_N=SplitModelConstants.PLAN_MHP_SELECTION, out_shape=(SplitModelConstants.IDX_N,SplitModelConstants.PLAN_WIDTH)) - else: - self.parse_mdn('plan', outs, in_N=0, out_N=0, - out_shape=(SplitModelConstants.IDX_N,SplitModelConstants.PLAN_WIDTH)) + + def split_outputs(self, outs: dict[str, np.ndarray]) -> None: if 'lane_lines' in outs: self.parse_mdn('lane_lines', outs, in_N=0, out_N=0, out_shape=(SplitModelConstants.NUM_LANE_LINES,SplitModelConstants.IDX_N,SplitModelConstants.LANE_LINES_WIDTH)) @@ -117,12 +132,14 @@ class Parser: self.parse_mdn('pose', outs, in_N=0, out_N=0, out_shape=(SplitModelConstants.POSE_WIDTH,)) self.parse_mdn('wide_from_device_euler', outs, in_N=0, out_N=0, out_shape=(SplitModelConstants.WIDE_FROM_DEVICE_WIDTH,)) self.parse_mdn('road_transform', outs, in_N=0, out_N=0, out_shape=(SplitModelConstants.POSE_WIDTH,)) + self.parse_dynamic_outputs(outs) self.split_outputs(outs) self.parse_categorical_crossentropy('desire_pred', outs, out_shape=(SplitModelConstants.DESIRE_PRED_LEN,SplitModelConstants.DESIRE_PRED_WIDTH)) self.parse_binary_crossentropy('meta', outs) return outs def parse_policy_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]: + self.parse_dynamic_outputs(outs) self.split_outputs(outs) if 'lat_planner_solution' in outs: self.parse_mdn('lat_planner_solution', outs, in_N=0, out_N=0, out_shape=(SplitModelConstants.IDX_N,SplitModelConstants.LAT_PLANNER_SOLUTION_WIDTH)) diff --git a/system/manager/manager.py b/system/manager/manager.py index b68207b691..c0c8813e48 100755 --- a/system/manager/manager.py +++ b/system/manager/manager.py @@ -55,6 +55,7 @@ def manager_init() -> None: ("CustomAccShortPressIncrement", "1"), ("DeviceBootMode", "0"), ("DynamicExperimentalControl", "0"), + ("DynamicModeldOutputs", "0"), ("HyundaiLongitudinalTuning", "0"), ("InteractivityTimeout", "0"), ("LagdToggle", "1"),