Skip to content

Add arc-length easing to mouse trajectory for natural velocity profile#231

Open
ulziibay-kernel wants to merge 1 commit intomainfrom
ulziibay/arc-length-velocity-easing
Open

Add arc-length easing to mouse trajectory for natural velocity profile#231
ulziibay-kernel wants to merge 1 commit intomainfrom
ulziibay/arc-length-velocity-easing

Conversation

@ulziibay-kernel
Copy link
Copy Markdown
Contributor

@ulziibay-kernel ulziibay-kernel commented Apr 27, 2026

Summary

Replaces index-based easeOutQuad point sampling in tweenPoints with arc-length-based easeInOutCubic sampling, so the Bezier trajectory produces physically varying pixel distances per step — small at start/end, large in the middle.

Problem

PR #228 added Gaussian timing jitter to mouse movement delays, but velocity = distance / time. The distance component was still near-constant (~15px per step) because the old easeOutQuad sampled by array index, which doesn't translate to physical spacing:

step 1: 15px in 28ms → velocity 0.54
step 2: 15px in 42ms → velocity 0.36
step 3: 15px in 35ms → velocity 0.43
step 4: 15px in 51ms → velocity 0.29

Velocity variance stays low (~0.08-3.21) despite varying timing, because pixel distance is constant.

Real human movement has a bell-shaped velocity profile (Fitts's law):

step 1:  3px in 45ms → velocity 0.07  (starting slow)
step 2: 12px in 20ms → velocity 0.60  (accelerating)
step 3: 25px in 15ms → velocity 1.67  (fast middle)
step 4:  8px in 55ms → velocity 0.15  (decelerating)

Fix

tweenPoints now:

  1. Builds a cumulative arc-length table along the raw Bezier curve
  2. Maps uniform t ∈ [0,1] through easeInOutCubic to get non-uniform arc-length positions
  3. Binary searches the arc-length table and linearly interpolates to get precise point coordinates

This produces:

  • Start/end: dense points, small pixel steps → slow velocity (acceleration/deceleration)
  • Middle: sparse points, large pixel steps → fast velocity (peak speed)

Combined with Gaussian timing from #228, velocity = (varying distance) / (varying time) → high variance matching human motor noise.

Test plan

  • TestHumanizeMouseTrajectory_VelocityProfile — verifies middle steps are larger than initial steps (acceleration profile) and step distance variance is substantial (>5)
  • All 15 existing mousetrajectory tests pass
  • All computer API tests pass

Made with Cursor


Note

Medium Risk
Moderate risk because it changes the core point-sampling algorithm and could alter downstream mouse movement behavior/anti-bot characteristics, though it’s localized and covered by a new regression test.

Overview
Updates HumanizeMouseTrajectory.tweenPoints to replace index-based easeOutQuad sampling with arc-length-based sampling driven by easeInOutCubic, including binary search + interpolation and guards for short/zero-length paths, so consecutive step distances vary (slow at start/end, faster mid-curve).

Adds TestHumanizeMouseTrajectory_VelocityProfile to assert the new bell-shaped step-distance profile (middle steps larger than early steps, with non-trivial variance).

Reviewed by Cursor Bugbot for commit f2c8aa5. Bugbot is set up for automated code reviews on this repo. Configure here.

The previous tweenPoints used easeOutQuad on array indices, producing
near-constant pixel distances between consecutive points (~15px per
step). With Gaussian timing jitter (PR #228), velocity = distance/time
still has low variance because the distance component is constant.

Real human mouse movement follows a bell-shaped velocity profile:
slow acceleration from rest, peak speed in the middle, deceleration
to the target (Fitts's law / minimum-jerk model). This requires
varying the pixel distance per step, not just the timing.

Replace index-based easeOutQuad with arc-length-based easeInOutCubic:
- Build cumulative arc-length table along the Bezier curve
- Sample at non-uniform arc-length positions via easeInOutCubic
- Binary search + linear interpolation for sub-segment precision

Result: steps range from ~3px at endpoints to ~25px in the middle,
creating the distance variance that produces human-like velocity
variance when combined with Gaussian timing.

Made-with: Cursor
@firetiger-agent
Copy link
Copy Markdown

Firetiger deploy monitoring skipped

This PR didn't match the auto-monitor filter configured on your GitHub connection:

Any PR that changes the kernel API. Monitor changes to API endpoints (packages/api/cmd/api/) and Temporal workflows (packages/api/lib/temporal) in the kernel repo

Reason: This PR modifies mouse trajectory easing logic (likely in a client or utility package), not kernel API endpoints or Temporal workflows as specified in the filter.

To monitor this PR anyway, reply with @firetiger monitor this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant