
Productive Robotics
Jog Controls Overhaul
Redesigned the robot's manual jog control system across the full stack — fixing 5 distinct frontend bugs in Vue.js touch event handling and a C++ real-time control bug where a Butterworth smoothing filter silently attenuated incremental jog commands to 4% of commanded distance. The fix required tracing through Vue touch events → ROS WebSocket messaging → C++ trajectory buffer signal processing.
Diagnosed 5 distinct frontend bugs in the Vue.js jog controls: (1) Touch + mouse double-fire on touch devices (both touchstart and mousedown triggered, sending duplicate jog commands). (2) Stop command interference — handleRelease emitted a 'release' event that triggered a zero-velocity jog command, fighting the incremental move. (3) updatePosition(0,0) sent speed=0 which stickChangeXY interpreted as a stop command, canceling the jog. (4) Visual joystick snap timing caused the UI to reset before the command was sent. (5) Speed multiplier removal required refactoring how jog speeds were calculated.
Implemented a 200ms tap/hold detection system: on pointerdown, a 200ms timer starts. If the pointer releases before 200ms → incremental jog (single fixed-distance move). If the pointer is still held after 200ms → continuous jog (robot moves until release). This unified interaction pattern replaced the previous broken system where tap and hold modes had separate, conflicting code paths. The detection uses setPointerCapture() for reliable tracking even when the pointer leaves the joystick element bounds.
The C++ backend bug was the most subtle: the TrajectoryBuffer's Butterworth low-pass filter (coefficient=500) passed only 0.2% of each position delta per cycle at 1kHz. For continuous jogs, new commands arrive every cycle and the filter converges over 500+ cycles — the operator sees smooth motion. For incremental jogs, one command is issued, the trajectory completes after ~20 cycles (~20ms), and is cleared from the buffer — but the filter has only output ~4% of the commanded motion. The robot moved ~0.4mm instead of 10mm. Fix: Added setSmoothingEnabled(bool) to the trajectory buffer, disabled for incremental moves, preserved for continuous jog.