mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-19 02:50:46 -04:00
precision camera stuff
This commit is contained in:
@@ -49,6 +49,7 @@ const CONTROL_ACTION_NAMES = [
|
||||
'setServoAngle',
|
||||
'nudgeServo',
|
||||
'goServoHome',
|
||||
'setCameraPrecisionMode',
|
||||
'runMacro',
|
||||
'stopAllMotion',
|
||||
'sendOiCommand',
|
||||
@@ -411,6 +412,15 @@ export function ControlSystemProvider({ children }) {
|
||||
setServoAngle(target);
|
||||
}, [pipeline.servoConfig, setServoAngle]);
|
||||
|
||||
const setCameraPrecisionMode = useCallback((active) => {
|
||||
/*
|
||||
This action only changes how the browser chooses servo increments. The Pi
|
||||
already accepts decimal angle targets, so no server or rover command shape
|
||||
changes are needed for precision camera mode.
|
||||
*/
|
||||
dispatch({ type: 'control/set-camera-precision-mode', payload: Boolean(active) });
|
||||
}, []);
|
||||
|
||||
const runMacro = useCallback(
|
||||
async (macroId) => {
|
||||
const macro = state.macros.find((item) => item.id === macroId) || null;
|
||||
@@ -675,6 +685,7 @@ export function ControlSystemProvider({ children }) {
|
||||
setServoAngle,
|
||||
nudgeServo,
|
||||
goServoHome,
|
||||
setCameraPrecisionMode,
|
||||
runMacro,
|
||||
stopAllMotion,
|
||||
sendOiCommand,
|
||||
@@ -701,6 +712,7 @@ export function ControlSystemProvider({ children }) {
|
||||
setServoAngle,
|
||||
nudgeServo,
|
||||
goServoHome,
|
||||
setCameraPrecisionMode,
|
||||
runMacro,
|
||||
stopAllMotion,
|
||||
sendOiCommand,
|
||||
|
||||
@@ -20,6 +20,12 @@ function createCameraState() {
|
||||
enabled: false,
|
||||
angle: null,
|
||||
config: null,
|
||||
/*
|
||||
Servo precision is UI/control state, not rover hardware state. Keeping it
|
||||
beside the camera angle lets every camera-tilt surface use the same
|
||||
precision setting while still sending the normal decimal angle commands.
|
||||
*/
|
||||
precisionMode: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -110,6 +116,7 @@ export function controlReducer(state, action) {
|
||||
...state.camera,
|
||||
enabled: Boolean(action.payload?.config),
|
||||
config: action.payload?.config ?? null,
|
||||
precisionMode: action.payload?.config ? state.camera.precisionMode : false,
|
||||
angle:
|
||||
typeof action.payload?.angle === 'number'
|
||||
? action.payload.angle
|
||||
@@ -123,6 +130,22 @@ export function controlReducer(state, action) {
|
||||
...state,
|
||||
camera: { ...state.camera, angle: action.payload },
|
||||
};
|
||||
case 'control/set-camera-precision-mode':
|
||||
if (state.camera.precisionMode === Boolean(action.payload)) {
|
||||
return state;
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
camera: {
|
||||
...state.camera,
|
||||
/*
|
||||
Movement inputs own this flag because precision camera mode is meant
|
||||
to follow movement precision mode automatically instead of becoming a
|
||||
separate toggle the driver has to remember to reset.
|
||||
*/
|
||||
precisionMode: Boolean(action.payload),
|
||||
},
|
||||
};
|
||||
case 'control/register-input-state': {
|
||||
const sourceKey = action.payload?.source || 'unknown';
|
||||
return {
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
computeKeyboardAuxMotors,
|
||||
computeKeyboardDriveVector,
|
||||
getKeyboardDriveSpeedOptions,
|
||||
isPrecisionDriveActive,
|
||||
resolveKeyboardSpeeds,
|
||||
} from './driveIntent.js';
|
||||
import { trackAnalyticsEvent } from '../../analytics/index.js';
|
||||
@@ -34,6 +35,7 @@ const TILT_INTERVAL_MIN = 5;
|
||||
const TILT_INTERVAL_MAX = 500;
|
||||
const TILT_SPEED_MIN = 1;
|
||||
const TILT_SPEED_MAX = 100;
|
||||
const PRECISION_SERVO_NUDGE_DEGREES = 0.25;
|
||||
const VIDEO_FILTER_SEQUENCE = ['none', 'grayscale', 'greenscale'];
|
||||
|
||||
function normalizeVideoFilter(value) {
|
||||
@@ -91,6 +93,7 @@ export default function KeyboardInputManager() {
|
||||
runMacro,
|
||||
stopAllMotion,
|
||||
registerInputState,
|
||||
setCameraPrecisionMode,
|
||||
toggleHeadlight,
|
||||
toggleLaser,
|
||||
startHorn,
|
||||
@@ -157,9 +160,16 @@ export default function KeyboardInputManager() {
|
||||
const latest = latestRef.current;
|
||||
if (!latest) return;
|
||||
const tokensSnapshot = new Set(activeTokensRef.current);
|
||||
const precisionActive = isPrecisionDriveActive(tokensSnapshot, latest.keymap);
|
||||
const speedOptions = getKeyboardDriveSpeedOptions(tokensSnapshot, latest.keymap, latest.keyboardSpeeds);
|
||||
const vector = computeKeyboardDriveVector(tokensSnapshot, latest.keymap);
|
||||
const aux = computeKeyboardAuxMotors(tokensSnapshot, latest.keymap);
|
||||
/*
|
||||
Keyboard precision is a held modifier, so publish the camera precision
|
||||
state from the same token snapshot that drives movement. This keeps the
|
||||
servo UI in lockstep with the actual precision-driving intent.
|
||||
*/
|
||||
latest.setCameraPrecisionMode(precisionActive);
|
||||
if (
|
||||
vector.x !== lastVectorRef.current.x ||
|
||||
vector.y !== lastVectorRef.current.y ||
|
||||
@@ -219,7 +229,10 @@ export default function KeyboardInputManager() {
|
||||
stopServoLoop();
|
||||
return;
|
||||
}
|
||||
latest.nudgeServo(nextDirection * latest.servoStep);
|
||||
const tokensSnapshot = new Set(activeTokensRef.current);
|
||||
const precisionActive = isPrecisionDriveActive(tokensSnapshot, latest.keymap);
|
||||
const servoStep = precisionActive ? PRECISION_SERVO_NUDGE_DEGREES : latest.servoStep;
|
||||
latest.nudgeServo(nextDirection * servoStep);
|
||||
servoIntervalRef.current = setTimeout(tick, latest.servoRepeatMs);
|
||||
};
|
||||
servoIntervalRef.current = setTimeout(tick, 0);
|
||||
@@ -288,6 +301,7 @@ export default function KeyboardInputManager() {
|
||||
latest?.stopHorn();
|
||||
}
|
||||
latest?.setMicPttActive(false);
|
||||
latest?.setCameraPrecisionMode(false);
|
||||
latest?.stopAllMotion();
|
||||
latest?.registerInputState(SOURCE, { keys: [], vector: ZERO_VECTOR, aux: ZERO_AUX });
|
||||
}, [stopServoLoop, stopSongLoop]);
|
||||
@@ -369,6 +383,7 @@ export default function KeyboardInputManager() {
|
||||
servoRepeatMs,
|
||||
servoStep,
|
||||
setAuxMotors,
|
||||
setCameraPrecisionMode,
|
||||
setDriveVector,
|
||||
setMicPttActive,
|
||||
setMode,
|
||||
|
||||
@@ -54,6 +54,16 @@ export function computeKeyboardDriveVector(keys, keymap) {
|
||||
};
|
||||
}
|
||||
|
||||
export function isPrecisionDriveActive(keys, keymap) {
|
||||
/*
|
||||
The slow modifier is the canonical precision-drive signal shared by physical
|
||||
keyboard input and the mobile pad's virtual-key path. Centralizing the check
|
||||
keeps camera precision coupled to the same driver intent instead of copying
|
||||
modifier-specific knowledge into each caller.
|
||||
*/
|
||||
return bindingActive(keymap?.slowModifier, keys);
|
||||
}
|
||||
|
||||
export function computeKeyboardAuxMotors(keys, keymap) {
|
||||
const allForward = bindingActive(keymap.auxAllForward, keys);
|
||||
if (allForward) {
|
||||
@@ -78,7 +88,7 @@ export function computeKeyboardAuxMotors(keys, keymap) {
|
||||
}
|
||||
|
||||
export function getKeyboardDriveSpeedOptions(keys, keymap, keyboardSpeeds) {
|
||||
const slowActive = bindingActive(keymap.slowModifier, keys);
|
||||
const slowActive = isPrecisionDriveActive(keys, keymap);
|
||||
return slowActive
|
||||
? { baseSpeed: keyboardSpeeds.precisionSpeed, boostSpeed: keyboardSpeeds.precisionSpeed }
|
||||
: { baseSpeed: keyboardSpeeds.baseSpeed, boostSpeed: keyboardSpeeds.turboSpeed };
|
||||
|
||||
Reference in New Issue
Block a user