[auto] highlight active step detection segments on graphs
Yellow background highlights the time range when a step is active (from detection until reset). L/R graph highlights step-left and step-right, F/B graph highlights step-forward and step-back. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>main
parent
26e3df6ad2
commit
9ad8dea4ff
|
|
@ -20,6 +20,7 @@ function drawGraph(
|
|||
getRight: (s: StepGraphSample) => number,
|
||||
threshold: number,
|
||||
reset: number,
|
||||
activeSignals: string[], // which step signals to highlight for this graph
|
||||
) {
|
||||
// Background
|
||||
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)'
|
||||
|
|
@ -39,6 +40,17 @@ function drawGraph(
|
|||
const toY = (v: number) => h / 2 - (v / maxAbs) * (h / 2 - 4)
|
||||
const toX = (i: number) => (i / (samples.length - 1)) * w
|
||||
|
||||
// Highlight active step segments
|
||||
for (let i = 0; i < samples.length; i++) {
|
||||
const s = samples[i]
|
||||
if (s.activeStep && activeSignals.includes(s.activeStep)) {
|
||||
const x0 = toX(i)
|
||||
const x1 = i < samples.length - 1 ? toX(i + 1) : x0 + 2
|
||||
ctx.fillStyle = 'rgba(255, 255, 0, 0.15)'
|
||||
ctx.fillRect(x0, 0, x1 - x0, h)
|
||||
}
|
||||
}
|
||||
|
||||
// Zero line
|
||||
ctx.strokeStyle = '#555'
|
||||
ctx.lineWidth = 1
|
||||
|
|
@ -124,10 +136,12 @@ export function StepGraphs({ samples, thresholdX, thresholdZ, reset, width = 280
|
|||
const fbCtx = fbCanvas.getContext('2d')!
|
||||
|
||||
drawGraph(lrCtx, samples, width, height, 'LEFT / RIGHT (X)',
|
||||
(s) => s.leftX, (s) => s.rightX, thresholdX, reset)
|
||||
(s) => s.leftX, (s) => s.rightX, thresholdX, reset,
|
||||
['step-left', 'step-right'])
|
||||
|
||||
drawGraph(fbCtx, samples, width, height, 'FORWARD / BACK (Z)',
|
||||
(s) => s.leftZ, (s) => s.rightZ, thresholdZ, reset)
|
||||
(s) => s.leftZ, (s) => s.rightZ, thresholdZ, reset,
|
||||
['step-forward', 'step-back'])
|
||||
}, [samples, thresholdX, thresholdZ, reset, width, height])
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ export interface StepGraphSample {
|
|||
rightX: number // right heel X displacement from baseline
|
||||
leftZ: number // left heel Z displacement from baseline
|
||||
rightZ: number // right heel Z displacement from baseline
|
||||
activeStep: GestureSignal // which step is active this frame (null if none)
|
||||
}
|
||||
|
||||
export interface GestureState {
|
||||
|
|
@ -285,23 +286,9 @@ export function detectGesture(
|
|||
}
|
||||
if (!leftAirborne || !rightAirborne) state.wasAirborne = false
|
||||
|
||||
// Collect step graph samples
|
||||
if (state.heelBaseL && state.heelBaseR && worldLandmarks?.length >= 33) {
|
||||
const lh = worldLandmarks[29], rh = worldLandmarks[30]
|
||||
state.stepGraph.push({
|
||||
time: now,
|
||||
leftX: lh.x - state.heelBaseL.x,
|
||||
rightX: rh.x - state.heelBaseR.x,
|
||||
leftZ: lh.z - state.heelBaseL.z,
|
||||
rightZ: rh.z - state.heelBaseR.z,
|
||||
})
|
||||
if (state.stepGraph.length > GRAPH_HISTORY) state.stepGraph.shift()
|
||||
}
|
||||
|
||||
// Step detection (worldLandmarks heel displacement from baseline)
|
||||
if (state.heelBaseL && state.heelBaseR && worldLandmarks?.length >= 33) {
|
||||
if (state.activeStep) {
|
||||
// Check if feet returned to center
|
||||
if (stepsReset(worldLandmarks, state.heelBaseL, state.heelBaseR, stepCfg)) {
|
||||
state.activeStep = null
|
||||
}
|
||||
|
|
@ -309,9 +296,28 @@ export function detectGesture(
|
|||
const step = detectStep(worldLandmarks, state.heelBaseL, state.heelBaseR, stepCfg)
|
||||
if (step) {
|
||||
state.activeStep = step
|
||||
// Collect sample before emitting (so this frame is captured)
|
||||
const lh = worldLandmarks[29], rh = worldLandmarks[30]
|
||||
state.stepGraph.push({
|
||||
time: now,
|
||||
leftX: lh.x - state.heelBaseL.x, rightX: rh.x - state.heelBaseR.x,
|
||||
leftZ: lh.z - state.heelBaseL.z, rightZ: rh.z - state.heelBaseR.z,
|
||||
activeStep: state.activeStep,
|
||||
})
|
||||
if (state.stepGraph.length > GRAPH_HISTORY) state.stepGraph.shift()
|
||||
return emit(step)
|
||||
}
|
||||
}
|
||||
|
||||
// Collect step graph sample (after detection so activeStep is current)
|
||||
const lh = worldLandmarks[29], rh = worldLandmarks[30]
|
||||
state.stepGraph.push({
|
||||
time: now,
|
||||
leftX: lh.x - state.heelBaseL.x, rightX: rh.x - state.heelBaseR.x,
|
||||
leftZ: lh.z - state.heelBaseL.z, rightZ: rh.z - state.heelBaseR.z,
|
||||
activeStep: state.activeStep,
|
||||
})
|
||||
if (state.stepGraph.length > GRAPH_HISTORY) state.stepGraph.shift()
|
||||
}
|
||||
|
||||
// Palms together
|
||||
|
|
|
|||
Loading…
Reference in New Issue