oxmpl-js 0.6.0

JavaScript/WASM Bindings for the OxMPL Library
Documentation
import oxmpl from 'oxmpl-js';
import { describe, expect, test } from 'vitest';

class AngleGoal {
  constructor(space, targetAngle, radius) {
    this.space = space;
    this.target = new oxmpl.base.SO2State(targetAngle);
    this.radius = radius;
  }
  isSatisfied(state) {
    return this.space.distance(state, this.target) <= this.radius;
  }
  distanceGoal(state) {
    return Math.max(0, this.space.distance(state, this.target) - this.radius);
  }
  sampleGoal() {
    return new oxmpl.base.SO2State(this.target.value);
  }
}

describe('PRM SO2 Integration Tests', () => {
  test('PRM problem in SO2', () => {
    const space = new oxmpl.base.SO2StateSpace();
    const startState = new oxmpl.base.SO2State(-Math.PI / 2.0);
    const goalRegion = new AngleGoal(space, Math.PI / 2.0, 0.2);
    const goal = new oxmpl.base.Goal(goalRegion);
    const problemDef = oxmpl.base.ProblemDefinition.fromSO2State(space, startState, goal);

    const validityCheckerFn = (state) => {
      return !(state.value > -0.5 && state.value < 0.5);
    };
    const validityChecker = new oxmpl.base.StateValidityChecker(validityCheckerFn);

    const planner_config = new oxmpl.base.PlannerConfig(0);
    const planner = new oxmpl.geometric.PRM(1.0, 1.0, problemDef, planner_config);
    planner.setup(validityChecker);
    planner.constructRoadmap();

    const path = planner.solve(5.0);
    const states = path.getStates();
    expect(states.length).toBeGreaterThan(1);
    expect(space.distance(states[0], startState)).toBeLessThan(1e-9);
    expect(goalRegion.isSatisfied(states[states.length - 1])).toBe(true);

    for (const state of states) {
      expect(validityCheckerFn(state)).toBe(true);
    }
  });
});