dualsense-ts
Version:
The natural interface for your DualSense Classic and DualSense Access controllers, with Typescript
44 lines • 1.48 kB
JavaScript
;
/**
* Minimal quaternion math for AHRS sensor fusion.
*
* Quaternions are represented as [w, x, y, z] tuples where w is the
* scalar part. All functions are pure — no mutations, no allocations
* beyond the returned tuple.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.IDENTITY = void 0;
exports.normalize = normalize;
exports.toEuler = toEuler;
/** Identity quaternion — no rotation. */
exports.IDENTITY = [1, 0, 0, 0];
/** Normalize a quaternion to unit length. */
function normalize(q) {
const [w, x, y, z] = q;
const invNorm = 1 / Math.sqrt(w * w + x * x + y * y + z * z);
return [w * invNorm, x * invNorm, y * invNorm, z * invNorm];
}
/**
* Extract Euler angles (Tait-Bryan ZYX intrinsic) from a unit quaternion.
*
* Convention: pitch = X-axis, yaw = Y-axis, roll = Z-axis.
* All angles in radians, range (-PI, PI].
*/
function toEuler(q) {
const [w, x, y, z] = q;
// Roll (Z-axis)
const sinr = 2 * (w * z + x * y);
const cosr = 1 - 2 * (y * y + z * z);
const roll = Math.atan2(sinr, cosr);
// Pitch (X-axis)
const sinp = 2 * (w * x - y * z);
const pitch = Math.abs(sinp) >= 1
? Math.sign(sinp) * (Math.PI / 2) // gimbal lock
: Math.asin(sinp);
// Yaw (Y-axis)
const siny = 2 * (w * y + z * x);
const cosy = 1 - 2 * (x * x + y * y);
const yaw = Math.atan2(siny, cosy);
return { pitch, yaw, roll };
}
//# sourceMappingURL=quaternion.js.map