BowlerKernel
DHChain.java
Go to the documentation of this file.
1 package com.neuronrobotics.sdk.addons.kinematics;
2 
3 import java.io.InputStream;
4 import java.util.ArrayList;
5 
6 
7 
8 import org.w3c.dom.Element;
9 import org.w3c.dom.Node;
10 import org.w3c.dom.NodeList;
11 
12 import Jama.Matrix;
13 
14 import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR;
15 import com.neuronrobotics.sdk.addons.kinematics.xml.XmlFactory;
16 import com.neuronrobotics.sdk.common.Log;
17 // TODO: Auto-generated Javadoc
18 
22 public class DHChain {
23 
25  private ArrayList<DHLink> links = new ArrayList<DHLink>();
26 
28  private ArrayList<TransformNR> chain = new ArrayList<TransformNR>();
29 
31  private ArrayList<TransformNR> intChain = new ArrayList<TransformNR>();
32 
34  private double[] upperLimits;
35 
37  private double[] lowerLimits;
38 
40  private boolean debug=false;
41 
44 
47 
50 
51 
58  this.kin = kin;
59 
60  }
61 
67  public void addLink(DHLink link){
68  if(!getLinks().contains(link)){
69  getLinks().add(link);
70  }
71  }
72 
78  public void removeLink(DHLink link){
79  if(getLinks().contains(link)){
80  getLinks().remove(link);
81  }
82  }
83 
84 
85 // public DHChain(double [] upperLimits,double [] lowerLimits, boolean debugViewer ) {
86 // this(upperLimits, lowerLimits);
87 //
88 // }
89 //
90 // public DHChain(double [] upperLimits,double [] lowerLimits ) {
91 //
92 // this.upperLimits = upperLimits;
93 // this.lowerLimits = lowerLimits;
94 // getLinks().add(new DHLink( 13, Math.toRadians(180), 32, Math.toRadians(-90)));//0->1
95 // getLinks().add(new DHLink( 25, Math.toRadians(-90), 93, Math.toRadians(180)));//1->2
96 // getLinks().add(new DHLink( 11, Math.toRadians(90), 24, Math.toRadians(90)));//2->3
97 // getLinks().add(new DHLink( 128, Math.toRadians(-90), 0, Math.toRadians(90)));//3->4
98 //
99 // getLinks().add(new DHLink( 0, Math.toRadians(0), 0, Math.toRadians(-90)));//4->5
100 // getLinks().add(new DHLink( 25, Math.toRadians(90), 0, Math.toRadians(0)));//5->tool
101 //
102 // forwardKinematics(new double [] {0,0,0,0,0,0});
103 // }
104 
113 public double[] inverseKinematics(TransformNR target,double[] jointSpaceVector )throws Exception {
114 
115  if(getLinks() == null)
116  return null;
117  long start = System.currentTimeMillis();
118 
119 
120  //is = new GradiantDecent(this,debug);
121  //is = new SearchTreeSolver(this,debug);
122  if(getInverseSolver() == null)
124 
125  double [] inv = getInverseSolver().inverseKinematics(target, jointSpaceVector,this);
126  if(debug){
127  //getViewer().updatePoseDisplay(getChain(jointSpaceVector));
128  }
129 
130  //Log.info( "Inverse Kinematics took "+(System.currentTimeMillis()-start)+"ms");
131  return inv;
132  }
133 
140  public TransformNR forwardKinematics(double[] jointSpaceVector) {
141  return forwardKinematics(jointSpaceVector, true);
142  }
143 
151  public TransformNR forwardKinematics(double[] jointSpaceVector, boolean store) {
152  return new TransformNR(forwardKinematicsMatrix(jointSpaceVector, store) );
153  }
154 
155 
156 
164  private double [] crossProduct(double[] a, double[] b){
165  double [] xProd = new double [3];
166 
167  xProd[0]=a[1]*b[2]-a[2]*b[1];
168  xProd[1]=a[2]*b[0]-a[0]*b[2];
169  xProd[2]=a[0]*b[1]-a[1]*b[0];
170 
171  return xProd;
172  }
173 
181  public Matrix forwardKinematicsMatrix(double[] jointSpaceVector, boolean store) {
182  return forwardKinematicsMatrix(jointSpaceVector,store?getCachedChain():null);
183  }
184  public Matrix forwardKinematicsMatrix(double[] jointSpaceVector, ArrayList<TransformNR> chainToLoad) {
185  if(getLinks() == null)
186  return new TransformNR().getMatrixTransform();
187  if (jointSpaceVector.length!=getLinks().size())
188  throw new IndexOutOfBoundsException("DH links do not match defined links. expected "+getLinks().size()+" got "+jointSpaceVector.length);
189  Matrix current = new TransformNR().getMatrixTransform();
190 
191  for(int i=0;i<getLinks().size();i++) {
192  LinkFactory factory2 = getFactory();
193  ArrayList<LinkConfiguration> linkConfigurations = factory2.getLinkConfigurations();
194  LinkConfiguration conf= linkConfigurations.get(i);
195  Matrix step;
196  if(conf.isPrismatic())
197  step= getLinks().get(i).DhStep(jointSpaceVector[i]);
198  else
199  step= getLinks().get(i).DhStep(Math.toRadians(jointSpaceVector[i]));
200  //Log.info( "Current:\n"+current+"Step:\n"+step);
201  current = current.times(step);
202  try {
203  final TransformNR pose =forwardOffset(new TransformNR(current));
204 
205 
206 
207  if(chainToLoad!=null){
208  if(intChain.size()<=i)
209  intChain.add(new TransformNR(step));
210  else{
211  intChain.set(i, new TransformNR(step));
212  }
213 
214  if(chainToLoad.size()<=i)
215  chainToLoad.add(pose);
216  else{
217  chainToLoad.set(i, pose);
218  }
219  }
220  }catch(java.lang.RuntimeException ex) {
221  String pose="[\n";
222  for(int x=0;x<jointSpaceVector.length;x++) {
223  pose=pose+" "+jointSpaceVector[x]+" , \n";
224  }
225  pose+="]";
226  throw new RuntimeException(ex.getMessage()+" for pose "+pose);
227  }
228  }
229  //Log.info( "Final:\n"+current);
230  return current;
231  }
232 
239  private TransformNR forwardOffset(TransformNR transformNR) {
240  return kin.forwardOffset(transformNR);
241  }
242 
248  public void setChain(ArrayList<TransformNR> chain) {
249  if(chain!=null)
250  this.chain = chain;
251  getCachedChain().clear();
252  //else
253  // new RuntimeException().printStackTrace();
254  }
255 
262  public ArrayList<TransformNR> getChain(double[] jointSpaceVector) {
263  ArrayList<TransformNR> chainToLoad = new ArrayList<TransformNR>();
264  forwardKinematicsMatrix(jointSpaceVector,chainToLoad);
265  return chainToLoad;
266  }
267 
273  public ArrayList<TransformNR> getCachedChain() {
274  if(chain==null)
275  chain=new ArrayList<TransformNR>();
276  return chain;
277  }
278 
284  public double[] getUpperLimits() {
285  // TODO Auto-generated method stub
286  return upperLimits;
287  }
288 
294  public double[] getlowerLimits() {
295  // TODO Auto-generated method stub
296  return lowerLimits;
297  }
298 
304  public void setLinks(ArrayList<DHLink> links) {
305  this.links = links;
306  }
307 
313  public ArrayList<DHLink> getLinks() {
314  return links;
315  }
316 
317  /* (non-Javadoc)
318  * @see java.lang.Object#toString()
319  */
320  public String toString(){
321  String s="";
322  for(DHLink l:getLinks()){
323  s+=l.toString()+"\n";
324  }
325  return s;
326 
327  }
328 
335  if(is==null){
336  is=new DhInverseSolver() {
337 
338  @Override
339  public double[] inverseKinematics(TransformNR target,
340  double[] jointSpaceVector,DHChain chain ) {
341  ArrayList<DHLink> links = chain.getLinks();
342  // THis is the jacobian for the given configuration
343  //Matrix jacobian = chain.getJacobian(jointSpaceVector);
344  Matrix taskSpacMatrix = target.getMatrixTransform();
345 
346  int linkNum = jointSpaceVector.length;
347  double [] inv = new double[linkNum];
348  // this is an ad-hock kinematic model for d-h parameters and only works for specific configurations
349 
350  double d = links.get(1).getD()- links.get(2).getD();
351  double r = links.get(0).getR();
352 
353  double lengthXYPlaneVect = Math.sqrt(Math.pow(target.getX(),2)+Math.pow(target.getY(),2));
354  double angleXYPlaneVect = Math.asin(target.getY()/lengthXYPlaneVect);
355 
356  double angleRectangleAdjustedXY =Math.asin(d/lengthXYPlaneVect);
357 
358  double lengthRectangleAdjustedXY = lengthXYPlaneVect* Math.cos(angleRectangleAdjustedXY)-r;
359 
360 
361  double orentation = angleXYPlaneVect-angleRectangleAdjustedXY;
362  if(Math.abs(Math.toDegrees(orentation))<0.01){
363  orentation=0;
364  }
365  double ySet = lengthRectangleAdjustedXY*Math.sin(orentation);
366  double xSet = lengthRectangleAdjustedXY*Math.cos(orentation);
367 
368 
369  double zSet = target.getZ() - links.get(0).getD();
370  if(links.size()>4){
371  zSet+=links.get(4).getD();
372  }
373  // Actual target for anylitical solution is above the target minus the z offset
374  TransformNR overGripper = new TransformNR(
375  xSet,
376  ySet,
377  zSet,
378  target.getRotation());
379 
380 
381  double l1 = links.get(1).getR();// First link length
382  double l2 = links.get(2).getR();
383 
384  double vect = Math.sqrt(xSet*xSet+ySet*ySet+zSet*zSet);
385  /*
386  println ( "TO: "+target);
387  println ( "Trangular TO: "+overGripper);
388  println ( "lengthXYPlaneVect: "+lengthXYPlaneVect);
389  println( "angleXYPlaneVect: "+Math.toDegrees(angleXYPlaneVect));
390  println( "angleRectangleAdjustedXY: "+Math.toDegrees(angleRectangleAdjustedXY));
391  println( "lengthRectangleAdjustedXY: "+lengthRectangleAdjustedXY);
392  println( "r: "+r);
393  println( "d: "+d);
394 
395  println( "x Correction: "+xSet);
396  println( "y Correction: "+ySet);
397 
398  println( "Orentation: "+Math.toDegrees(orentation));
399  println( "z: "+zSet);
400  */
401 
402 
403  if (vect > l1+l2 || vect<0 ||lengthRectangleAdjustedXY<0 ) {
404  throw new RuntimeException("Hypotenus too long: "+vect+" longer then "+l1+l2);
405  }
406  //from https://www.mathsisfun.com/algebra/trig-solving-sss-triangles.html
407  double a=l2;
408  double b=l1;
409  double c=vect;
410  double A =Math.acos((Math.pow(b,2)+ Math.pow(c,2) - Math.pow(a,2)) / (2.0*b*c));
411  double B =Math.acos((Math.pow(c,2)+ Math.pow(a,2) - Math.pow(b,2)) / (2.0*a*c));
412  double C =Math.PI-A-B;//Rule of triangles
413  double elevation = Math.asin(zSet/vect);
414 
415  /*
416  println( "vect: "+vect);
417  println( "A: "+Math.toDegrees(A));
418  println( "elevation: "+Math.toDegrees(elevation));
419  println( "l1 from x/y plane: "+Math.toDegrees(A+elevation));
420  println( "l2 from l1: "+Math.toDegrees(C));
421  */
422  inv[0] = Math.toDegrees(orentation);
423  inv[1] = -Math.toDegrees((A+elevation+links.get(1).getTheta()));
424  if((int)links.get(1).getAlpha() ==180){
425  inv[2] = (Math.toDegrees(C))-180-//interior angle of the triangle, map to external angle
426  Math.toDegrees(links.get(2).getTheta());// offset for kinematics
427  }
428  if((int)links.get(1).getAlpha() ==0){
429  inv[2] = -(Math.toDegrees(C))+Math.toDegrees(links.get(2).getTheta());// offset for kinematics
430  }
431  if(links.size()>3)
432  inv[3] =(inv[1] -inv[2]);// keep it parallell
433  // We know the wrist twist will always be 0 for this model
434  if(links.size()>4)
435  inv[4] = inv[0];//keep the tool orentation paralell from the base
436 
437  for(int i=0;i<inv.length;i++){
438  if(Math.abs(inv[i]) < 0.01){
439  inv[i]=0;
440  }
441 // println( "Link#"+i+" is set to "+inv[i]);
442  }
443  int i=3;
444  if(links.size()>3)
445  i=5;
446  //copy over remaining links so they do not move
447  for(;i<inv.length && i<jointSpaceVector.length ;i++){
448  inv[i]=jointSpaceVector[i];
449  }
450  return inv;
451  }
452  };
453 
454  }
455  return is;
456  }
457 
464  this.is = is;
465  }
466 
473  return factory;
474  }
475 
484  this.factory = factory;
485  }
486 
487 }
TransformNR forwardKinematics(double[] jointSpaceVector, boolean store)
Definition: DHChain.java:151
TransformNR forwardOffset(TransformNR transformNR)
Definition: DHChain.java:239
ArrayList< TransformNR > getCachedChain()
Definition: DHChain.java:273
void setChain(ArrayList< TransformNR > chain)
Definition: DHChain.java:248
TransformNR forwardKinematics(double[] jointSpaceVector)
Definition: DHChain.java:140
Matrix forwardKinematicsMatrix(double[] jointSpaceVector, ArrayList< TransformNR > chainToLoad)
Definition: DHChain.java:184
double[] inverseKinematics(TransformNR target, double[] jointSpaceVector)
Definition: DHChain.java:113
double[] crossProduct(double[] a, double[] b)
Definition: DHChain.java:164
ArrayList< TransformNR > getChain(double[] jointSpaceVector)
Definition: DHChain.java:262
Matrix forwardKinematicsMatrix(double[] jointSpaceVector, boolean store)
Definition: DHChain.java:181
void setLinks(ArrayList< DHLink > links)
Definition: DHChain.java:304
ArrayList< LinkConfiguration > getLinkConfigurations()
double[] inverseKinematics(TransformNR target, double[] jointSpaceVector, DHChain chain)