Runs the Solver asynchronously in a WebWorker. The worker owns a copy of the frames and the
resulting joint values are copied back onto the frames on the main thread as solves complete.
import { HemisphereLight, MathUtils } from 'three';
import URDFLoader from 'urdf-loader';
import { Goal, URDFUtils, IKUtils } from 'closed-chain-ik';
import { WorkerSolver } from 'closed-chain-ik/worker';
// scene, camera and renderer are initialized here
const URL = 'https://raw.githubusercontent.com/gkjohnson/urdf-loaders/master/urdf/T12/urdf/T12_flipped.URDF';
scene.add( new HemisphereLight( 0xffffff, 0x444444, 3 ) );
camera.position.set( 6, 5, 8 );
const robot = await new URDFLoader().loadAsync( URL );
robot.rotation.x = Math.PI / 2;
robot.position.y = 1.25;
for ( let i = 1; i <= 6; i ++ ) {
robot.setJointValue( `HP${ i }`, MathUtils.degToRad( 30 ) );
robot.setJointValue( `KP${ i }`, MathUtils.degToRad( 90 ) );
robot.setJointValue( `AP${ i }`, MathUtils.degToRad( - 30 ) );
}
robot.updateMatrixWorld( true );
scene.add( robot );
const ik = URDFUtils.urdfRobotToIKRoot( robot );
URDFUtils.setIKFromUrdf( ik, robot );
IKUtils.saveRestPose( ik );
const goals = {};
ik.traverse( frame => {
if ( ! /^Foot/.test( frame.name ) ) return;
const goal = new Goal();
goal.makeClosure( frame );
frame.getWorldPosition( goal.position );
frame.getWorldQuaternion( goal.quaternion );
goal.setMatrixNeedsUpdate();
goals[ frame.name ] = goal;
} );
const goal = goals.Foot1;
const start = [ ...goal.position ];
const solver = new WorkerSolver( ik );
renderer.setAnimationLoop( time => {
const angle = time / 800;
goal.setPosition( start[ 0 ] + 0.6 * Math.cos( angle ), start[ 1 ] - 0.2 + 0.6 * Math.sin( angle ), start[ 2 ] );
solver.updateFrameState( goal );
if ( ! solver.running ) solver.solve();
URDFUtils.setUrdfFromIK( robot, ik );
renderer.render( scene, camera );
} );On this page
Properties
The roots to solve for. If modified updateStructure must be called.
The SOLVE_STATUS of each chain from the most recent solve in the worker.
Whether a solve is running in the worker.
Methods
new WorkerSolver(
// The roots of the trees to solve.
roots: Frame | Array<Frame>
)updateStructure(): voidSends the structure of the trees to the worker. Must be called whenever the parent child structure, the degrees of freedom of a joint, or the joint values are changed on the main thread.
updateSolverSettings(
// Option names and values as listed on `Solver`.
settings: Object
): voidSets the given Solver options on the solver in the worker.
updateFrameState(
// The frames to copy.
...frames: Frame
): voidCopies the frame transforms and joint settings, everything except the joint values being solved for, to the worker. Copies every frame if none are given.
solve(): voidStarts a solve loop in the worker if one is not running. The loop stops on its own once no
chain returns SOLVE_STATUS.TIMEOUT.
stop(): voidStops the solve loop in the worker.
dispose(): voidStops the solve loop and terminates the worker.