Wednesday, November 08, 2017

Trying Caliko FABRIK Inverse Kinematics in 2D

I downloaded Caliko, the FABRIK inverse kinematic solver in Java.  It has great documentation, along with guidance about how to properly use its jars as libraries in Eclipse (I don't do much Java, glad they mentioned that).  The Javadocs for Caliko is excellent, so I took one of their examples, removed the visualization and added information about the location of bones in the chain and the angles between them:

package caliko_test;
import au.edu.federation.caliko.*;
import au.edu.federation.caliko.FabrikChain2D.BaseboneConstraintType2D;
import au.edu.federation.caliko.visualisation.*;
import au.edu.federation.utils.*;
public class caliko_test {
public static void main(String[] args)
{
// reference unit vectors
Vec2f UP = new Vec2f(0.0f, 1.0f);
Vec2f DOWN = new Vec2f(0.0f, -1.0f);
Vec2f LEFT = new Vec2f(-1.0f, 0.0f);
Vec2f RIGHT = new Vec2f(1.0f, 0.0f);
FabrikStructure2D structure = new FabrikStructure2D();
FabrikChain2D chain = new FabrikChain2D();
chain.setFixedBaseMode(true);
float constraintAngle = 90.0f;
// Create the basebone, set constraints and add it to the chain
FabrikBone2D base = new FabrikBone2D(new Vec2f(0.0f,0.0f), new Vec2f(0.0f,56) );
base.setClockwiseConstraintDegs(constraintAngle);
base.setAnticlockwiseConstraintDegs(constraintAngle);
chain.addBone(base);
// Fix the basebone and constrain it to the positive Y-axis
chain.setBaseboneConstraintType(BaseboneConstraintType2D.GLOBAL_ABSOLUTE);
chain.setBaseboneConstraintUV(UP);
// Create and add the second bones
chain.addConsecutiveConstrainedBone(UP, 146f, constraintAngle, constraintAngle);
chain.addConsecutiveConstrainedBone(UP, 150f, constraintAngle, constraintAngle);
// Finally, add the chain to the structure
structure.addChain(chain);
Vec2f myTarget = new Vec2f(350f, 40f);
chain.setMaxIterationAttempts(15);
System.out.println("MaxIteractionAttempts: "+chain.getMaxIterationAttempts());
System.out.println("Distance to Target: " + chain.solveForTarget(myTarget));
for(int i=0;i<chain.getNumBones();++i){
System.out.println("Bone("+i+") DirectionUV: " + chain.getBone(i).getDirectionUV().toString());
if(i>0){
System.out.println("Angle of Bone("+(i-1)+") with Bone("+i+"): "+
chain.getBone(i-1).getDirectionUV().getSignedAngleDegsTo(chain.getBone(i).getDirectionUV()));
}
System.out.println("Bone("+i+") EndLocation: "+ chain.getBone(i).getEndLocation().x +","+chain.getBone(i).getEndLocation().y);
}
System.out.println("Target: " + myTarget.toString());
}
}

Here is an example solution output:

MaxIteractionAttempts: 15
Distance to Target: 2.0320811
Bone(0) DirectionUV: 0.949, 0.315
Bone(0) EndLocation: 53.155647,17.620361
Bone(1) DirectionUV: 0.992, 0.124
Angle of Bone(0) with Bone(1): -11.213276
Bone(1) EndLocation: 198.0278,35.73278
Bone(2) DirectionUV: 1.000, 0.028
Angle of Bone(1) with Bone(2): -5.5179296
Bone(2) EndLocation: 347.96872,39.942963
Target: 350.000, 40.000
Because I don't have a good OpenGL working right now, I just took the data from the chain and plotted it in Excel.  Here are some examples - the red dot is the target:



No comments: