mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-19 00:02:08 +08:00
Curves
This commit is contained in:
@@ -36,6 +36,7 @@ const state = reactive({
|
||||
fetched: false,
|
||||
activeSectionSlug: "",
|
||||
numericUpdating: {},
|
||||
actionUpdating: {},
|
||||
favoriteLoading: false,
|
||||
favoriteSaving: false,
|
||||
favoriteOptions: [],
|
||||
@@ -860,6 +861,35 @@ async function resetNumericParam(param) {
|
||||
})
|
||||
}
|
||||
|
||||
async function runSettingAction(param) {
|
||||
const key = String(param?.key || "")
|
||||
const endpoint = String(param?.action_endpoint || "")
|
||||
if (!key || !endpoint || state.actionUpdating[key]) return
|
||||
|
||||
const confirmation = String(param?.confirm_message || `Run ${param?.label || key}?`)
|
||||
if (!window.confirm(confirmation)) return
|
||||
|
||||
state.actionUpdating = { ...state.actionUpdating, [key]: true }
|
||||
try {
|
||||
const response = await fetch(endpoint, { method: "POST" })
|
||||
const payload = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(payload.error || response.statusText || "Action failed")
|
||||
}
|
||||
|
||||
const updated = payload.updated && typeof payload.updated === "object" ? payload.updated : {}
|
||||
state.values = { ...state.values, ...updated }
|
||||
showParamSnackbar(payload.message || `${param?.label || key} completed.`)
|
||||
scheduleSyncInputs()
|
||||
} catch (error) {
|
||||
showParamSnackbar(error?.message || `${param?.label || key} failed.`, "error")
|
||||
} finally {
|
||||
const next = { ...state.actionUpdating }
|
||||
delete next[key]
|
||||
state.actionUpdating = next
|
||||
}
|
||||
}
|
||||
|
||||
async function updateParam(key, elType) {
|
||||
if (String(key).toLowerCase() === "starpilotfavoriteslots") {
|
||||
await saveFavoriteSlots(state.favoriteSlots)
|
||||
@@ -1230,6 +1260,7 @@ function renderSettingRow(p) {
|
||||
|
||||
const isNumeric = p.ui_type === "numeric"
|
||||
const isColor = p.ui_type === "color"
|
||||
const isAction = p.ui_type === "action"
|
||||
const isGroup = isGroupParam(p)
|
||||
const isChild = p.parent_key ? "ds-child-modifier" : ""
|
||||
const lockReason = () => getSettingLockReason(p)
|
||||
@@ -1238,7 +1269,16 @@ function renderSettingRow(p) {
|
||||
const flmTrialSummary = p.key === "AdvancedLateralTune" ? getFlmTrialSummary() : null
|
||||
let rowControl = ""
|
||||
|
||||
if (isNumeric) {
|
||||
if (isAction) {
|
||||
rowControl = html`
|
||||
<button
|
||||
class="ds-reset-btn"
|
||||
disabled="${() => isLocked() || !!state.actionUpdating[p.key]}"
|
||||
@click="${() => runSettingAction(p)}">
|
||||
${() => state.actionUpdating[p.key] ? "Resetting..." : (p.action_label || "Run")}
|
||||
</button>
|
||||
`
|
||||
} else if (isNumeric) {
|
||||
rowControl = html`
|
||||
<div class="ds-stepper-container">
|
||||
${(() => {
|
||||
|
||||
@@ -626,6 +626,16 @@
|
||||
"ui_type": "toggle",
|
||||
"parent_key": "CurveSpeedController"
|
||||
},
|
||||
{
|
||||
"key": "ResetCurveData",
|
||||
"label": "Reset Curve Data",
|
||||
"description": "Clear learned Curve Speed Controller data and begin training again from the default lateral acceleration.",
|
||||
"ui_type": "action",
|
||||
"action_label": "Reset",
|
||||
"action_endpoint": "/api/curve_speed_controller/reset",
|
||||
"confirm_message": "Reset all learned Curve Speed Controller data? Training will restart from the default value.",
|
||||
"parent_key": "CurveSpeedController"
|
||||
},
|
||||
{
|
||||
"key": "CustomPersonalities",
|
||||
"label": "Driving Personalities",
|
||||
|
||||
@@ -47,6 +47,7 @@ class WritableFakeParams:
|
||||
def __init__(self, values=None):
|
||||
self.values = dict(values or {})
|
||||
self.writes = []
|
||||
self.removals = []
|
||||
|
||||
def get(self, key, encoding=None, default=None, block=False):
|
||||
del encoding, block
|
||||
@@ -66,6 +67,10 @@ class WritableFakeParams:
|
||||
self.writes.append((key, bool(value)))
|
||||
self.values[key] = bool(value)
|
||||
|
||||
def remove(self, key):
|
||||
self.removals.append(key)
|
||||
self.values.pop(key, None)
|
||||
|
||||
|
||||
def _params_client(monkeypatch, values, device_type):
|
||||
fake_params = WritableFakeParams(values)
|
||||
@@ -236,3 +241,40 @@ def test_legacy_try_raylib_ui_payload_updates_use_old_ui(monkeypatch):
|
||||
assert fake_params.values["UseOldUI"] is False
|
||||
assert fake_params.values["TryRaylibUI"] is True
|
||||
assert fake_params.writes == [("UseOldUI", False), ("TryRaylibUI", True)]
|
||||
|
||||
|
||||
def test_curve_speed_controller_reset_clears_learned_data_offroad(monkeypatch):
|
||||
client, fake_params = _params_client(monkeypatch, {
|
||||
"IsOnroad": False,
|
||||
"CalibratedLateralAcceleration": 2.73,
|
||||
"CalibrationProgress": 48.0,
|
||||
"CurvatureData": {"0.01": {"average": 2.73, "count": 12}},
|
||||
}, "tici")
|
||||
|
||||
response = client.post("/api/curve_speed_controller/reset")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.get_json()["updated"] == {
|
||||
"CalibratedLateralAcceleration": 2.0,
|
||||
"CalibrationProgress": 0.0,
|
||||
}
|
||||
assert fake_params.values["CalibratedLateralAcceleration"] == 2.0
|
||||
assert "CalibrationProgress" not in fake_params.values
|
||||
assert "CurvatureData" not in fake_params.values
|
||||
assert fake_params.removals == ["CalibrationProgress", "CurvatureData"]
|
||||
|
||||
|
||||
def test_curve_speed_controller_reset_rejected_onroad(monkeypatch):
|
||||
client, fake_params = _params_client(monkeypatch, {
|
||||
"IsOnroad": True,
|
||||
"CalibratedLateralAcceleration": 2.73,
|
||||
"CalibrationProgress": 48.0,
|
||||
"CurvatureData": {"0.01": {"average": 2.73, "count": 12}},
|
||||
}, "tici")
|
||||
|
||||
response = client.post("/api/curve_speed_controller/reset")
|
||||
|
||||
assert response.status_code == 403
|
||||
assert response.get_json()["error"] == "Curve Speed Controller data can only be reset while parked."
|
||||
assert fake_params.writes == []
|
||||
assert fake_params.removals == []
|
||||
|
||||
@@ -4539,6 +4539,23 @@ def setup(app):
|
||||
return canonical_model_key(str(value).strip()), 200
|
||||
return value, 200
|
||||
|
||||
@app.route("/api/curve_speed_controller/reset", methods=["POST"])
|
||||
def reset_curve_speed_controller_data():
|
||||
if params.get_bool("IsOnroad"):
|
||||
return jsonify({"error": "Curve Speed Controller data can only be reset while parked."}), 403
|
||||
|
||||
params.put("CalibratedLateralAcceleration", 2.0)
|
||||
params.remove("CalibrationProgress")
|
||||
params.remove("CurvatureData")
|
||||
|
||||
return jsonify({
|
||||
"message": "Curve Speed Controller data reset. Training will restart on the next drive.",
|
||||
"updated": {
|
||||
"CalibratedLateralAcceleration": 2.0,
|
||||
"CalibrationProgress": 0.0,
|
||||
},
|
||||
}), 200
|
||||
|
||||
@app.route("/api/params/all", methods=["GET"])
|
||||
def get_all_params():
|
||||
migrate_cancel_button_controls(params)
|
||||
|
||||
Reference in New Issue
Block a user