test.cpp
Go to the documentation of this file.
1 #include "methods.h"
2 #include "util.h"
3 
4 using namespace std;
5 
6 #include <unistd.h>
7 #include <random>
8 #include <iostream>
9 
41 int main(int argc, char **argv)
42 {
43  // Configuration of the experiments -------------------------------------------------------------------------
44 
45  // Statistics that will be computed for each method and noise level
46  // This must be in accordance with the TestMethod function in util.cpp
47  unsigned int nResults=7;
48  string resultLabel[nResults];
49  resultLabel[MeanDstE] = "Mean_Distance_Error";
50  resultLabel[MaxDstE] = "Max_Distance_Error";
51  resultLabel[MinDstE] = "Min_Distance_Error";
52  resultLabel[MeanOrtoE] = "Mean_Ortonormality_Error";
53  resultLabel[MaxOrtoE] = "Max_Ortonormality_Error";
54  resultLabel[MinOrtoE] = "Min_Ortonormality_Error";
55  resultLabel[AverageT] = "Average_Execution_Time";
56 
57  // The methods that will be evaluated
58  unsigned int nMethods=5;
59  ONMethod *method[nMethods] = {ExactMethod,
64  string methodLabel[nMethods] = {"ExactMethod",
65  "ApproxMethod",
66  "CayleyMethod",
67  "SVDMethodEigen",
68  "SVDMethodIQRSVD"};
69 
70  // Parameters setting ----------------------------------------------------------------------------------------
71 
72  // default parameters
73  unsigned int noiseTicks=100;
74  unsigned int nRep=1000000;
75 
76  unsigned int rs=time(0); // A random random seed
77 
78  real lowNoise=0.0;
79  real highNoise=0.5;
80 
81  bool print=false;
82  bool quiet=false;
83  bool gaussian=false;
84  bool fixedMatrix=false;
85  // A rotation matrix (without noise)
86  Matrix3 M;
87  // Random quaternion
88  Vector4 q;
89  // Error with respect to the random rotation matrix
90  Matrix3 E;
91  //Format to print the user-provided matrix, if given
92  IOFormat fmt(StreamPrecision, DontAlignCols, " ", " ", "", "", "", "");
93 
94  // Check if the user provided alternative parameters
95  int c;
96  opterr=0; // so that getopt does not generate errors
97  while ((c=getopt(argc,argv,"t:mr:s:l:u:pqg"))!=-1)
98  {
99  switch (c)
100  {
101  case 't':
102  noiseTicks=(unsigned int)atoi(optarg);
103  break;
104  case 'm':
105  fixedMatrix=true;
106  if ((optind+9)>argc)
107  {
108  cerr << "Not enough inputs to define a matrix" << endl;
109  exit(EXIT_FAILURE);
110  }
111  M(0,0)=(real)atof(argv[optind]);
112  M(0,1)=(real)atof(argv[optind+1]);
113  M(0,2)=(real)atof(argv[optind+2]);
114  M(1,0)=(real)atof(argv[optind+3]);
115  M(1,1)=(real)atof(argv[optind+4]);
116  M(1,2)=(real)atof(argv[optind+5]);
117  M(2,0)=(real)atof(argv[optind+6]);
118  M(2,1)=(real)atof(argv[optind+7]);
119  M(2,2)=(real)atof(argv[optind+8]);
120  optind+=9;
121  E=(M.transpose()*M)-Matrix3::Identity();
122  if ((E.norm()>1e-18)||(M.determinant()!=1.0))
123  {
124  cerr << "The input matrix is not a rotation matrix" << endl;
125  exit(EXIT_FAILURE);
126  }
127  break;
128  case 'r':
129  nRep=(unsigned int)atoi(optarg);
130  break;
131  case 's':
132  rs=(unsigned int)atoi(optarg);
133  break;
134  case 'l':
135  lowNoise=(real)atof(optarg);
136  break;
137  case 'h':
138  highNoise=(real)atof(optarg);
139  break;
140  case 'p':
141  print=true;
142  break;
143  case 'q':
144  quiet=true;
145  break;
146  case 'g':
147  gaussian=true;
148  break;
149  default:
150  cerr << "Usage: "<< argv[0] <<" [-l low_error_bound] [-h high_error_bound] [-t noise_ticks] [-m m00 m01 m02 m10 m11 m12 m20 m21 m22] [-r num_repetitions] [-s random_seed] [-g] [-p] [-q]"<< endl;
151  exit(EXIT_FAILURE);
152  }
153  }
154 
155  // Print the settings
156  if (!quiet)
157  {
158  cout << "Executing " << argv[0] << " with arguments:" << endl;
159  #if (USE_DOUBLE)
160  cout << " Precison : double" << endl;
161  #else
162  cout << " Precision : single" << endl;
163  #endif
164  if (fixedMatrix)
165  cout << " Input matrix [-m]: " << M.format(fmt) << endl;
166  else
167  cout << " Num. random matrices [-r]: " << nRep << endl;
168  cout << " Low noise [-l]: " << lowNoise << endl;
169  cout << " High noise [-h]: " << highNoise << endl;
170  cout << " Noise ticks [-t]: " << noiseTicks << endl;
171  cout << " Random seed [-s]: " << rs << endl;
172  cout << " Gaussian noise [-g]: " << gaussian << endl;
173  cout << " Print results [-p]: " << print << endl;
174  }
175 
176  // Fix the random seed for uniform distributions
177  srand(rs);
178 
179  // Fix the random seed for uniform distributions
180  default_random_engine e(rs);
181 
182  // Discretize the noise range
183  noise noiseLevel = Array<real,Dynamic,1>::LinSpaced(noiseTicks,lowNoise,highNoise);
184 
185  // Allocate space for the results of the tests --------------------------------------------------------------
186 
187  // A table with all the results: 'nResults' values for each method (nMethods)
188  // and each error tick (noiseTicks),
189  double ***results;
190  results=new double**[nMethods];
191  for(unsigned int k=0;k<nMethods;k++)
192  {
193  results[k]=new double*[noiseTicks];
194  for (unsigned int i=0;i<noiseTicks;i++)
195  results[k][i]=new double[nResults];
196  }
197 
198  // Perform all the experiments for the different noise levels -----------------------------------------------
199 
200  // The collection of noisy rotation matrices (M with added noise)
201  Matrix3 *N=new Matrix3[nRep];
202 
203  // for each noise level ...
204  for (unsigned int i=0;i<noiseTicks;i++)
205  {
206  if (!quiet)
207  cout << "Noise level: " << noiseLevel(i) << " (" << i+1 << "/" << noiseTicks << ")"<< endl;
208 
209  // Generate 'nRep' noisy matrices ----------------------------------------------------------
210  // We use the same nosiy matrices for all the methods
211  if (!quiet)
212  {
213  if (fixedMatrix)
214  cout << " Introducing noise the given matrix" << endl;
215  else
216  cout << " Generating " << nRep << " random noisy rotation matrices" << endl;
217  }
218 
219  for(unsigned int j=0;j<nRep;j++)
220  {
221  /* If we fixed a matrix, we use it to add the noise. Otherwise we
222  generate a random matrix and then add the noise */
223  if (!fixedMatrix)
224  {
225  RandomQuaternion(q);
226  Quat2Mat(M,q);
227  }
228  if (noiseLevel(i)==0.0)
229  N[j]=M;
230  else
231  {
232  RandomMatrix(E,noiseLevel(i),gaussian,e);
233  N[j]=M+E;
234  }
235  }
236 
237  // Check all the methods at the current noise level ----------------------------------------
238  for(unsigned int k=0;k<nMethods;k++)
239  {
240  if (!quiet)
241  cout << " Testing method: " << methodLabel[k] << endl;
242  TestMethod(method[k],nRep,N,results[k][i]);
243  }
244  }
245 
246  // Report the results ---------------------------------------------------------------------------------------
247  if ((!quiet)&&(print))
248  PrintResults(nMethods,methodLabel,nResults,resultLabel,noiseTicks,noiseLevel,results);
249  SaveResults(nMethods,methodLabel,nResults,resultLabel,gaussian,noiseTicks,noiseLevel,results);
250 
251  return(EXIT_SUCCESS);
252 
253 }