option to disable bumpoff

This commit is contained in:
legop3
2026-03-25 21:43:28 -04:00
parent d74879caa9
commit 904f28eeef
5 changed files with 186 additions and 128 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -11,7 +11,7 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" /> <meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
<title>Multi Roomba Rover</title> <title>Multi Roomba Rover</title>
<script type="module" crossorigin src="/assets/index-DNMLDCtc.js"></script> <script type="module" crossorigin src="/assets/index-DWSaRjmF.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CwUXm7Ls.css"> <link rel="stylesheet" crossorigin href="/assets/index-CwUXm7Ls.css">
</head> </head>
<body> <body>
+22
View File
@@ -33,10 +33,15 @@ export default function SettingsPanel() {
hudMapDesktop: false, hudMapDesktop: false,
connectionTransport: 'websocket', connectionTransport: 'websocket',
swapMobileControlColumns: false, swapMobileControlColumns: false,
driveMacroBackoffEnabled: true,
}); });
const { value: audioSettings, save: saveAudioSettings } = useSettingsNamespace('audio', AUDIO_SETTINGS_DEFAULTS); const { value: audioSettings, save: saveAudioSettings } = useSettingsNamespace('audio', AUDIO_SETTINGS_DEFAULTS);
const connectionTransport = pageSettings?.connectionTransport || 'websocket'; const connectionTransport = pageSettings?.connectionTransport || 'websocket';
const swapMobileControlColumns = Boolean(pageSettings?.swapMobileControlColumns); const swapMobileControlColumns = Boolean(pageSettings?.swapMobileControlColumns);
const driveMacroBackoffEnabled =
typeof pageSettings?.driveMacroBackoffEnabled === 'boolean'
? pageSettings.driveMacroBackoffEnabled
: true;
const masterVolume = Number.isFinite(audioSettings?.masterVolume) ? audioSettings.masterVolume : AUDIO_SETTINGS_DEFAULTS.masterVolume; const masterVolume = Number.isFinite(audioSettings?.masterVolume) ? audioSettings.masterVolume : AUDIO_SETTINGS_DEFAULTS.masterVolume;
const alertVolume = Number.isFinite(audioSettings?.alertVolume) ? audioSettings.alertVolume : AUDIO_SETTINGS_DEFAULTS.alertVolume; const alertVolume = Number.isFinite(audioSettings?.alertVolume) ? audioSettings.alertVolume : AUDIO_SETTINGS_DEFAULTS.alertVolume;
const roverVolume = Number.isFinite(audioSettings?.roverVolume) ? audioSettings.roverVolume : AUDIO_SETTINGS_DEFAULTS.roverVolume; const roverVolume = Number.isFinite(audioSettings?.roverVolume) ? audioSettings.roverVolume : AUDIO_SETTINGS_DEFAULTS.roverVolume;
@@ -87,6 +92,11 @@ export default function SettingsPanel() {
const checked = Boolean(event.target.checked); const checked = Boolean(event.target.checked);
savePageSettings((current) => ({ ...(current ?? {}), swapMobileControlColumns: checked })); savePageSettings((current) => ({ ...(current ?? {}), swapMobileControlColumns: checked }));
}; };
const handleDriveMacroBackoffEnabled = (event) => {
const checked = Boolean(event.target.checked);
savePageSettings((current) => ({ ...(current ?? {}), driveMacroBackoffEnabled: checked }));
};
return ( return (
<Tabs defaultTab="keybindings"> <Tabs defaultTab="keybindings">
<TabList> <TabList>
@@ -133,6 +143,18 @@ export default function SettingsPanel() {
<span>Swap control columns (put joystick on the left)</span> <span>Swap control columns (put joystick on the left)</span>
</label> </label>
</section> </section>
<section className="panel-section space-y-0.5 text-sm">
<p className="text-slate-400">Macros</p>
<label className="flex items-center gap-0.5 text-slate-200">
<input
type="checkbox"
className="accent-emerald-500"
checked={driveMacroBackoffEnabled}
onChange={handleDriveMacroBackoffEnabled}
/>
<span>Enable backward bump in drive macro</span>
</label>
</section>
<section className="panel-section space-y-0.5 text-sm"> <section className="panel-section space-y-0.5 text-sm">
<p className="text-slate-400">Audio</p> <p className="text-slate-400">Audio</p>
<label className="grid gap-0.5 text-slate-200"> <label className="grid gap-0.5 text-slate-200">
+38 -2
View File
@@ -36,6 +36,23 @@ function clampServoAngle(config, value) {
return clamp(value, min, max); return clamp(value, min, max);
} }
function removeDriveSequenceBackoff(steps = []) {
if (!Array.isArray(steps) || steps.length < 3) return steps;
const last3 = steps.slice(-3);
const [backoffStep, pauseStep, stopStep] = last3;
const isBackoffStep =
backoffStep?.type === 'drive' &&
Number(backoffStep?.speeds?.left) === -300 &&
Number(backoffStep?.speeds?.right) === -300;
const isPauseStep = pauseStep?.type === 'pause' && Number(pauseStep?.duration) === 600;
const isStopStep =
stopStep?.type === 'drive' &&
Number(stopStep?.speeds?.left) === 0 &&
Number(stopStep?.speeds?.right) === 0;
if (!isBackoffStep || !isPauseStep || !isStopStep) return steps;
return steps.slice(0, -3);
}
export function ControlSystemProvider({ children }) { export function ControlSystemProvider({ children }) {
const [state, dispatch] = useReducer(controlReducer, initialControlState); const [state, dispatch] = useReducer(controlReducer, initialControlState);
const prevModeRef = useRef(null); const prevModeRef = useRef(null);
@@ -48,7 +65,12 @@ export function ControlSystemProvider({ children }) {
value: controlSettings, value: controlSettings,
save: saveControlSettings, save: saveControlSettings,
} = useSettingsNamespace('controls', { keymap: DEFAULT_KEYMAP, macros: DEFAULT_MACROS }); } = useSettingsNamespace('controls', { keymap: DEFAULT_KEYMAP, macros: DEFAULT_MACROS });
const { value: pageSettings } = useSettingsNamespace('page', { driveMacroBackoffEnabled: true });
const { value: hornSettings } = useSettingsNamespace('horn', HORN_SETTINGS_DEFAULTS); const { value: hornSettings } = useSettingsNamespace('horn', HORN_SETTINGS_DEFAULTS);
const driveMacroBackoffEnabled =
typeof pageSettings?.driveMacroBackoffEnabled === 'boolean'
? pageSettings.driveMacroBackoffEnabled
: true;
const { session, homeAssistantSetState } = useSession(); const { session, homeAssistantSetState } = useSession();
const roverId = session?.assignment?.roverId ?? null; const roverId = session?.assignment?.roverId ?? null;
const overcurrentLimiter = useOvercurrentLimiter(roverId); const overcurrentLimiter = useOvercurrentLimiter(roverId);
@@ -280,18 +302,32 @@ export function ControlSystemProvider({ children }) {
async (macroId) => { async (macroId) => {
const macro = state.macros.find((item) => item.id === macroId) || null; const macro = state.macros.find((item) => item.id === macroId) || null;
if (!macro) return; if (!macro) return;
let macroToRun = macro;
if (macroId === 'drive-sequence') { if (macroId === 'drive-sequence') {
turnOnAllLights(); turnOnAllLights();
if (!session?.homeAssistant?.entities) { if (!session?.homeAssistant?.entities) {
pendingLightsRef.current = true; pendingLightsRef.current = true;
} }
recordControlIntent(); recordControlIntent();
if (!driveMacroBackoffEnabled) {
macroToRun = {
...macro,
steps: removeDriveSequenceBackoff(macro.steps),
};
}
} else if (macroId === 'seek-dock') { } else if (macroId === 'seek-dock') {
recordControlIntent(); recordControlIntent();
} }
await pipeline.runMacroSteps(macro); await pipeline.runMacroSteps(macroToRun);
}, },
[pipeline, recordControlIntent, session?.homeAssistant?.entities, state.macros, turnOnAllLights], [
driveMacroBackoffEnabled,
pipeline,
recordControlIntent,
session?.homeAssistant?.entities,
state.macros,
turnOnAllLights,
],
); );
const stopAllMotion = useCallback(() => { const stopAllMotion = useCallback(() => {