Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Kinetic movement: cursor follows classical mechanics with
- * fluid (but not viscous) drag and Coulombian kinetic friction.
- *
- * Parameters:
- *
- * accn: acceleration when `key_down`
- * drag: drag coefficient
- * fric: friction coefficient
- * maxs: max speed in `report_mouse_t` units / 15ms
- *
- * Non-linear ODE (Riccati w/ q₁ = 0) model:
- *
- * a(t) = fric + (key_down(t) ? diagonal(t) ? accn/√2 : accn : 0)
- * dv(t)/dt = dir(t) × a(t) - sgn(v(t)) × (fric + drag × v(t)²)
- *
- * where `v(t)` is velocity, with `dir(t)` ∈ {0,±1}, `key_down(t)`, and
- * `diagonal(t)` corresponding to the state of the mousekey arrows.
- *
- * Note the `fric` term in the definition of `a(t)`, such that we
- * are _barely_ able to overcome friction when `accn` is set to 0.
- * This feels like the more intuitive behaviour for the end-user,
- * rather than requiring `accn > fric` for any acceleration at all.
- *
- * For `v(t) > 0`, `a(t) - fric = accn`, and starting with `v(0) = 0`,
- * there is a closed-form solution for `v(t)`:
- *
- * v(t) = √(accn/drag) × tanh(√(accn × drag) × t)
- *
- * Numerical approximation:
- *
- * Playing fast & loose with the Euler method, we can rewrite
- * the above as a recurrence relation with time step `dt`:
- *
- * v(t+dt) = v(t) + a(t) × dt
- * - sgn(v) × (fric + drag × v(t)²) × dt
- *
- * from which we derive the displacement for the current step:
- *
- * ds(t) = ½(v(t+dt) + v(t)) × dt
- *
- * We scale this by `maxs` to give `report_mouse_t` units.
- *
- * References:
- *
- * https://en.wikipedia.org/wiki/Drag_equation
- * https://en.wikipedia.org/wiki/Coulomb_damping
- * https://en.wikipedia.org/wiki/Ordinary_differential_equation
- * https://en.wikipedia.org/wiki/Euler_method
- * https://en.wikipedia.org/wiki/Riccati_equation with q₁ = 0
- * https://www.wolframalpha.com/ solve dv/dt = a - d × v(t)²; v(0) = 0
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement