SRBA: Sparser Relative Bundle Adjustment
|
00001 /* +---------------------------------------------------------------------------+ 00002 | Mobile Robot Programming Toolkit (MRPT) | 00003 | http://www.mrpt.org/ | 00004 | | 00005 | Copyright (c) 2005-2015, Individual contributors, see AUTHORS file | 00006 | See: http://www.mrpt.org/Authors - All rights reserved. | 00007 | Released under BSD License. See details in http://www.mrpt.org/License | 00008 +---------------------------------------------------------------------------+ */ 00009 00010 #pragma once 00011 00015 #include "observations_MonocularCamera.h" 00016 00017 00018 #include <mrpt/utils/TCamera.h> 00019 #include <mrpt/utils/TStereoCamera.h> 00020 #include <mrpt/tfest.h> // for use in landmark_matcher<> 00021 00022 namespace srba { 00023 namespace observations { 00030 struct StereoCamera 00031 { 00032 static const size_t OBS_DIMS = 4; 00033 00035 struct obs_data_t 00036 { 00037 mrpt::utils::TPixelCoordf left_px, right_px; 00038 00040 template <class ARRAY> 00041 inline void getAsArray(ARRAY &obs) const { 00042 obs[0] = left_px.x; obs[1] = left_px.y; 00043 obs[2] = right_px.x; obs[3] = right_px.y; 00044 } 00045 }; 00046 00049 struct TObservationParams 00050 { 00051 mrpt::utils::TStereoCamera camera_calib; 00052 }; 00053 }; 00054 00056 template <> struct landmark_matcher<StereoCamera> 00057 { 00058 template <class POSE> 00059 static bool find_relative_pose( 00060 const mrpt::aligned_containers<StereoCamera::obs_data_t>::vector_t & new_kf_obs, 00061 const mrpt::aligned_containers<StereoCamera::obs_data_t>::vector_t & old_kf_obs, 00062 const StereoCamera::TObservationParams ¶ms, 00063 POSE &pose_new_kf_wrt_old_kf 00064 ) 00065 { 00066 ASSERT_(new_kf_obs.size()==old_kf_obs.size()) 00067 const size_t N=new_kf_obs.size(); 00068 // project stereo points to 3D and use them to find out the relative pose: 00069 const double cx = params.camera_calib.leftCamera.cx(), cy = params.camera_calib.leftCamera.cy(), baseline = params.camera_calib.rightCameraPose.x(), f = params.camera_calib.leftCamera.fx(); 00070 mrpt::utils::TMatchingPairList matches; 00071 matches.reserve(N); 00072 for (size_t i=0;i<N;i++) 00073 { 00074 // Point 1: 00075 const double disparity_old = old_kf_obs[i].left_px.x - old_kf_obs[i].right_px.x; 00076 if (disparity_old<=.0) continue; // Invalid 3D point 00077 const mrpt::math::TPoint3D pt_old( 00078 ( old_kf_obs[i].left_px.x - cx )*baseline/disparity_old, 00079 ( old_kf_obs[i].left_px.y - cy )*baseline/disparity_old, 00080 f*baseline/disparity_old ); 00081 // Point 2: 00082 const double disparity_new = new_kf_obs[i].left_px.x - new_kf_obs[i].right_px.x; 00083 if (disparity_new<=.0) continue; // Invalid 3D point 00084 const mrpt::math::TPoint3D pt_new( 00085 ( new_kf_obs[i].left_px.x - cx )*baseline/disparity_new, 00086 ( new_kf_obs[i].left_px.y - cy )*baseline/disparity_new, 00087 f*baseline/disparity_new ); 00088 00089 matches.push_back( mrpt::utils::TMatchingPair(i,i, pt_old.x,pt_old.y,pt_old.z, pt_new.x,pt_new.y,pt_new.z ) ); 00090 } 00091 // Least-square optimal transformation: 00092 if (POSE::rotation_dimensions==2) 00093 { // SE(2) 00094 mrpt::math::TPose2D found_pose; 00095 if (!mrpt::tfest::se2_l2(matches,found_pose)) 00096 return false; 00097 pose_new_kf_wrt_old_kf = POSE( mrpt::poses::CPose2D(found_pose)); 00098 } 00099 else 00100 { // SE(3) 00101 mrpt::poses::CPose3DQuat found_pose; 00102 double found_scale; 00103 if (!mrpt::tfest::se3_l2(matches,found_pose,found_scale)) 00104 return false; 00105 pose_new_kf_wrt_old_kf = POSE(found_pose); 00106 } 00107 return true; 00108 } 00109 }; 00110 00112 } 00113 } // end NS