BowlerKernel
DeltaIKModel.java
Go to the documentation of this file.
1 package com.neuronrobotics.sdk.addons.kinematics.ik;
2 
3 import java.util.ArrayList;
4 
5 import com.neuronrobotics.sdk.addons.kinematics.DHChain;
6 import com.neuronrobotics.sdk.addons.kinematics.DHLink;
7 import com.neuronrobotics.sdk.addons.kinematics.DhInverseSolver;
8 import com.neuronrobotics.sdk.addons.kinematics.math.RotationNR;
9 import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR;
10 
11 public class DeltaIKModel implements DhInverseSolver {
12 
13  boolean debug = false;
14 
15  int limbIndex =0;
16 
17  @Override
18  public double[] inverseKinematics(TransformNR target, double[] jointSpaceVector, DHChain chain) {
19  return inverseKinematics6dof(target,jointSpaceVector,chain);
20  }
21  TransformNR linkOffset(DHLink link) {
22  return new TransformNR(link.DhStep(0));
23  }
24  double length(TransformNR tr) {
25  return Math.sqrt(
26  Math.pow(tr.getX(), 2)+
27  Math.pow(tr.getY(), 2)+
28  Math.pow(tr.getZ(), 2)
29  );
30  }
31 
32 
33  public double[] inverseKinematics6dof(TransformNR target, double[] jointSpaceVector, DHChain chain) {
34 
35  ArrayList<DHLink> links = chain.getLinks();
36  int linkNum = jointSpaceVector.length;
37  TransformNR l0Offset = linkOffset(links.get(0));
38  TransformNR l1Offset = linkOffset(links.get(1));
39  TransformNR l2Offset = linkOffset(links.get(2));
40  TransformNR l3Offset = linkOffset(links.get(3));
41  // Vector decompose the tip target
42  double z = target.getZ();
43  double y = target.getY();
44  double x = target.getX();
45  TransformNR targetNoRot =new TransformNR(x,y,z,new RotationNR());
46 
47  RotationNR q = target.getRotation();
48  TransformNR newCenter =target.copy();
49  // Start by finding the IK to the wrist center
50  if(linkNum>=6) {
51  //offset for tool
52  //if(debug)System.out.println( "Offestting for tool"
53  TransformNR tool = new TransformNR();
54  if(linkNum==7)
55  tool=linkOffset(links.get(6));
56  // compute the transform from tip to wrist center
57  TransformNR wristCenterOffsetTransform = linkOffset(links.get(5)).times(tool);
58  //System.out.println( wristCenterOffsetTransform
59  // take off the tool from the target to get the center of the wrist
60  newCenter = target.times(wristCenterOffsetTransform.inverse());
61  }
62 
63  // recompute the X,y,z with the new center
64  z = newCenter.getZ();
65  y = newCenter.getY();
66  x = newCenter.getX();
67  //xyz now are at the wrist center
68  // Compute the xy plane projection of the tip
69  // this is the angle of the tipto the base link
70  if(x==0&&y==0) {
71  System.out.println( "Singularity! try something else");
72  return inverseKinematics6dof(target.copy().translateX(0.01),jointSpaceVector,chain);
73  }
74  if(debug)System.out.println( "Wrist center for IK "+x+","+y+","+z);
75  double baseVectorAngle = Math.toDegrees(Math.atan2(y , x));
76  double elbowLink1CompositeLength = length(l1Offset);
77  double elbowLink2CompositeLength=length(l3Offset);
78  double wristVect = length(newCenter);
79  if(debug)System.out.println( "elbowLink1CompositeLength "+elbowLink1CompositeLength);
80  if(debug)System.out.println( "elbowLink2CompositeLength "+elbowLink2CompositeLength);
81  if(debug)System.out.println( "Elbo Hypotinuse "+wristVect);
82  double elbowTiltAngle =-( Math.toDegrees(
83  Math.acos(
84  (
85  Math.pow(elbowLink2CompositeLength,2)+
86  Math.pow(elbowLink1CompositeLength,2)
87  -Math.pow(wristVect,2)
88  )
89  /
90  (2*elbowLink2CompositeLength*elbowLink1CompositeLength)
91  )
92  ));
93  if(debug)System.out.println( "Elbow angle "+elbowTiltAngle);
94  jointSpaceVector[2]=elbowTiltAngle - Math.toDegrees(links.get(2).getTheta());
95 
96  TransformNR local = new TransformNR(0,0,0,new RotationNR(0, -baseVectorAngle, 0));
97  TransformNR tipOnXVect = local.times(newCenter);
98  double elZ = tipOnXVect.getZ();
99  double elX = tipOnXVect.getX();
100  double L1 = length(l1Offset);
101  double L2 = length(l3Offset);
102 
103  if(debug)System.out.println( "L1 "+L1+" l2 "+L2+" z "+elZ+" x "+elX);
111  double asinVal = elZ/L2;
112  if(asinVal>1 || asinVal<-1)
113  throw new RuntimeException("Target outside workspace, passive links too short to reach "+L2);
114  double theta2 = Math.asin(asinVal);
115 
116  double L3 = L2*Math.cos(theta2);
117  double theta1 = Math.acos(
118  (
119  Math.pow(L1, 2) +
120  Math.pow(elX, 2)-
121  Math.pow(L3, 2)
122  )/
123  (2 * L1 *elX)
124  );
125  jointSpaceVector[0]=-(90-(Math.toDegrees(theta1)+baseVectorAngle));
126  TransformNR reorent;
127  try {
128  reorent =new TransformNR(0,0,0,new RotationNR(0, -jointSpaceVector[0], 0));
129  }catch (Throwable t){
130  //t.printStackTrace()
131  throw new RuntimeException( "error calculating base angle: \nL1 "+L1+
132  " \nl2 "+L2+
133  " \nz "+elZ+
134  " \nx "+elX+
135  " \nl3 "+L3+
136  " \ntheta2 "+Math.toDegrees(theta2)+
137  " \nasinVal "+asinVal
138 
139  );
140  }
141  TransformNR sphericalElbowTartget = reorent.times(newCenter);
142  //System.out.println( newCenter
143  //System.out.println( sphericalElbowTartget
144  sphericalElbowTartget = new TransformNR(0.0,-sphericalElbowTartget.getY(),0.0, new RotationNR()).times(sphericalElbowTartget);
145  //System.out.println( sphericalElbowTartget
146  double theta3 = Math.atan2(sphericalElbowTartget.getZ(), sphericalElbowTartget.getX());
147  jointSpaceVector[1]=-Math.toDegrees(theta3) ;
148 
149  //return jointSpaceVector
150 
155  double[] wristLinks=new double[jointSpaceVector.length];
156  for(int i=0;i<3;i++) {
157  wristLinks[i]=jointSpaceVector[i];
158  }
159  for(int i=3;i<jointSpaceVector.length;i++) {
160  wristLinks[i]=0;
161  }
162  ArrayList<TransformNR> chainToLoad =new ArrayList<>();
163  chain.forwardKinematicsMatrix(wristLinks,chainToLoad);
164  TransformNR startOfWristSet=chain.kin.inverseOffset(chainToLoad.get(2));
165  TransformNR virtualcenter = newCenter.times(new TransformNR(0,0,10,
166  new RotationNR(Math.toDegrees(links.get(5).getAlpha()),0,0)));
167  TransformNR wristMOvedToCenter0 =startOfWristSet
168  .inverse()// move back from base ot wrist to world home
169  .times(virtualcenter);// move forward to target, leaving the angle between the tip and the start of the rotation
170  //if(debug)System.out.println( wristMOvedToCenter0
171  RotationNR qWrist=wristMOvedToCenter0.getRotation();
172  if(wristMOvedToCenter0.getX()==0&&wristMOvedToCenter0.getY()==0) {
173  System.out.println( "Singularity! try something else");
174  return inverseKinematics6dof(target.copy().translateX(0.01),jointSpaceVector,chain);
175  }
176  double closest= (Math.toDegrees(Math.atan2(wristMOvedToCenter0.getY(), wristMOvedToCenter0.getX()))-Math.toDegrees(links.get(3).getTheta()));
177 
178  jointSpaceVector[3]=closest;
179  wristLinks[3]=jointSpaceVector[3];
180  if(jointSpaceVector.length==4)
181  return jointSpaceVector;
182 
183  chainToLoad =new ArrayList<>();
188  chainToLoad.clear();
189  chain.forwardKinematicsMatrix(wristLinks,chainToLoad);
190  TransformNR startOfWristSet2=chain.kin.inverseOffset(chainToLoad.get(3));
191 
192  TransformNR wristMOvedToCenter1 =startOfWristSet2
193  .inverse()// move back from base ot wrist to world home
194  .times(virtualcenter);// move forward to target, leaving the angle between the tip and the start of the rotation
195  //if(debug)System.out.println( " Middle link =" +wristMOvedToCenter1
196  RotationNR qWrist2=wristMOvedToCenter1.getRotation();
197  if(wristMOvedToCenter1.getX()==0&&wristMOvedToCenter1.getY()==0) {
198  System.out.println( "Singularity! try something else");
199  return inverseKinematics6dof(target.copy().translateX(0.01),jointSpaceVector,chain);
200  }
201  jointSpaceVector[4]=(Math.toDegrees(Math.atan2(wristMOvedToCenter1.getY(), wristMOvedToCenter1.getX()))-
202  Math.toDegrees(links.get(4).getTheta())-
203  90);
204  wristLinks[4]=jointSpaceVector[4];
205  if(jointSpaceVector.length==5)
206  return jointSpaceVector;
207  chainToLoad =new ArrayList<>();
212  chain.forwardKinematicsMatrix(wristLinks,chainToLoad);
213  TransformNR startOfWristSet3=chain.kin.inverseOffset(chainToLoad.get(4));
214  TransformNR tool = new TransformNR();
215  if(linkNum==7)
216  tool=linkOffset(links.get(6));
217  TransformNR wristMOvedToCenter2 =startOfWristSet3
218  .inverse()// move back from base ot wrist to world home
219  .times(target.times(tool.inverse()));// move forward to target, leaving the angle between the tip and the start of the rotation
220  //if(debug)System.out.println( "\n\nLastLink " +wristMOvedToCenter2
221  RotationNR qWrist3=wristMOvedToCenter2.getRotation();
222  jointSpaceVector[5]=(Math.toDegrees(qWrist3.getRotationAzimuth())-Math.toDegrees(links.get(5).getTheta()));
223 
224  return jointSpaceVector;
225  }
226 
227 }
Matrix forwardKinematicsMatrix(double[] jointSpaceVector, boolean store)
Definition: DHChain.java:181
double[] inverseKinematics6dof(TransformNR target, double[] jointSpaceVector, DHChain chain)
double[] inverseKinematics(TransformNR target, double[] jointSpaceVector, DHChain chain)