mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
112 lines
3.4 KiB
JavaScript
112 lines
3.4 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
advanceUrdfJointValues,
|
|
easeUrdfJointAnimation,
|
|
interpolateUrdfJointValues,
|
|
jointValueMapsClose,
|
|
URDF_JOINT_ANIMATION_DURATION_MS,
|
|
URDF_JOINT_ANIMATION_FOLLOW_MS
|
|
} from "./jointAnimation.js";
|
|
|
|
function roundedMap(values) {
|
|
return Object.fromEntries(
|
|
Object.entries(values).map(([key, value]) => [key, Math.round(value * 1000) / 1000])
|
|
);
|
|
}
|
|
|
|
test("easeUrdfJointAnimation clamps progress to the animation range", () => {
|
|
assert.equal(easeUrdfJointAnimation(-1), 0);
|
|
assert.equal(easeUrdfJointAnimation(1.5), 1);
|
|
assert.equal(easeUrdfJointAnimation(0), 0);
|
|
assert.equal(easeUrdfJointAnimation(1), 1);
|
|
assert.equal(easeUrdfJointAnimation(0.5), 0.5);
|
|
assert.ok(easeUrdfJointAnimation(0.25) < 0.25);
|
|
assert.ok(easeUrdfJointAnimation(0.75) > 0.75);
|
|
});
|
|
|
|
test("URDF joint animations use a deliberate smooth duration", () => {
|
|
assert.equal(URDF_JOINT_ANIMATION_DURATION_MS, 840);
|
|
assert.equal(URDF_JOINT_ANIMATION_FOLLOW_MS, 240);
|
|
});
|
|
|
|
test("interpolateUrdfJointValues eases each target joint value", () => {
|
|
const halfway = interpolateUrdfJointValues(
|
|
{ shoulder: 0, elbow: 10 },
|
|
{ shoulder: 90, elbow: -10 },
|
|
0.5
|
|
);
|
|
|
|
assert.equal(halfway.done, false);
|
|
assert.deepEqual(roundedMap(halfway.values), {
|
|
elbow: 0,
|
|
shoulder: 45
|
|
});
|
|
});
|
|
|
|
test("interpolateUrdfJointValues uses the shortest wrapped path for continuous joints", () => {
|
|
const halfway = interpolateUrdfJointValues(
|
|
{ shoulder: -170 },
|
|
{ shoulder: 170 },
|
|
0.5,
|
|
undefined,
|
|
new Set(["shoulder"])
|
|
);
|
|
|
|
assert.equal(halfway.done, false);
|
|
assert.deepEqual(roundedMap(halfway.values), {
|
|
shoulder: -180
|
|
});
|
|
});
|
|
|
|
test("interpolateUrdfJointValues snaps to target values at completion", () => {
|
|
const result = interpolateUrdfJointValues(
|
|
{ shoulder: 89.9995, elbow: 10 },
|
|
{ shoulder: 90 },
|
|
1
|
|
);
|
|
|
|
assert.equal(result.done, true);
|
|
assert.deepEqual(result.values, { shoulder: 90 });
|
|
});
|
|
|
|
test("advanceUrdfJointValues follows moving targets without overshooting", () => {
|
|
const first = advanceUrdfJointValues({ shoulder: 0 }, { shoulder: 90 }, 16);
|
|
const redirected = advanceUrdfJointValues(first.values, { shoulder: 30 }, 16);
|
|
|
|
assert.equal(first.done, false);
|
|
assert.ok(first.values.shoulder > 0);
|
|
assert.ok(first.values.shoulder < 90);
|
|
assert.equal(redirected.done, false);
|
|
assert.ok(redirected.values.shoulder > first.values.shoulder);
|
|
assert.ok(redirected.values.shoulder < 30);
|
|
});
|
|
|
|
test("advanceUrdfJointValues snaps close values to the target", () => {
|
|
const result = advanceUrdfJointValues({ shoulder: 89.9995 }, { shoulder: 90 }, 16);
|
|
|
|
assert.equal(result.done, true);
|
|
assert.deepEqual(result.values, { shoulder: 90 });
|
|
});
|
|
|
|
test("advanceUrdfJointValues rotates continuous joints along the shortest path", () => {
|
|
const result = advanceUrdfJointValues(
|
|
{ shoulder: -170 },
|
|
{ shoulder: 170 },
|
|
16,
|
|
undefined,
|
|
undefined,
|
|
new Set(["shoulder"])
|
|
);
|
|
|
|
assert.equal(result.done, false);
|
|
assert.ok(result.values.shoulder < -170);
|
|
assert.ok(result.values.shoulder > -190);
|
|
});
|
|
|
|
test("jointValueMapsClose compares normalized finite joint values", () => {
|
|
assert.equal(jointValueMapsClose({ shoulder: "90" }, { shoulder: 90.0005 }), true);
|
|
assert.equal(jointValueMapsClose({ shoulder: 90, elbow: 0 }, { shoulder: 90 }), false);
|
|
assert.equal(jointValueMapsClose({ shoulder: 90 }, { shoulder: 91 }), false);
|
|
});
|