transformCoords.cc
Go to the documentation of this file.
1 
18 /* system includes */
19 /* (none) */
20 
21 /* my includes */
22 #include "transformCoords.h"
23 #include "BirdTrack_impl.h"
24 #include "math.h"
25 #include "complex.h"
26 #include "polynomial.h"
27 #include "quaternion.h"
28 
29 // Emitter unter dem Tisch auf nem Wasserkasten - Wird nur verwendet falls nix anderes zur Verfgung steht
30 #define POLHEMUS_POS_X 1284.6
31 #define POLHEMUS_POS_Y 1319.2
32 #define POLHEMUS_POS_Z -553.0
33 #define KOORD_OFFSET_X -16.0
34 #define KOORD_OFFSET_Y 65.0
35 #define KOORD_OFFSET_Z 0.0
36 
38 
39 double fobCoordList[256][6];
40 double worldCoordList[256][6];
42 
43 void
45 {
46  calibrated=false;
47  countCoord=0;
48 }
49 
51 {
52  calibrated=false;
53  countCoord=0;
54 }
55 
57 {
58 }
59 
60 /*
61 bool
62 transformCoords::loadCalibFile(const char *srcFileName)
63 { //Load and Save is not implemented yet, since the Calibration GUI is able to load and save the
64  //Coord lists anyway
65  return true;
66 }
67 
68 bool
69 transformCoords::saveCalibFile(const char *srcFileName)
70 { //Same here
71  return true;
72 }
73 */
74 double S[3][3];
75 double N[4][4];
76 double Cm[3];
77 double Cs[3];
78 double c2,c1,c0;
79 double l;
80 int ERR=0;
81 
82 quaternion solution;//Rotation
83 double scale;//Scale
84 double trans[3];//
85 quaternion transq;//Translation
86 
87 void calcC(){
88  for (int x=0;x<3;x++)
89  Cs[x]=Cm[x]=0;
90  for (int i=0;i<countCoord;i++)
91  {
92  for (int x=0;x<3;x++)
93  {
94  Cs[x]+=worldCoordList[i][x];
95  Cm[x]+=fobCoordList[i][x];
96  }
97  }
98  for (int x=0;x<3;x++)
99  {
100  Cs[x]=Cs[x]/countCoord;
101  Cm[x]=Cm[x]/countCoord;
102  }
103 
104 }
105 
106 double sqr(double a){
107  return a*a;
108 }
109 
110 void calcS(){
111  double distf=0,distw=0;
112 
113  for (int x=0;x<3;x++)
114  for (int y=0;y<3;y++)
115  S[x][y]=0;
116 
117  for (int i=0;i<countCoord;i++)
118  {distw+=sqrt(sqr(worldCoordList[i][0]-Cs[0])+sqr(worldCoordList[i][1]-Cs[1])+sqr(worldCoordList[i][2]-Cs[2]));
119  distf+=sqrt(sqr(fobCoordList[i][0]-Cs[0])+sqr(fobCoordList[i][1]-Cs[1])+sqr(fobCoordList[i][2]-Cs[2]));
120  }
121  distf=distf*distw/countCoord/countCoord/10; //??? Was ist dieser distf-Faktor?
122 
123  for (int i=0;i<countCoord;i++)
124  for (int x=0;x<3;x++)
125  for (int y=0;y<3;y++)
126  S[x][y]+=(worldCoordList[i][x]-Cs[x])*(fobCoordList[i][y]-Cm[y])/distf;
127 }
128 
129 void calcN(){
130  N[0][0]=S[0][0]+S[1][1]+S[2][2]; N[0][1]=S[1][2]-S[2][1]; N[0][2]=S[2][0]-S[0][2]; N[0][3]=S[0][1]-S[1][0];
131  N[1][0]=S[1][2]-S[2][1]; N[1][1]=S[0][0]-S[1][1]-S[2][2]; N[1][2]=S[0][1]+S[1][0]; N[1][3]=S[2][0]+S[0][2];
132  N[2][0]=S[2][0]-S[0][2]; N[2][1]=S[0][1]+S[1][0]; N[2][2]=-S[0][0]+S[1][1]-S[2][2]; N[2][3]=S[1][2]+S[2][1];
133  N[3][0]=S[0][1]-S[1][0]; N[3][1]=S[2][0]+S[0][2]; N[3][2]=S[1][2]+S[2][1]; N[3][3]=-S[0][0]-S[1][1]+S[2][2];
134 }
135 
136 void calc_c(){
137 c2= (N[0][0]*N[2][2] - sqr(N[0][2])) + (N[1][1]*N[2][2] - sqr(N[1][2])) +
138  (N[0][0]*N[3][3] - sqr(N[0][3])) + (N[1][1]*N[3][3] - sqr(N[1][3])) +
139  (N[2][2]*N[3][3] + sqr(N[2][3])) + (N[0][0]*N[1][1] - sqr(N[0][1]));
140 
141 c1 = -N[1][1]*(N[2][2]*N[3][3] - sqr(N[2][3])) + N[1][2]*(N[3][3]*N[1][2] - N[2][3]*N[1][3]) - N[1][3]*(N[1][2]*N[2][3] - N[2][2]*N[1][3])
142  -N[0][0]*(N[2][2]*N[3][3] - sqr(N[2][3])) + N[0][2]*(N[3][3]*N[0][2] - N[2][3]*N[0][3]) - N[0][3]*(N[2][3]*N[0][2] - N[2][2]*N[0][3])
143  -N[0][0]*(N[1][1]*N[3][3] - sqr(N[1][3])) + N[0][1]*(N[3][3]*N[0][1] - N[1][3]*N[0][3]) - N[0][3]*(N[0][1]*N[1][3] - N[1][1]*N[0][3])
144  -N[0][0]*(N[1][1]*N[2][2] - sqr(N[1][2])) + N[0][1]*(N[2][2]*N[0][1] - N[1][2]*N[0][2]) - N[0][2]*(N[0][1]*N[1][2] - N[1][1]*N[0][2]);
145 
146 c0 = (N[0][0]*N[1][1] - sqr(N[0][1]))*(N[2][2]*N[3][3] - sqr(N[2][3])) + (N[0][1]*N[0][2] - N[0][0]*N[1][2])*(N[1][2]*N[3][3] - N[2][3]*N[1][3])
147  + (N[0][0]*N[1][3] - N[0][1]*N[0][3]) * (N[1][2]*N[2][3] - N[2][2]*N[1][3]) + (N[0][1]*N[1][2] - N[1][1]*N[0][2])*(N[0][2]*N[3][3] - N[2][3]*N[0][3])
148  + (N[1][1]*N[0][3] - N[0][1]*N[1][3]) * (N[0][2]*N[2][3] - N[2][2]*N[0][3]) + sqr(N[0][2]*N[1][3] - N[1][2]*N[0][3]);
149 //printf("x^4+%fx^2+%fx+%f\n",c2,c1,c0);
150 }
151 
153  double a[4];
154  double x1,x2,x3,x4;
155  int c;
156  int i;
157  int b=0;
158  c=solve_biquadratic(1,0,c2,c1,c0,&x1,&x2,&x3,&x4);
159  a[0]=x1;a[1]=x2;a[2]=x3;a[3]=x4;
160  printf("Solutions for Lamda (%d): ",c);
161  for (i=0;i<c;i++) printf("%f ",a[i]);
162  printf("\n");
163  if (c!=0) l=a[0]; else l=-HUGE_VAL;
164  if (c>1)
165  for (i=1;i<c;i++)
166  if (a[i]>l) l=a[i];
167  for (i=1;i<c;i++)
168  if (abs(a[i]-l)<epsilon) b++;
169  if (b>1) ERR=1; //Zwei gleiche maximale Eigenwerte -> Der dazugeh�ige Eigenraum ist nicht eindimensional
170  printf ("Error after find_max_lambda: %d\n", ERR);
171 }
172 
173 void flipLines(int a,int b){//Flips two lines within the matrix
174  for (int i=0;i<4;i++)
175  {
176  double c=N[a][i];
177  N[a][i]=N[b][i];
178  N[b][i]=c;
179  }
180 }
181 
182 void mAddLines(int to,int from,double value){//Adds line "from" to line "to muliplied with "value"
183  for (int i=0;i<4;i++)
184  N[to][i]+=N[from][i]*value;
185 }
186 
187 void setQuat(int pos,quaternion* q,double value)//If you ever need to access a quaternion like an array
188 {
189  switch (pos)
190  {
191  case 0:q->r=value;break;
192  case 1:q->i=value;break;
193  case 2:q->j=value;break;
194  case 3:q->k=value;break;
195  }
196 }
197 
198 double NB[4][4];
199 
201 //Calculation of N-Lambda*I
202  solution.r=0;
203  solution.i=0;
204  solution.j=0;
205  solution.k=0;
206  for (int i=0;i<4;i++)
207  N[i][i]-=l;
208  for (int i=0;i<4;i++)
209  for (int j=0;j<4;j++)
210  NB[i][j]=N[i][j];
211  {
212  int j=-1;
213  for (int i=0;i<4;i++)
214  {int l=0;
215  for (int k=0;k<4;k++)
216  {
217  if (abs(N[k][i])>epsilon) l++;
218  }
219  if (l==1) j=i;
220  }
221  if (j>=0) {setQuat(j,&solution,1);return;} //One row is zero, so there is a solution with one value not equal zero
222  }
223  for (int i1=0;i1<4;i1++) //there is a solution with two value not equal zero
224  for (int j=0;j<3;j++)
225  if ((i1!=j)&&(abs(N[0][i1])>epsilon))
226  { int s=0;
227  for (int k=1;k<4;k++)
228  if ((abs(N[k][i1])<epsilon)&&(abs(N[k][j])<epsilon)) s++;
229  else if (abs(N[k][i1])>epsilon)
230  if (abs(N[k][j]/N[k][i1]-N[0][j]/N[0][i1])<epsilon) s++;
231  if (s==3)
232  {
233  setQuat(j,&solution,N[0][i1]);
234  setQuat(i1,&solution,-N[0][j]);
235  return;
236  }
237  }
238  //try to find a solution with (a,b,1,0) and a,b!=0
239  {
240  int m=-1;
241  int n,p;
242  for (int i2=1;i2<4;i2++)
243  if (abs(N[0][0]*N[i2][1]-N[i2][0]*N[0][1])>=epsilon) //Sind Zeile 1 und m linear abh�gig?
244  {m=i2;break;}
245  double a=-(N[m][2]*N[0][0]-N[0][2]*N[m][0])/(N[0][0]*N[m][1]-N[m][0]*N[0][1]);
246  double b= (N[m][2]*N[0][1]-N[0][2]*N[m][1])/(N[0][0]*N[m][1]-N[m][0]*N[0][1]);
247  if (m>0) //Es gibt eine zu m linear unabh�gige Zeile
248  {
249  switch (m) //Bestimmung der beiden bisher nichtbenutzten Zeilen
250  {
251  case 1:n=2;p=3;break;
252  case 2:n=1;p=3;break;
253  case 3:n=1;p=2;break;
254  }
255  if ((abs(a*N[n][0]+b*N[n][1]+N[n][2])<epsilon)&&(abs(a*N[p][0]+b*N[p][1]+N[p][2])<epsilon))
256  {
257  setQuat(0,&solution,a);
258  setQuat(1,&solution,b);
259  setQuat(2,&solution,1);
260  return;
261  }
262  }
263 
264  }
265 //Gibt es wenigstens eine Lösung mit (a,b,c,1)
266  solution.k=1;
267  for (int i=0;i<4;i++) //
268  N[i][3]*=-1;
269  if (abs(N[0][0])<epsilon) flipLines(0,1);
270  if (abs(N[0][0])<epsilon) flipLines(0,2);
271  if (abs(N[0][0])<epsilon) flipLines(0,3);
272  if (abs(N[0][0])<epsilon) {ERR=2;return;}//Darf eigentlich nicht passieren
273 
274  for (int i=1;i<4;i++)
275  mAddLines(i,0,-N[i][0]/N[0][0]);//Erste Spalte auf Null setzen
276  if (abs(N[1][1])<epsilon) flipLines(1,2);
277  if (abs(N[1][1])<epsilon) flipLines(1,3);
278  if (abs(N[1][1])<epsilon) {ERR=2;return;}//Darf eigentlich auch nicht passieren
279 
280  for (int i=2;i<4;i++)
281  mAddLines(i,1,-N[i][1]/N[1][1]);//Zweite Spalte auf Null setzen
282  if (abs(N[2][2])<epsilon) flipLines(2,3);
283  if (abs(N[2][2])<epsilon) {ERR=2;return;}//Darf auch nicht passieren
284  if ((abs(N[2][2])<epsilon)&&(abs(N[2][3])>=epsilon)) {ERR=3;return;} //Es gibt keine Lösung
285  if ((abs(N[3][2])<epsilon)&&(abs(N[3][3])>=epsilon)) {ERR=3;return;} //Es gibt keine Lösung
286  for (int i=0;i<2;i++)
287  if (abs(N[i][i])<epsilon) {ERR=4;return;} //Der Lösungsraum ist nicht eindimensional
288 
289  if ((abs(N[3][3])<epsilon)&&(abs(N[4][4])<epsilon)) {ERR=4;return;} //Der Lösungsraum ist nicht eindimensional
290 
291  solution.k=1;
292  solution.j=(0.5*N[2][3]/N[2][2]+0.5*N[3][3]/N[3][2]);
293  solution.i=((N[1][3]-solution.j*N[1][2])/N[1][1]);
294  solution.r=((N[0][3]-solution.j*N[0][2]-solution.i*N[0][1])/N[0][0]);
295 }
296 
298 {
299 double a=0;
300 double b=0;
301 for (int i=0;i<countCoord;i++)
302 {
303  a+=sqr(worldCoordList[i][0]-Cs[0])+sqr(worldCoordList[i][1]-Cs[1])+sqr(worldCoordList[i][2]-Cs[2]);
304  b+=sqr(fobCoordList[i][0]-Cm[0])+sqr(fobCoordList[i][1]-Cm[1])+sqr(fobCoordList[i][2]-Cm[2]);
305 }
306 scale=sqrt(a/b);
307  printf("Scale is %f\n",scale);
308 }
309 
311 {quaternion tr,cm,cs;
312 cm.r=0;
313 cm.i=Cm[0];
314 cm.j=Cm[1];
315 cm.k=Cm[2];
316 cs.r=0;
317 cs.i=Cs[0];
318 cs.j=Cs[1];
319 cs.k=Cs[2];
320 tr=qsub(cs,qscale(scale,qmul(qmul(solution,cm),qinv(solution))));
321 trans[0]=tr.i;
322 trans[1]=tr.j;
323 trans[2]=tr.k;
324 transq=tr;
325  printf("Transformation Vector is:%f %f %f\n",trans[0],trans[1],trans[2]);
326 }
327 
328 void transform_point(double xi, double yi, double zi,double* xo, double* yo, double* zo)
329 {
330 quaternion q;
331 q.r=0;
332 q.i=xi;
333 q.j=yi;
334 q.k=zi;
335 q=qadd(transq,qscale(scale,qmul(qmul(solution,q),qinv(solution))));
336 *xo=q.i;
337 *yo=q.j;
338 *zo=q.k;
339 }
340 
341 bool
342 transformCoords::addCalibrationData(double *fobCoords,double *worldCoords)
343 {
344  ERR=0;
345  //try to compute transformation from all available data and return true if calibration is possible with available data
346  if (countCoord<256)
347  {
348  for (int i=0;i<6;i++)
349  {
350  worldCoordList[countCoord][i]=worldCoords[i];
351  fobCoordList[countCoord][i]=fobCoords[i];
352  }
353  countCoord++;
354  }
355  if (countCoord>=3)
356  {
357  calcC();
358  calc_scale();
359  calcS();
360  calcN();
361  calc_c();
362  find_max_lambda();
363  if (ERR==0)
364  {
365  calc_eigenVec();
366  solution.i=-solution.i;
367  solution.j=-solution.j;
368  solution.k=-solution.k;
369  printf("Rotation Quaternion:");
370  qprint(solution);
371  }
372  if (ERR==0)
373  calc_trans();
374  calibrated=(ERR==0);
375  }
376  //Calibrate from available data and set calibrated=false if there is some unsolveable trouble
377  cout << "Calibrated: " << calibrated << "(error: " << ERR << ")\n";
378  return calibrated;
379 }
380 
381 void
383 { double x,y,z;
384  if (calibrated)
385  {
386  x=v[0];
387  y=v[1];
388  z=v[2];
389  transform_point(x,y,z,&x,&y,&z);
390  v[0]=x;
391  v[1]=y;
392  v[2]=z;
393  }
394  else
395  {
396  printf("Not calibrated call of transform\n");
397  //Actually nothing to do, except you want to implement some generic calibration
398  }
399 }
400 
401 
402 
403 bool
405 {
406  return calibrated;
407 }
408 
409 #if transformCoords_test
410 #include <stdio.h>
411 int main(int argc, char **argv)
412 {
413  // This is a module-test block. You can put code here that tests
414  // just the contents of this C file, and build it by saying
415  // make transformCoords_test
416  // Then, run the resulting executable (transformCoords_test).
417  // If it works as expected, the module is probably correct. ;-)
418 
419  fprintf(stderr, "Testing transformCoords\n");
420 
421  return 0;
422 }
423 #endif /* transformCoords_test */
quaternion qadd(quaternion a, quaternion b)
double Cm[3]
int ERR
void calc_eigenVec()
void calcS()
void setQuat(int pos, quaternion *q, double value)
int main(int argc, char **argv)
void calcN()
XmlRpcServer s
void mAddLines(int to, int from, double value)
void find_max_lambda()
quaternion qscale(double s, quaternion a)
TFSIMD_FORCE_INLINE const tfScalar & y() const
void transform_point(double xi, double yi, double zi, double *xo, double *yo, double *zo)
int n
double NB[4][4]
quaternion transq
void flipLines(int a, int b)
int countCoord
quaternion qsub(quaternion a, quaternion b)
quaternion solution
double sqr(double a)
void calc_c()
TFSIMD_FORCE_INLINE const tfScalar & x() const
bool addCalibrationData(double *fobCoords, double *worldCoords)
double l
void transform(double *v)
double fobCoordList[256][6]
quaternion qmul(quaternion a, quaternion b)
TFSIMD_FORCE_INLINE const tfScalar & z() const
double scale
void calc_scale()
double c0
quaternion qinv(quaternion a)
void calcC()
double Cs[3]
void qprint(quaternion c)
double S[3][3]
double c2
bool calibrated
double abs(quaternion a)
int solve_biquadratic(double a4, double a3, double a2, double a1, double a0, double *x1, double *x2, double *x3, double *x4)
double N[4][4]
double worldCoordList[256][6]
void calc_trans()
double epsilon
double c1
double trans[3]


asr_flock_of_birds
Author(s): Bernhardt Andre, Engelmann Stephan, Giesler Björn, Heller Florian, Jäkel Rainer, Nguyen Trung, Pardowitz Michael, Weckesser Peter, Yi Xie, Zöllner Raoul
autogenerated on Mon Jun 10 2019 12:44:40