Spaces:
Running
Running
| import { describe, expect, it } from "vitest"; | |
| import { | |
| clamp, | |
| degToRad, | |
| flat16, | |
| matrixToRpyDeg, | |
| nest16, | |
| radToDeg, | |
| rpyToMatrixDeg, | |
| worldHeadYawDeg, | |
| } from "../../src/util/math"; | |
| // Cross-validation oracle: the SDK's own math utilities. | |
| import { matrixToRpy as sdkMatrixToRpy, rpyToMatrix as sdkRpyToMatrix } from "@pollen-robotics/reachy-mini-sdk"; | |
| describe("basic conversions", () => { | |
| it("deg/rad round-trip", () => { | |
| expect(degToRad(180)).toBeCloseTo(Math.PI, 10); | |
| expect(radToDeg(Math.PI / 2)).toBeCloseTo(90, 10); | |
| expect(radToDeg(degToRad(33.3))).toBeCloseTo(33.3, 10); | |
| }); | |
| it("clamp", () => { | |
| expect(clamp(5, -1, 1)).toBe(1); | |
| expect(clamp(-5, -1, 1)).toBe(-1); | |
| expect(clamp(0.5, -1, 1)).toBe(0.5); | |
| }); | |
| it("flat16/nest16 round-trip", () => { | |
| const flat = Array.from({ length: 16 }, (_, i) => i); | |
| const nested = nest16(flat); | |
| expect(nested).toHaveLength(4); | |
| expect(nested[2]).toEqual([8, 9, 10, 11]); | |
| expect(flat16(nested)).toEqual(flat); | |
| expect(flat16(flat)).toEqual(flat); | |
| }); | |
| it("worldHeadYawDeg composes body + local", () => { | |
| expect(worldHeadYawDeg(45, -25)).toBe(20); | |
| }); | |
| }); | |
| describe("rpy ↔ matrix", () => { | |
| it("identity at zero", () => { | |
| const m = rpyToMatrixDeg(0, 0, 0); | |
| expect(m[0]).toBeCloseTo(1); | |
| expect(m[5]).toBeCloseTo(1); | |
| expect(m[10]).toBeCloseTo(1); | |
| expect(m[15]).toBe(1); | |
| }); | |
| it("round-trips across the safe envelope", () => { | |
| for (const [r, p, y] of [ | |
| [0, 0, 0], | |
| [10, -20, 30], | |
| [-39, 39, -170], | |
| [5.5, -12.25, 61], | |
| ] as const) { | |
| const back = matrixToRpyDeg(rpyToMatrixDeg(r, p, y)); | |
| expect(back.roll).toBeCloseTo(r, 6); | |
| expect(back.pitch).toBeCloseTo(p, 6); | |
| expect(back.yaw).toBeCloseTo(y, 6); | |
| } | |
| }); | |
| it("matches the SDK's rotation convention", () => { | |
| for (const [r, p, y] of [ | |
| [10, 20, 30], | |
| [-25, 15, -60], | |
| [0, -40, 120], | |
| ] as const) { | |
| const ours = rpyToMatrixDeg(r, p, y); | |
| const theirs = flat16(sdkRpyToMatrix(r, p, y) as unknown as number[][] | number[]); | |
| theirs.forEach((v, i) => expect(ours[i]).toBeCloseTo(v, 8)); | |
| const back = sdkMatrixToRpy(nest16(ours) as never) as { roll: number; pitch: number; yaw: number }; | |
| expect(back.roll).toBeCloseTo(r, 6); | |
| expect(back.pitch).toBeCloseTo(p, 6); | |
| expect(back.yaw).toBeCloseTo(y, 6); | |
| } | |
| }); | |
| }); | |