00001
00011 #ifndef VSLAM_POSE_GRAPH_H_INCLUDED
00012 #define VSLAM_POSE_GRAPH_H_INCLUDED
00013
00014 #include "utils.h"
00015 #include "tf/transform_listener.h"
00016 #include "sensor_msgs/CameraInfo.h"
00017 #include "sensor_msgs/CompressedImage.h"
00018 #include "cv_bridge/cv_bridge.h"
00019 #include "image_transport/image_transport.h"
00020 #include "Sophus/se3.h"
00021
00022 #include "feature_matching.h"
00023
00024 #include <vector>
00025 #include <string>
00026 #include <iostream>
00027 #include <fstream>
00028 #include <opencv2/core/core.hpp>
00029 #include <opencv2/imgproc/imgproc.hpp>
00030 #include <opencv2/highgui/highgui.hpp>
00031 #include <opencv2/features2d/features2d.hpp>
00032 #include <opencv2/calib3d/calib3d.hpp>
00033 #include <assert.h>
00034 #include <algorithm>
00035 #include <boost/graph/adjacency_list.hpp>
00036 #include <boost/graph/depth_first_search.hpp>
00037 #include <map>
00038
00039
00040
00041
00042 namespace boost{
00058
00059
00066
00067
00069 enum vertex_kp_t { vertex_kp = 101 };
00071 enum vertex_desc_t { vertex_desc = 102 };
00073
00081 enum vertex_fix_idx_t { vertex_fix_idx = 103 };
00082
00084 enum vertex_seq_t { vertex_seq = 104 };
00085
00087 enum vertex_transform_t { vertex_transform = 105 };
00088
00093 enum vertex_keyframe_flag_t { vertex_keyframe_flag = 106 };
00094
00096 enum vertex_debug_info_t { vertex_debug_info = 107 };
00097
00099 enum vertex_timestamp_t { vertex_timestamp = 108 };
00100
00102 enum edge_kp_idx_map_t { edge_kp_idx_map= 201 };
00103
00105
00106 enum edge_transform_t { edge_transform= 202 };
00107
00109 enum edge_rel_scale_error_t { edge_rel_scale_error= 203 };
00110
00112 enum graph_points_t { graph_points= 301 };
00113
00114 BOOST_INSTALL_PROPERTY(vertex, kp);
00115 BOOST_INSTALL_PROPERTY(vertex, desc);
00116 BOOST_INSTALL_PROPERTY(vertex, fix_idx);
00117 BOOST_INSTALL_PROPERTY(vertex, seq);
00118 BOOST_INSTALL_PROPERTY(vertex, transform);
00119 BOOST_INSTALL_PROPERTY(vertex, keyframe_flag);
00120 BOOST_INSTALL_PROPERTY(vertex, debug_info);
00121 BOOST_INSTALL_PROPERTY(vertex, timestamp);
00122
00123 BOOST_INSTALL_PROPERTY(edge, kp_idx_map);
00124 BOOST_INSTALL_PROPERTY(edge, transform);
00125 BOOST_INSTALL_PROPERTY(edge, rel_scale_error);
00126
00127 BOOST_INSTALL_PROPERTY(graph, points);
00129
00131 }
00132
00133
00134 namespace vslam{
00138 using boost::vertex_kp;
00139 using boost::vertex_desc;
00140 using boost::vertex_fix_idx;
00141 using boost::vertex_seq;
00142 using boost::vertex_transform;
00143 using boost::vertex_keyframe_flag;
00144 using boost::vertex_debug_info;
00145 using boost::vertex_timestamp;
00146 using boost::edge_kp_idx_map;
00147 using boost::edge_transform;
00148 using boost::edge_rel_scale_error;
00149
00150 using boost::vertex_kp_t;
00151 using boost::vertex_desc_t;
00152 using boost::vertex_fix_idx_t;
00153 using boost::vertex_seq_t;
00154 using boost::vertex_transform_t;
00155 using boost::vertex_keyframe_flag_t;
00156 using boost::vertex_debug_info_t;
00157 using boost::vertex_timestamp_t;
00158 using boost::edge_kp_idx_map_t;
00159 using boost::edge_transform_t;
00160 using boost::edge_rel_scale_error_t;
00161
00162 using std::list;
00163 using std::map;
00164
00165 using boost::graph_traits; using boost::property_map; using boost::tie;
00166
00167
00168 const int BAD_INDEX = -1;
00169
00170
00172 template<class G> class FeatureID{
00173 public:
00174 typename graph_traits<G>::vertex_descriptor vd;
00175 int vidx;
00176
00177 FeatureID(typename graph_traits<G>::vertex_descriptor _vd, int _vidx) :
00178 vd(_vd), vidx(_vidx) {}
00179 };
00180
00182 template<class G> bool isLandmakFeature(const G& g, const FeatureID<G>& fid){
00183 get(vertex_fix_idx, g, fid.vd)[0];
00184 return get(vertex_fix_idx, g, fid.vd)[fid.vidx]!=BAD_INDEX;
00185 }
00186
00191 template<typename G> struct Point;
00192
00193 namespace lmdetails{
00194 template<class G> class PointsLoc;
00195 }
00196
00202 template<class G> class Points{
00203 private:
00204 lmdetails::PointsLoc<G> points;
00205
00206 public:
00207 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00208
00209 void activateLandmarks(
00210 const G&g, typename graph_traits<G>::vertex_descriptor v, int keep_num);
00211
00212 const Point<G> & getPoint(int idx) const;
00213
00214 void lmEstimateUpd(int lm_id, Vector3d& new_estimate);
00215
00216 void lmEstimateUpdChecked(int lm_id, Vector3d& new_estimate);
00217
00218 void deleteLmObs(G&g, const FeatureID<G>& obs);
00219
00220 int size() const;
00221
00222
00223 bool fixNewLandmark( FeatureID<G> fa, FeatureID<G> fm, FeatureID<G> fb, G& g);
00224
00225 bool fixNewObservation( FeatureID<G> fa, FeatureID<G> fb, G& g);
00226 };
00227
00228
00233
00234 class VertexDebugInfo{
00235 public:
00236 uint64_t seq;
00237 uint64_t timestamp;
00238 bool is_kf;
00239
00240
00241
00242
00243 int num_init_landmarks;
00244 int num_uinit_landmarks;
00245 double avg_reprojection_error;
00246 double max_reprojection_error;
00247 int num_discontinued_landmarks;
00248 int num_extended_landmarks;
00249 SE3 gt_T_wc;
00250 map<std::string, double> double_propmap;
00251 };
00252
00253
00254
00256
00257 typedef boost::adjacency_list<
00258 boost::vecS,
00259 boost::vecS,
00260 boost::directedS,
00261 boost::property<vertex_kp_t, std::vector<cv::KeyPoint>,
00262 boost::property<vertex_desc_t, cv::Mat,
00263 boost::property<vertex_fix_idx_t, vector<int>,
00264 boost::property<vertex_seq_t, int,
00265 boost::property<boost::vertex_keyframe_flag_t, int,
00266 boost::property<boost::vertex_debug_info_t, VertexDebugInfo,
00267 boost::property<boost::vertex_timestamp_t, uint64_t,
00268 boost::property<vertex_transform_t, SE3> > > > > > > >,
00269 boost::property<edge_kp_idx_map_t, map<int,int>,
00270 boost::property<edge_transform_t, SE3,
00271 boost::property<edge_rel_scale_error_t, double> > > > PoseGraph;
00272
00273 typedef graph_traits<PoseGraph>::vertex_descriptor PGVertexD;
00274 typedef graph_traits<PoseGraph>::edge_descriptor PGEdgeD;
00275
00276 typedef ALIGNED<pair<int, Vector3d> >::vector IdxPoint3dVec;
00277
00278
00285 template<class G> class PerformanceLogger{
00286 public:
00287 typedef typename boost::graph_traits<G>::vertex_descriptor VDT;
00288 private:
00289 G& g;
00290 VDT vd;
00291 std::string str;
00292 ros::WallTime start_time;
00293 bool stop_forced;
00294 public:
00295 PerformanceLogger(G& _g, VDT _vd, std::string name_tag) : g(_g), vd(_vd){
00296 str = "timings_" + name_tag + "_d_x";
00297 start_time = ros::WallTime::now();
00298 stop_forced = false;
00299 }
00300
00301 ~PerformanceLogger(){
00302 if(!stop_forced) forceStop();
00303 }
00304
00305 void forceStop(){
00306 assert(!stop_forced);
00307 ros::WallDuration duration = ros::WallTime::now() - start_time;
00308 map<std::string, double> & propmap = get(vertex_debug_info, g, vd).double_propmap;
00309 if(propmap.find(str)!=propmap.end()){
00310 str += "x";
00311 }
00312 propmap[str] = duration.toSec();
00313 stop_forced=true;
00314 }
00315 };
00316
00327 template<typename G> class EdgeBuilder{
00328 public:
00329 typedef typename graph_traits<G>::vertex_descriptor VertexD;
00330 typedef typename graph_traits<G>::edge_descriptor EdgeD;
00331
00332 protected:
00333 static void featureSelection(G& g, VertexD vd, int target_num, vector<int>& keep_idxs,
00334 vector<cv::KeyPoint>& sel_keypoints, cv::Mat& sel_descriptors);
00335
00336 public:
00350 bool build(const VertexD & src, const VertexD & dst, Points<G> & points, G & g){
00351 return buildImpl(src, dst, points, g);
00352 }
00353
00354 virtual bool buildImpl(
00355 const VertexD & src, const VertexD & dst, Points<G> & points, G & g) = 0;
00356 };
00357
00358
00359
00363 template<typename G> class MonoFtrClassEdgeBuilder : public EdgeBuilder<G>{
00364 public:
00365 typedef typename graph_traits<G>::vertex_descriptor VertexD;
00366 typedef typename graph_traits<G>::edge_descriptor EdgeD;
00367 protected:
00368 std::tr1::shared_ptr<RobustFeatureMatcher> rmatcher;
00369
00370 static void compute3viewStructure(VertexD vad, VertexD vbd, VertexD vcd, G & g,
00371 IdxPoint3dVec&, SE3&);
00372
00373 static void matchScaleFindNewLandmarks(
00374 VertexD vsrc, VertexD vdest, Points<G> & points, G & g);
00375
00376 static void computeScale(VertexD contactvd, VertexD newvd, G & g, Points<G>& points,
00377 SE3& scaled_T_vbd_vcd);
00378
00379 bool unguidedMatching(
00380 const vector<cv::KeyPoint>& sel_tvd_keypoints,
00381 const vector<cv::KeyPoint>& sel_qvd_keypoints,
00382 const cv::Mat& sel_tvd_descriptors,
00383 const cv::Mat& sel_qvd_descriptors,
00384 SE3& T_tvd_qvd,
00385 std::vector<cv::DMatch>& global_dmatches_c1c2);
00386
00387 void guidedMatching( G& g, VertexD c1vd, VertexD c2vd);
00388 public:
00389 MonoFtrClassEdgeBuilder<G>(std::tr1::shared_ptr<RobustFeatureMatcher> _rmatcher) :
00390 rmatcher(_rmatcher) {}
00391
00392
00393 virtual bool buildImpl(
00394 const VertexD & src, const VertexD & dst, Points<G> & points, G & g);
00395 };
00396
00397
00398
00399 inline std::tr1::shared_ptr<RobustFeatureMatcher> constructRMatcher(
00400 std::tr1::shared_ptr<cv::DescriptorMatcher> _dmatcher,
00401 std::tr1::shared_ptr<EMatrixModelBuilder> _minbuilder,
00402 std::tr1::shared_ptr<EMatrixModelBuilder> _builder =
00403 std::tr1::shared_ptr<EMatrixModelBuilder>());
00405
00406
00409
00411 class NMSOptions{
00412 public:
00413 bool do_nms;
00414 int target_num_points;
00415
00417 NMSOptions() : do_nms(false) {}
00419 NMSOptions(int _target_num_points) : do_nms(true), target_num_points(_target_num_points) {}
00420 };
00421
00430 template<class PoseGraphT> class OneDetectorNodeBuilder {
00431 protected:
00432 shared_ptr<cv::DescriptorExtractor> extractor;
00433 shared_ptr<cv::FeatureDetector> detector;
00434 shared_ptr<cv::ORB> feature_2d_detector;
00435 cv::Mat mask;
00436 NMSOptions nms_options;
00437
00438 OneDetectorNodeBuilder(NMSOptions _nms_options = NMSOptions()) : nms_options(_nms_options) {
00439 cv::Mat mask0 = cv::imread(image_mask_file);
00440 cv::cvtColor(mask0, mask, CV_RGB2GRAY);
00441 }
00442 public:
00443 typedef cv::Mat InputType;
00444
00445 cv::Mat getPoseImage(const InputType& in){
00446 return in.clone();
00447 }
00448
00460 bool build(const cv::Mat & image, int image_seq_num, uint64_t pose_timestamp,
00461 typename graph_traits<PoseGraphT>::vertex_descriptor & vd, PoseGraphT& g);
00462
00464 void demolish(PoseGraphT& g, Points<PoseGraphT>& points,
00465 typename graph_traits<PoseGraphT>::vertex_descriptor & vd);
00466 };
00467
00468 template<class PoseGraphT>
00469 class CustomOneDetectorNodeBuilder : public OneDetectorNodeBuilder<PoseGraphT>{
00470 public:
00471 typedef cv::Mat InputType;
00472 CustomOneDetectorNodeBuilder(
00473 std::tr1::shared_ptr<cv::FeatureDetector> _detector,
00474 std::tr1::shared_ptr<cv::DescriptorExtractor> _extractor){
00475 this->detector=_detector;
00476 this->extractor=_extractor;
00477 }
00478 };
00479
00480 template<class PoseGraphT>
00481 class CustomOneDetectorNodeBuilderFeature2D : public OneDetectorNodeBuilder<PoseGraphT>{
00482 public:
00483 typedef cv::Mat InputType;
00484 CustomOneDetectorNodeBuilderFeature2D(
00485 std::tr1::shared_ptr<cv::ORB> _feature_2d_detector) :
00486 OneDetectorNodeBuilder<PoseGraphT>(NMSOptions(4000)){
00487 this->feature_2d_detector=_feature_2d_detector;
00488 }
00489 };
00490
00493 }
00494
00495
00496
00497
00498
00499 #include <boost/graph/dijkstra_shortest_paths.hpp>
00500
00501 #include <iostream>
00502 #include <cmath>
00503 #include <tr1/functional>
00504 namespace vslam{
00506 template<class PoseGraphT> class AllWeightsOneWeightMap {
00507 PoseGraphT* dummy;
00508 };
00509 }
00510
00511 namespace boost{
00513 template<class PoseGraphT> struct property_traits<vslam::AllWeightsOneWeightMap<PoseGraphT> >{
00514 typedef int value_type;
00515 typedef int reference;
00516 typedef typename graph_traits<PoseGraphT>::edge_descriptor key_type;
00517 typedef readable_property_map_tag category;
00518 };
00519 }
00520
00521 namespace vslam{
00526 template<class PoseGraphT> int get(
00527 AllWeightsOneWeightMap<PoseGraphT> pmap,
00528 typename boost::property_traits<AllWeightsOneWeightMap<PoseGraphT> >::key_type vd){
00529 return 1;
00530 };
00531 }
00532
00533
00534
00535 #include "graph_builder.h"
00536 #endif
00537