v0.0.7
closed-chain-ik
Inverse kinematics solver for closed-chain and parallel mechanisms commonly found in robotics. Enables solving complex linkage systems like hexapod platforms, delta robots, and other parallel manipulators.
inverse kinematicsroboticsgame dev
import { HemisphereLight, MathUtils } from 'three';
import URDFLoader from 'urdf-loader';
import { Solver, Goal, IKRootsHelper, URDFUtils, IKUtils } from 'closed-chain-ik';
// 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 );
// an IK tree matching the robot; its root keeps all six degrees of freedom, so the body can move
const ik = URDFUtils.urdfRobotToIKRoot( robot );
URDFUtils.setIKFromUrdf( ik, robot );
IKUtils.saveRestPose( ik );
// a goal holds each foot where it stands, closing six chains through the body
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();
} );
// a goal on the body holds it level and moves it in a circle while it bobs up and down; the legs
// follow to keep the feet planted
const body = ik.find( frame => frame.name === 'Body' );
const bodyGoal = new Goal();
bodyGoal.makeClosure( body );
body.getWorldQuaternion( bodyGoal.quaternion );
const start = [ 0, 0, 0 ];
body.getWorldPosition( start );
// draw the IK links and joints, solid where visible and faint through the robot
const helper = new IKRootsHelper( ik );
helper.setColor( 0xe91e63 );
const drawThroughHelper = new IKRootsHelper( ik );
drawThroughHelper.setColor( 0xe91e63 );
drawThroughHelper.setDrawThrough( true );
scene.add( helper, drawThroughHelper );
const solver = new Solver( ik );
renderer.setAnimationLoop( time => {
const angle = time / 800;
bodyGoal.setPosition( start[ 0 ] + 0.4 * Math.cos( angle ), start[ 1 ] + 0.35 * Math.sin( 2 * angle ), start[ 2 ] + 0.4 * Math.sin( angle ) );
solver.solve();
URDFUtils.setUrdfFromIK( robot, ik );
renderer.render( scene, camera );
} );Install
npm install github:gkjohnson/closed-chain-ik-js#v0.0.7Changelog
0.0.7
Added
- "closed-chain-ik/core", "closed-chain-ik/three", and "closed-chain-ik/worker" entry points so the three.js and worker code can be imported separately.
Changed
- "WorkerSolver" must now be imported from "closed-chain-ik/worker" instead of the root entry point.
- Steps that increase the error are retried at smaller scales within the same iteration instead of being reverted and shrinking every following step.
- SVD solves damp near singular directions with a threshold that adapts as steps are rejected or accepted so steps stay bounded near singularities.
Fixed
- "useSVD" silently falling back to damped least squares when there are more free DoF than constraint rows.
- Jacobian columns for joints above a closure fork only accounting for one side of the closure.
- Solver throwing when a chain has no free degrees of freedom or when a joint with "targetSet" is part of a solved chain, and target joints stepping away from their targets.
- Target joint rotation error using a signed sum so opposing or negative errors could report as converged.
- Cached Jacobian pseudo inverse being reused after "dampingFactor" or "useSVD" changed.
- Frame.setWorldQuaternion producing the wrong result when the frame already had a local rotation, and Frame.traverseParents leaving shared traversal state in use after an early stop.
- Joint.getDoFQuaternion, getRestPoseQuaternion, and getTargetQuaternion treating radians as degrees.
- URDFUtils.setIKFromUrdf not transferring the root rotation to the IK root DoF.
- WorkerSolver.stop not stopping the worker and "running" being cleared prematurely.
- IKRootsHelper.dispose throwing and removed helpers being retained after updateStructure.
0.0.6
Added
- Basic benchmark for solve.
- Used damped pseudo inverse for SVD case.
- Make progressively smaller step sizes towards goals if an IK chain is diverging.
- Jacobian pseudo inverse caching for opportunistic performance gain.
- Added "saveRestPose" to "IKUtils" export.
Changed
- Simplified internal Matrix initialization.
- Use analytic Jacobian.
- Remove "translationStep" and "rotatinoStep" options.
- Use a simplified formulation for rest pose calculations for a significant speed up when using rest pose.
- Move "findRoots" to "IKUtils" export.
- Moved "urdfRobotToIKRoot", "setUrdfFromIK", "setIKFromUrdf" to URDFUtils export.
- URDFUtils.setIKFromUrdf: Root DoF values are now set with taking the IK root into account.
- URDFUtils.urdfRobotToIKRoot: The produced IK system now accounts for any existing changes to the URDF joint values.
Fixed
- Fixed case where Matrices were not zeroed out when fetched from MatrixPool, possibly causing some outdated values to be used in calculations.
0.0.5
Fixed
- Adjust package version requirements.
- Set the type and module entry in the package.
- Updated the project to work with three.js r159 and up.
Changed
- Removed
IKRootsHelper.setResolution.