Coder Social home page Coder Social logo

gkjohnson / closed-chain-ik-js Goto Github PK

View Code? Open in Web Editor NEW
164.0 9.0 26.0 6.39 MB

A generalized inverse kinematics solver that supports closed chains for parallel kinematics systems, dynamic reconfiguration, and arbitrary joint configuration based on damped least squares error minimization techniques

Home Page: https://gkjohnson.github.io/closed-chain-ik-js/dist/index.html

License: Apache License 2.0

JavaScript 97.43% HTML 2.57%
inverse-kinematics javascript threejs graphics robotics least-squares joints parallel animation control

closed-chain-ik-js's People

Contributors

dependabot[bot] avatar felixfaire avatar gkjohnson avatar lgtm-migrator avatar marcatec avatar minitoine avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

closed-chain-ik-js's Issues

Minimal example without three / ikHelper

Hi. It would be really helpful to have a minimalistic working example in the readme or the repo. I have tried to create a minimal example of the solver based on the "goals" sample with a basic procedurally moving goal and i cannot get the solver to converge even in the simplest of cases. Copying the "goals" samples line for line without the mouse interaction also seems to lead to "DIVERGED" or "STALLED" in every case. Is there something i am missing?

Here is the code I am trying to get working. Any help appreciated, thanks

const solverOptions = {
	maxIterations: 3,
	divergeThreshold: 0.005,
	stallThreshold: 1e-3,
	translationErrorClamp: 0.25,
	rotationErrorClamp: 0.25,
	translationConvergeThreshold: 1e-3,
	rotationConvergeThreshold: 1e-3,
	restPoseFactor: 0.001,
};

let ikRoot = null;
let currRoot = null;

for ( let i = 0; i < 6; i ++ ) {

  const link = new Link();
  const joint = new Joint();
  joint.setPosition( 0.0, 1.0, 0 );
  joint.setDoF( i % 2 ? DOF.EX : DOF.EZ );
  joint.setDoFValues( Math.PI / 4 );
  joint.setRestPoseValues( Math.PI / 4 );
  joint.restPoseSet = true;
  joint.setMinLimits( - 0.9 * Math.PI );
  joint.setMaxLimits( 0.9 * Math.PI );

  link.addChild( joint );

  if ( currRoot ) {
    currRoot.addChild( link );
  }

  if ( ikRoot === null ) {
    ikRoot = link;
  }

  currRoot = joint;
}

const finalLink = new Link();
finalLink.setPosition( 0, 0.5, 0 );
currRoot.addChild( finalLink );

// TODO: rotation seems not to work here
let goal = new Goal();
goal.makeClosure( finalLink );
goal.setGoalDoF(DOF.X, DOF.Y, DOF.Z);

// create solver
const solver = new Solver( [ ikRoot, goal ] );
Object.assign( solver, solverOptions );



..animationLoop() 
{
  goal.setPosition(Math.cos(elapsedTime) * 3.0, 3.0, 1.0);

  let statuses = solver.solve();
  
  let statusString = "";
  statuses.forEach((s, i) => {
    statusString+= SOLVE_STATUS_NAMES[statuses[i]] + ", ";
  })
  console.log(statusString);
}

Improve Solver Performance

  • Matrix operation performance (#1)
  • See if set for each can be improved
  • Linear solver memory (#2)
  • Don't use updateMatrixWorld( true ). Just call updateMatrixWorld() when needed to keep things up to date. (#17)

WorkerSolver: Improve memory footprint of shared buffer

  • Minimize memory footprints of update list -- maybe store a separate list for links from joints because links take up far less memory than the joints.

  • Only copy over what has changed or needs to change (send message to worker with diff?)

  • Array could be tightly packed and indices stored for each element

  • Goal don't need to take up as much data (#25)

  • Sort the links, joints, and goals so they are stored in links, joints, goals order and offsets can be stored for where each starts. Then unnecessary memory can be removed.

Related to #6

Links: Track closure joints

Track the closing joints in an array so they can be traversed and closure joints / goals don't need to be added to the solver separately.

core npm module / package

Amazing work.

It would be fantastic if the core parts of this lib could be abstracted into an npm package. From what I can see this would only need gl-matrix and linear-solve as dependancies which would also help reduce bundle size for projects not using three.js or needing model loading etc.

Use quaternion to represent error when a joint has 3 degrees of freedom and a target is set

It may just be easiest to handle a full quaternion here always. This is an issue with ball joints (3dof) that are not goals / closures because the solver will try to move all the individual joint degrees of freedom. Closures are comparing error using quaternion differences.

The complexity of using quaternions only when a joint is 3dof is complicated -- it would be best to pick one and stick with it.

Joints: Add a feature to weight the priority of solving a joint

Will need to multiply the jacobian delta error by the a weight.

Single weight per joint? Or different weight per Joint DoF?

Can this be accomplished by multiplying the jacobian entries by a weight and then dividing it out again after the solve when applying the angle?

WorkerSolver uses 3x memory

Memory for joint state is stored in the frames themselves, the shared arraybuffer, and the copy in the worker.

  • Use lower resolution arrays (32 bit vs 64)
  • Because the solver only ever modifies the DoFValues fields and the main thread is only expected to modify the others they could all just back their fields with the same large array buffer. It would be important that the goal data is only modified between solves, though, to avoid inconsistent solves.

API: Consider adding `getByName` function

To easily search and get the first element found by name. Would help when trying to get a joint or link by name from a URDF robot.

Alternatively a find function could be added that will let you pass a function like Array.find

Root joint / link cannot be used to create closure joint

const l1 = new Link();
const j1 = new Joint();
const l2 = new Link();
const j2 = new Joint();

l1.addChild( j1 );
j1.addChild( l2 );
j2.addChild( l1 ); // error because l1 is an ancestor

We likely need an explicit "create closure" function.

Use SVD approach to get pseudoinverse

For improved behavior at singularities / extended joints and numerical stability. Provide option to use SVD or transpose method or automatically choose the best approach?

This could help improve the null space projection rest pose jitter

WorkerSolver: Add API for using a custom worker

Something like an encapsulated class that can be instantiated in the worker that can listen to messages so users can write custom logic that listens to and modifies worker state manually.

class RemoteWorkerSolver extends Solver {

    consumeMessage( event );
    onDispatchMessage( event );

}
class WorkerSolver {

    constructor( roots, worker = new Worker( './WorkerSolver.worker.js' ) );

}

WorkerSolverRemote should also be able to use non synced joints so some joints can only live in the worker.

Open Questions

  • Should the solver automatically solve indefinitely until a non timeout result is hit? Or should it be up to the user worker to call solve?

IK Helper: Visualize joint limits

  • rotational limits
  • translation limits
  • make rotation limit visualizations a different color so they don't blend
  • hide infinite limits?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.