MLPnPsolver.cpp 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. /**
  2. * This file is part of ORB-SLAM3
  3. *
  4. * Copyright (C) 2017-2021 Carlos Campos, Richard Elvira, Juan J. Gómez Rodríguez, José M.M. Montiel and Juan D. Tardós, University of Zaragoza.
  5. * Copyright (C) 2014-2016 Raúl Mur-Artal, José M.M. Montiel and Juan D. Tardós, University of Zaragoza.
  6. *
  7. * ORB-SLAM3 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
  8. * License as published by the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * ORB-SLAM3 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
  12. * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with ORB-SLAM3.
  16. * If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /******************************************************************************
  19. * Author: Steffen Urban *
  20. * Contact: urbste@gmail.com *
  21. * License: Copyright (c) 2016 Steffen Urban, ANU. All rights reserved. *
  22. * *
  23. * Redistribution and use in source and binary forms, with or without *
  24. * modification, are permitted provided that the following conditions *
  25. * are met: *
  26. * * Redistributions of source code must retain the above copyright *
  27. * notice, this list of conditions and the following disclaimer. *
  28. * * Redistributions in binary form must reproduce the above copyright *
  29. * notice, this list of conditions and the following disclaimer in the *
  30. * documentation and/or other materials provided with the distribution. *
  31. * * Neither the name of ANU nor the names of its contributors may be *
  32. * used to endorse or promote products derived from this software without *
  33. * specific prior written permission. *
  34. * *
  35. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"*
  36. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE *
  37. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE *
  38. * ARE DISCLAIMED. IN NO EVENT SHALL ANU OR THE CONTRIBUTORS BE LIABLE *
  39. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL *
  40. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR *
  41. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *
  42. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *
  43. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY *
  44. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *
  45. * SUCH DAMAGE. *
  46. ******************************************************************************/
  47. #include "MLPnPsolver.h"
  48. #include <Eigen/Sparse>
  49. namespace ORB_SLAM3 {
  50. MLPnPsolver::MLPnPsolver(const Frame &F, const vector<MapPoint *> &vpMapPointMatches):
  51. mnInliersi(0), mnIterations(0), mnBestInliers(0), N(0), mpCamera(F.mpCamera){
  52. mvpMapPointMatches = vpMapPointMatches;
  53. mvBearingVecs.reserve(F.mvpMapPoints.size());
  54. mvP2D.reserve(F.mvpMapPoints.size());
  55. mvSigma2.reserve(F.mvpMapPoints.size());
  56. mvP3Dw.reserve(F.mvpMapPoints.size());
  57. mvKeyPointIndices.reserve(F.mvpMapPoints.size());
  58. mvAllIndices.reserve(F.mvpMapPoints.size());
  59. int idx = 0;
  60. for(size_t i = 0, iend = mvpMapPointMatches.size(); i < iend; i++){
  61. MapPoint* pMP = vpMapPointMatches[i];
  62. if(pMP){
  63. if(!pMP -> isBad()){
  64. if(i >= F.mvKeysUn.size()) continue;
  65. const cv::KeyPoint &kp = F.mvKeysUn[i];
  66. mvP2D.push_back(kp.pt);
  67. mvSigma2.push_back(F.mvLevelSigma2[kp.octave]);
  68. //Bearing vector should be normalized
  69. cv::Point3f cv_br = mpCamera->unproject(kp.pt);
  70. cv_br /= cv_br.z;
  71. bearingVector_t br(cv_br.x,cv_br.y,cv_br.z);
  72. mvBearingVecs.push_back(br);
  73. //3D coordinates
  74. Eigen::Matrix<float,3,1> posEig = pMP -> GetWorldPos();
  75. point_t pos(posEig(0),posEig(1),posEig(2));
  76. mvP3Dw.push_back(pos);
  77. mvKeyPointIndices.push_back(i);
  78. mvAllIndices.push_back(idx);
  79. idx++;
  80. }
  81. }
  82. }
  83. SetRansacParameters();
  84. }
  85. //RANSAC methods
  86. bool MLPnPsolver::iterate(int nIterations, bool &bNoMore, vector<bool> &vbInliers, int &nInliers, Eigen::Matrix4f &Tout){
  87. Tout.setIdentity();
  88. bNoMore = false;
  89. vbInliers.clear();
  90. nInliers=0;
  91. if(N<mRansacMinInliers)
  92. {
  93. bNoMore = true;
  94. return false;
  95. }
  96. vector<size_t> vAvailableIndices;
  97. int nCurrentIterations = 0;
  98. while(mnIterations<mRansacMaxIts || nCurrentIterations<nIterations)
  99. {
  100. nCurrentIterations++;
  101. mnIterations++;
  102. vAvailableIndices = mvAllIndices;
  103. //Bearing vectors and 3D points used for this ransac iteration
  104. bearingVectors_t bearingVecs(mRansacMinSet);
  105. points_t p3DS(mRansacMinSet);
  106. vector<int> indexes(mRansacMinSet);
  107. // Get min set of points
  108. for(short i = 0; i < mRansacMinSet; ++i)
  109. {
  110. int randi = DUtils::Random::RandomInt(0, vAvailableIndices.size()-1);
  111. int idx = vAvailableIndices[randi];
  112. bearingVecs[i] = mvBearingVecs[idx];
  113. p3DS[i] = mvP3Dw[idx];
  114. indexes[i] = i;
  115. vAvailableIndices[randi] = vAvailableIndices.back();
  116. vAvailableIndices.pop_back();
  117. }
  118. //By the moment, we are using MLPnP without covariance info
  119. cov3_mats_t covs(1);
  120. //Result
  121. transformation_t result;
  122. // Compute camera pose
  123. computePose(bearingVecs,p3DS,covs,indexes,result);
  124. //Save result
  125. mRi[0][0] = result(0,0);
  126. mRi[0][1] = result(0,1);
  127. mRi[0][2] = result(0,2);
  128. mRi[1][0] = result(1,0);
  129. mRi[1][1] = result(1,1);
  130. mRi[1][2] = result(1,2);
  131. mRi[2][0] = result(2,0);
  132. mRi[2][1] = result(2,1);
  133. mRi[2][2] = result(2,2);
  134. mti[0] = result(0,3);mti[1] = result(1,3);mti[2] = result(2,3);
  135. // Check inliers
  136. CheckInliers();
  137. if(mnInliersi>=mRansacMinInliers)
  138. {
  139. // If it is the best solution so far, save it
  140. if(mnInliersi>mnBestInliers)
  141. {
  142. mvbBestInliers = mvbInliersi;
  143. mnBestInliers = mnInliersi;
  144. cv::Mat Rcw(3,3,CV_64F,mRi);
  145. cv::Mat tcw(3,1,CV_64F,mti);
  146. Rcw.convertTo(Rcw,CV_32F);
  147. tcw.convertTo(tcw,CV_32F);
  148. mBestTcw.setIdentity();
  149. mBestTcw.block<3,3>(0,0) = Converter::toMatrix3f(Rcw);
  150. mBestTcw.block<3,1>(0,3) = Converter::toVector3f(tcw);
  151. Eigen::Matrix<double, 3, 3, Eigen::RowMajor> eigRcw(mRi[0]);
  152. Eigen::Vector3d eigtcw(mti);
  153. }
  154. if(Refine())
  155. {
  156. nInliers = mnRefinedInliers;
  157. vbInliers = vector<bool>(mvpMapPointMatches.size(),false);
  158. for(int i=0; i<N; i++)
  159. {
  160. if(mvbRefinedInliers[i])
  161. vbInliers[mvKeyPointIndices[i]] = true;
  162. }
  163. Tout = mRefinedTcw;
  164. return true;
  165. }
  166. }
  167. }
  168. if(mnIterations>=mRansacMaxIts)
  169. {
  170. bNoMore=true;
  171. if(mnBestInliers>=mRansacMinInliers)
  172. {
  173. nInliers=mnBestInliers;
  174. vbInliers = vector<bool>(mvpMapPointMatches.size(),false);
  175. for(int i=0; i<N; i++)
  176. {
  177. if(mvbBestInliers[i])
  178. vbInliers[mvKeyPointIndices[i]] = true;
  179. }
  180. Tout = mBestTcw;
  181. return true;
  182. }
  183. }
  184. return false;
  185. }
  186. void MLPnPsolver::SetRansacParameters(double probability, int minInliers, int maxIterations, int minSet, float epsilon, float th2){
  187. mRansacProb = probability;
  188. mRansacMinInliers = minInliers;
  189. mRansacMaxIts = maxIterations;
  190. mRansacEpsilon = epsilon;
  191. mRansacMinSet = minSet;
  192. N = mvP2D.size(); // number of correspondences
  193. mvbInliersi.resize(N);
  194. // Adjust Parameters according to number of correspondences
  195. int nMinInliers = N*mRansacEpsilon;
  196. if(nMinInliers<mRansacMinInliers)
  197. nMinInliers=mRansacMinInliers;
  198. if(nMinInliers<minSet)
  199. nMinInliers=minSet;
  200. mRansacMinInliers = nMinInliers;
  201. if(mRansacEpsilon<(float)mRansacMinInliers/N)
  202. mRansacEpsilon=(float)mRansacMinInliers/N;
  203. // Set RANSAC iterations according to probability, epsilon, and max iterations
  204. int nIterations;
  205. if(mRansacMinInliers==N)
  206. nIterations=1;
  207. else
  208. nIterations = ceil(log(1-mRansacProb)/log(1-pow(mRansacEpsilon,3)));
  209. mRansacMaxIts = max(1,min(nIterations,mRansacMaxIts));
  210. mvMaxError.resize(mvSigma2.size());
  211. for(size_t i=0; i<mvSigma2.size(); i++)
  212. mvMaxError[i] = mvSigma2[i]*th2;
  213. }
  214. void MLPnPsolver::CheckInliers(){
  215. mnInliersi=0;
  216. for(int i=0; i<N; i++)
  217. {
  218. point_t p = mvP3Dw[i];
  219. cv::Point3f P3Dw(p(0),p(1),p(2));
  220. cv::Point2f P2D = mvP2D[i];
  221. float xc = mRi[0][0]*P3Dw.x+mRi[0][1]*P3Dw.y+mRi[0][2]*P3Dw.z+mti[0];
  222. float yc = mRi[1][0]*P3Dw.x+mRi[1][1]*P3Dw.y+mRi[1][2]*P3Dw.z+mti[1];
  223. float zc = mRi[2][0]*P3Dw.x+mRi[2][1]*P3Dw.y+mRi[2][2]*P3Dw.z+mti[2];
  224. cv::Point3f P3Dc(xc,yc,zc);
  225. cv::Point2f uv = mpCamera->project(P3Dc);
  226. float distX = P2D.x-uv.x;
  227. float distY = P2D.y-uv.y;
  228. float error2 = distX*distX+distY*distY;
  229. if(error2<mvMaxError[i])
  230. {
  231. mvbInliersi[i]=true;
  232. mnInliersi++;
  233. }
  234. else
  235. {
  236. mvbInliersi[i]=false;
  237. }
  238. }
  239. }
  240. bool MLPnPsolver::Refine(){
  241. vector<int> vIndices;
  242. vIndices.reserve(mvbBestInliers.size());
  243. for(size_t i=0; i<mvbBestInliers.size(); i++)
  244. {
  245. if(mvbBestInliers[i])
  246. {
  247. vIndices.push_back(i);
  248. }
  249. }
  250. //Bearing vectors and 3D points used for this ransac iteration
  251. bearingVectors_t bearingVecs;
  252. points_t p3DS;
  253. vector<int> indexes;
  254. for(size_t i=0; i<vIndices.size(); i++)
  255. {
  256. int idx = vIndices[i];
  257. bearingVecs.push_back(mvBearingVecs[idx]);
  258. p3DS.push_back(mvP3Dw[idx]);
  259. indexes.push_back(i);
  260. }
  261. //By the moment, we are using MLPnP without covariance info
  262. cov3_mats_t covs(1);
  263. //Result
  264. transformation_t result;
  265. // Compute camera pose
  266. computePose(bearingVecs,p3DS,covs,indexes,result);
  267. // Check inliers
  268. CheckInliers();
  269. mnRefinedInliers =mnInliersi;
  270. mvbRefinedInliers = mvbInliersi;
  271. if(mnInliersi>mRansacMinInliers)
  272. {
  273. cv::Mat Rcw(3,3,CV_64F,mRi);
  274. cv::Mat tcw(3,1,CV_64F,mti);
  275. Rcw.convertTo(Rcw,CV_32F);
  276. tcw.convertTo(tcw,CV_32F);
  277. mRefinedTcw.setIdentity();
  278. mRefinedTcw.block<3,3>(0,0) = Converter::toMatrix3f(Rcw);
  279. mRefinedTcw.block<3,1>(0,3) = Converter::toVector3f(tcw);
  280. Eigen::Matrix<double, 3, 3, Eigen::RowMajor> eigRcw(mRi[0]);
  281. Eigen::Vector3d eigtcw(mti);
  282. return true;
  283. }
  284. return false;
  285. }
  286. //MLPnP methods
  287. void MLPnPsolver::computePose(const bearingVectors_t &f, const points_t &p, const cov3_mats_t &covMats,
  288. const std::vector<int> &indices, transformation_t &result) {
  289. size_t numberCorrespondences = indices.size();
  290. assert(numberCorrespondences > 5);
  291. bool planar = false;
  292. // compute the nullspace of all vectors
  293. std::vector<Eigen::MatrixXd> nullspaces(numberCorrespondences);
  294. Eigen::MatrixXd points3(3, numberCorrespondences);
  295. points_t points3v(numberCorrespondences);
  296. points4_t points4v(numberCorrespondences);
  297. for (size_t i = 0; i < numberCorrespondences; i++) {
  298. bearingVector_t f_current = f[indices[i]];
  299. points3.col(i) = p[indices[i]];
  300. // nullspace of right vector
  301. Eigen::JacobiSVD<Eigen::MatrixXd, Eigen::HouseholderQRPreconditioner>
  302. svd_f(f_current.transpose(), Eigen::ComputeFullV);
  303. nullspaces[i] = svd_f.matrixV().block(0, 1, 3, 2);
  304. points3v[i] = p[indices[i]];
  305. }
  306. //////////////////////////////////////
  307. // 1. test if we have a planar scene
  308. //////////////////////////////////////
  309. Eigen::Matrix3d planarTest = points3 * points3.transpose();
  310. Eigen::FullPivHouseholderQR<Eigen::Matrix3d> rankTest(planarTest);
  311. Eigen::Matrix3d eigenRot;
  312. eigenRot.setIdentity();
  313. // if yes -> transform points to new eigen frame
  314. //if (minEigenVal < 1e-3 || minEigenVal == 0.0)
  315. //rankTest.setThreshold(1e-10);
  316. if (rankTest.rank() == 2) {
  317. planar = true;
  318. // self adjoint is faster and more accurate than general eigen solvers
  319. // also has closed form solution for 3x3 self-adjoint matrices
  320. // in addition this solver sorts the eigenvalues in increasing order
  321. Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigen_solver(planarTest);
  322. eigenRot = eigen_solver.eigenvectors().real();
  323. eigenRot.transposeInPlace();
  324. for (size_t i = 0; i < numberCorrespondences; i++)
  325. points3.col(i) = eigenRot * points3.col(i);
  326. }
  327. //////////////////////////////////////
  328. // 2. stochastic model
  329. //////////////////////////////////////
  330. Eigen::SparseMatrix<double> P(2 * numberCorrespondences,
  331. 2 * numberCorrespondences);
  332. bool use_cov = false;
  333. P.setIdentity(); // standard
  334. // if we do have covariance information
  335. // -> fill covariance matrix
  336. if (covMats.size() == numberCorrespondences) {
  337. use_cov = true;
  338. int l = 0;
  339. for (size_t i = 0; i < numberCorrespondences; ++i) {
  340. // invert matrix
  341. cov2_mat_t temp = nullspaces[i].transpose() * covMats[i] * nullspaces[i];
  342. temp = temp.inverse().eval();
  343. P.coeffRef(l, l) = temp(0, 0);
  344. P.coeffRef(l, l + 1) = temp(0, 1);
  345. P.coeffRef(l + 1, l) = temp(1, 0);
  346. P.coeffRef(l + 1, l + 1) = temp(1, 1);
  347. l += 2;
  348. }
  349. }
  350. //////////////////////////////////////
  351. // 3. fill the design matrix A
  352. //////////////////////////////////////
  353. const int rowsA = 2 * numberCorrespondences;
  354. int colsA = 12;
  355. Eigen::MatrixXd A;
  356. if (planar) {
  357. colsA = 9;
  358. A = Eigen::MatrixXd(rowsA, 9);
  359. } else
  360. A = Eigen::MatrixXd(rowsA, 12);
  361. A.setZero();
  362. // fill design matrix
  363. if (planar) {
  364. for (size_t i = 0; i < numberCorrespondences; ++i) {
  365. point_t pt3_current = points3.col(i);
  366. // r12
  367. A(2 * i, 0) = nullspaces[i](0, 0) * pt3_current[1];
  368. A(2 * i + 1, 0) = nullspaces[i](0, 1) * pt3_current[1];
  369. // r13
  370. A(2 * i, 1) = nullspaces[i](0, 0) * pt3_current[2];
  371. A(2 * i + 1, 1) = nullspaces[i](0, 1) * pt3_current[2];
  372. // r22
  373. A(2 * i, 2) = nullspaces[i](1, 0) * pt3_current[1];
  374. A(2 * i + 1, 2) = nullspaces[i](1, 1) * pt3_current[1];
  375. // r23
  376. A(2 * i, 3) = nullspaces[i](1, 0) * pt3_current[2];
  377. A(2 * i + 1, 3) = nullspaces[i](1, 1) * pt3_current[2];
  378. // r32
  379. A(2 * i, 4) = nullspaces[i](2, 0) * pt3_current[1];
  380. A(2 * i + 1, 4) = nullspaces[i](2, 1) * pt3_current[1];
  381. // r33
  382. A(2 * i, 5) = nullspaces[i](2, 0) * pt3_current[2];
  383. A(2 * i + 1, 5) = nullspaces[i](2, 1) * pt3_current[2];
  384. // t1
  385. A(2 * i, 6) = nullspaces[i](0, 0);
  386. A(2 * i + 1, 6) = nullspaces[i](0, 1);
  387. // t2
  388. A(2 * i, 7) = nullspaces[i](1, 0);
  389. A(2 * i + 1, 7) = nullspaces[i](1, 1);
  390. // t3
  391. A(2 * i, 8) = nullspaces[i](2, 0);
  392. A(2 * i + 1, 8) = nullspaces[i](2, 1);
  393. }
  394. } else {
  395. for (size_t i = 0; i < numberCorrespondences; ++i) {
  396. point_t pt3_current = points3.col(i);
  397. // r11
  398. A(2 * i, 0) = nullspaces[i](0, 0) * pt3_current[0];
  399. A(2 * i + 1, 0) = nullspaces[i](0, 1) * pt3_current[0];
  400. // r12
  401. A(2 * i, 1) = nullspaces[i](0, 0) * pt3_current[1];
  402. A(2 * i + 1, 1) = nullspaces[i](0, 1) * pt3_current[1];
  403. // r13
  404. A(2 * i, 2) = nullspaces[i](0, 0) * pt3_current[2];
  405. A(2 * i + 1, 2) = nullspaces[i](0, 1) * pt3_current[2];
  406. // r21
  407. A(2 * i, 3) = nullspaces[i](1, 0) * pt3_current[0];
  408. A(2 * i + 1, 3) = nullspaces[i](1, 1) * pt3_current[0];
  409. // r22
  410. A(2 * i, 4) = nullspaces[i](1, 0) * pt3_current[1];
  411. A(2 * i + 1, 4) = nullspaces[i](1, 1) * pt3_current[1];
  412. // r23
  413. A(2 * i, 5) = nullspaces[i](1, 0) * pt3_current[2];
  414. A(2 * i + 1, 5) = nullspaces[i](1, 1) * pt3_current[2];
  415. // r31
  416. A(2 * i, 6) = nullspaces[i](2, 0) * pt3_current[0];
  417. A(2 * i + 1, 6) = nullspaces[i](2, 1) * pt3_current[0];
  418. // r32
  419. A(2 * i, 7) = nullspaces[i](2, 0) * pt3_current[1];
  420. A(2 * i + 1, 7) = nullspaces[i](2, 1) * pt3_current[1];
  421. // r33
  422. A(2 * i, 8) = nullspaces[i](2, 0) * pt3_current[2];
  423. A(2 * i + 1, 8) = nullspaces[i](2, 1) * pt3_current[2];
  424. // t1
  425. A(2 * i, 9) = nullspaces[i](0, 0);
  426. A(2 * i + 1, 9) = nullspaces[i](0, 1);
  427. // t2
  428. A(2 * i, 10) = nullspaces[i](1, 0);
  429. A(2 * i + 1, 10) = nullspaces[i](1, 1);
  430. // t3
  431. A(2 * i, 11) = nullspaces[i](2, 0);
  432. A(2 * i + 1, 11) = nullspaces[i](2, 1);
  433. }
  434. }
  435. //////////////////////////////////////
  436. // 4. solve least squares
  437. //////////////////////////////////////
  438. Eigen::MatrixXd AtPA;
  439. if (use_cov)
  440. AtPA = A.transpose() * P * A; // setting up the full normal equations seems to be unstable
  441. else
  442. AtPA = A.transpose() * A;
  443. Eigen::JacobiSVD<Eigen::MatrixXd> svd_A(AtPA, Eigen::ComputeFullV);
  444. Eigen::MatrixXd result1 = svd_A.matrixV().col(colsA - 1);
  445. ////////////////////////////////
  446. // now we treat the results differently,
  447. // depending on the scene (planar or not)
  448. ////////////////////////////////
  449. rotation_t Rout;
  450. translation_t tout;
  451. if (planar) // planar case
  452. {
  453. rotation_t tmp;
  454. // until now, we only estimated
  455. // row one and two of the transposed rotation matrix
  456. tmp << 0.0, result1(0, 0), result1(1, 0),
  457. 0.0, result1(2, 0), result1(3, 0),
  458. 0.0, result1(4, 0), result1(5, 0);
  459. // row 3
  460. tmp.col(0) = tmp.col(1).cross(tmp.col(2));
  461. tmp.transposeInPlace();
  462. double scale = 1.0 / std::sqrt(std::abs(tmp.col(1).norm() * tmp.col(2).norm()));
  463. // find best rotation matrix in frobenius sense
  464. Eigen::JacobiSVD<Eigen::MatrixXd> svd_R_frob(tmp, Eigen::ComputeFullU | Eigen::ComputeFullV);
  465. rotation_t Rout1 = svd_R_frob.matrixU() * svd_R_frob.matrixV().transpose();
  466. // test if we found a good rotation matrix
  467. if (Rout1.determinant() < 0)
  468. Rout1 *= -1.0;
  469. // rotate this matrix back using the eigen frame
  470. Rout1 = eigenRot.transpose() * Rout1;
  471. translation_t t = scale * translation_t(result1(6, 0), result1(7, 0), result1(8, 0));
  472. Rout1.transposeInPlace();
  473. Rout1 *= -1;
  474. if (Rout1.determinant() < 0.0)
  475. Rout1.col(2) *= -1;
  476. // now we have to find the best out of 4 combinations
  477. rotation_t R1, R2;
  478. R1.col(0) = Rout1.col(0);
  479. R1.col(1) = Rout1.col(1);
  480. R1.col(2) = Rout1.col(2);
  481. R2.col(0) = -Rout1.col(0);
  482. R2.col(1) = -Rout1.col(1);
  483. R2.col(2) = Rout1.col(2);
  484. vector<transformation_t, Eigen::aligned_allocator<transformation_t>> Ts(4);
  485. Ts[0].block<3, 3>(0, 0) = R1;
  486. Ts[0].block<3, 1>(0, 3) = t;
  487. Ts[1].block<3, 3>(0, 0) = R1;
  488. Ts[1].block<3, 1>(0, 3) = -t;
  489. Ts[2].block<3, 3>(0, 0) = R2;
  490. Ts[2].block<3, 1>(0, 3) = t;
  491. Ts[3].block<3, 3>(0, 0) = R2;
  492. Ts[3].block<3, 1>(0, 3) = -t;
  493. vector<double> normVal(4);
  494. for (int i = 0; i < 4; ++i) {
  495. point_t reproPt;
  496. double norms = 0.0;
  497. for (int p = 0; p < 6; ++p) {
  498. reproPt = Ts[i].block<3, 3>(0, 0) * points3v[p] + Ts[i].block<3, 1>(0, 3);
  499. reproPt = reproPt / reproPt.norm();
  500. norms += (1.0 - reproPt.transpose() * f[indices[p]]);
  501. }
  502. normVal[i] = norms;
  503. }
  504. std::vector<double>::iterator
  505. findMinRepro = std::min_element(std::begin(normVal), std::end(normVal));
  506. int idx = std::distance(std::begin(normVal), findMinRepro);
  507. Rout = Ts[idx].block<3, 3>(0, 0);
  508. tout = Ts[idx].block<3, 1>(0, 3);
  509. } else // non-planar
  510. {
  511. rotation_t tmp;
  512. tmp << result1(0, 0), result1(3, 0), result1(6, 0),
  513. result1(1, 0), result1(4, 0), result1(7, 0),
  514. result1(2, 0), result1(5, 0), result1(8, 0);
  515. // get the scale
  516. double scale = 1.0 /
  517. std::pow(std::abs(tmp.col(0).norm() * tmp.col(1).norm() * tmp.col(2).norm()), 1.0 / 3.0);
  518. //double scale = 1.0 / std::sqrt(std::abs(tmp.col(0).norm() * tmp.col(1).norm()));
  519. // find best rotation matrix in frobenius sense
  520. Eigen::JacobiSVD<Eigen::MatrixXd> svd_R_frob(tmp, Eigen::ComputeFullU | Eigen::ComputeFullV);
  521. Rout = svd_R_frob.matrixU() * svd_R_frob.matrixV().transpose();
  522. // test if we found a good rotation matrix
  523. if (Rout.determinant() < 0)
  524. Rout *= -1.0;
  525. // scale translation
  526. tout = Rout * (scale * translation_t(result1(9, 0), result1(10, 0), result1(11, 0)));
  527. // find correct direction in terms of reprojection error, just take the first 6 correspondences
  528. vector<double> error(2);
  529. vector<Eigen::Matrix4d, Eigen::aligned_allocator<Eigen::Matrix4d>> Ts(2);
  530. for (int s = 0; s < 2; ++s) {
  531. error[s] = 0.0;
  532. Ts[s] = Eigen::Matrix4d::Identity();
  533. Ts[s].block<3, 3>(0, 0) = Rout;
  534. if (s == 0)
  535. Ts[s].block<3, 1>(0, 3) = tout;
  536. else
  537. Ts[s].block<3, 1>(0, 3) = -tout;
  538. Ts[s] = Ts[s].inverse().eval();
  539. for (int p = 0; p < 6; ++p) {
  540. bearingVector_t v = Ts[s].block<3, 3>(0, 0) * points3v[p] + Ts[s].block<3, 1>(0, 3);
  541. v = v / v.norm();
  542. error[s] += (1.0 - v.transpose() * f[indices[p]]);
  543. }
  544. }
  545. if (error[0] < error[1])
  546. tout = Ts[0].block<3, 1>(0, 3);
  547. else
  548. tout = Ts[1].block<3, 1>(0, 3);
  549. Rout = Ts[0].block<3, 3>(0, 0);
  550. }
  551. //////////////////////////////////////
  552. // 5. gauss newton
  553. //////////////////////////////////////
  554. rodrigues_t omega = rot2rodrigues(Rout);
  555. Eigen::VectorXd minx(6);
  556. minx[0] = omega[0];
  557. minx[1] = omega[1];
  558. minx[2] = omega[2];
  559. minx[3] = tout[0];
  560. minx[4] = tout[1];
  561. minx[5] = tout[2];
  562. mlpnp_gn(minx, points3v, nullspaces, P, use_cov);
  563. Rout = rodrigues2rot(rodrigues_t(minx[0], minx[1], minx[2]));
  564. tout = translation_t(minx[3], minx[4], minx[5]);
  565. // result inverse as opengv uses this convention
  566. result.block<3, 3>(0, 0) = Rout;
  567. result.block<3, 1>(0, 3) = tout;
  568. }
  569. Eigen::Matrix3d MLPnPsolver::rodrigues2rot(const Eigen::Vector3d &omega) {
  570. rotation_t R = Eigen::Matrix3d::Identity();
  571. Eigen::Matrix3d skewW;
  572. skewW << 0.0, -omega(2), omega(1),
  573. omega(2), 0.0, -omega(0),
  574. -omega(1), omega(0), 0.0;
  575. double omega_norm = omega.norm();
  576. if (omega_norm > std::numeric_limits<double>::epsilon())
  577. R = R + sin(omega_norm) / omega_norm * skewW
  578. + (1 - cos(omega_norm)) / (omega_norm * omega_norm) * (skewW * skewW);
  579. return R;
  580. }
  581. Eigen::Vector3d MLPnPsolver::rot2rodrigues(const Eigen::Matrix3d &R) {
  582. rodrigues_t omega;
  583. omega << 0.0, 0.0, 0.0;
  584. double trace = R.trace() - 1.0;
  585. double wnorm = acos(trace / 2.0);
  586. if (wnorm > std::numeric_limits<double>::epsilon())
  587. {
  588. omega[0] = (R(2, 1) - R(1, 2));
  589. omega[1] = (R(0, 2) - R(2, 0));
  590. omega[2] = (R(1, 0) - R(0, 1));
  591. double sc = wnorm / (2.0*sin(wnorm));
  592. omega *= sc;
  593. }
  594. return omega;
  595. }
  596. void MLPnPsolver::mlpnp_gn(Eigen::VectorXd &x, const points_t &pts, const std::vector<Eigen::MatrixXd> &nullspaces,
  597. const Eigen::SparseMatrix<double> Kll, bool use_cov) {
  598. const int numObservations = pts.size();
  599. const int numUnknowns = 6;
  600. // check redundancy
  601. assert((2 * numObservations - numUnknowns) > 0);
  602. // =============
  603. // set all matrices up
  604. // =============
  605. Eigen::VectorXd r(2 * numObservations);
  606. Eigen::VectorXd rd(2 * numObservations);
  607. Eigen::MatrixXd Jac(2 * numObservations, numUnknowns);
  608. Eigen::VectorXd g(numUnknowns, 1);
  609. Eigen::VectorXd dx(numUnknowns, 1); // result vector
  610. Jac.setZero();
  611. r.setZero();
  612. dx.setZero();
  613. g.setZero();
  614. int it_cnt = 0;
  615. bool stop = false;
  616. const int maxIt = 5;
  617. double epsP = 1e-5;
  618. Eigen::MatrixXd JacTSKll;
  619. Eigen::MatrixXd A;
  620. // solve simple gradient descent
  621. while (it_cnt < maxIt && !stop) {
  622. mlpnp_residuals_and_jacs(x, pts,
  623. nullspaces,
  624. r, Jac, true);
  625. if (use_cov)
  626. JacTSKll = Jac.transpose() * Kll;
  627. else
  628. JacTSKll = Jac.transpose();
  629. A = JacTSKll * Jac;
  630. // get system matrix
  631. g = JacTSKll * r;
  632. // solve
  633. Eigen::LDLT<Eigen::MatrixXd> chol(A);
  634. dx = chol.solve(g);
  635. // this is to prevent the solution from falling into a wrong minimum
  636. // if the linear estimate is spurious
  637. if (dx.array().abs().maxCoeff() > 5.0 || dx.array().abs().minCoeff() > 1.0)
  638. break;
  639. // observation update
  640. Eigen::MatrixXd dl = Jac * dx;
  641. if (dl.array().abs().maxCoeff() < epsP) {
  642. stop = true;
  643. x = x - dx;
  644. break;
  645. } else
  646. x = x - dx;
  647. ++it_cnt;
  648. }//while
  649. // result
  650. }
  651. void MLPnPsolver::mlpnp_residuals_and_jacs(const Eigen::VectorXd &x, const points_t &pts,
  652. const std::vector<Eigen::MatrixXd> &nullspaces, Eigen::VectorXd &r,
  653. Eigen::MatrixXd &fjac, bool getJacs) {
  654. rodrigues_t w(x[0], x[1], x[2]);
  655. translation_t T(x[3], x[4], x[5]);
  656. rotation_t R = rodrigues2rot(w);
  657. int ii = 0;
  658. Eigen::MatrixXd jacs(2, 6);
  659. for (int i = 0; i < pts.size(); ++i)
  660. {
  661. Eigen::Vector3d ptCam = R*pts[i] + T;
  662. ptCam /= ptCam.norm();
  663. r[ii] = nullspaces[i].col(0).transpose()*ptCam;
  664. r[ii + 1] = nullspaces[i].col(1).transpose()*ptCam;
  665. if (getJacs)
  666. {
  667. // jacs
  668. mlpnpJacs(pts[i],
  669. nullspaces[i].col(0), nullspaces[i].col(1),
  670. w, T,
  671. jacs);
  672. // r
  673. fjac(ii, 0) = jacs(0, 0);
  674. fjac(ii, 1) = jacs(0, 1);
  675. fjac(ii, 2) = jacs(0, 2);
  676. fjac(ii, 3) = jacs(0, 3);
  677. fjac(ii, 4) = jacs(0, 4);
  678. fjac(ii, 5) = jacs(0, 5);
  679. // s
  680. fjac(ii + 1, 0) = jacs(1, 0);
  681. fjac(ii + 1, 1) = jacs(1, 1);
  682. fjac(ii + 1, 2) = jacs(1, 2);
  683. fjac(ii + 1, 3) = jacs(1, 3);
  684. fjac(ii + 1, 4) = jacs(1, 4);
  685. fjac(ii + 1, 5) = jacs(1, 5);
  686. }
  687. ii += 2;
  688. }
  689. }
  690. void MLPnPsolver::mlpnpJacs(const point_t& pt, const Eigen::Vector3d& nullspace_r,
  691. const Eigen::Vector3d& nullspace_s, const rodrigues_t& w,
  692. const translation_t& t, Eigen::MatrixXd& jacs){
  693. double r1 = nullspace_r[0];
  694. double r2 = nullspace_r[1];
  695. double r3 = nullspace_r[2];
  696. double s1 = nullspace_s[0];
  697. double s2 = nullspace_s[1];
  698. double s3 = nullspace_s[2];
  699. double X1 = pt[0];
  700. double Y1 = pt[1];
  701. double Z1 = pt[2];
  702. double w1 = w[0];
  703. double w2 = w[1];
  704. double w3 = w[2];
  705. double t1 = t[0];
  706. double t2 = t[1];
  707. double t3 = t[2];
  708. double t5 = w1*w1;
  709. double t6 = w2*w2;
  710. double t7 = w3*w3;
  711. double t8 = t5+t6+t7;
  712. double t9 = sqrt(t8);
  713. double t10 = sin(t9);
  714. double t11 = 1.0/sqrt(t8);
  715. double t12 = cos(t9);
  716. double t13 = t12-1.0;
  717. double t14 = 1.0/t8;
  718. double t16 = t10*t11*w3;
  719. double t17 = t13*t14*w1*w2;
  720. double t19 = t10*t11*w2;
  721. double t20 = t13*t14*w1*w3;
  722. double t24 = t6+t7;
  723. double t27 = t16+t17;
  724. double t28 = Y1*t27;
  725. double t29 = t19-t20;
  726. double t30 = Z1*t29;
  727. double t31 = t13*t14*t24;
  728. double t32 = t31+1.0;
  729. double t33 = X1*t32;
  730. double t15 = t1-t28+t30+t33;
  731. double t21 = t10*t11*w1;
  732. double t22 = t13*t14*w2*w3;
  733. double t45 = t5+t7;
  734. double t53 = t16-t17;
  735. double t54 = X1*t53;
  736. double t55 = t21+t22;
  737. double t56 = Z1*t55;
  738. double t57 = t13*t14*t45;
  739. double t58 = t57+1.0;
  740. double t59 = Y1*t58;
  741. double t18 = t2+t54-t56+t59;
  742. double t34 = t5+t6;
  743. double t38 = t19+t20;
  744. double t39 = X1*t38;
  745. double t40 = t21-t22;
  746. double t41 = Y1*t40;
  747. double t42 = t13*t14*t34;
  748. double t43 = t42+1.0;
  749. double t44 = Z1*t43;
  750. double t23 = t3-t39+t41+t44;
  751. double t25 = 1.0/pow(t8,3.0/2.0);
  752. double t26 = 1.0/(t8*t8);
  753. double t35 = t12*t14*w1*w2;
  754. double t36 = t5*t10*t25*w3;
  755. double t37 = t5*t13*t26*w3*2.0;
  756. double t46 = t10*t25*w1*w3;
  757. double t47 = t5*t10*t25*w2;
  758. double t48 = t5*t13*t26*w2*2.0;
  759. double t49 = t10*t11;
  760. double t50 = t5*t12*t14;
  761. double t51 = t13*t26*w1*w2*w3*2.0;
  762. double t52 = t10*t25*w1*w2*w3;
  763. double t60 = t15*t15;
  764. double t61 = t18*t18;
  765. double t62 = t23*t23;
  766. double t63 = t60+t61+t62;
  767. double t64 = t5*t10*t25;
  768. double t65 = 1.0/sqrt(t63);
  769. double t66 = Y1*r2*t6;
  770. double t67 = Z1*r3*t7;
  771. double t68 = r1*t1*t5;
  772. double t69 = r1*t1*t6;
  773. double t70 = r1*t1*t7;
  774. double t71 = r2*t2*t5;
  775. double t72 = r2*t2*t6;
  776. double t73 = r2*t2*t7;
  777. double t74 = r3*t3*t5;
  778. double t75 = r3*t3*t6;
  779. double t76 = r3*t3*t7;
  780. double t77 = X1*r1*t5;
  781. double t78 = X1*r2*w1*w2;
  782. double t79 = X1*r3*w1*w3;
  783. double t80 = Y1*r1*w1*w2;
  784. double t81 = Y1*r3*w2*w3;
  785. double t82 = Z1*r1*w1*w3;
  786. double t83 = Z1*r2*w2*w3;
  787. double t84 = X1*r1*t6*t12;
  788. double t85 = X1*r1*t7*t12;
  789. double t86 = Y1*r2*t5*t12;
  790. double t87 = Y1*r2*t7*t12;
  791. double t88 = Z1*r3*t5*t12;
  792. double t89 = Z1*r3*t6*t12;
  793. double t90 = X1*r2*t9*t10*w3;
  794. double t91 = Y1*r3*t9*t10*w1;
  795. double t92 = Z1*r1*t9*t10*w2;
  796. double t102 = X1*r3*t9*t10*w2;
  797. double t103 = Y1*r1*t9*t10*w3;
  798. double t104 = Z1*r2*t9*t10*w1;
  799. double t105 = X1*r2*t12*w1*w2;
  800. double t106 = X1*r3*t12*w1*w3;
  801. double t107 = Y1*r1*t12*w1*w2;
  802. double t108 = Y1*r3*t12*w2*w3;
  803. double t109 = Z1*r1*t12*w1*w3;
  804. double t110 = Z1*r2*t12*w2*w3;
  805. double t93 = t66+t67+t68+t69+t70+t71+t72+t73+t74+t75+t76+t77+t78+t79+t80+t81+t82+t83+t84+t85+t86+t87+t88+t89+t90+t91+t92-t102-t103-t104-t105-t106-t107-t108-t109-t110;
  806. double t94 = t10*t25*w1*w2;
  807. double t95 = t6*t10*t25*w3;
  808. double t96 = t6*t13*t26*w3*2.0;
  809. double t97 = t12*t14*w2*w3;
  810. double t98 = t6*t10*t25*w1;
  811. double t99 = t6*t13*t26*w1*2.0;
  812. double t100 = t6*t10*t25;
  813. double t101 = 1.0/pow(t63,3.0/2.0);
  814. double t111 = t6*t12*t14;
  815. double t112 = t10*t25*w2*w3;
  816. double t113 = t12*t14*w1*w3;
  817. double t114 = t7*t10*t25*w2;
  818. double t115 = t7*t13*t26*w2*2.0;
  819. double t116 = t7*t10*t25*w1;
  820. double t117 = t7*t13*t26*w1*2.0;
  821. double t118 = t7*t12*t14;
  822. double t119 = t13*t24*t26*w1*2.0;
  823. double t120 = t10*t24*t25*w1;
  824. double t121 = t119+t120;
  825. double t122 = t13*t26*t34*w1*2.0;
  826. double t123 = t10*t25*t34*w1;
  827. double t131 = t13*t14*w1*2.0;
  828. double t124 = t122+t123-t131;
  829. double t139 = t13*t14*w3;
  830. double t125 = -t35+t36+t37+t94-t139;
  831. double t126 = X1*t125;
  832. double t127 = t49+t50+t51+t52-t64;
  833. double t128 = Y1*t127;
  834. double t129 = t126+t128-Z1*t124;
  835. double t130 = t23*t129*2.0;
  836. double t132 = t13*t26*t45*w1*2.0;
  837. double t133 = t10*t25*t45*w1;
  838. double t138 = t13*t14*w2;
  839. double t134 = -t46+t47+t48+t113-t138;
  840. double t135 = X1*t134;
  841. double t136 = -t49-t50+t51+t52+t64;
  842. double t137 = Z1*t136;
  843. double t140 = X1*s1*t5;
  844. double t141 = Y1*s2*t6;
  845. double t142 = Z1*s3*t7;
  846. double t143 = s1*t1*t5;
  847. double t144 = s1*t1*t6;
  848. double t145 = s1*t1*t7;
  849. double t146 = s2*t2*t5;
  850. double t147 = s2*t2*t6;
  851. double t148 = s2*t2*t7;
  852. double t149 = s3*t3*t5;
  853. double t150 = s3*t3*t6;
  854. double t151 = s3*t3*t7;
  855. double t152 = X1*s2*w1*w2;
  856. double t153 = X1*s3*w1*w3;
  857. double t154 = Y1*s1*w1*w2;
  858. double t155 = Y1*s3*w2*w3;
  859. double t156 = Z1*s1*w1*w3;
  860. double t157 = Z1*s2*w2*w3;
  861. double t158 = X1*s1*t6*t12;
  862. double t159 = X1*s1*t7*t12;
  863. double t160 = Y1*s2*t5*t12;
  864. double t161 = Y1*s2*t7*t12;
  865. double t162 = Z1*s3*t5*t12;
  866. double t163 = Z1*s3*t6*t12;
  867. double t164 = X1*s2*t9*t10*w3;
  868. double t165 = Y1*s3*t9*t10*w1;
  869. double t166 = Z1*s1*t9*t10*w2;
  870. double t183 = X1*s3*t9*t10*w2;
  871. double t184 = Y1*s1*t9*t10*w3;
  872. double t185 = Z1*s2*t9*t10*w1;
  873. double t186 = X1*s2*t12*w1*w2;
  874. double t187 = X1*s3*t12*w1*w3;
  875. double t188 = Y1*s1*t12*w1*w2;
  876. double t189 = Y1*s3*t12*w2*w3;
  877. double t190 = Z1*s1*t12*w1*w3;
  878. double t191 = Z1*s2*t12*w2*w3;
  879. double t167 = t140+t141+t142+t143+t144+t145+t146+t147+t148+t149+t150+t151+t152+t153+t154+t155+t156+t157+t158+t159+t160+t161+t162+t163+t164+t165+t166-t183-t184-t185-t186-t187-t188-t189-t190-t191;
  880. double t168 = t13*t26*t45*w2*2.0;
  881. double t169 = t10*t25*t45*w2;
  882. double t170 = t168+t169;
  883. double t171 = t13*t26*t34*w2*2.0;
  884. double t172 = t10*t25*t34*w2;
  885. double t176 = t13*t14*w2*2.0;
  886. double t173 = t171+t172-t176;
  887. double t174 = -t49+t51+t52+t100-t111;
  888. double t175 = X1*t174;
  889. double t177 = t13*t24*t26*w2*2.0;
  890. double t178 = t10*t24*t25*w2;
  891. double t192 = t13*t14*w1;
  892. double t179 = -t97+t98+t99+t112-t192;
  893. double t180 = Y1*t179;
  894. double t181 = t49+t51+t52-t100+t111;
  895. double t182 = Z1*t181;
  896. double t193 = t13*t26*t34*w3*2.0;
  897. double t194 = t10*t25*t34*w3;
  898. double t195 = t193+t194;
  899. double t196 = t13*t26*t45*w3*2.0;
  900. double t197 = t10*t25*t45*w3;
  901. double t200 = t13*t14*w3*2.0;
  902. double t198 = t196+t197-t200;
  903. double t199 = t7*t10*t25;
  904. double t201 = t13*t24*t26*w3*2.0;
  905. double t202 = t10*t24*t25*w3;
  906. double t203 = -t49+t51+t52-t118+t199;
  907. double t204 = Y1*t203;
  908. double t205 = t1*2.0;
  909. double t206 = Z1*t29*2.0;
  910. double t207 = X1*t32*2.0;
  911. double t208 = t205+t206+t207-Y1*t27*2.0;
  912. double t209 = t2*2.0;
  913. double t210 = X1*t53*2.0;
  914. double t211 = Y1*t58*2.0;
  915. double t212 = t209+t210+t211-Z1*t55*2.0;
  916. double t213 = t3*2.0;
  917. double t214 = Y1*t40*2.0;
  918. double t215 = Z1*t43*2.0;
  919. double t216 = t213+t214+t215-X1*t38*2.0;
  920. jacs(0, 0) = t14*t65*(X1*r1*w1*2.0+X1*r2*w2+X1*r3*w3+Y1*r1*w2+Z1*r1*w3+r1*t1*w1*2.0+r2*t2*w1*2.0+r3*t3*w1*2.0+Y1*r3*t5*t12+Y1*r3*t9*t10-Z1*r2*t5*t12-Z1*r2*t9*t10-X1*r2*t12*w2-X1*r3*t12*w3-Y1*r1*t12*w2+Y1*r2*t12*w1*2.0-Z1*r1*t12*w3+Z1*r3*t12*w1*2.0+Y1*r3*t5*t10*t11-Z1*r2*t5*t10*t11+X1*r2*t12*w1*w3-X1*r3*t12*w1*w2-Y1*r1*t12*w1*w3+Z1*r1*t12*w1*w2-Y1*r1*t10*t11*w1*w3+Z1*r1*t10*t11*w1*w2-X1*r1*t6*t10*t11*w1-X1*r1*t7*t10*t11*w1+X1*r2*t5*t10*t11*w2+X1*r3*t5*t10*t11*w3+Y1*r1*t5*t10*t11*w2-Y1*r2*t5*t10*t11*w1-Y1*r2*t7*t10*t11*w1+Z1*r1*t5*t10*t11*w3-Z1*r3*t5*t10*t11*w1-Z1*r3*t6*t10*t11*w1+X1*r2*t10*t11*w1*w3-X1*r3*t10*t11*w1*w2+Y1*r3*t10*t11*w1*w2*w3+Z1*r2*t10*t11*w1*w2*w3)-t26*t65*t93*w1*2.0-t14*t93*t101*(t130+t15*(-X1*t121+Y1*(t46+t47+t48-t13*t14*w2-t12*t14*w1*w3)+Z1*(t35+t36+t37-t13*t14*w3-t10*t25*w1*w2))*2.0+t18*(t135+t137-Y1*(t132+t133-t13*t14*w1*2.0))*2.0)*(1.0/2.0);
  921. jacs(0, 1) = t14*t65*(X1*r2*w1+Y1*r1*w1+Y1*r2*w2*2.0+Y1*r3*w3+Z1*r2*w3+r1*t1*w2*2.0+r2*t2*w2*2.0+r3*t3*w2*2.0-X1*r3*t6*t12-X1*r3*t9*t10+Z1*r1*t6*t12+Z1*r1*t9*t10+X1*r1*t12*w2*2.0-X1*r2*t12*w1-Y1*r1*t12*w1-Y1*r3*t12*w3-Z1*r2*t12*w3+Z1*r3*t12*w2*2.0-X1*r3*t6*t10*t11+Z1*r1*t6*t10*t11+X1*r2*t12*w2*w3-Y1*r1*t12*w2*w3+Y1*r3*t12*w1*w2-Z1*r2*t12*w1*w2-Y1*r1*t10*t11*w2*w3+Y1*r3*t10*t11*w1*w2-Z1*r2*t10*t11*w1*w2-X1*r1*t6*t10*t11*w2+X1*r2*t6*t10*t11*w1-X1*r1*t7*t10*t11*w2+Y1*r1*t6*t10*t11*w1-Y1*r2*t5*t10*t11*w2-Y1*r2*t7*t10*t11*w2+Y1*r3*t6*t10*t11*w3-Z1*r3*t5*t10*t11*w2+Z1*r2*t6*t10*t11*w3-Z1*r3*t6*t10*t11*w2+X1*r2*t10*t11*w2*w3+X1*r3*t10*t11*w1*w2*w3+Z1*r1*t10*t11*w1*w2*w3)-t26*t65*t93*w2*2.0-t14*t93*t101*(t18*(Z1*(-t35+t94+t95+t96-t13*t14*w3)-Y1*t170+X1*(t97+t98+t99-t13*t14*w1-t10*t25*w2*w3))*2.0+t15*(t180+t182-X1*(t177+t178-t13*t14*w2*2.0))*2.0+t23*(t175+Y1*(t35-t94+t95+t96-t13*t14*w3)-Z1*t173)*2.0)*(1.0/2.0);
  922. jacs(0, 2) = t14*t65*(X1*r3*w1+Y1*r3*w2+Z1*r1*w1+Z1*r2*w2+Z1*r3*w3*2.0+r1*t1*w3*2.0+r2*t2*w3*2.0+r3*t3*w3*2.0+X1*r2*t7*t12+X1*r2*t9*t10-Y1*r1*t7*t12-Y1*r1*t9*t10+X1*r1*t12*w3*2.0-X1*r3*t12*w1+Y1*r2*t12*w3*2.0-Y1*r3*t12*w2-Z1*r1*t12*w1-Z1*r2*t12*w2+X1*r2*t7*t10*t11-Y1*r1*t7*t10*t11-X1*r3*t12*w2*w3+Y1*r3*t12*w1*w3+Z1*r1*t12*w2*w3-Z1*r2*t12*w1*w3+Y1*r3*t10*t11*w1*w3+Z1*r1*t10*t11*w2*w3-Z1*r2*t10*t11*w1*w3-X1*r1*t6*t10*t11*w3-X1*r1*t7*t10*t11*w3+X1*r3*t7*t10*t11*w1-Y1*r2*t5*t10*t11*w3-Y1*r2*t7*t10*t11*w3+Y1*r3*t7*t10*t11*w2+Z1*r1*t7*t10*t11*w1+Z1*r2*t7*t10*t11*w2-Z1*r3*t5*t10*t11*w3-Z1*r3*t6*t10*t11*w3-X1*r3*t10*t11*w2*w3+X1*r2*t10*t11*w1*w2*w3+Y1*r1*t10*t11*w1*w2*w3)-t26*t65*t93*w3*2.0-t14*t93*t101*(t18*(Z1*(t46-t113+t114+t115-t13*t14*w2)-Y1*t198+X1*(t49+t51+t52+t118-t7*t10*t25))*2.0+t23*(X1*(-t97+t112+t116+t117-t13*t14*w1)+Y1*(-t46+t113+t114+t115-t13*t14*w2)-Z1*t195)*2.0+t15*(t204+Z1*(t97-t112+t116+t117-t13*t14*w1)-X1*(t201+t202-t13*t14*w3*2.0))*2.0)*(1.0/2.0);
  923. jacs(0, 3) = r1*t65-t14*t93*t101*t208*(1.0/2.0);
  924. jacs(0, 4) = r2*t65-t14*t93*t101*t212*(1.0/2.0);
  925. jacs(0, 5) = r3*t65-t14*t93*t101*t216*(1.0/2.0);
  926. jacs(1, 0) = t14*t65*(X1*s1*w1*2.0+X1*s2*w2+X1*s3*w3+Y1*s1*w2+Z1*s1*w3+s1*t1*w1*2.0+s2*t2*w1*2.0+s3*t3*w1*2.0+Y1*s3*t5*t12+Y1*s3*t9*t10-Z1*s2*t5*t12-Z1*s2*t9*t10-X1*s2*t12*w2-X1*s3*t12*w3-Y1*s1*t12*w2+Y1*s2*t12*w1*2.0-Z1*s1*t12*w3+Z1*s3*t12*w1*2.0+Y1*s3*t5*t10*t11-Z1*s2*t5*t10*t11+X1*s2*t12*w1*w3-X1*s3*t12*w1*w2-Y1*s1*t12*w1*w3+Z1*s1*t12*w1*w2+X1*s2*t10*t11*w1*w3-X1*s3*t10*t11*w1*w2-Y1*s1*t10*t11*w1*w3+Z1*s1*t10*t11*w1*w2-X1*s1*t6*t10*t11*w1-X1*s1*t7*t10*t11*w1+X1*s2*t5*t10*t11*w2+X1*s3*t5*t10*t11*w3+Y1*s1*t5*t10*t11*w2-Y1*s2*t5*t10*t11*w1-Y1*s2*t7*t10*t11*w1+Z1*s1*t5*t10*t11*w3-Z1*s3*t5*t10*t11*w1-Z1*s3*t6*t10*t11*w1+Y1*s3*t10*t11*w1*w2*w3+Z1*s2*t10*t11*w1*w2*w3)-t14*t101*t167*(t130+t15*(Y1*(t46+t47+t48-t113-t138)+Z1*(t35+t36+t37-t94-t139)-X1*t121)*2.0+t18*(t135+t137-Y1*(-t131+t132+t133))*2.0)*(1.0/2.0)-t26*t65*t167*w1*2.0;
  927. jacs(1, 1) = t14*t65*(X1*s2*w1+Y1*s1*w1+Y1*s2*w2*2.0+Y1*s3*w3+Z1*s2*w3+s1*t1*w2*2.0+s2*t2*w2*2.0+s3*t3*w2*2.0-X1*s3*t6*t12-X1*s3*t9*t10+Z1*s1*t6*t12+Z1*s1*t9*t10+X1*s1*t12*w2*2.0-X1*s2*t12*w1-Y1*s1*t12*w1-Y1*s3*t12*w3-Z1*s2*t12*w3+Z1*s3*t12*w2*2.0-X1*s3*t6*t10*t11+Z1*s1*t6*t10*t11+X1*s2*t12*w2*w3-Y1*s1*t12*w2*w3+Y1*s3*t12*w1*w2-Z1*s2*t12*w1*w2+X1*s2*t10*t11*w2*w3-Y1*s1*t10*t11*w2*w3+Y1*s3*t10*t11*w1*w2-Z1*s2*t10*t11*w1*w2-X1*s1*t6*t10*t11*w2+X1*s2*t6*t10*t11*w1-X1*s1*t7*t10*t11*w2+Y1*s1*t6*t10*t11*w1-Y1*s2*t5*t10*t11*w2-Y1*s2*t7*t10*t11*w2+Y1*s3*t6*t10*t11*w3-Z1*s3*t5*t10*t11*w2+Z1*s2*t6*t10*t11*w3-Z1*s3*t6*t10*t11*w2+X1*s3*t10*t11*w1*w2*w3+Z1*s1*t10*t11*w1*w2*w3)-t26*t65*t167*w2*2.0-t14*t101*t167*(t18*(X1*(t97+t98+t99-t112-t192)+Z1*(-t35+t94+t95+t96-t139)-Y1*t170)*2.0+t15*(t180+t182-X1*(-t176+t177+t178))*2.0+t23*(t175+Y1*(t35-t94+t95+t96-t139)-Z1*t173)*2.0)*(1.0/2.0);
  928. jacs(1, 2) = t14*t65*(X1*s3*w1+Y1*s3*w2+Z1*s1*w1+Z1*s2*w2+Z1*s3*w3*2.0+s1*t1*w3*2.0+s2*t2*w3*2.0+s3*t3*w3*2.0+X1*s2*t7*t12+X1*s2*t9*t10-Y1*s1*t7*t12-Y1*s1*t9*t10+X1*s1*t12*w3*2.0-X1*s3*t12*w1+Y1*s2*t12*w3*2.0-Y1*s3*t12*w2-Z1*s1*t12*w1-Z1*s2*t12*w2+X1*s2*t7*t10*t11-Y1*s1*t7*t10*t11-X1*s3*t12*w2*w3+Y1*s3*t12*w1*w3+Z1*s1*t12*w2*w3-Z1*s2*t12*w1*w3-X1*s3*t10*t11*w2*w3+Y1*s3*t10*t11*w1*w3+Z1*s1*t10*t11*w2*w3-Z1*s2*t10*t11*w1*w3-X1*s1*t6*t10*t11*w3-X1*s1*t7*t10*t11*w3+X1*s3*t7*t10*t11*w1-Y1*s2*t5*t10*t11*w3-Y1*s2*t7*t10*t11*w3+Y1*s3*t7*t10*t11*w2+Z1*s1*t7*t10*t11*w1+Z1*s2*t7*t10*t11*w2-Z1*s3*t5*t10*t11*w3-Z1*s3*t6*t10*t11*w3+X1*s2*t10*t11*w1*w2*w3+Y1*s1*t10*t11*w1*w2*w3)-t26*t65*t167*w3*2.0-t14*t101*t167*(t18*(Z1*(t46-t113+t114+t115-t138)-Y1*t198+X1*(t49+t51+t52+t118-t199))*2.0+t23*(X1*(-t97+t112+t116+t117-t192)+Y1*(-t46+t113+t114+t115-t138)-Z1*t195)*2.0+t15*(t204+Z1*(t97-t112+t116+t117-t192)-X1*(-t200+t201+t202))*2.0)*(1.0/2.0);
  929. jacs(1, 3) = s1*t65-t14*t101*t167*t208*(1.0/2.0);
  930. jacs(1, 4) = s2*t65-t14*t101*t167*t212*(1.0/2.0);
  931. jacs(1, 5) = s3*t65-t14*t101*t167*t216*(1.0/2.0);
  932. }
  933. }//End namespace ORB_SLAM2