00001
00025 #include "utils.h"
00026 #include "pose_graph.h"
00027 #include "tests/testutils.h"
00028 #include "data_dump.h"
00029
00030
00031 #include "ros/ros.h"
00032 #include "tf/transform_listener.h"
00033 #include "sensor_msgs/CameraInfo.h"
00034 #include "sensor_msgs/CompressedImage.h"
00035 #include "nav_msgs/Odometry.h"
00036 #include "cv_bridge/cv_bridge.h"
00037 #include "image_transport/image_transport.h"
00038 #include "vis.h"
00039 #include "vo.h"
00040 #include "emat_estimation.h"
00041
00042
00043 #include <vector>
00044 #include <string>
00045 #include <iostream>
00046 #include <opencv2/core/core.hpp>
00047 #include <opencv2/imgproc/imgproc.hpp>
00048 #include <opencv2/highgui/highgui.hpp>
00049 #include <opencv2/features2d/features2d.hpp>
00050 #include <opencv2/calib3d/calib3d.hpp>
00051 #include "graph_opt.h"
00052 #include <boost/filesystem.hpp>
00053
00054 #include "vslam_utils/common.h"
00055
00056
00057
00061 namespace vslam{
00062
00064
00065 std::string image_mask_file;
00067
00068 std::string image_sample_file;
00070
00071 boost::filesystem::path debug_output_path;
00072
00073
00074
00075
00076
00077
00084 template<
00085 template<template<class> class, class> class VisualOdometryTT,
00086 template<class> class NodeBuilderTT,
00087 class PoseGraphT>
00088 class VORosInterface{
00089 protected:
00091 typedef VisualOdometryTT<NodeBuilderTT, PoseGraphT> VOType;
00092
00093 ros::NodeHandle & nhandle;
00094 ros::NodeHandle & nhandle_priv;
00095 image_transport::ImageTransport it;
00096 shared_ptr<VOType> vo;
00097
00098 image_transport::Subscriber sub;
00099 tf::TransformListener listener;
00100 ros::Publisher odometry_pub;
00101
00102 public:
00106 VORosInterface(
00107 ros::NodeHandle & _nhandle, ros::NodeHandle & _nhandle_priv, shared_ptr<VOType> _vo) :
00108 nhandle(_nhandle), nhandle_priv(_nhandle_priv), it(_nhandle), vo(_vo){
00117 sub=it.subscribe("/viz/pano_vodom/image", 2, &VORosInterface::chatterCallback,
00118 this);
00119 ROS_INFO("subscribed to topic /viz/pano_vodom/image");
00120
00121 odometry_pub = nhandle.advertise<nav_msgs::Odometry>(
00122 "visual_odom", 50);
00123 }
00124
00125 protected:
00127 int seqFromTimestamp(ros::Time t){
00128 const int range = (int)std::pow(10,4);
00129 int seq;
00130 seq = (t.sec % range)*10;
00131 seq = seq + (t.nsec) / (int)std::pow(10, 8);
00132 return seq;
00133 }
00134
00136 void confirmResolutionOrExit(const cv::Mat & image){
00137 int w = image.size().width;
00138 int h = image.size().height;
00139 if(w!=1600 || h!=800){
00140 ROS_ERROR_STREAM("Incorrect resolution of input images detected (width: " <<
00141 w << ", height: " << h << ")!");
00142 ros::shutdown();
00143 }
00144 }
00145
00152 void chatterCallback( const sensor_msgs::ImageConstPtr & it_image){
00153 ROS_INFO("new image recieved");
00154 cv_bridge::CvImagePtr cv_image = cv_bridge::toCvCopy(it_image, "rgb8");
00155
00156 bool debug_images;
00157 bool trajectory_file;
00158 nhandle_priv.param<bool>("debug_images", debug_images, false);
00159 nhandle_priv.param<bool>("trajectory_file", trajectory_file, false);
00160 confirmResolutionOrExit(cv_image->image);
00161
00162 shared_ptr<SE3> T_wc = vo->processPose(
00163 cv_image->image,
00164 seqFromTimestamp(it_image->header.stamp),
00165 it_image->header.stamp.toNSec(),
00166 debug_images,
00167 trajectory_file);
00168
00169 if(T_wc){
00170 SE3 T_cw = coordFrameConventionLocalToROS(T_wc->inverse());
00171 geometry_msgs::Pose pose = getPoseFromTcwInSE3(T_cw);
00172
00173 nav_msgs::Odometry odom;
00174 odom.pose.pose=pose;
00175 odom.header=it_image->header;
00176 if(nhandle_priv.hasParam("odometry_frame_id")){
00177 nhandle_priv.getParam("odometry_frame_id", odom.header.frame_id);
00178 } else{
00179 ROS_WARN("odometry_frame_id parameter not set. exitting.");
00180 ros::shutdown();
00181 }
00182
00183 odometry_pub.publish(odom);
00184 }
00185 }
00186 };
00187
00188
00189
00190
00191
00192 typedef CovisibilityKeyframeVisualOdometry<OneDetectorNodeBuilder, PoseGraph> VOType1;
00193
00194
00195
00196
00198 shared_ptr<OneDetectorNodeBuilder<PoseGraph> > buildOrbNBuilder(){
00199 shared_ptr<cv::ORB> orb;
00200
00201 orb.reset(new cv::ORB(10000, 1.15, 1));
00202 shared_ptr<OneDetectorNodeBuilder<PoseGraph> > nbuilder;
00203 nbuilder.reset(new CustomOneDetectorNodeBuilderFeature2D<PoseGraph>(orb));
00204 return nbuilder;
00205 }
00206
00208 shared_ptr<OneDetectorNodeBuilder<PoseGraph> > buildFASTbRIEFNBuilder(){
00209 shared_ptr<cv::FeatureDetector> detector;
00210 shared_ptr<cv::DescriptorExtractor> extractor;
00211 detector.reset(new cv::DynamicAdaptedFeatureDetector(
00212 new cv::FastAdjuster(20, false), 2000, 10000, 5));
00213 extractor.reset(new cv::BriefDescriptorExtractor(64));
00214 shared_ptr<OneDetectorNodeBuilder<PoseGraph> > nbuilder;
00215 nbuilder.reset(new CustomOneDetectorNodeBuilder<PoseGraph>(detector, extractor));
00216 return nbuilder;
00217 }
00218
00225 shared_ptr<VOType1> buildVOObject(){
00226 shared_ptr<OneDetectorNodeBuilder<PoseGraph> > nbuilder;
00227 shared_ptr<EdgeBuilder<PoseGraph> > ebuilder;
00228 {
00229 nbuilder=buildOrbNBuilder();
00230 shared_ptr<RobustFeatureMatcher> rmatcher = constructRMatcher(
00231 shared_ptr<cv::DescriptorMatcher>(new cv::BFMatcher(cv::NORM_HAMMING)),
00232 shared_ptr<EMatrixModelBuilder>(
00233 new LiHartley5ptFrom6ptsBuilderStd((M_PI / 180.0)*1.0)));
00234 rmatcher->setRatio(0.80);
00235 rmatcher->setRansacIterationsNum(300);
00236 ebuilder.reset(new MonoFtrClassEdgeBuilder<PoseGraph>(rmatcher));
00237 }
00238 shared_ptr<VOType1> vo;
00239 vo.reset(new VOType1(nbuilder, ebuilder, 0.8, 3,
00240 shared_ptr<VodomLogger<PoseGraph> >(new VertexDebugInfoLogger<PoseGraph>())));
00241 return vo;
00242 }
00243
00244 }
00245
00246 int main(int argc, char** argv){
00247 using namespace vslam;
00248 ros::init(argc, argv, "visual_odometry");
00249 ros::NodeHandle nhandle_priv("~");
00250 ros::NodeHandle nhandle;
00251
00252
00253 getROSParamOrExit(nhandle_priv, "image_mask_file", image_mask_file);
00254 getROSParamOrExit(nhandle_priv, "image_sample_file", image_sample_file);
00255 getROSParamAsPathOrExit(nhandle_priv, "debug_output_dir", debug_output_path);
00256
00257 shared_ptr<VOType1> vo = buildVOObject();
00258 VORosInterface<CovisibilityKeyframeVisualOdometry, OneDetectorNodeBuilder, PoseGraph>
00259 interface(nhandle, nhandle_priv, vo);
00260
00261 ros::spin();
00262 return 0;
00263 }
00264
00265
00266
00267