@eroscripts/osr-emu
Version:
A web-based graphical emulator for open source strokers.
78 lines (65 loc) • 2.54 kB
text/typescript
import { constrain, map } from './util.js';
const MIN_SMOOTH_INTERVAL = 3; // Minimum auto-smooth ramp interval for live commands (ms)
const MAX_SMOOTH_INTERVAL = 100; // Maximum auto-smooth ramp interval for live commands (ms)
/**
* A class that emulates the behavior of an axis as coded on the OSR Firmware (v3.3)
*/
export default class Axis {
name = '';
_startTime = 0;
_startPosition = 5000;
_targetTime = 0;
_targetPosition = 5000;
_minInterval = MAX_SMOOTH_INTERVAL;
constructor(name: string) {
this.name = name;
}
set(magnitude: number, ext?: 'S' | 'I', extMagnitude: number = 0) {
const currentTime = performance.now();
magnitude = constrain(magnitude, 0, 9999);
extMagnitude = constrain(extMagnitude, 0, 9999999);
if (!extMagnitude || (ext !== 'S' && ext !== 'I')) {
// Live command
// Update auto-smooth regulator
const lastInterval = currentTime - this._startTime;
if (lastInterval > this._minInterval && this._minInterval < MAX_SMOOTH_INTERVAL) {
this._minInterval += 1;
}
else if (lastInterval < this._minInterval && this._minInterval > MIN_SMOOTH_INTERVAL) {
this._minInterval -= 1;
}
this._startPosition = this.getPosition();
this._targetTime = currentTime + this._minInterval;
}
else if (ext === 'S') {
// Speed command
const speed = extMagnitude / 100; // Interpret extMagntitude as units per 100 ms.
this._startPosition = this.getPosition();
const distance = Math.abs(magnitude - this._startPosition);
const duration = Math.floor(distance / speed);
this._targetTime = currentTime + duration;
}
else if (ext === 'I') {
// Interval command
const duration = extMagnitude; // Interpret extMagnitude as the duration of the move in ms.
this._startPosition = this.getPosition();
this._targetTime = currentTime + duration;
}
this._startTime = currentTime;
this._targetPosition = magnitude;
}
getPosition() {
let position; // 0 - 9999
const currentTime = performance.now();
if (currentTime > this._targetTime) {
position = this._targetPosition;
}
else if (currentTime > this._startTime) {
position = map(currentTime, this._startTime, this._targetTime, this._startPosition, this._targetPosition);
}
else {
position = this._startPosition;
}
return constrain(position, 0, 9999);
}
}