BowlerKernel
DeltaRobotKinematics.java
Go to the documentation of this file.
1 package com.neuronrobotics.replicator.driver.delta;
2 
3 import com.neuronrobotics.sdk.addons.kinematics.math.RotationNR;
4 import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR;
5 
6 // TODO: Auto-generated Javadoc
10 public class DeltaRobotKinematics {
11  //Sample code from http://forums.trossenrobotics.com/tutorials/introduction-129/delta-robot-kinematics-3276/
12  // robot geometry
14  // (look at pics above for explanation)
15  DeltaRobotConfig configuration;
16 
23  configuration=new DeltaRobotConfig(config);
24  }
25 
26 
28  // trigonometric private ants
29  private double sqrt3 = Math.sqrt(3.0);
30 
32  private double pi = Math.PI; // PI
33 
35  private double sin120 = sqrt3/2.0;
36 
38  private double cos120 = -0.5;
39 
41  private double tan60 = sqrt3;
42 
44  private double sin30 = 0.5;
45 
47  private double tan30 = 1/sqrt3;
48 
49  // forward kinematics: (theta1, theta2, theta3) -> (x0, y0, z0)
56  // returned status: CartesianCoordinante=OK, null=non-existing position
57  public TransformNR delta_calcForward(double [] input) {
58  double x0, y0, z0;
59  for(int i=0;i<3;i++){
60  if(input[i]>=85)
61  throw new RuntimeException("Angle hit toggle point: "+input[i] );
62  }
63  double theta1 = Math.toRadians(input[0]);
64  double theta2 = Math.toRadians(input[1]);
65  double theta3 = Math.toRadians(input[2]);
66  double t = (getF()-getE())*tan30/2;
67 
68  double y1 = -(t + getRf()*Math.cos(theta1));
69  double z1 = -getRf()*Math.sin(theta1);
70 
71  double y2 = (t + getRf()*Math.cos(theta2))*sin30;
72  double x2 = y2*tan60;
73  double z2 = -getRf()*Math.sin(theta2);
74 
75  double y3 = (t + getRf()*Math.cos(theta3))*sin30;
76  double x3 = -y3*tan60;
77  double z3 = -getRf()*Math.sin(theta3);
78 
79  double dnm = (y2-y1)*x3-(y3-y1)*x2;
80 
81  double w1 = y1*y1 + z1*z1;
82  double w2 = x2*x2 + y2*y2 + z2*z2;
83  double w3 = x3*x3 + y3*y3 + z3*z3;
84 
85  // x = (a1*z + b1)/dnm
86  double a1 = (z2-z1)*(y3-y1)-(z3-z1)*(y2-y1);
87  double b1 = -((w2-w1)*(y3-y1)-(w3-w1)*(y2-y1))/2.0;
88 
89  // y = (a2*z + b2)/dnm;
90  double a2 = -(z2-z1)*x3+(z3-z1)*x2;
91  double b2 = ((w2-w1)*x3 - (w3-w1)*x2)/2.0;
92 
93  // a*z^2 + b*z + c = 0
94  double a = a1*a1 + a2*a2 + dnm*dnm;
95  double b = 2*(a1*b1 + a2*(b2-y1*dnm) - z1*dnm*dnm);
96  double c = (b2-y1*dnm)*(b2-y1*dnm) + b1*b1 + dnm*dnm*(z1*z1 - getRe()*getRe());
97 
98  // discriminant
99  double d = b*b - (double)4.0*a*c;
100  if (d < 0) return null; // non-existing point
101 
102  z0 = -(double)0.5*(b+Math.sqrt(d))/a;
103  x0 = (a1*z0 + b1)/dnm;
104  y0 = (a2*z0 + b2)/dnm;
105  return new TransformNR(x0, y0, z0, new RotationNR());
106  }
107 
108  // inverse kinematics
117  // helper functions, calculates angle theta1 (for YZ-pane)
118  private double delta_calcAngleYZ(double x0, double y0, double z0 ) {
119  double theta;
120 // if(z0<=0)
121 // throw new RuntimeException("Z values must be greater then zero");
122  double y1 = -0.5 * 0.57735 * getF(); // f/2 * tg 30
123  y0 -= 0.5 * 0.57735 * getE(); // shift center to edge
124  // z = a + b*y
125  double a = (x0*x0 + y0*y0 + z0*z0 +getRf()*getRf() - getRe()*getRe() - y1*y1)/(2*z0);
126  double b = (y1-y0)/z0;
127  // discriminant
128  double d = -(a+b*y1)*(a+b*y1)+getRf()*(b*b*getRf()+getRf());
129  if (d < 0)
130  throw new RuntimeException("Out Of Workspace! Inverse kinematics failed, D < 0"); // non-existing point
131  double yj = (y1 - a*b - Math.sqrt(d))/(b*b + 1); // chooMath.sing outer point
132  double zj = a + b*yj;
133  theta = Math.atan(-zj/(y1 - yj)) + ((yj>y1)?180.0:0.0);
134  return theta;
135  }
136 
137  // inverse kinematics: (x0, y0, z0) -> (theta1, theta2, theta3)
144  // returned status: 0=OK, -1=non-existing position
145  public double [] delta_calcInverse(TransformNR input ) {
146  double theta1, theta2, theta3;
147  double x0 = input.getX();
148  double y0 = input.getY();
149  double z0 = input.getZ();
150  if(z0==0) {
151  z0=.0001;
152  }
153  theta1 = theta2 = theta3 = 0;
154  theta1 = delta_calcAngleYZ(x0, y0, z0);
155  theta2 = delta_calcAngleYZ(x0*cos120 + y0*sin120, y0*cos120-x0*sin120, z0); // rotate coords to +120 deg
156  theta3 = delta_calcAngleYZ(x0*cos120 - y0*sin120, y0*cos120+x0*sin120, z0); // rotate coords to -120 deg
157  return new double[] {Math.toDegrees(theta1),Math.toDegrees(theta2),Math.toDegrees(theta3)};
158  }
159 
165  public double getE() {
166  return configuration.getE();
167  }
168 
174  public double getF() {
175  return configuration.getF();
176  }
177 
183  public double getRe() {
184  return configuration.getRe();
185  }
186 
192  public double getRf() {
193  return configuration.getRf();
194  }
195 }