Skip to content

Commit b4ef69c

Browse files
committed
fix: compare contact evals at report precision
1 parent 768943f commit b4ef69c

3 files changed

Lines changed: 26 additions & 2 deletions

File tree

packages/posecode-eval/src/checks.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ export const CONTACT_ERROR_MAX = REACH_TOLERANCE;
5858
*/
5959
export const LOCOMOTION_FOOT_CONTACT_MAX = 0.06;
6060

61+
/**
62+
* Compare contact residuals at the same millimetre precision shown in reports.
63+
* This avoids displaying an apparent equality such as 0.030m ≤ 0.030m while
64+
* failing because of a sub-millimetre solver difference.
65+
*/
66+
export function withinDisplayedContactTolerance(
67+
error: number,
68+
tolerance: number,
69+
): boolean {
70+
return Math.round(error * 1000) <= Math.round(tolerance * 1000);
71+
}
72+
6173
/** Find a phase by name; throws a failing outcome path if missing. */
6274
function phase(result: ProbeResult, name: string): PhasePose | null {
6375
return result.phases.find((p) => p.name === name) ?? null;
@@ -190,7 +202,7 @@ export function genericChecks(result: ProbeResult): CheckOutcome[] {
190202
clipTravels && footFloorContact ? LOCOMOTION_FOOT_CONTACT_MAX : CONTACT_ERROR_MAX;
191203
out.push({
192204
id: `contact-position:${suffix}`,
193-
pass: contact.error <= tolerance,
205+
pass: withinDisplayedContactTolerance(contact.error, tolerance),
194206
detail: `${contact.error.toFixed(3)}m residual (want ≤ ${tolerance.toFixed(3)}m)`,
195207
});
196208
});

packages/posecode-eval/src/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,13 @@ export {
5656
torsoForwardPitchDeg,
5757
torsoPitchDeg,
5858
} from "./metrics.js";
59-
export { CONTACT_ERROR_MAX, genericChecks, phaseCheck, MOVEMENT_CHECKS } from "./checks.js";
59+
export {
60+
CONTACT_ERROR_MAX,
61+
genericChecks,
62+
phaseCheck,
63+
withinDisplayedContactTolerance,
64+
MOVEMENT_CHECKS,
65+
} from "./checks.js";
6066
export type { CheckOutcome, MovementChecks } from "./checks.js";
6167
export { runEval, renderReport } from "./report.js";
6268
export type { EvalOptions, EvalReport, MovementReport, MovementSource } from "./report.js";

packages/posecode-eval/test/eval.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
palmFloorAngleDeg,
1818
phaseMaxLandmarkSpeed,
1919
spineCurlDeg,
20+
withinDisplayedContactTolerance,
2021
} from "../src/index.js";
2122

2223
const examplesDir = resolve(
@@ -25,6 +26,11 @@ const examplesDir = resolve(
2526
);
2627

2728
describe("probe", () => {
29+
it("judges contact residuals at the millimetre precision shown in reports", () => {
30+
expect(withinDisplayedContactTolerance(0.03049, 0.03)).toBe(true);
31+
expect(withinDisplayedContactTolerance(0.03051, 0.03)).toBe(false);
32+
});
33+
2834
it("reports parse errors instead of throwing", () => {
2935
const r = probeMovement("not posecode at all");
3036
expect(r.ok).toBe(false);

0 commit comments

Comments
 (0)