BowlerKernel
RotationNR.java
Go to the documentation of this file.
1 package com.neuronrobotics.sdk.addons.kinematics.math;
2 
3 import Jama.Matrix;
4 
5 import org.apache.commons.math3.geometry.euclidean.threed.CardanEulerSingularityException;
6 import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
7 import org.apache.commons.math3.geometry.euclidean.threed.RotationConvention;
8 import org.apache.commons.math3.geometry.euclidean.threed.RotationOrder;
9 
10 import com.neuronrobotics.sdk.common.Log;
11 
12 // TODO: Auto-generated Javadoc
21 public class RotationNR {
22 
24  // double[][] rotationMatrix = ;
25  private Rotation storage = new Rotation(1, 0, 0, 0, false);
26  private static RotationOrder order = RotationOrder.ZYX;
27  private static RotationConvention convention = RotationConvention.VECTOR_OPERATOR;
28 
29 
33  public RotationNR() {
34  }
35 
44  public RotationNR(Rotation store) {
45  storage = store;
46  }
47 
58  // create a new object with the given simplified rotations
59  public RotationNR(double tilt, double azumeth, double elevation) {
60  if (Double.isNaN(tilt))
61  throw new RuntimeException("Value can not be NaN");
62  if (Double.isNaN(azumeth))
63  throw new RuntimeException("Value can not be NaN");
64  if (Double.isNaN(elevation))
65  throw new RuntimeException("Value can not be NaN");
66  if (elevation > 90 || elevation < -90) {
67  throw new RuntimeException("Elevation can not be greater than 90 nor less than -90");
68  }
69  loadFromAngles(tilt, azumeth, elevation);
70  if (Double.isNaN(getRotationMatrix2QuaturnionW()) || Double.isNaN(getRotationMatrix2QuaturnionX())
71  || Double.isNaN(getRotationMatrix2QuaturnionY()) || Double.isNaN(getRotationMatrix2QuaturnionZ())) {
72  Log.error("Failing to set proper angle, jittering");
73  loadFromAngles(tilt + Math.random() * .02 + .001, azumeth + Math.random() * .02 + .001,
74  elevation + Math.random() * .02 + .001);
75  }
76 
77  }
78 
85  public RotationNR(double[][] rotationMatrix) {
86  loadRotations(rotationMatrix);
87  }
88 
95  public RotationNR(double[] values) {
96  this(values[0], values[1], values[2], values[3]);
97  }
98 
106  public static RotationNR getRotationX(double rotationAngleDegrees) {
107  double[][] rotation = new double[3][3];
108  double rotationAngleRadians = Math.PI / 180 * rotationAngleDegrees;
109 
110  // Rotation matrix, 1st column
111  rotation[0][0] = 1;
112  rotation[1][0] = 0;
113  rotation[2][0] = 0;
114  // Rotation matrix, 2nd column
115  rotation[0][1] = 0;
116  rotation[1][1] = Math.cos(rotationAngleRadians);
117  rotation[2][1] = Math.sin(rotationAngleRadians);
118  // Rotation matrix, 3rd column
119  rotation[0][2] = 0;
120  rotation[1][2] = -Math.sin(rotationAngleRadians);
121  rotation[2][2] = Math.cos(rotationAngleRadians);
122 
123  return new RotationNR(rotation);
124  }
125 
133  public static RotationNR getRotationY(double rotationAngleDegrees) {
134  double[][] rotation = new double[3][3];
135  double rotationAngleRadians = Math.PI / 180 * rotationAngleDegrees;
136 
137  // Rotation matrix, 1st column
138  rotation[0][0] = Math.cos(rotationAngleRadians);
139  rotation[1][0] = 0;
140  rotation[2][0] = -Math.sin(rotationAngleRadians);
141  // Rotation matrix, 2nd column
142  rotation[0][1] = 0;
143  rotation[1][1] = 1;
144  rotation[2][1] = 0;
145  // Rotation matrix, 3rd column
146  rotation[0][2] = Math.sin(rotationAngleRadians);
147  rotation[1][2] = 0;
148  rotation[2][2] = Math.cos(rotationAngleRadians);
149 
150  return new RotationNR(rotation);
151  }
152 
160  public static RotationNR getRotationZ(double rotationAngleDegrees) {
161  double[][] rotation = new double[3][3];
162  double rotationAngleRadians = Math.PI / 180 * rotationAngleDegrees;
163 
164  // Rotation matrix, 1st column
165  rotation[0][0] = Math.cos(rotationAngleRadians);
166  rotation[1][0] = Math.sin(rotationAngleRadians);
167  rotation[2][0] = 0;
168  // Rotation matrix, 2nd column
169  rotation[0][1] = -Math.sin(rotationAngleRadians);
170  rotation[1][1] = Math.cos(rotationAngleRadians);
171  rotation[2][1] = 0;
172  // Rotation matrix, 3rd column
173  rotation[0][2] = 0;
174  rotation[1][2] = 0;
175  rotation[2][2] = 1;
176 
177  return new RotationNR(rotation);
178  }
179 
192  // create a new object with the given components
193  public RotationNR(double w, double x, double y, double z) {
194  quaternion2RotationMatrix(w, x, y, z);
195  }
196 
203  public RotationNR(Matrix m) {
204  double[][] rotation = new double[3][3];
205  for (int i = 0; i < 3; i++) {
206  for (int j = 0; j < 3; j++) {
207  rotation[i][j] = m.get(i, j);
208  }
209  }
210  loadRotations(rotation);
211  }
212 
219  private void loadRotations(double[][] rotM) {
220  if (rotM.length != 3)
221  throw new RuntimeException("Must be 3x3 rotation matrix");
222  for (int i = 0; i < 3; i++) {
223  if (rotM[i].length != 3) {
224  throw new RuntimeException("Must be 3x3 rotation matrix");
225  }
226  }
227  setStorage(new Rotation(rotM, 0.00001));
228  }
229 
235  public double[][] getRotationMatrix() {
236 
237  return getStorage().getMatrix();
238  }
239 
240  /*
241  * (non-Javadoc)
242  *
243  * @see java.lang.Object#toString()
244  */
245  // return a string representation of the invoking object
246  public String toString() {
247  try{
248  return "Quaturnion: " + "W=" + getRotationMatrix2QuaturnionW() + ", " + "x=" + getRotationMatrix2QuaturnionX()
249  + ", " + "y=" + getRotationMatrix2QuaturnionY() + ", " + "z=" + getRotationMatrix2QuaturnionZ() + "\n"
250  + "Rotation angle (degrees): " + "az= " + Math.toDegrees(getRotationAzimuth()) + ", elev= "
251  + Math.toDegrees(getRotationElevation()) + ", tilt=" + Math.toDegrees(getRotationTilt());
252  }catch(Exception ex){
253  return "Rotation error"+ex.getLocalizedMessage();
254  }
255 
256  }
257 
265  // return a string representation of the invoking object
266  public String toString(double[][] array) {
267  String s = "[\n";
268  for (int i = 0; i < 3; i++) {
269  s += "[ ";
270  for (int j = 0; j < 3; j++) {
271  s += array[i][j] + "\t\t";
272  }
273  s += " ]\n";
274  }
275  s += "]";
276  return "Matrix = " + s;
277  }
278 
291  protected void quaternion2RotationMatrix(double w, double x, double y, double z) {
292  if (Double.isNaN(w))
293  throw new RuntimeException("Value can not be NaN");
294  if (Double.isNaN(x))
295  throw new RuntimeException("Value can not be NaN");
296  if (Double.isNaN(y))
297  throw new RuntimeException("Value can not be NaN");
298  if (Double.isNaN(z))
299  throw new RuntimeException("Value can not be NaN");
300  setStorage(new Rotation(w,- x, -y, -z, true));
301  }
302 
314  public static boolean bound(double low, double high, double n) {
315  return n >= low && n <= high;
316  }
317 
318  private void loadFromAngles(double tilt, double azumeth, double elevation) {
319  setStorage(new Rotation(getOrder(), getConvention(), Math.toRadians(azumeth), Math.toRadians(elevation),
320  Math.toRadians(tilt)));
321  }
322 
328  public double getRotationTilt() {
329  return getAngle(2);
330  }
331 
337  public double getRotationElevation() {
338  return getAngle(1);
339 
340  }
341 
347  public double getRotationAzimuth() {
348  return getAngle(0);
349  }
350  private void simpilfyAngles(double [] angles){
351  double epsilon=1.0E-7;
352  if(Math.abs(angles[0] - Math.toRadians(180)) < epsilon&&
353  Math.abs(angles[2] - Math.toRadians(180)) < epsilon ){
354  if(!(Math.abs(getRotationMatrix2QuaturnionZ())>epsilon))
355  angles[0]=0;
356  if(!(Math.abs(getRotationMatrix2QuaturnionX())>epsilon))
357  angles[2]=0;
358  }
359  }
360  private double eulerFix(double offsetSize, int index){
361  double offset = (index==1?offsetSize:0);
362  TransformNR current = new TransformNR(0, 0, 0, this);
363  TransformNR newTf = current.times(new TransformNR(0, 0, 0, new RotationNR(0,0,Math.toDegrees(offsetSize))));
364  double[] angles = newTf.getRotation().getStorage().getAngles(getOrder(), getConvention());
365  simpilfyAngles(angles);
366  double finalResult= angles[index];
367  return finalResult+offset;
368  }
369  private double getAngle(int index){
370 
371  try {
372  return getStorage().getAngles(getOrder(), getConvention())[index];
373  } catch (CardanEulerSingularityException e) {
374  try {
375  return eulerFix( Math.toRadians(5), index);
376  } catch (CardanEulerSingularityException ex) {
377  return eulerFix( Math.toRadians(-5), index);
378 
379  }
380  }
381  }
382 
383 
390  return getStorage().getQ0();
391  }
392 
399  return -getStorage().getQ1();
400  }
401 
408  return -getStorage().getQ2();
409  }
410 
417  return -getStorage().getQ3();
418  }
419 
420  public static RotationOrder getOrder() {
421  return order;
422  }
423 
424  public static void setOrder(RotationOrder o) {
425  order = o;
426  }
427 
428  public static RotationConvention getConvention() {
429  return convention;
430  }
431 
432  public static void setConvention(RotationConvention convention) {
434  }
435 
436  public Rotation getStorage() {
437  return storage;
438  }
439 
440  public void setStorage(Rotation storage) {
441  this.storage = storage;
442  }
443 
444  public void set(double[][] poseRot) {
445  loadRotations(poseRot);
446  }
447 
448 
449 
450 }
double eulerFix(double offsetSize, int index)
void loadFromAngles(double tilt, double azumeth, double elevation)
static RotationNR getRotationY(double rotationAngleDegrees)
RotationNR(double w, double x, double y, double z)
void quaternion2RotationMatrix(double w, double x, double y, double z)
RotationNR(double tilt, double azumeth, double elevation)
Definition: RotationNR.java:59
static void setConvention(RotationConvention convention)
static boolean bound(double low, double high, double n)
static RotationNR getRotationZ(double rotationAngleDegrees)
static RotationNR getRotationX(double rotationAngleDegrees)
static void error(String message)
Definition: Log.java:92