1 /******************************************************************************
2 * Author: Laurent Kneip *
3 * Contact: kneip.laurent@gmail.com *
4 * License: Copyright (c) 2013 Laurent Kneip, ANU. All rights reserved. *
5 * *
6 * Redistribution and use in source and binary forms, with or without *
7 * modification, are permitted provided that the following conditions *
8 * are met: *
9 * * Redistributions of source code must retain the above copyright *
10 * notice, this list of conditions and the following disclaimer. *
11 * * Redistributions in binary form must reproduce the above copyright *
12 * notice, this list of conditions and the following disclaimer in the *
13 * documentation and/or other materials provided with the distribution. *
14 * * Neither the name of ANU nor the names of its contributors may be *
15 * used to endorse or promote products derived from this software without *
16 * specific prior written permission. *
17 * *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"*
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE *
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE *
21 * ARE DISCLAIMED. IN NO EVENT SHALL ANU OR THE CONTRIBUTORS BE LIABLE *
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL *
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR *
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY *
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *
28 * SUCH DAMAGE. *
29 ******************************************************************************/
30
31
32 #include <math.h>
33 #include <vector>
34 #include <Eigen/NonLinearOptimization>
35 #include <Eigen/NumericalDiff>
36
37 #include <opengv/relative_pose/modules/main.hpp>
38 #include <opengv/relative_pose/modules/fivept_nister/modules.hpp>
39 #include <opengv/relative_pose/modules/fivept_stewenius/modules.hpp>
40 #include <opengv/relative_pose/modules/fivept_kneip/modules.hpp>
41 #include <opengv/relative_pose/modules/eigensolver/modules.hpp>
42 #include <opengv/relative_pose/modules/sixpt/modules.hpp>
43 #include <opengv/relative_pose/modules/ge/modules.hpp>
44 #include <opengv/OptimizationFunctor.hpp>
45 #include <opengv/math/arun.hpp>
46 #include <opengv/math/cayley.hpp>
47 #include <opengv/math/Sturm.hpp>
48
49 #include <stdio.h>
50 #include <iostream>
51
52 void
fivept_stewenius_main(const Eigen::Matrix<double,9,4> & EE,complexEssentials_t & complexEssentials)53 opengv::relative_pose::modules::fivept_stewenius_main(
54 const Eigen::Matrix<double,9,4> & EE,
55 complexEssentials_t & complexEssentials )
56 {
57 Eigen::Matrix<double,10,20> A;
58 fivept_stewenius::composeA(EE,A);
59
60 Eigen::Matrix<double,10,10> A1 = A.block(0,0,10,10);
61 Eigen::Matrix<double,10,10> A2 = A.block(0,10,10,10);
62
63 Eigen::FullPivLU< Eigen::Matrix<double,10,10> > luA1(A1);
64 Eigen::Matrix<double,10,10> A3 = luA1.inverse()*A2;
65
66 Eigen::Matrix<double,10,10> M;
67 M.block(0,0,3,10) = -A3.block(0,0,3,10);
68 M.block(3,0,2,10) = -A3.block(4,0,2,10);
69 M.row(5) = -A3.row(7);
70 M.block(6,0,4,10) = Eigen::Matrix<double,4,10>::Zero();
71 M(6,0) = 1.0;
72 M(7,1) = 1.0;
73 M(8,3) = 1.0;
74 M(9,6) = 1.0;
75
76 Eigen::EigenSolver< Eigen::Matrix<double,10,10> > Eig(M,true);
77
78 //Eigen::Matrix<std::complex<double>,10,1> D = Eig.eigenvalues();
79 Eigen::Matrix<std::complex<double>,10,10> V = Eig.eigenvectors();
80
81 Eigen::Matrix<std::complex<double>,3,10> V1;
82 V1 = V.block(6,0,3,10);
83
84 Eigen::Matrix<std::complex<double>,3,10> V2;
85 V2.row(0) = V.row(9);
86 V2.row(1) = V.row(9);
87 V2.row(2) = V.row(9);
88
89 Eigen::Matrix<std::complex<double>,4,10> SOLS;
90
91 for( int r = 0; r < 3; r++ )
92 {
93 for( int c = 0; c < 10; c++ )
94 SOLS(r,c) = V1(r,c)/V2(r,c);
95 }
96
97 SOLS.row(3) = Eigen::Matrix<std::complex<double>,1,10>::
98 Constant(std::complex<double>(1.0,0.0));
99
100 Eigen::Matrix<std::complex<double>,9,10> Evec = EE * SOLS;
101
102 Eigen::Matrix<std::complex<double>,1,10> norms;
103 for( int c = 0; c < 10; c++ )
104 {
105 norms(0,c) = std::complex<double>(0.0,0.0);
106
107 for( int r = 0; r < 9; r++ )
108 norms(0,c) += pow( Evec(r,c), 2 );
109
110 norms(0,c) = sqrt(norms(0,c));
111 }
112
113 Eigen::Matrix<std::complex<double>,9,10> EvecNorms;
114 for( int i = 0; i < 9; i++ )
115 EvecNorms.row(i) = norms;
116
117 for( int r = 0; r < 9; r++ )
118 {
119 for( int c = 0; c < 10; c++ )
120 Evec(r,c) = Evec(r,c) / EvecNorms(r,c);
121 }
122
123 for( int c = 0; c < 10; c++ )
124 {
125 complexEssential_t complexEssential;
126
127 complexEssential.row(0) = Evec.block(0,c,3,1).transpose();
128 complexEssential.row(1) = Evec.block(3,c,3,1).transpose();
129 complexEssential.row(2) = Evec.block(6,c,3,1).transpose();
130
131 complexEssentials.push_back(complexEssential);
132 }
133 }
134
135 void
fivept_nister_main(const Eigen::Matrix<double,9,4> & EE,essentials_t & essentials)136 opengv::relative_pose::modules::fivept_nister_main(
137 const Eigen::Matrix<double,9,4> & EE,
138 essentials_t & essentials )
139 {
140 Eigen::Matrix<double,10,20> A;
141 fivept_nister::composeA(EE,A);
142
143 Eigen::Matrix<double,10,10> A1 = A.block(0,0,10,10);
144 Eigen::Matrix<double,10,10> A2 = A.block(0,10,10,10);
145
146 Eigen::FullPivLU< Eigen::Matrix<double,10,10> > luA1(A1);
147 Eigen::Matrix<double,10,10> A3 = luA1.inverse()*A2;
148
149 Eigen::Matrix<double,1,4> b11_part1 = Eigen::Matrix<double,1,4>::Zero();
150 b11_part1.block<1,3>(0,1) = A3.block<1,3>(4,0);
151 Eigen::Matrix<double,1,4> b11_part2 = Eigen::Matrix<double,1,4>::Zero();
152 b11_part2.block<1,3>(0,0) = A3.block<1,3>(5,0);
153 Eigen::Matrix<double,1,4> b11 = b11_part1 - b11_part2;
154
155 Eigen::Matrix<double,1,4> b21_part1 = Eigen::Matrix<double,1,4>::Zero();
156 b21_part1.block<1,3>(0,1) = A3.block<1,3>(6,0);
157 Eigen::Matrix<double,1,4> b21_part2 = Eigen::Matrix<double,1,4>::Zero();
158 b21_part2.block<1,3>(0,0) = A3.block<1,3>(7,0);
159 Eigen::Matrix<double,1,4> b21 = b21_part1 - b21_part2;
160
161 Eigen::Matrix<double,1,4> b31_part1 = Eigen::Matrix<double,1,4>::Zero();
162 b31_part1.block<1,3>(0,1) = A3.block<1,3>(8,0);
163 Eigen::Matrix<double,1,4> b31_part2 = Eigen::Matrix<double,1,4>::Zero();
164 b31_part2.block<1,3>(0,0) = A3.block<1,3>(9,0);
165 Eigen::Matrix<double,1,4> b31 = b31_part1 - b31_part2;
166
167 Eigen::Matrix<double,1,4> b12_part1 = Eigen::Matrix<double,1,4>::Zero();
168 b12_part1.block<1,3>(0,1) = A3.block<1,3>(4,3);
169 Eigen::Matrix<double,1,4> b12_part2 = Eigen::Matrix<double,1,4>::Zero();
170 b12_part2.block<1,3>(0,0) = A3.block<1,3>(5,3);
171 Eigen::Matrix<double,1,4> b12 = b12_part1 - b12_part2;
172
173 Eigen::Matrix<double,1,4> b22_part1 = Eigen::Matrix<double,1,4>::Zero();
174 b22_part1.block<1,3>(0,1) = A3.block<1,3>(6,3);
175 Eigen::Matrix<double,1,4> b22_part2 = Eigen::Matrix<double,1,4>::Zero();
176 b22_part2.block<1,3>(0,0) = A3.block<1,3>(7,3);
177 Eigen::Matrix<double,1,4> b22 = b22_part1 - b22_part2;
178
179 Eigen::Matrix<double,1,4> b32_part1 = Eigen::Matrix<double,1,4>::Zero();
180 b32_part1.block<1,3>(0,1) = A3.block<1,3>(8,3);
181 Eigen::Matrix<double,1,4> b32_part2 = Eigen::Matrix<double,1,4>::Zero();
182 b32_part2.block<1,3>(0,0) = A3.block<1,3>(9,3);
183 Eigen::Matrix<double,1,4> b32 = b32_part1 - b32_part2;
184
185 Eigen::Matrix<double,1,5> b13_part1 = Eigen::Matrix<double,1,5>::Zero();
186 b13_part1.block<1,4>(0,1) = A3.block<1,4>(4,6);
187 Eigen::Matrix<double,1,5> b13_part2 = Eigen::Matrix<double,1,5>::Zero();
188 b13_part2.block<1,4>(0,0) = A3.block<1,4>(5,6);
189 Eigen::Matrix<double,1,5> b13 = b13_part1 - b13_part2;
190
191 Eigen::Matrix<double,1,5> b23_part1 = Eigen::Matrix<double,1,5>::Zero();
192 b23_part1.block<1,4>(0,1) = A3.block<1,4>(6,6);
193 Eigen::Matrix<double,1,5> b23_part2 = Eigen::Matrix<double,1,5>::Zero();
194 b23_part2.block<1,4>(0,0) = A3.block<1,4>(7,6);
195 Eigen::Matrix<double,1,5> b23 = b23_part1 - b23_part2;
196
197 Eigen::Matrix<double,1,5> b33_part1 = Eigen::Matrix<double,1,5>::Zero();
198 b33_part1.block<1,4>(0,1) = A3.block<1,4>(8,6);
199 Eigen::Matrix<double,1,5> b33_part2 = Eigen::Matrix<double,1,5>::Zero();
200 b33_part2.block<1,4>(0,0) = A3.block<1,4>(9,6);
201 Eigen::Matrix<double,1,5> b33 = b33_part1 - b33_part2;
202
203 Eigen::Matrix<double,1,8> p1_part1;
204 fivept_nister::computeSeventhOrderPolynomial(b23,b12,p1_part1);
205 Eigen::Matrix<double,1,8> p1_part2;
206 fivept_nister::computeSeventhOrderPolynomial(b13,b22,p1_part2);
207 Eigen::Matrix<double,1,8> p1 = p1_part1 - p1_part2;
208 Eigen::Matrix<double,1,8> p2_part1;
209 fivept_nister::computeSeventhOrderPolynomial(b13,b21,p2_part1);
210 Eigen::Matrix<double,1,8> p2_part2;
211 fivept_nister::computeSeventhOrderPolynomial(b23,b11,p2_part2);
212 Eigen::Matrix<double,1,8> p2 = p2_part1 - p2_part2;
213 Eigen::Matrix<double,1,7> p3_part1;
214 fivept_nister::computeSixthOrderPolynomial(b11,b22,p3_part1);
215 Eigen::Matrix<double,1,7> p3_part2;
216 fivept_nister::computeSixthOrderPolynomial(b12,b21,p3_part2);
217 Eigen::Matrix<double,1,7> p3 = p3_part1 - p3_part2;
218
219 Eigen::Matrix<double,1,11> p_order10_part1;
220 fivept_nister::computeTenthOrderPolynomialFrom73(p1,b31,p_order10_part1);
221 Eigen::Matrix<double,1,11> p_order10_part2;
222 fivept_nister::computeTenthOrderPolynomialFrom73(p2,b32,p_order10_part2);
223 Eigen::Matrix<double,1,11> p_order10_part3;
224 fivept_nister::computeTenthOrderPolynomialFrom64(p3,b33,p_order10_part3);
225 Eigen::Matrix<double,1,11> p_order10 =
226 p_order10_part1 + p_order10_part2 + p_order10_part3;
227
228 math::Sturm sturmSequence(p_order10);
229 std::vector<double> roots = sturmSequence.findRoots();
230
231 Eigen::MatrixXd Evec(9,roots.size());
232
233 for( size_t i = 0; i < roots.size(); i++ )
234 {
235 double z = roots[i];
236 double x = fivept_nister::polyVal(p1,z)/fivept_nister::polyVal(p3,z);
237 double y = fivept_nister::polyVal(p2,z)/fivept_nister::polyVal(p3,z);
238
239 //pollishing here
240 fivept_nister::pollishCoefficients(A,x,y,z);
241
242 Evec.col(i) = x*EE.col(0) + y*EE.col(1) + z*EE.col(2) + EE.col(3);
243 }
244
245 Eigen::MatrixXd norms(1,roots.size());
246 for( size_t c = 0; c < roots.size(); c++ )
247 {
248 norms(0,c) = 0.0;
249
250 for( int r = 0; r < 9; r++ )
251 norms(0,c) += pow( Evec(r,c), 2 );
252
253 norms(0,c) = sqrt(norms(0,c));
254 }
255
256 Eigen::MatrixXd EvecNorms(9,roots.size());
257 for( size_t i = 0; i < 9; i++ )
258 EvecNorms.row(i) = norms;
259
260 for( size_t r = 0; r < 9; r++ )
261 {
262 for( size_t c = 0; c < roots.size(); c++ )
263 Evec(r,c) = Evec(r,c) / EvecNorms(r,c);
264 }
265
266 for( size_t c = 0; c < roots.size(); c++ )
267 {
268 essential_t essential;
269
270 essential.row(0) = Evec.block<3,1>(0,c).transpose();
271 essential.row(1) = Evec.block<3,1>(3,c).transpose();
272 essential.row(2) = Evec.block<3,1>(6,c).transpose();
273
274 essentials.push_back(essential);
275 }
276 }
277
278 void
fivept_kneip_main(const Eigen::Matrix<double,3,5> & f1,const Eigen::Matrix<double,3,5> & f2,rotations_t & rotations)279 opengv::relative_pose::modules::fivept_kneip_main(
280 const Eigen::Matrix<double,3,5> & f1,
281 const Eigen::Matrix<double,3,5> & f2,
282 rotations_t & rotations )
283 {
284 Eigen::Matrix<double,66,197> groebnerMatrix =
285 Eigen::Matrix<double,66,197>::Zero();
286 Eigen::Matrix3d temp1 = Eigen::Matrix3d::Zero();
287 Eigen::Matrix3d temp2 = Eigen::Matrix3d::Zero();
288 std::vector<Eigen::Matrix3d, Eigen::aligned_allocator<Eigen::Matrix3d> > c_1;
289 c_1.push_back(temp1);
290 c_1.push_back(temp1);
291 c_1.push_back(temp1);
292 std::vector<Eigen::Matrix3d, Eigen::aligned_allocator<Eigen::Matrix3d> > c_2;
293 c_2.push_back(temp2);
294 c_2.push_back(temp2);
295 c_2.push_back(temp2);
296
297 int currentRow = 0;
298
299 for( int firstFeat = 0; firstFeat < 5; firstFeat++ )
300 {
301 for( int secondFeat = firstFeat + 1; secondFeat < 5; secondFeat++ )
302 {
303 temp1 = f1.col(firstFeat)*f1.col(secondFeat).transpose();
304 temp2 = f2.col(firstFeat)*f2.col(secondFeat).transpose();
305
306 for( int thirdFeat = secondFeat + 1; thirdFeat < 5; thirdFeat++ )
307 {
308 c_1[0] = temp1 * f1(0,thirdFeat);
309 c_1[1] = temp1 * f1(1,thirdFeat);
310 c_1[2] = temp1 * f1(2,thirdFeat);
311 c_2[0] = temp2 * f2(0,thirdFeat);
312 c_2[1] = temp2 * f2(1,thirdFeat);
313 c_2[2] = temp2 * f2(2,thirdFeat);
314
315 groebnerMatrix.row(currentRow++) =
316 fivept_kneip::initEpncpRowR( c_1, c_2 );
317 }
318 }
319 }
320
321 fivept_kneip::initMatrix(groebnerMatrix);
322 fivept_kneip::computeBasis(groebnerMatrix);
323
324 Eigen::Matrix<double,20,20> M = Eigen::Matrix<double,20,20>::Zero();
325 M.block<10,20>(0,0) = -groebnerMatrix.block<10,20>(51,177);
326 M(10,1) = 1.0;
327 M(11,2) = 1.0;
328 M(12,3) = 1.0;
329 M(13,4) = 1.0;
330 M(14,5) = 1.0;
331 M(15,6) = 1.0;
332 M(16,7) = 1.0;
333 M(17,8) = 1.0;
334 M(18,9) = 1.0;
335 M(19,18) = 1.0;
336
337 Eigen::EigenSolver< Eigen::Matrix<double,20,20> > Eig(M,true);
338 Eigen::Matrix<std::complex<double>,20,1> D = Eig.eigenvalues();
339 Eigen::Matrix<std::complex<double>,20,20> V = Eig.eigenvectors();
340
341 //Eigen::Matrix<std::complex<double>,9,1> tempVector;
342 rotation_t finalRotation = Eigen::Matrix3d::Zero();
343 for( unsigned int i = 0; i < 20; i++ )
344 {
345 std::complex<double> tempp;
346 tempp = D[i];
347
348 //check if we have a real solution
349 if( fabs(tempp.imag()) < 0.1 )
350 {
351 tempp = V(18,i)/V(19,i);
352 finalRotation(0,0) = tempp.real();// tempVector[0] = tempp;
353 tempp = V(17,i)/V(19,i);
354 finalRotation(0,1) = tempp.real();// tempVector[1] = tempp;
355 tempp = V(16,i)/V(19,i);
356 finalRotation(0,2) = tempp.real();// tempVector[2] = tempp;
357 tempp = V(15,i)/V(19,i);
358 finalRotation(1,0) = tempp.real();// tempVector[3] = tempp;
359 tempp = V(14,i)/V(19,i);
360 finalRotation(1,1) = tempp.real();// tempVector[4] = tempp;
361 tempp = V(13,i)/V(19,i);
362 finalRotation(1,2) = tempp.real();// tempVector[5] = tempp;
363 tempp = V(12,i)/V(19,i);
364 finalRotation(2,0) = tempp.real();// tempVector[6] = tempp;
365 tempp = V(11,i)/V(19,i);
366 finalRotation(2,1) = tempp.real();// tempVector[7] = tempp;
367 tempp = V(10,i)/V(19,i);
368 finalRotation(2,2) = tempp.real();// tempVector[8] = tempp;
369
370 double tempNorm = finalRotation.row(1).norm();
371 finalRotation.row(1) = finalRotation.row(1) / tempNorm;
372 tempNorm = finalRotation.row(2).norm();
373 finalRotation.row(2) = finalRotation.row(2) / tempNorm;
374
375 //check if the normalized rotation matrix has determinant close enough to 1
376 if( fabs( finalRotation.determinant() - 1.0 ) < 0.1 )
377 {
378 Eigen::Matrix3d eval;
379 double totalEval = 0.0;
380 eval.col(0) = f1.col(0).cross(finalRotation*f2.col(0));
381 eval.col(1) = f1.col(1).cross(finalRotation*f2.col(1));
382 eval.col(2) = f1.col(2).cross(finalRotation*f2.col(2));
383 totalEval += fabs(eval.determinant());
384 eval.col(0) = f1.col(0).cross(finalRotation*f2.col(0));
385 eval.col(1) = f1.col(1).cross(finalRotation*f2.col(1));
386 eval.col(2) = f1.col(3).cross(finalRotation*f2.col(3));
387 totalEval += fabs(eval.determinant());
388 eval.col(0) = f1.col(0).cross(finalRotation*f2.col(0));
389 eval.col(1) = f1.col(1).cross(finalRotation*f2.col(1));
390 eval.col(2) = f1.col(4).cross(finalRotation*f2.col(4));
391 totalEval += fabs(eval.determinant());
392 eval.col(0) = f1.col(0).cross(finalRotation*f2.col(0));
393 eval.col(1) = f1.col(2).cross(finalRotation*f2.col(2));
394 eval.col(2) = f1.col(3).cross(finalRotation*f2.col(3));
395 totalEval += fabs(eval.determinant());
396 eval.col(0) = f1.col(0).cross(finalRotation*f2.col(0));
397 eval.col(1) = f1.col(2).cross(finalRotation*f2.col(2));
398 eval.col(2) = f1.col(4).cross(finalRotation*f2.col(4));
399 totalEval += fabs(eval.determinant());
400 eval.col(0) = f1.col(0).cross(finalRotation*f2.col(0));
401 eval.col(1) = f1.col(3).cross(finalRotation*f2.col(3));
402 eval.col(2) = f1.col(4).cross(finalRotation*f2.col(4));
403 totalEval += fabs(eval.determinant());
404 eval.col(0) = f1.col(1).cross(finalRotation*f2.col(1));
405 eval.col(1) = f1.col(2).cross(finalRotation*f2.col(2));
406 eval.col(2) = f1.col(3).cross(finalRotation*f2.col(3));
407 totalEval += fabs(eval.determinant());
408 eval.col(0) = f1.col(1).cross(finalRotation*f2.col(1));
409 eval.col(1) = f1.col(2).cross(finalRotation*f2.col(2));
410 eval.col(2) = f1.col(4).cross(finalRotation*f2.col(4));
411 totalEval += fabs(eval.determinant());
412 eval.col(0) = f1.col(1).cross(finalRotation*f2.col(1));
413 eval.col(1) = f1.col(3).cross(finalRotation*f2.col(3));
414 eval.col(2) = f1.col(4).cross(finalRotation*f2.col(4));
415 totalEval += fabs(eval.determinant());
416 eval.col(0) = f1.col(2).cross(finalRotation*f2.col(2));
417 eval.col(1) = f1.col(3).cross(finalRotation*f2.col(3));
418 eval.col(2) = f1.col(4).cross(finalRotation*f2.col(4));
419 totalEval += fabs(eval.determinant());
420 totalEval += fabs(
421 finalRotation(0,0)*finalRotation(0,0)+
422 finalRotation(0,1)*finalRotation(0,1)+
423 finalRotation(0,2)*finalRotation(0,2)-1);
424 totalEval += fabs(
425 finalRotation(0,0)*finalRotation(1,0)+
426 finalRotation(0,1)*finalRotation(1,1)+
427 finalRotation(0,2)*finalRotation(1,2));
428 totalEval += fabs(
429 finalRotation(0,0)*finalRotation(2,0)+
430 finalRotation(0,1)*finalRotation(2,1)+
431 finalRotation(0,2)*finalRotation(2,2));
432 totalEval += fabs(
433 finalRotation(1,0)*finalRotation(1,0)+
434 finalRotation(1,1)*finalRotation(1,1)+
435 finalRotation(1,2)*finalRotation(1,2)-1);
436 totalEval += fabs(
437 finalRotation(1,0)*finalRotation(2,0)+
438 finalRotation(1,1)*finalRotation(2,1)+
439 finalRotation(1,2)*finalRotation(2,2));
440 totalEval += fabs(
441 finalRotation(2,0)*finalRotation(2,0)+
442 finalRotation(2,1)*finalRotation(2,1)+
443 finalRotation(2,2)*finalRotation(2,2)-1);
444 totalEval += fabs(
445 finalRotation(1,0)*finalRotation(2,1)-
446 finalRotation(2,0)*finalRotation(1,1)-finalRotation(0,2));
447 totalEval += fabs(
448 finalRotation(2,0)*finalRotation(0,1)-
449 finalRotation(0,0)*finalRotation(2,1)-finalRotation(1,2));
450 totalEval += fabs(
451 finalRotation(0,0)*finalRotation(1,1)-
452 finalRotation(1,0)*finalRotation(0,1)-finalRotation(2,2));
453
454 //check if the initial constraints are fullfilled to a sufficient extend
455 if( totalEval < 0.001 )
456 {
457 Eigen::Matrix<double,3,5> normalVectors;
458 normalVectors.col(0) = f1.col(0).cross(finalRotation * f2.col(0));
459 normalVectors.col(1) = f1.col(1).cross(finalRotation * f2.col(1));
460 normalVectors.col(2) = f1.col(2).cross(finalRotation * f2.col(2));
461 normalVectors.col(3) = f1.col(3).cross(finalRotation * f2.col(3));
462 normalVectors.col(4) = f1.col(4).cross(finalRotation * f2.col(4));
463
464 Eigen::Vector3d trans01 =
465 normalVectors.col(0).cross(normalVectors.col(1));
466 Eigen::Vector3d trans02 =
467 normalVectors.col(0).cross(normalVectors.col(2));
468 Eigen::Vector3d trans03 =
469 normalVectors.col(0).cross(normalVectors.col(3));
470 Eigen::Vector3d trans04 =
471 normalVectors.col(0).cross(normalVectors.col(4));
472 Eigen::Vector3d trans12 =
473 normalVectors.col(1).cross(normalVectors.col(2));
474 Eigen::Vector3d trans13 =
475 normalVectors.col(1).cross(normalVectors.col(3));
476 Eigen::Vector3d trans14 =
477 normalVectors.col(1).cross(normalVectors.col(4));
478 Eigen::Vector3d trans23 =
479 normalVectors.col(2).cross(normalVectors.col(3));
480 Eigen::Vector3d trans24 =
481 normalVectors.col(2).cross(normalVectors.col(4));
482 Eigen::Vector3d trans34 =
483 normalVectors.col(3).cross(normalVectors.col(4));
484
485 Eigen::Vector3d tempVector1;
486 Eigen::Vector3d tempVector2;
487
488 bool positive = true;
489
490 for( int i = 0; i < 5; i++ )
491 {
492 tempVector1 = trans01.cross( f1.col(i) );
493 tempVector2 = trans01.cross( finalRotation * f2.col(i) );
494 if( tempVector1.dot(tempVector2) < 0 )
495 {
496 positive = false;
497 break;
498 }
499 tempVector1 = trans02.cross( f1.col(i) );
500 tempVector2 = trans02.cross( finalRotation * f2.col(i) );
501 if( tempVector1.dot(tempVector2) < 0 )
502 {
503 positive = false;
504 break;
505 }
506 tempVector1 = trans03.cross( f1.col(i) );
507 tempVector2 = trans03.cross( finalRotation * f2.col(i) );
508 if( tempVector1.dot(tempVector2) < 0 )
509 {
510 positive = false;
511 break;
512 }
513 tempVector1 = trans04.cross( f1.col(i) );
514 tempVector2 = trans04.cross( finalRotation * f2.col(i) );
515 if( tempVector1.dot(tempVector2) < 0 )
516 {
517 positive = false;
518 break;
519 }
520 tempVector1 = trans12.cross( f1.col(i) );
521 tempVector2 = trans12.cross( finalRotation * f2.col(i) );
522 if( tempVector1.dot(tempVector2) < 0 )
523 {
524 positive = false;
525 break;
526 }
527 tempVector1 = trans13.cross( f1.col(i) );
528 tempVector2 = trans13.cross( finalRotation * f2.col(i) );
529 if( tempVector1.dot(tempVector2) < 0 )
530 {
531 positive = false;
532 break;
533 }
534 tempVector1 = trans14.cross( f1.col(i) );
535 tempVector2 = trans14.cross( finalRotation * f2.col(i) );
536 if( tempVector1.dot(tempVector2) < 0 )
537 {
538 positive = false;
539 break;
540 }
541 tempVector1 = trans23.cross( f1.col(i) );
542 tempVector2 = trans23.cross( finalRotation * f2.col(i) );
543 if( tempVector1.dot(tempVector2) < 0 )
544 {
545 positive = false;
546 break;
547 }
548 tempVector1 = trans24.cross( f1.col(i) );
549 tempVector2 = trans24.cross( finalRotation * f2.col(i) );
550 if( tempVector1.dot(tempVector2) < 0 )
551 {
552 positive = false;
553 break;
554 }
555 tempVector1 = trans34.cross( f1.col(i) );
556 tempVector2 = trans34.cross( finalRotation * f2.col(i) );
557 if( tempVector1.dot(tempVector2) < 0 )
558 {
559 positive = false;
560 break;
561 }
562 }
563
564 //finally, check if the cheiriality constraint is fullfilled to
565 //sufficient extend
566 if( positive )
567 rotations.push_back(finalRotation);
568 }
569 }
570 }
571 }
572 }
573
574 namespace opengv
575 {
576 namespace relative_pose
577 {
578 namespace modules
579 {
580
581 struct Eigensolver_step : OptimizationFunctor<double>
582 {
583 const Eigen::Matrix3d & _xxF;
584 const Eigen::Matrix3d & _yyF;
585 const Eigen::Matrix3d & _zzF;
586 const Eigen::Matrix3d & _xyF;
587 const Eigen::Matrix3d & _yzF;
588 const Eigen::Matrix3d & _zxF;
589
Eigensolver_stepopengv::relative_pose::modules::Eigensolver_step590 Eigensolver_step(
591 const Eigen::Matrix3d & xxF,
592 const Eigen::Matrix3d & yyF,
593 const Eigen::Matrix3d & zzF,
594 const Eigen::Matrix3d & xyF,
595 const Eigen::Matrix3d & yzF,
596 const Eigen::Matrix3d & zxF ) :
597 OptimizationFunctor<double>(3,3),
598 _xxF(xxF),_yyF(yyF),_zzF(zzF),_xyF(xyF),_yzF(yzF),_zxF(zxF) {}
599
operator ()opengv::relative_pose::modules::Eigensolver_step600 int operator()(const Eigen::VectorXd &x, Eigen::VectorXd &fvec) const
601 {
602 cayley_t cayley = x;
603 Eigen::Matrix<double,1,3> jacobian;
604 eigensolver::getSmallestEVwithJacobian(
605 _xxF,_yyF,_zzF,_xyF,_yzF,_zxF,cayley,jacobian);
606
607 fvec[0] = jacobian(0,0);
608 fvec[1] = jacobian(0,1);
609 fvec[2] = jacobian(0,2);
610 return 0;
611 }
612 };
613
614 }
615 }
616 }
617
618 struct myPair {
619 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
620
621 Eigen::Vector3d first;
622 double second;
623 };
624
operator <(const myPair & p1,const myPair & p2)625 bool operator<( const myPair & p1, const myPair & p2 ) {
626 if( p1.second > p2.second )
627 return true;
628 return false;
629 }
630
631 void
eigensolver_main(const Eigen::Matrix3d & xxF,const Eigen::Matrix3d & yyF,const Eigen::Matrix3d & zzF,const Eigen::Matrix3d & xyF,const Eigen::Matrix3d & yzF,const Eigen::Matrix3d & zxF,eigensolverOutput_t & output)632 opengv::relative_pose::modules::eigensolver_main(
633 const Eigen::Matrix3d & xxF,
634 const Eigen::Matrix3d & yyF,
635 const Eigen::Matrix3d & zzF,
636 const Eigen::Matrix3d & xyF,
637 const Eigen::Matrix3d & yzF,
638 const Eigen::Matrix3d & zxF,
639 eigensolverOutput_t & output )
640 {
641 const int n=3;
642 VectorXd x(n);
643
644 x = math::rot2cayley(output.rotation);
645 Eigensolver_step functor(xxF,yyF,zzF,xyF,yzF,zxF );
646 NumericalDiff<Eigensolver_step> numDiff(functor);
647 LevenbergMarquardt< NumericalDiff<Eigensolver_step> > lm(numDiff);
648
649 lm.resetParameters();
650 lm.parameters.ftol = 0.00005;
651 lm.parameters.xtol = 1.E1*NumTraits<double>::epsilon();
652 lm.parameters.maxfev = 100;
653 lm.minimize(x);
654
655 cayley_t cayley = x;
656 rotation_t R = math::cayley2rot(cayley);
657
658 Eigen::Matrix3d M = eigensolver::composeM(xxF,yyF,zzF,xyF,yzF,zxF,cayley);
659 Eigen::EigenSolver< Eigen::Matrix3d > Eig(M,true);
660 Eigen::Matrix<std::complex<double>,3,1> D_complex = Eig.eigenvalues();
661 Eigen::Matrix<std::complex<double>,3,3> V_complex = Eig.eigenvectors();
662 eigenvalues_t D;
663 eigenvectors_t V;
664
665 std::vector< myPair > pairs;
666 for(size_t i = 0; i < 3; i++) {
667 myPair newPair;
668 newPair.second = D_complex[i].real();
669 for(size_t j = 0; j < 3; j++)
670 newPair.first(j,0) = V_complex(j,i).real();
671 pairs.push_back(newPair);
672 }
673 std::sort(pairs.begin(),pairs.end());
674 for(size_t i = 0; i < 3; i++) {
675 D[i] = pairs[i].second;
676 V.col(i) = pairs[i].first;
677 }
678
679 double translationMagnitude = sqrt(pow(D[0],2) + pow(D[1],2));
680 translation_t t = translationMagnitude * V.col(2);
681
682 output.translation = t;
683 output.rotation = R;
684 output.eigenvalues = D;
685 output.eigenvectors = V;
686
687 }
688
689 void
sixpt_main(Eigen::Matrix<double,6,6> & L1,Eigen::Matrix<double,6,6> & L2,rotations_t & solutions)690 opengv::relative_pose::modules::sixpt_main(
691 Eigen::Matrix<double,6,6> & L1,
692 Eigen::Matrix<double,6,6> & L2,
693 rotations_t & solutions)
694 {
695
696 //create vectors of Pluecker coordinates
697 std::vector< Eigen::Matrix<double,6,1>, Eigen::aligned_allocator<Eigen::Matrix<double,6,1> > > L1vec;
698 std::vector< Eigen::Matrix<double,6,1>, Eigen::aligned_allocator<Eigen::Matrix<double,6,1> > > L2vec;
699 for(int i = 0; i < 6; i++ )
700 {
701 L1vec.push_back( L1.col(i) );
702 L2vec.push_back( L2.col(i) );
703 }
704
705 //setup the action matrix
706 Eigen::Matrix<double,64,64> Action = Eigen::Matrix<double,64,64>::Zero();
707 sixpt::setupAction( L1vec, L2vec, Action );
708
709 //finally eigen-decompose the action-matrix and obtain the solutions
710 Eigen::EigenSolver< Eigen::Matrix<double,64,64> > Eig(Action,true);
711 Eigen::Matrix<std::complex<double>,64,64> EV = Eig.eigenvectors();
712
713 solutions.reserve(64);
714 for( int c = 0; c < 64; c++ )
715 {
716 cayley_t solution;
717 for( int r = 0; r < 3; r++ )
718 {
719 std::complex<double> temp = EV(60+r,c)/EV(63,c);
720 solution[r] = temp.real();
721 }
722
723 solutions.push_back(math::cayley2rot(solution).transpose());
724 }
725 }
726
727 namespace opengv
728 {
729 namespace relative_pose
730 {
731 namespace modules
732 {
733
734 struct Ge_step : OptimizationFunctor<double>
735 {
736 const Eigen::Matrix3d & _xxF;
737 const Eigen::Matrix3d & _yyF;
738 const Eigen::Matrix3d & _zzF;
739 const Eigen::Matrix3d & _xyF;
740 const Eigen::Matrix3d & _yzF;
741 const Eigen::Matrix3d & _zxF;
742 const Eigen::Matrix<double,3,9> & _x1P;
743 const Eigen::Matrix<double,3,9> & _y1P;
744 const Eigen::Matrix<double,3,9> & _z1P;
745 const Eigen::Matrix<double,3,9> & _x2P;
746 const Eigen::Matrix<double,3,9> & _y2P;
747 const Eigen::Matrix<double,3,9> & _z2P;
748 const Eigen::Matrix<double,9,9> & _m11P;
749 const Eigen::Matrix<double,9,9> & _m12P;
750 const Eigen::Matrix<double,9,9> & _m22P;
751
Ge_stepopengv::relative_pose::modules::Ge_step752 Ge_step(
753 const Eigen::Matrix3d & xxF,
754 const Eigen::Matrix3d & yyF,
755 const Eigen::Matrix3d & zzF,
756 const Eigen::Matrix3d & xyF,
757 const Eigen::Matrix3d & yzF,
758 const Eigen::Matrix3d & zxF,
759 const Eigen::Matrix<double,3,9> & x1P,
760 const Eigen::Matrix<double,3,9> & y1P,
761 const Eigen::Matrix<double,3,9> & z1P,
762 const Eigen::Matrix<double,3,9> & x2P,
763 const Eigen::Matrix<double,3,9> & y2P,
764 const Eigen::Matrix<double,3,9> & z2P,
765 const Eigen::Matrix<double,9,9> & m11P,
766 const Eigen::Matrix<double,9,9> & m12P,
767 const Eigen::Matrix<double,9,9> & m22P ) :
768 OptimizationFunctor<double>(3,3),
769 _xxF(xxF),_yyF(yyF),_zzF(zzF),_xyF(xyF),_yzF(yzF),_zxF(zxF),
770 _x1P(x1P),_y1P(y1P),_z1P(z1P),_x2P(x2P),_y2P(y2P),_z2P(z2P),
771 _m11P(m11P),_m12P(m12P),_m22P(m22P) {}
772
operator ()opengv::relative_pose::modules::Ge_step773 int operator()(const Eigen::VectorXd &x, Eigen::VectorXd &fvec) const
774 {
775 cayley_t cayley = x;
776 Eigen::Matrix<double,1,3> jacobian;
777 ge::getCostWithJacobian(
778 _xxF,_yyF,_zzF,_xyF,_yzF,_zxF,
779 _x1P,_y1P,_z1P,_x2P,_y2P,_z2P,_m11P,_m12P,_m22P,cayley,jacobian,1);
780
781 fvec[0] = jacobian(0,0);
782 fvec[1] = jacobian(0,1);
783 fvec[2] = jacobian(0,2);
784
785 return 0;
786 }
787 };
788
789 }
790 }
791 }
792
793 struct myPair_ge {
794 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
795
796 Eigen::Vector4d first;
797 double second;
798 };
799
operator <(const myPair_ge & p1,const myPair_ge & p2)800 bool operator<( const myPair_ge & p1, const myPair_ge & p2 ) {
801 if( p1.second > p2.second )
802 return true;
803 return false;
804 }
805
806 void
ge_main(const Eigen::Matrix3d & xxF,const Eigen::Matrix3d & yyF,const Eigen::Matrix3d & zzF,const Eigen::Matrix3d & xyF,const Eigen::Matrix3d & yzF,const Eigen::Matrix3d & zxF,const Eigen::Matrix<double,3,9> & x1P,const Eigen::Matrix<double,3,9> & y1P,const Eigen::Matrix<double,3,9> & z1P,const Eigen::Matrix<double,3,9> & x2P,const Eigen::Matrix<double,3,9> & y2P,const Eigen::Matrix<double,3,9> & z2P,const Eigen::Matrix<double,9,9> & m11P,const Eigen::Matrix<double,9,9> & m12P,const Eigen::Matrix<double,9,9> & m22P,const cayley_t & startingPoint,geOutput_t & output)807 opengv::relative_pose::modules::ge_main(
808 const Eigen::Matrix3d & xxF,
809 const Eigen::Matrix3d & yyF,
810 const Eigen::Matrix3d & zzF,
811 const Eigen::Matrix3d & xyF,
812 const Eigen::Matrix3d & yzF,
813 const Eigen::Matrix3d & zxF,
814 const Eigen::Matrix<double,3,9> & x1P,
815 const Eigen::Matrix<double,3,9> & y1P,
816 const Eigen::Matrix<double,3,9> & z1P,
817 const Eigen::Matrix<double,3,9> & x2P,
818 const Eigen::Matrix<double,3,9> & y2P,
819 const Eigen::Matrix<double,3,9> & z2P,
820 const Eigen::Matrix<double,9,9> & m11P,
821 const Eigen::Matrix<double,9,9> & m12P,
822 const Eigen::Matrix<double,9,9> & m22P,
823 const cayley_t & startingPoint,
824 geOutput_t & output )
825 {
826 //this one doesn't work, probably because of double numerical differentiation
827 //use ge_main2, which is an implementation of gradient descent
828 const int n=3;
829 VectorXd x(n);
830
831 x = startingPoint;
832 Ge_step functor(xxF,yyF,zzF,xyF,yzF,zxF,
833 x1P,y1P,z1P,x2P,y2P,z2P,m11P,m12P,m22P);
834 NumericalDiff<Ge_step> numDiff(functor);
835 LevenbergMarquardt< NumericalDiff<Ge_step> > lm(numDiff);
836
837 lm.resetParameters();
838 lm.parameters.ftol = 0.000001;//1.E1*NumTraits<double>::epsilon();
839 lm.parameters.xtol = 1.E1*NumTraits<double>::epsilon();
840 lm.parameters.maxfev = 100;
841 lm.minimize(x);
842
843 cayley_t cayley = x;
844 rotation_t R = math::cayley2rot(cayley);
845
846 Eigen::Matrix4d G = ge::composeG(xxF,yyF,zzF,xyF,yzF,zxF,
847 x1P,y1P,z1P,x2P,y2P,z2P,m11P,m12P,m22P,cayley);
848
849 Eigen::EigenSolver< Eigen::Matrix4d > Eig(G,true);
850 Eigen::Matrix<std::complex<double>,4,1> D_complex = Eig.eigenvalues();
851 Eigen::Matrix<std::complex<double>,4,4> V_complex = Eig.eigenvectors();
852 Eigen::Vector4d D;
853 Eigen::Matrix4d V;
854
855 std::vector< myPair_ge > pairs;
856 for(size_t i = 0; i < 4; i++) {
857 myPair_ge newPair;
858 newPair.second = D_complex[i].real();
859 for(size_t j = 0; j < 4; j++)
860 newPair.first(j,0) = V_complex(j,i).real();
861 pairs.push_back(newPair);
862 }
863 std::sort(pairs.begin(),pairs.end());
864 for(size_t i = 0; i < 4; i++) {
865 D[i] = pairs[i].second;
866 V.col(i) = pairs[i].first;
867 }
868
869 double factor = V(3,3);
870 Eigen::Vector4d t = (1.0/factor) * V.col(3);
871
872 output.translation = t;
873 output.rotation = R;
874 output.eigenvalues = D;
875 output.eigenvectors = V;
876 }
877
878 void
ge_main2(const Eigen::Matrix3d & xxF,const Eigen::Matrix3d & yyF,const Eigen::Matrix3d & zzF,const Eigen::Matrix3d & xyF,const Eigen::Matrix3d & yzF,const Eigen::Matrix3d & zxF,const Eigen::Matrix<double,3,9> & x1P,const Eigen::Matrix<double,3,9> & y1P,const Eigen::Matrix<double,3,9> & z1P,const Eigen::Matrix<double,3,9> & x2P,const Eigen::Matrix<double,3,9> & y2P,const Eigen::Matrix<double,3,9> & z2P,const Eigen::Matrix<double,9,9> & m11P,const Eigen::Matrix<double,9,9> & m12P,const Eigen::Matrix<double,9,9> & m22P,const cayley_t & startingPoint,geOutput_t & output)879 opengv::relative_pose::modules::ge_main2(
880 const Eigen::Matrix3d & xxF,
881 const Eigen::Matrix3d & yyF,
882 const Eigen::Matrix3d & zzF,
883 const Eigen::Matrix3d & xyF,
884 const Eigen::Matrix3d & yzF,
885 const Eigen::Matrix3d & zxF,
886 const Eigen::Matrix<double,3,9> & x1P,
887 const Eigen::Matrix<double,3,9> & y1P,
888 const Eigen::Matrix<double,3,9> & z1P,
889 const Eigen::Matrix<double,3,9> & x2P,
890 const Eigen::Matrix<double,3,9> & y2P,
891 const Eigen::Matrix<double,3,9> & z2P,
892 const Eigen::Matrix<double,9,9> & m11P,
893 const Eigen::Matrix<double,9,9> & m12P,
894 const Eigen::Matrix<double,9,9> & m22P,
895 const cayley_t & startingPoint,
896 geOutput_t & output )
897 {
898 //todo: the optimization strategy is something that can possibly be improved:
899 //-one idea is to check the gradient at the new sampling point, if that derives
900 // too much, we have to stop
901 //-another idea consists of having linear change of lambda, instead of exponential (safer, but slower)
902
903 double lambda = 0.01;
904 double maxLambda = 0.08;
905 double modifier = 2.0;
906 int maxIterations = 50;
907 double min_xtol = 0.00001;
908 bool disablingIncrements = true;
909 bool print = false;
910
911 cayley_t cayley;
912
913 double disturbanceAmplitude = 0.3;
914 bool found = false;
915 int randomTrialCount = 0;
916
917 while( !found && randomTrialCount < 5 )
918 {
919 if(randomTrialCount > 2)
920 disturbanceAmplitude = 0.6;
921
922 if( randomTrialCount == 0 )
923 cayley = startingPoint;
924 else
925 {
926 cayley = startingPoint;
927 Eigen::Vector3d disturbance;
928 disturbance[0] = (((double) rand())/ ((double) RAND_MAX)-0.5)*2.0*disturbanceAmplitude;
929 disturbance[1] = (((double) rand())/ ((double) RAND_MAX)-0.5)*2.0*disturbanceAmplitude;
930 disturbance[2] = (((double) rand())/ ((double) RAND_MAX)-0.5)*2.0*disturbanceAmplitude;
931 cayley += disturbance;
932 }
933
934 lambda = 0.01;
935 int iterations = 0;
936 double smallestEV = ge::getCost(xxF,yyF,zzF,xyF,yzF,zxF,
937 x1P,y1P,z1P,x2P,y2P,z2P,m11P,m12P,m22P,cayley,1);
938
939 while( iterations < maxIterations )
940 {
941 Eigen::Matrix<double,1,3> jacobian;
942 ge::getQuickJacobian(xxF,yyF,zzF,xyF,yzF,zxF,
943 x1P,y1P,z1P,x2P,y2P,z2P,m11P,m12P,m22P,cayley,smallestEV,jacobian,1);
944
945 double norm = sqrt(pow(jacobian[0],2.0) + pow(jacobian[1],2.0) + pow(jacobian[2],2.0));
946 cayley_t normalizedJacobian = (1/norm) * jacobian.transpose();
947
948 cayley_t samplingPoint = cayley - lambda * normalizedJacobian;
949 double samplingEV = ge::getCost(xxF,yyF,zzF,xyF,yzF,zxF,
950 x1P,y1P,z1P,x2P,y2P,z2P,m11P,m12P,m22P,samplingPoint,1);
951
952 if(print)
953 {
954 std::cout << iterations << ": " << samplingPoint.transpose();
955 std::cout << " lambda: " << lambda << " EV: " << samplingEV << std::endl;
956 }
957
958 if( iterations == 0 || !disablingIncrements )
959 {
960 while( samplingEV < smallestEV )
961 {
962 smallestEV = samplingEV;
963 if( lambda * modifier > maxLambda )
964 break;
965 lambda *= modifier;
966 samplingPoint = cayley - lambda * normalizedJacobian;
967 samplingEV = ge::getCost(xxF,yyF,zzF,xyF,yzF,zxF,
968 x1P,y1P,z1P,x2P,y2P,z2P,m11P,m12P,m22P,samplingPoint,1);
969
970 if(print)
971 {
972 std::cout << iterations << ": " << samplingPoint.transpose();
973 std::cout << " lambda: " << lambda << " EV: " << samplingEV << std::endl;
974 }
975 }
976 }
977
978 while( samplingEV > smallestEV )
979 {
980 lambda /= modifier;
981 samplingPoint = cayley - lambda * normalizedJacobian;
982 samplingEV = ge::getCost(xxF,yyF,zzF,xyF,yzF,zxF,
983 x1P,y1P,z1P,x2P,y2P,z2P,m11P,m12P,m22P,samplingPoint,1);
984
985 if(print)
986 {
987 std::cout << iterations << ": " << samplingPoint.transpose();
988 std::cout << " lambda: " << lambda << " EV: " << samplingEV << std::endl;
989 }
990 }
991
992 //apply update
993 cayley = samplingPoint;
994 smallestEV = samplingEV;
995
996 //stopping condition (check if the update was too small)
997 if( lambda < min_xtol )
998 break;
999
1000 iterations++;
1001 }
1002
1003 //try to see if we can robustly identify each time we enter up in the wrong minimum
1004 if( cayley.norm() < 0.01 )
1005 {
1006 //we are close to the origin, test the EV 2
1007 double ev2 = ge::getCost(xxF,yyF,zzF,xyF,yzF,zxF,
1008 x1P,y1P,z1P,x2P,y2P,z2P,m11P,m12P,m22P,cayley,0);
1009 if( ev2 > 0.001 )
1010 randomTrialCount++;
1011 else
1012 found = true;
1013 }
1014 else
1015 found = true;
1016 }
1017
1018 Eigen::Matrix4d G = ge::composeG(xxF,yyF,zzF,xyF,yzF,zxF,
1019 x1P,y1P,z1P,x2P,y2P,z2P,m11P,m12P,m22P,cayley);
1020
1021 Eigen::EigenSolver< Eigen::Matrix4d > Eig(G,true);
1022 Eigen::Matrix<std::complex<double>,4,1> D_complex = Eig.eigenvalues();
1023 Eigen::Matrix<std::complex<double>,4,4> V_complex = Eig.eigenvectors();
1024 Eigen::Vector4d D;
1025 Eigen::Matrix4d V;
1026
1027 std::vector< myPair_ge > pairs;
1028 for(size_t i = 0; i < 4; i++) {
1029 myPair_ge newPair;
1030 newPair.second = D_complex[i].real();
1031 for(size_t j = 0; j < 4; j++)
1032 newPair.first(j,0) = V_complex(j,i).real();
1033 pairs.push_back(newPair);
1034 }
1035 std::sort(pairs.begin(),pairs.end());
1036 for(size_t i = 0; i < 4; i++) {
1037 D[i] = pairs[i].second;
1038 V.col(i) = pairs[i].first;
1039 }
1040
1041 double factor = V(3,3);
1042 Eigen::Vector4d t = (1.0/factor) * V.col(3);
1043
1044 output.translation = t;
1045 output.rotation = math::cayley2rot(cayley);
1046 output.eigenvalues = D;
1047 output.eigenvectors = V;
1048 }
1049
1050 void
ge_plot(const Eigen::Matrix3d & xxF,const Eigen::Matrix3d & yyF,const Eigen::Matrix3d & zzF,const Eigen::Matrix3d & xyF,const Eigen::Matrix3d & yzF,const Eigen::Matrix3d & zxF,const Eigen::Matrix<double,3,9> & x1P,const Eigen::Matrix<double,3,9> & y1P,const Eigen::Matrix<double,3,9> & z1P,const Eigen::Matrix<double,3,9> & x2P,const Eigen::Matrix<double,3,9> & y2P,const Eigen::Matrix<double,3,9> & z2P,const Eigen::Matrix<double,9,9> & m11P,const Eigen::Matrix<double,9,9> & m12P,const Eigen::Matrix<double,9,9> & m22P,geOutput_t & output)1051 opengv::relative_pose::modules::ge_plot(
1052 const Eigen::Matrix3d & xxF,
1053 const Eigen::Matrix3d & yyF,
1054 const Eigen::Matrix3d & zzF,
1055 const Eigen::Matrix3d & xyF,
1056 const Eigen::Matrix3d & yzF,
1057 const Eigen::Matrix3d & zxF,
1058 const Eigen::Matrix<double,3,9> & x1P,
1059 const Eigen::Matrix<double,3,9> & y1P,
1060 const Eigen::Matrix<double,3,9> & z1P,
1061 const Eigen::Matrix<double,3,9> & x2P,
1062 const Eigen::Matrix<double,3,9> & y2P,
1063 const Eigen::Matrix<double,3,9> & z2P,
1064 const Eigen::Matrix<double,9,9> & m11P,
1065 const Eigen::Matrix<double,9,9> & m12P,
1066 const Eigen::Matrix<double,9,9> & m22P,
1067 geOutput_t & output )
1068 {
1069 cayley_t cayley = math::rot2cayley(output.rotation);
1070
1071 ge::getEV(xxF,yyF,zzF,xyF,yzF,zxF,
1072 x1P,y1P,z1P,x2P,y2P,z2P,m11P,m12P,m22P,cayley,output.eigenvalues);
1073
1074 output.eigenvectors = ge::composeG(xxF,yyF,zzF,xyF,yzF,zxF,
1075 x1P,y1P,z1P,x2P,y2P,z2P,m11P,m12P,m22P,cayley);
1076 }
1077