00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <ros/ros.h>
00042 #include <visualization_msgs/Marker.h>
00043 #include <visualization_msgs/MarkerArray.h>
00044 #include <geometry_msgs/Point.h>
00045
00046 #include <vslam_system/vslam.h>
00047 #include <posest/pe3d.h>
00048 #include <sba/sba.h>
00049 #include <sba/sba_file_io.h>
00050 #include <frame_common/frame.h>
00051 #include <boost/shared_ptr.hpp>
00052 #include <fstream>
00053 #include <dirent.h>
00054 #include <fnmatch.h>
00055 #include <time.h>
00056 #include <opencv/highgui.h>
00057 #include <opencv2/legacy/legacy.hpp>
00058 #include <opencv2/nonfree/nonfree.hpp>
00059 #include <rosbag/bag.h>
00060 #include <rosbag/view.h>
00061 #include <sensor_msgs/CameraInfo.h>
00062 #include <stereo_msgs/DisparityImage.h>
00063 #include <sensor_msgs/Image.h>
00064 #include <cv_bridge/CvBridge.h>
00065
00066 using namespace std;
00067 using namespace sba;
00068 using namespace frame_common;
00069 using namespace Eigen;
00070 using namespace vslam;
00071 using namespace pcl;
00072
00073
00074 #define VISMATCH
00075
00076
00077 class VisBundler
00078 {
00079 public:
00080 VisBundler( const string& bag_filename, const string& vocabulary_tree_filename,
00081 const string& voc_weights_filename, cv::DescriptorExtractor* descriptor_extractor );
00082 ~VisBundler();
00083
00084 bool step();
00085 void spin();
00086 protected:
00087 void publishRegisteredPointclouds( ) const;
00088 void drawgraph( int dec ) const;
00089
00090
00091 ros::NodeHandle node_handle_;
00092 vslam::VslamSystem vslam_;
00093 rosbag::Bag bag_;
00094 rosbag::View view_;
00095 rosbag::View::iterator message_iterator_;
00096 ros::Publisher pt_pub_;
00097 ros::Publisher cam_pub_;
00098 ros::Publisher pc_pub_;
00099 };
00100
00101 VisBundler::VisBundler( const string& bag_filename, const string& vocabulary_tree_filename,
00102 const string& vocabulary_weights_filename, cv::DescriptorExtractor* descriptor_extractor )
00103 : node_handle_("~")
00104 , vslam_( vocabulary_tree_filename, vocabulary_weights_filename )
00105 , bag_( bag_filename )
00106 , view_( bag_ )
00107 , message_iterator_( view_.begin() )
00108 , pt_pub_( node_handle_.advertise<visualization_msgs::Marker>("points", 0) )
00109 , cam_pub_( node_handle_.advertise<visualization_msgs::Marker>("cameras", 0) )
00110 , pc_pub_( node_handle_.advertise<sensor_msgs::PointCloud2>("pointcloud", 1) )
00111 {
00112 vslam_.frame_processor_.setFrameDescriptor( descriptor_extractor );
00113 vslam_.setPointcloudProc(boost::shared_ptr<frame_common::PointcloudProc>(new frame_common::PointcloudProc()));
00114 vslam_.doPointPlane = false;
00115
00116
00117 vslam_.setKeyDist(0.01);
00118 vslam_.setKeyAngle(0.05);
00119 vslam_.setKeyInliers(200);
00120 vslam_.setHuber(40.0);
00121 vslam_.vo_.pose_estimator_->wy = 128;
00122 vslam_.vo_.pose_estimator_->wx = 128;
00123 vslam_.vo_.pose_estimator_->numRansac = 10000;
00124 vslam_.vo_.sba.verbose = false;
00125 vslam_.sba_.verbose = false;
00126
00127 srand(time(0));
00128
00129 #ifdef VISMATCH
00130 cv::namedWindow("VO tracks",0);
00131 cv::namedWindow("color image");
00132 #endif
00133 }
00134
00135 VisBundler::~VisBundler()
00136 {
00137 }
00138
00139 void VisBundler::publishRegisteredPointclouds( ) const
00140 {
00141 pcl::PointCloud<pcl::PointXYZRGB> cloud;
00142 pcl::PointCloud<pcl::PointXYZRGB> registered_cloud;
00143
00144 for(size_t i=0; i < vslam_.vo_.frames.size(); i++)
00145 {
00146
00147 if (vslam_.vo_.sba.nodes.size() < i)
00148 break;
00149 if (vslam_.vo_.frames[i].dense_pointcloud.points.size() <= 0)
00150 continue;
00151 Eigen::Quaterniond rot = vslam_.vo_.sba.nodes[i].qrot;
00152 Eigen::Vector3d trans = vslam_.vo_.sba.nodes[i].trans.head<3>();
00153
00154 transformPointCloud<PointXYZRGB>(vslam_.vo_.frames[i].dense_pointcloud, cloud, Vector3f(0,0,0), rot.cast<float>());
00155 transformPointCloud<PointXYZRGB>(cloud, cloud, trans.cast<float>(), Quaternionf(1, 0, 0, 0));
00156
00157 Quaternionf qr = Quaternionf(.5, 0, 0, .5).normalized()*Quaternionf(.5, -.5, .5, -0.5).normalized();
00158 transformPointCloud<PointXYZRGB>(cloud, cloud, Vector3f(0,0,0), qr);
00159
00160 registered_cloud.header = vslam_.vo_.frames[i].dense_pointcloud.header;
00161 registered_cloud += cloud;
00162 }
00163
00164 sensor_msgs::PointCloud2 cloud_out;
00165 pcl::toROSMsg (registered_cloud, cloud_out);
00166 cloud_out.header.frame_id = "/pgraph";
00167 pc_pub_.publish (cloud_out);
00168 }
00169
00170
00171
00172
00173 void VisBundler::drawgraph( int dec ) const
00174 {
00175 visualization_msgs::Marker cammark, ptmark, cstmark;
00176 cammark.header.frame_id = "/pgraph";
00177 cammark.header.stamp = ros::Time();
00178 cammark.ns = "pgraph";
00179 cammark.id = 0;
00180 cammark.action = visualization_msgs::Marker::ADD;
00181 cammark.pose.position.x = 0;
00182 cammark.pose.position.y = 0;
00183 cammark.pose.position.z = 0;
00184 cammark.pose.orientation.x = 0.0;
00185 cammark.pose.orientation.y = 0.0;
00186 cammark.pose.orientation.z = 0.0;
00187 cammark.pose.orientation.w = 1.0;
00188 cammark.scale.x = 0.02;
00189 cammark.scale.y = 0.02;
00190 cammark.scale.z = 0.02;
00191 cammark.color.r = 0.0f;
00192 cammark.color.g = 1.0f;
00193 cammark.color.b = 1.0f;
00194 cammark.color.a = 1.0f;
00195 cammark.lifetime = ros::Duration();
00196 cammark.type = visualization_msgs::Marker::LINE_LIST;
00197
00198 ptmark = cammark;
00199 ptmark.color.r = 1.0f;
00200 ptmark.color.g = 0.0f;
00201 ptmark.color.b = 0.0f;
00202 ptmark.color.a = 0.5f;
00203 ptmark.scale.x = 0.01;
00204 ptmark.scale.y = 0.01;
00205 ptmark.scale.z = 0.01;
00206 ptmark.type = visualization_msgs::Marker::POINTS;
00207
00208 cstmark = cammark;
00209 cstmark.color.r = 1.0f;
00210 cstmark.color.g = 1.0f;
00211 cstmark.color.b = 0.0f;
00212 cstmark.color.a = 1.0f;
00213 cstmark.scale.x = 0.03;
00214 cstmark.scale.y = 0.1;
00215 cstmark.scale.z = 0.1;
00216 cstmark.type = visualization_msgs::Marker::LINE_LIST;
00217
00218
00219
00220 int npts = vslam_.vo_.sba.tracks.size();
00221
00222
00223 if (npts <= 0) return;
00224
00225
00226 ptmark.points.resize(npts/dec+1);
00227 for (int i=0, ii=0; i<npts; i+=dec, ii++)
00228 {
00229 const Vector4d &pt = vslam_.vo_.sba.tracks[i].point;
00230 ptmark.points[ii].x = pt(0);
00231 ptmark.points[ii].y = pt(2);
00232 ptmark.points[ii].z = -pt(1);
00233 }
00234
00235
00236 int ncams = vslam_.vo_.sba.nodes.size();
00237 cammark.points.resize(ncams*6);
00238 for (int i=0, ii=0; i<ncams; i++)
00239 {
00240 const Node &nd = vslam_.vo_.sba.nodes[i];
00241 Vector3d opt;
00242 Matrix<double,3,4> tr;
00243 transformF2W(tr,nd.trans,Quaternion<double>(nd.qrot));
00244
00245 cammark.points[ii].x = nd.trans.x();
00246 cammark.points[ii].y = nd.trans.z();
00247 cammark.points[ii++].z = -nd.trans.y();
00248 opt = tr*Vector4d(0,0,0.3,1);
00249 cammark.points[ii].x = opt.x();
00250 cammark.points[ii].y = opt.z();
00251 cammark.points[ii++].z = -opt.y();
00252
00253 cammark.points[ii].x = nd.trans.x();
00254 cammark.points[ii].y = nd.trans.z();
00255 cammark.points[ii++].z = -nd.trans.y();
00256 opt = tr*Vector4d(0.2,0,0,1);
00257 cammark.points[ii].x = opt.x();
00258 cammark.points[ii].y = opt.z();
00259 cammark.points[ii++].z = -opt.y();
00260
00261 cammark.points[ii].x = nd.trans.x();
00262 cammark.points[ii].y = nd.trans.z();
00263 cammark.points[ii++].z = -nd.trans.y();
00264 opt = tr*Vector4d(0,0.1,0,1);
00265 cammark.points[ii].x = opt.x();
00266 cammark.points[ii].y = opt.z();
00267 cammark.points[ii++].z = -opt.y();
00268 }
00269
00270
00271 int num_tracks = vslam_.vo_.sba.tracks.size();
00272 int ii = cammark.points.size();
00273
00274 for (int i=0; i < num_tracks; i++)
00275 {
00276 const ProjMap &prjs = vslam_.vo_.sba.tracks[i].projections;
00277 for (ProjMap::const_iterator itr = prjs.begin(); itr != prjs.end(); itr++)
00278 {
00279 const Proj &prj = (*itr).second;
00280 if (prj.pointPlane)
00281 {
00282 cammark.points.resize(ii+2);
00283 Point pt0 = vslam_.vo_.sba.tracks[i].point;
00284 Vector3d plane_point = prj.plane_point;
00285 Vector3d plane_normal = prj.plane_normal;
00286 Eigen::Vector3d w = pt0.head<3>()-plane_point;
00287
00288 Eigen::Vector3d projpt = pt0.head<3>() - (w.dot(plane_normal))*plane_normal;
00289
00290 Vector3d pt1 = projpt;
00291
00292 cammark.points[ii].x = pt0.x();
00293 cammark.points[ii].y = pt0.z();
00294 cammark.points[ii++].z = -pt0.y();
00295 cammark.points[ii].x = pt1.x();
00296 cammark.points[ii].y = pt1.z();
00297 cammark.points[ii++].z = -pt1.y();
00298 }
00299 }
00300 }
00301
00302
00303 #if 0
00304
00305 int ncons = vslam_.vo_.spa.p2cons.size();
00306 cstmark.points.resize(ncons*6);
00307
00308 for (int i=0, ii=0; i<ncons; i++)
00309 {
00310 ConP2 &con = vslam_.vo_.spa.p2cons[i];
00311 Node &nd0 = vslam_.vo_.spa.nodes[con.ndr];
00312 Node &nd1 = vslam_.vo_.spa.nodes[con.nd1];
00313
00314 Node &nd = vslam_.vo_.spa.nodes[i];
00315 Vector3d opt;
00316 Matrix<double,3,4> tr;
00317 transformF2W(tr,nd.trans,Quaternion<double>(nd.qrot));
00318
00319 cstmark.points[ii].x = nd.trans.x();
00320 cstmark.points[ii].y = nd.trans.z();
00321 cstmark.points[ii++].z = -nd.trans.y();
00322 opt = tr*Vector4d(0,0,0.3,1);
00323 cstmark.points[ii].x = opt.x();
00324 cstmark.points[ii].y = opt.z();
00325 cstmark.points[ii++].z = -opt.y();
00326
00327 cstmark.points[ii].x = nd.trans.x();
00328 cstmark.points[ii].y = nd.trans.z();
00329 cstmark.points[ii++].z = -nd.trans.y();
00330 opt = tr*Vector4d(0.2,0,0,1);
00331 cstmark.points[ii].x = opt.x();
00332 cstmark.points[ii].y = opt.z();
00333 cstmark.points[ii++].z = -opt.y();
00334
00335 cstmark.points[ii].x = nd.trans.x();
00336 cstmark.points[ii].y = nd.trans.z();
00337 cstmark.points[ii++].z = -nd.trans.y();
00338 opt = tr*Vector4d(0,0.1,0,1);
00339 cstmark.points[ii].x = opt.x();
00340 cstmark.points[ii].y = opt.z();
00341 cstmark.points[ii++].z = -opt.y();
00342
00343 #if 0
00344 cstmark.points[ii].x = nd0.trans.x();
00345 cstmark.points[ii].y= nd0.trans.z();
00346 cstmark.points[ii++].z = -nd0.trans.y();
00347 cstmark.points[ii].x = nd1.trans.x();
00348 cstmark.points[ii].y = nd1.trans.z();
00349 cstmark.points[ii++].z = -nd1.trans.y();
00350 #endif
00351 }
00352 #endif // SPA
00353
00354 cam_pub_.publish(cammark);
00355 pt_pub_.publish(ptmark);
00356
00357
00358 }
00359
00360
00361 bool VisBundler::step( )
00362 {
00363 static boost::shared_ptr< sensor_msgs::CameraInfo > camera_info_left;
00364 static boost::shared_ptr< sensor_msgs::CameraInfo > camera_info_right;
00365 static boost::shared_ptr< sensor_msgs::Image > color_image;
00366 static boost::shared_ptr< stereo_msgs::DisparityImage > disparity_image;
00367
00368 static int message_count = 0;
00369 while( message_iterator_ != view_.end() )
00370 {
00371 if( message_iterator_->getTopic() == "/primesense/left/camera_info" )
00372 {
00373 camera_info_left = message_iterator_->instantiate<sensor_msgs::CameraInfo>();
00374 }
00375
00376 else if( message_iterator_->getTopic() == "/primesense/right/camera_info" )
00377 {
00378 camera_info_right = message_iterator_->instantiate<sensor_msgs::CameraInfo>();
00379 }
00380
00381 else if( message_iterator_->getTopic() == "/primesense/left/color_image_raw" )
00382 {
00383 color_image = message_iterator_->instantiate<sensor_msgs::Image>();
00384 }
00385 else if( message_iterator_->getTopic() == "/primesense/disparity" )
00386 {
00387 disparity_image = message_iterator_->instantiate<stereo_msgs::DisparityImage>();
00388 }
00389
00390 ++message_iterator_;
00391 ++message_count;
00392
00393 if( message_count > 3 )
00394 {
00395 ros::Time oldest = min( min( color_image->header.stamp, camera_info_right->header.stamp ) ,
00396 min( camera_info_left->header.stamp, disparity_image->header.stamp ) );
00397
00398 ros::Time newest = max( max( color_image->header.stamp, camera_info_right->header.stamp ) ,
00399 max( camera_info_left->header.stamp, disparity_image->header.stamp ) );
00400
00401 if( oldest == newest )
00402 {
00403 CamParams camera_params;
00404 camera_params.fx = camera_info_left->K[0];
00405 camera_params.fy = camera_info_left->K[4];
00406 camera_params.cx = camera_info_left->K[2];
00407 camera_params.cx = camera_info_left->K[5];
00408 camera_params.tx = - camera_info_right->P[3] / camera_params.fx;
00409
00410 static sensor_msgs::CvBridge cvImageBridge;
00411 cv::Mat image( cvImageBridge.imgMsgToCv( color_image ) );
00412
00413 cv::Mat grayImage;
00414 cv::cvtColor( image, grayImage, CV_RGB2GRAY );
00415 static sensor_msgs::CvBridge cvDisparityBridge;
00416 cvDisparityBridge.fromImage( disparity_image->image );
00417 cv::Mat disp_image32f = cvDisparityBridge.toIpl();
00418 cv::Mat disp_image16u;
00419
00420 disp_image32f.convertTo( disp_image16u, CV_16UC1, 32.0 );
00421
00422 bool is_keyframe = vslam_.addFrame( camera_params, grayImage, disp_image16u, 32.0, true );
00423
00424 if (is_keyframe)
00425 {
00426
00427 imshow("color image", image );
00428 vslam_.sba_.doSBA(10,1e-4,SBA_SPARSE_CHOLESKY);
00429
00431 int n = vslam_.sba_.nodes.size();
00432
00433
00434
00435 if (n%1 == 0)
00436 {
00437 drawgraph( 1 );
00438 publishRegisteredPointclouds( );
00439 drawgraph( 1 );
00440 publishRegisteredPointclouds( );
00441 for (int i=0; i<5; i++)
00442 {
00443
00444 cout << i << endl;
00445 vslam_.vo_.sba.doSBA( 1,1.0e-5,0 );
00446 drawgraph( 1 );
00447 publishRegisteredPointclouds( );
00448 drawgraph( 1 );
00449 publishRegisteredPointclouds( );
00450 }
00451 }
00452
00453
00454 if (n > 10 && n%500 == 0)
00455 {
00456 char fn[1024];
00457 sprintf(fn,"newcollege%d.g2o", n);
00458 sba::writeGraphFile(fn,vslam_.sba_);
00459 sprintf(fn,"newcollege%dm.g2o", n);
00460 sba::writeGraphFile(fn,vslam_.sba_,true);
00461 }
00462
00463 int nnsba = 10;
00464 if (n > 4 && n%nnsba == 0)
00465 {
00466 cout << "Running large SBA" << endl;
00467 vslam_.refine();
00468 }
00469
00470 break;
00471 }
00472 #ifdef VISMATCH
00473 cv::Mat display;
00474 drawVOtracks(grayImage, vslam_.vo_.frames, display);
00475 cv::imshow("VO tracks", display);
00476 #endif
00477 }
00478 }
00479 }
00480
00481 return (message_iterator_ != view_.end());
00482 }
00483
00484
00485 void VisBundler::spin()
00486 {
00487 bool quit = false;
00488 bool paused = true;
00489 while( node_handle_.ok() && !quit )
00490 {
00491 ros::spinOnce();
00492 char key = cv::waitKey( 10 ) & 0xFF;
00493 switch( key )
00494 {
00495 case 27:
00496 case 'Q':
00497 case 'q':
00498 quit = true;
00499 break;
00500 case ' ':
00501 paused = !paused;
00502 break;
00503 case 's':
00504 case 'S':
00505 paused = true;
00506 step();
00507 break;
00508 }
00509 if( !paused )
00510 {
00511 step();
00512 }
00513 }
00514 }
00515
00516 int main(int argc, char** argv)
00517 {
00518 if (argc < 5)
00519 {
00520 cout <<"Usage: " << argv[0] << " <bag file> <vocab tree file> <vocab weights file> <calonder trees file>" << endl;
00521 exit(0);
00522 }
00523
00524
00525 ros::init(argc, argv, "VisBundler");
00526 typedef cv::CalonderDescriptorExtractor<float> Calonder;
00527 typedef cv::SiftDescriptorExtractor Sift;
00528 VisBundler visbundler( argv[1], argv[2], argv[3], new Calonder(argv[4]) );
00529
00530 visbundler.spin();
00531
00532 return 0;
00533 }