1 #include <Geometry/RotationAveraging.hh>
2 #include <Base/Geometry/Quaternion.hh>
3 #include <Base/Math/Matrix.hh>
4 #include <Base/Math/Random.hh>
5 #include <Geometry/RMatrix.hh>
28 return std::min(fabs(dAngle), std::min(fabs(dAngle + 2*M_PI), fabs(dAngle - 2*M_PI)));
35 return std::min(fabs(dAngle), std::min(fabs(dAngle + 2*M_PI), fabs(dAngle - 2*M_PI)));
38 void AccumulateError(
double error,
double &sum,
double &sqsum,
unsigned int &count)
45 int main(
int argc,
char** argv)
47 const unsigned int trials = 100;
48 const double sigma = 2.0 * M_PI / 180.0;
49 const unsigned int minNum = 10, maxNum = 80, numStep = 10;
50 const unsigned int range = (maxNum - minNum) / numStep + 1;
51 const unsigned int methods = 7;
52 std::vector<std::vector<double> > avgErrors(methods, std::vector<double>(range, 0.0));
53 std::vector<std::vector<double> > stdErrors(methods, std::vector<double>(range, 0.0));
54 std::vector<std::string> methodNames(methods);
55 methodNames[0] =
"angle/axis L2-mean";
56 methodNames[1] =
"quaternion L2-mean";
57 methodNames[2] =
"geodesic L2-mean";
58 methodNames[3] =
"geodesic L1-mean";
59 methodNames[4] =
"chordal L2-mean";
60 methodNames[5] =
"quaternion L2 (quat.)";
61 methodNames[6] =
"chordal L2 (quat.)";
68 cout <<
"Computing mean rotation for " << minNum <<
" to " << maxNum
69 <<
" rotation measurements with angular error of sigma = "
70 << sigma * 180.0 / M_PI <<
" degree for " << trials <<
" trials" << endl;
71 for (
unsigned int k = 0; k < range; k++)
73 const unsigned int num = minNum + k * numStep;
74 std::vector<unsigned int> numSuccess(methods, 0);
75 for (
unsigned int t = 0; t < trials; t++)
80 for (
unsigned int j = 0; j < 3; j++)
89 std::vector<BIAS::RMatrix> measR;
91 std::vector<BIAS::Quaternion<double> > measQ;
93 for (
unsigned int i = 0; i < num; i++)
96 for (
unsigned int j = 0; j < 3; j++)
102 measR.push_back(gtR * errR);
104 errR.GetQuaternion(errQ);
105 measQ.push_back(gtQ * errQ);
111 AccumulateError(AngleError(gtR, meanR),
112 avgErrors[0][k], stdErrors[0][k], numSuccess[0]);
114 AccumulateError(AngleError(gtR, meanR),
115 avgErrors[1][k], stdErrors[1][k], numSuccess[1]);
117 AccumulateError(AngleError(gtR, meanR),
118 avgErrors[2][k], stdErrors[2][k], numSuccess[2]);
120 AccumulateError(AngleError(gtR, meanR),
121 avgErrors[3][k], stdErrors[3][k], numSuccess[3]);
123 AccumulateError(AngleError(gtR, meanR),
124 avgErrors[4][k], stdErrors[4][k], numSuccess[4]);
126 AccumulateError(AngleError(gtQ, meanQ),
127 avgErrors[5][k], stdErrors[5][k], numSuccess[5]);
129 AccumulateError(AngleError(gtQ, meanQ),
130 avgErrors[6][k], stdErrors[6][k], numSuccess[6]);
131 cout <<
"\r" << (int)(100.0 * (k*trials+t+1) / (double)(range*trials))
132 <<
"% done..." << flush;
135 for (
unsigned int m = 0; m < methods; m++) {
136 avgErrors[m][k] /= (double)numSuccess[m];
137 stdErrors[m][k] = sqrt(stdErrors[m][k] / (
double)numSuccess[m] -
138 avgErrors[m][k]*avgErrors[m][k]);
144 printf(
" %21s ",
"Average errors");
145 for (
unsigned int k = 0; k < range; k++)
146 printf(
"| %8d ", minNum + k * numStep);
147 cout <<
"rotations" << endl << flush;
148 for (
unsigned int i = 0; i < 23; i++)
150 for (
unsigned int k = 0; k < range; k++)
151 cout <<
"+----------";
152 cout <<
"---------" << endl << flush;
153 for (
unsigned int m = 0; m < methods; m++) {
154 printf(
" %21s ", methodNames[m].c_str());
155 for (
unsigned int k = 0; k < range; k++)
156 printf(
"| %6f ", avgErrors[m][k]*180.0/M_PI);
157 cout <<
"degree" << endl << flush;
158 printf(
" %18s +- ",
"");
159 for (
unsigned int k = 0; k < range; k++)
160 printf(
"| %6f ", stdErrors[m][k]*180.0/M_PI);
161 cout <<
"degree" << endl << flush;
162 for (
unsigned int i = 0; i < 23; i++)
164 for (
unsigned int k = 0; k < range; k++)
165 cout <<
"+----------";
166 cout <<
"---------" << endl << flush;
170 const std::string filename =
"ExampleRotationAveraging.log";
171 std::ofstream fout(filename.c_str());
172 for (
unsigned int k = 0; k < range; k++)
173 fout << minNum + k * numStep <<
" ";
174 fout << endl << flush;
175 for (
unsigned int m = 0; m < methods; m++) {
176 for (
unsigned int k = 0; k < range; k++)
177 fout << avgErrors[m][k] <<
" ";
178 fout << endl << flush;
181 cout <<
"Results written to file \"" << filename <<
"\"." << endl;
184 const std::string mfilename =
"ExampleRotationAveraging.m";
185 std::ofstream mfout(mfilename.c_str());
187 for (
unsigned int k = 0; k < range; k++)
188 mfout << minNum + k * numStep <<
" ";
189 mfout <<
"];" << endl << flush;
191 for (
unsigned int m = 0; m < methods; m++) {
192 for (
unsigned int k = 0; k < range; k++)
193 mfout << avgErrors[m][k] <<
" ";
195 mfout <<
"];" << endl << flush;
197 mfout << endl <<
" " << flush;
199 mfout <<
"plot(x, y*180/pi)" << endl;
201 for (
unsigned int m = 0; m < methods; m++) {
202 mfout <<
"'" << methodNames[m] <<
"'";
203 if (m+1 < methods) mfout <<
", ";
205 mfout <<
")" << endl << flush;
207 cout <<
"Created Matlab plot file \"" << mfilename <<
"\"." << endl;
void SetMaxIterations(unsigned int num)
Set maximal number of iterations for geodesic L1-/L2-mean computation.
int ChordalL2Mean(const std::vector< BIAS::RMatrix > &R, BIAS::RMatrix &meanR)
Compute chordal L2-mean of rotations.
int LogarithmicL2Mean(const std::vector< BIAS::RMatrix > &R, BIAS::RMatrix &meanR)
Compute matrix logarithm L2-mean of rotations.
double GetUniformDistributed(const double min, const double max)
on succesive calls return uniform distributed random variable between min and max ...
void SetTolerance(double epsilon)
Set threshold for convergence of iterative geodesic L1-/L2-mean computation.
int GetQuaternion(Quaternion< ROTATION_MATRIX_TYPE > &quat) const
Calculates quaternion representation for this rotation matrix.
Quaternion< QUAT_TYPE > Inverse() const
returns the Inverse rotation Quaternion
QUAT_TYPE GetRotationAngle() const
Returns rotation angle notation in radians.
int GeodesicL1Mean(const std::vector< BIAS::RMatrix > &R, BIAS::RMatrix &meanR)
Compute geodesic L1-mean (geodesic median) of rotations.
void SetFromAxisAngle(Vector3< ROTATION_MATRIX_TYPE > w)
Set from rotation axis * angle (modified Rodrigues vector)
int GeodesicL2Mean(const std::vector< BIAS::RMatrix > &R, BIAS::RMatrix &meanR)
Compute geodesic L2-mean (Karcher/geometric mean) of rotations.
Matrix3x3< T > Transpose() const
returns transposed matrix tested 12.06.2002
Computes mean of rotations due to different measures.
double GetNormalDistributed(const double mean, const double sigma)
on succesive calls return normal distributed random variable with mean and standard deviation sigma ...
int QuaternionL2Mean(const std::vector< BIAS::RMatrix > &R, BIAS::RMatrix &meanR)
Compute quaternion L2-mean of rotations.
ROTATION_MATRIX_TYPE GetRotationAngle() const
Interface for angle component of GetRotationAxisAngle()
Vector3< T > & Normalize()
normalize this vector to length 1
class for producing random numbers from different distributions