utils.h
Go to the documentation of this file.
00001 //part of the source code of master thesis, source code produced by Jiri Divis
00007 #ifndef VSLAM_UTILS_H_INCLUDED
00008 #define VSLAM_UTILS_H_INCLUDED
00009 
00010 #define ROSCONSOLE_MIN_SEVERITY ROSCONSOLE_SEVERITY_DEBUG
00011 
00012 //turn of eigen alignment stuff.
00013 #define EIGEN_DONT_ALIGN
00014 #define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
00015 
00016 #include <Eigen/Dense>
00017 #include <Eigen/StdVector>
00018 #include <vector>
00019 #include <list>
00020 #include <set>
00021 #include <assert.h>
00022 #include "ros/ros.h"
00023 #include <opencv2/core/core.hpp>
00024 #include <opencv2/imgproc/imgproc.hpp>
00025 #include <opencv2/highgui/highgui.hpp>
00026 #include <opencv2/features2d/features2d.hpp>
00027 #include <opencv2/calib3d/calib3d.hpp>
00028 #include <boost/tr1/memory.hpp>
00029 #include <boost/tr1/cmath.hpp>
00030 #include <iostream>
00031 #include <boost/foreach.hpp>
00032 #include <boost/random.hpp>
00033 #include <boost/filesystem.hpp>
00034 #include "Sophus/se3.h"
00035 #include "Sophus/so3.h"
00036 
00037 #include "nav_msgs/Odometry.h"
00038 
00040 extern boost::mt19937 rng_mt19937; 
00041 
00042 const double PI = std::atan(1.0)*4; //TODO remove
00043 
00044 template <typename T1, typename T2 = T1>
00045 struct ALIGNED {
00046   typedef std::vector<T1, Eigen::aligned_allocator<T1> > vector;
00047   typedef std::list<T1, Eigen::aligned_allocator<T1> > list;
00048   typedef std::set<T1, Eigen::aligned_allocator<T1> > set;
00049   typedef std::map<T1, T2> map; //XXX
00050 };
00051 
00052 typedef ALIGNED<Eigen::Vector3d>::vector Points3dSTL;
00053 typedef ALIGNED<Eigen::Vector2d>::vector Points2dSTL;
00054 typedef ALIGNED<std::pair<int, Eigen::Vector3d> >::vector IdxPoint3dVec;
00055 typedef ALIGNED<std::pair<int, Eigen::Vector2d> >::vector IdxPoint2dVec;
00056 typedef std::pair<Eigen::Vector3d, Eigen::Vector3d> ImageMatch;
00057 typedef ALIGNED<ImageMatch>::vector ImageMatchVec;
00058 
00059 using Eigen::Vector2f;
00060 using Eigen::Vector2d; using Eigen::Vector3d; using Eigen::VectorXd;
00061 using Eigen::Matrix3d; using Eigen::Matrix4d; using Eigen::MatrixXd; using Eigen::Matrix;
00062 using std::tr1::shared_ptr;
00063 using std::cout; using std::cerr; using std::endl; using std::pair; using std::make_pair;
00064 using std::list; using std::map; using std::vector; 
00065 using Sophus::SE3; using Sophus::SO3;
00066 //using std::tr1::isfinite;
00067 
00068 namespace vslam{
00069     extern std::string image_mask_file;
00070     extern std::string image_sample_file;
00071     extern boost::filesystem::path debug_output_path;
00072 }
00073 
00074 class PanoramaParams{
00075     public:
00076         static const int width = 1600;
00077         static const int height = 800;
00078 };
00079 
00080 
00081 
00082 /*1st index is 0*/
00083 template<class T> T linspace_idx(T first, T last, int count, T idx){
00084     if(idx > count - 1.0){
00085         T tmp = ((T)count - 1) + 0.0000001;
00086         idx = (idx / tmp - (T)std::tr1::round(idx / tmp)) * tmp;
00087     }
00088     return first + ((last-first) / (T)((T)count - 1)) * idx;
00089 }
00090 
00091 template<class T> T inv_linspace_idx(T first, T last, int count, T val){
00092     return (val - first) / ((last-first) / (T)(count - 1));
00093 }
00094 
00095 template<class Iterator> void printContainer(Iterator b, Iterator e, const char * separator){
00096     while(b!=e){
00097         cout << *b << separator;
00098         ++b;
00099     }
00100 }
00101 
00105 template<class ImageParamsObj> class ImageCoordinate{
00106     private:
00107         bool initialized;
00108         double azimuth;
00109         double elevation;
00110 
00111     public:
00112         typedef ImageParamsObj Params;
00113 
00114         ImageCoordinate() : initialized(false) {}
00115 
00116         //pixel coordinate (x,y)=(0,0) is at the upper-left corner of the image. 
00117         //(x,y)=(width-1,height-1) is bottom right corner
00118         static ImageCoordinate<ImageParamsObj> fromPixel(Eigen::Vector2d pixel){
00119             ImageCoordinate<ImageParamsObj> obj;
00120             obj.azimuth = linspace_idx(
00121                     (double)0,
00122                     (double)(ImageParamsObj::width - 1) / (double)ImageParamsObj::width * (-2.0)*M_PI, 
00123                     ImageParamsObj::width,
00124                     pixel(0) - (double)(((int)ImageParamsObj::width) / 2)); 
00125             obj.elevation = -linspace_idx(-M_PI / 2.0, M_PI / 2.0, ImageParamsObj::height, pixel(1));
00126             obj.initialized = true;
00127             return obj;
00128         }
00129 
00130         //(azimuth,elevation)=(0,0) corresponds to (0,0,1) i.e. z-ray.
00131         static ImageCoordinate<ImageParamsObj> fromSpherical(Eigen::Vector2d spherical){
00132             ImageCoordinate<ImageParamsObj> obj;
00133             obj.azimuth = spherical(0);
00134             obj.elevation = spherical(1);
00135             obj.initialized = true;
00136             return obj;
00137         }
00138 
00139         static ImageCoordinate<ImageParamsObj> fromHomogenous(Eigen::Vector3d homogenous){
00140             ImageCoordinate<ImageParamsObj> obj;
00141             homogenous.normalize();
00142             double x = homogenous(0);
00143             double y = homogenous(1);
00144             double z = homogenous(2);
00145 
00146             double r_xz = std::sqrt(x*x + z*z);
00147             obj.azimuth = std::atan2(-x, z);
00148             obj.elevation = std::atan2(y, r_xz);
00149             obj.initialized = true;
00150             return obj;
00151         }
00152 
00153         Eigen::Vector2d getPixel() const{
00154             assert(initialized);
00155             Eigen::Vector2d t;
00156             t(0) = inv_linspace_idx(
00157                     (double)0, 
00158                     (double)(ImageParamsObj::width - 1) / (double)ImageParamsObj::width * (-2.0)*M_PI,
00159                     ImageParamsObj::width, 
00160                     azimuth) + (double)(((int)ImageParamsObj::width) / 2);
00161             t(1) = inv_linspace_idx(-M_PI / 2.0, M_PI / 2.0, ImageParamsObj::height, -elevation);
00162             return t;
00163         }
00164 
00165         Eigen::Vector2d getSpherical() const{
00166             assert(initialized);
00167             return Eigen::Vector2d(azimuth, elevation);
00168         }
00169 
00170         Eigen::Vector3d getHomogenous() const{
00171             assert(initialized);
00172             Eigen::Vector3d direction;
00173             direction(0) = -std::sin( azimuth ) * std::cos( elevation );
00174             direction(1) = std::sin( elevation );
00175             direction(2) = std::cos( azimuth ) * std::cos( elevation );
00176             return direction;
00177         }
00178 
00179         void print(){
00180             {
00181                 Vector2d c = getPixel();
00182                 cout << "pixel coordinates: " << "x: " << c(0) << "y: " << c(1) << endl;
00183             }
00184             cout << "spherical coordinates: " <<
00185                     "azimuth/PI: " << azimuth / M_PI << "elevation/PI: " << elevation / M_PI << endl;
00186             {
00187                 Vector3d c = getHomogenous();
00188                 cout << "homogenous coordinates: " <<
00189                         "x: " << c(0) << "y: " << c(1) << "z: " << c(2) << endl;
00190             }
00191         }
00192 }; 
00193 
00194 typedef ImageCoordinate<PanoramaParams> PanoImCoord;
00195 typedef vector<PanoImCoord> ImageCoordinateVec;
00196 
00197 
00198 inline Vector2d homogenousToPixel(const Vector3d & hom){
00199     return PanoImCoord::fromHomogenous(hom).getPixel();
00200 }
00201 
00202 
00204 template<typename T> class Maybe {
00205     T * obj;
00206 
00207     Maybe(){
00208         obj = 0;
00209     }
00210     public:
00211 
00212     const static Maybe<T> no;
00213     static Maybe<T> yes(const T & _obj){
00214         Maybe m;
00215         m.obj=new T(_obj);
00216         return m;
00217     }
00218 
00219     T & value() const{
00220         assert(obj != NULL);
00221         return *obj;
00222     }
00223 
00224     operator bool(){
00225         return obj != NULL;
00226     }
00227 
00228     bool operator==(const Maybe<T> & _obj) const{
00229         if(obj && _obj){
00230             return *obj == *(_obj.obj);
00231         } else{
00232             return false;
00233         }
00234     }
00235 
00236     bool operator!=(const Maybe<T> & _obj) const{
00237         return !(*this == _obj);
00238     }
00239 
00240     Maybe(const Maybe<T> & _obj){
00241         if(_obj == Maybe<T>::no){
00242             obj = 0;
00243         } else{
00244             obj = new T(_obj.value());
00245         }
00246     }
00247 };
00248  //end of Cam module
00250 
00251 inline ImageMatch computeMatch(const Vector2d& px_c1, const Vector2d& px_c2){
00252     PanoImCoord c1 = PanoImCoord::fromPixel(px_c1);
00253     PanoImCoord c2 = PanoImCoord::fromPixel(px_c2);
00254     return ImageMatch(c1.getHomogenous(), c2.getHomogenous());
00255 }
00256 
00257 
00258 template<class T> cv::Point cvPointFromVector2(Eigen::Matrix<T, 2, 1> vec){
00259     return cv::Point(vec(0), vec(1));
00260 }
00261 
00262 
00263 
00264 ImageMatchVec imageMatchCoords(const vector<cv::KeyPoint> & tkpts, const vector<cv::KeyPoint> & qkpts,
00265         const std::vector<cv::DMatch> &matches);
00266 
00267 typedef Eigen::Matrix<double, 3, Eigen::Dynamic> PointMatrix;
00268 
00269 void points3dSTLToPointMatrix(const Points3dSTL & pts, PointMatrix & ptmat);
00270 
00271 ImageMatchVec buildImageMatchesFrom3dPoints(
00272         const SE3 & T_wc1, const SE3 & T_wc2, const Points3dSTL & points);
00273 
00274 Points3dSTL projectPoints(SE3 T_sd, const Points3dSTL & points);
00275 
00276 
00278 void generateRandomScene(
00279         const Vector3d & upper_left_deep,
00280         const Vector3d & bottom_right_shallow,
00281         double target_num_vec,
00282         Points3dSTL & points);
00283 
00285 void generateRandomTrajectory(
00286         const Vector3d & upper_left_deep,
00287         const Vector3d & bottom_right_shallow,
00288         int num_stops,
00289         ALIGNED<SE3>::vector & transforms);
00290 
00292 inline void generateLineTrajectory(
00293         const Vector3d & start,
00294         const Vector3d & end,
00295         int num_stops,
00296         ALIGNED<SE3>::vector & transforms){ //T_wcx transforms for each pose
00297     Points3dSTL poses;
00298     Points3dSTL orientations;
00299     Vector3d normalized_direction = (end-start).normalized();
00300     double track_len = (end-start).norm();
00301     double segment_len = track_len / (double) (num_stops - 1);
00302     Vector3d tmp=start;
00303     for(int i=0; i<num_stops; i++){
00304         transforms.push_back(SE3(SO3(0, 0, 0), -tmp));
00305         tmp = (tmp + normalized_direction * segment_len).eval();
00306     }
00307 }
00308 
00309 
00310 template< class T> class SingleVariableWrapper{
00311     protected:
00312         T value_var;
00313     public:
00314         T val() const { return value_var; };
00315 };
00316 
00317 class SpeedAsNaturalNumber : public SingleVariableWrapper<int>{
00318     public:
00319         SpeedAsNaturalNumber(int speed){
00320             value_var = speed;
00321             assert(speed >=0);
00322         }
00323 };
00324 
00325 class TimeAsNaturalNumber : public SingleVariableWrapper<int>{
00326     public:
00327         TimeAsNaturalNumber(int time){
00328             value_var=time;
00329             assert(time >=0);
00330         }
00331 };
00332 
00333 struct SpeedSegment{
00334     SE3 T_c1c2;
00335     SpeedAsNaturalNumber speed_mul;
00336     TimeAsNaturalNumber time_mul;
00337 
00338     SpeedSegment(const SE3& _T_c1c2, SpeedAsNaturalNumber _speed_mul, TimeAsNaturalNumber _time_mul) :
00339             T_c1c2(_T_c1c2), speed_mul(_speed_mul), time_mul(_time_mul) {}
00340 };
00341 
00342 inline void constructTrajectoryFromSpeedSegments(
00343         std::vector<SpeedSegment> speed_segments,
00344         ALIGNED<SE3>::vector& transforms){
00345     transforms.push_back(SE3());
00346     SE3 prevT_wc = SE3();
00347     BOOST_FOREACH(SpeedSegment segment, speed_segments){
00348         SE3 T_c1ct = SE3();
00349         for(int i=0; i < segment.speed_mul.val(); i++){
00350             T_c1ct = T_c1ct * (T_c1ct.inverse() * segment.T_c1c2 * T_c1ct);
00351         }
00352         for(int i=0; i < segment.time_mul.val(); i++){
00353             SE3 T_wc = prevT_wc * (prevT_wc.inverse() * T_c1ct * prevT_wc);
00354             transforms.push_back(T_wc);
00355             prevT_wc = T_wc;
00356         }
00357     }
00358 }
00359 
00360 bool isApprox(double num, double target_num, double error);
00361 
00362 
00364 inline std::string seqencedName(int seq, std::string name){
00365     std::ostringstream s;
00366     s << seq << "_" << name;
00367     return s.str();
00368 }
00369 
00370 inline Vector3d coordFrameConventionLocalToROS(const Vector3d& vec){
00371     return Vector3d(vec(2), -vec(0), vec(1));
00372     //return vec;
00373 }
00374 
00375 inline SE3 coordFrameConventionLocalToROS(const SE3& T){
00376     //coordinate switch done using change of basis from internal to external coordinates(matrix C).
00377     Eigen::Matrix4d C = Eigen::Matrix4d::Zero();
00378     C(0,2)=1; C(1,0)=-1; C(2,1)=1; C(3,3)=1;
00379     Eigen::Matrix4d M = C * T.matrix() * C.inverse();
00380     return SE3(M.block(0,0,3,3), M.block(0,3,3,1));
00381     //return T;
00382 }
00383 
00384 /*------------------------------------------------------------------------------------------*/
00385 //Defunct attempt to automaticly specify allocator for Eigen types.
00386 /*------------------------------------------------------------------------------------------*/
00387 template<class T> struct EigenAllocTraits{
00388     typedef std::allocator<T> alloc;
00389 };
00390 
00391 template<> struct EigenAllocTraits<Vector3d>{
00392     typedef Eigen::aligned_allocator<Vector3d> alloc; 
00393 };
00394 
00395 /*------------------------------------------------------------------------------------------*/
00396 //Stuff for working with ordered index-value pairs
00397 /*------------------------------------------------------------------------------------------*/
00398 
00400 template<class T1, class T2> T1 getFirst(const pair<T1, T2>& pair){
00401     return pair.first;
00402 }
00403 
00405 template<class T1, class T2> T2 getSecond(const pair<T1, T2>& pair){
00406     return pair.second;
00407 }
00408 
00409 
00417 template< class TR, template<class, class> class C, template<class> class A, class T> 
00418         C<TR, typename EigenAllocTraits<TR>::alloc > 
00419         transformF(const C<T, A<T> > & container, TR (*f)(const T&)){
00420     C<TR, typename EigenAllocTraits<TR>::alloc > result;
00421     std::transform(container.begin(), container.end(), std::back_inserter(result), f);
00422     return result;
00423 }
00424 
00425 
00432 template<class C1, class C2> C1 getCommon(const C1 & idx1, const C2 & idx2){ 
00433     C1 result;
00434     typename C1::const_iterator i1 = idx1.begin();
00435     typename C2::const_iterator i2 = idx2.begin();
00436     while(i1 != idx1.end() && i2 != idx2.end()){
00437         if(*i2 < *i1) { ++i2; continue; }
00438         if(*i1 < *i2) { ++i1; continue; }
00439         result.push_back(*i1);
00440         ++i1; ++i2;
00441     }
00442     return result;
00443 }
00444 
00445 
00447 template<template<class, class> class C1, template<class, class> class C2, 
00448         template<class> class Alloc1, template<class> class Alloc2, class TK, class TV>
00449 list<pair<TK, TV>, Alloc2<pair<TK, TV> > > 
00450         indexBy(const C1<TK, Alloc1<TK> >& idx, const C2<TV, Alloc2<TV> >& points){
00451     list<pair<TK, TV>, Alloc2<pair<TK, TV> > > result;
00452     std::transform(idx.begin(), idx.end(), points.begin(), back_inserter(result), 
00453             std::make_pair<TK, TV>);
00454     return result;
00455 }
00456 
00457 
00464 template<template<class, class> class C1, template<class, class> class C2, 
00465         class T1, class T2, template<class> class A1, template<class> class A2>
00466 C1<pair<T1, T2>, A1<pair<T1, T2> > > 
00467         getByIdx(const C1<pair<T1, T2>, A1<pair<T1, T2> > > & pts, const C2<T1, A2<T1> >& idx){
00468     typedef C1<pair<T1, T2>, A1<pair<T1, T2> > > C1I;
00469     C1I result;
00470     typename C1I::const_iterator pi = pts.begin();
00471     BOOST_FOREACH(T1 i, idx){
00472         while(i != pi->first) ++pi;
00473         result.push_back(*pi);
00474     }
00475     return result;
00476 }
00477 
00478 
00480 template<template<class, class, class, class> class M, class V, class K, class Cmp, 
00481     template<class> class Alloc> 
00482 list<pair<K, V>, Alloc<pair<K, V> > > mapToList(const M<K, V, Cmp, Alloc<pair< const K, V> > >& map){
00483     list<pair<K, V>, Alloc<pair<K, V> > > result(map.begin(), map.end());
00484     return result;
00485 }
00486 
00487 
00489 template<template<class, class> class CT, template<class, class> class CS, class T,
00490     template<class> class Alloc>
00491 CT<T, Alloc<T> > switchCont(const CS<T, Alloc<T> > & container){
00492     return CT<T, Alloc<T> >(container.begin(), container.end());
00493 }
00494 
00495 
00497 inline Matrix3d sE3ToE(const SE3 & T){
00498     return (SO3::hat(T.translation()) * T.rotation_matrix()).eval();
00499 }
00500 
00501 
00502 
00504 template<class T> list<T> makeSeq(T first, T last, T step){
00505     list<T> result;
00506     for(T i = first; i <= last; i += step){
00507         result.push_back(i);
00508     }
00509     return result;
00510 }
00511 
00512 template<class T> bool truePred(const T& t){ return true; }
00513 
00515 template<template<class,class> class C1, template<class, class> class C2, class T, class A>
00516         list<T> inverse_idxs(const C1<T, A>& idx, const C2<T, A>& all_idx){
00517     typename C1<T, A>::const_iterator it = idx.begin();
00518     typename C2<T, A>::const_iterator it_all = all_idx.begin();
00519     list<T> inv_idx;
00520     while(it_all != all_idx.end()){
00521         if(*it_all != *it) inv_idx.push_back(*it_all);
00522         else ++it;
00523         ++it_all;
00524     }
00525     return inv_idx;
00526 } 
00527 
00528 
00529 template<template<class,class> class C, class T> 
00530 C<T, std::allocator<T> > mkOneValueCont(const T& value){
00531     C<T, std::allocator<T> > container;
00532     std::back_insert_iterator<C<T, std::allocator<T> > > it = back_inserter(container);
00533     it = value;
00534     return container;
00535 }
00536 
00537 template<template<class,class> class C, class T> 
00538 C<T, Eigen::aligned_allocator<T> > mkOneValueContAA(const T& value){
00539     C<T, Eigen::aligned_allocator<T> > container;
00540     //std::back_insert_iterator<C<T, Eigen::aligned_allocator<T> > > it = back_inserter(container);
00541     //it = value;
00542     container.push_back(value);
00543     return container;
00544 }
00545 
00546 inline geometry_msgs::Pose getPoseFromTcwInSE3(const SE3& T_cw){
00547     geometry_msgs::Pose pose;
00548 
00549     Vector3d t = T_cw.translation();
00550     geometry_msgs::Point point;
00551     point.x=t(0);
00552     point.y=t(1);
00553     point.z=t(2);
00554     pose.position = point;
00555 
00556     geometry_msgs::Quaternion quat;
00557     Eigen::Quaterniond q = T_cw.unit_quaternion();
00558     quat.x=q.x();
00559     quat.y=q.y();
00560     quat.z=q.z();
00561     quat.w=q.w();
00562     pose.orientation = quat;
00563 
00564     return pose;
00565 }
00566 
00567 
00568 /*------------------------------------------------------------------------------------------*/
00570 template<class T> vector<T> getArrayIdices(const vector<T>& array, const vector<int>& idxs){
00571     typename vector<int>::const_iterator it = idxs.begin();
00572     vector<T> result;
00573     while(it!=idxs.end()){
00574         result.push_back(array[*it]);
00575         ++it;
00576     }
00577     return result;
00578 }
00579 
00581 template<class T> cv::Mat getArrayIdices(const cv::Mat& mat, const vector<int>& idxs){
00582     cv::Mat result(0, mat.size().width, mat.type());
00583     result.reserve(idxs.size());
00584     typename vector<int>::const_iterator it = idxs.begin();
00585     while(it!=idxs.end()){
00586         result.push_back(mat.row(*it));
00587         ++it;
00588     }
00589     return result;
00590 }
00591 
00592 /*------------------------------------------------------------------------------------------*/
00593 
00594 template<template<class T, class = std::allocator<T> > class C, class T> C<T> 
00595 mkContainer(const T& val){
00596     C<T> container;
00597     container.push_back(val);
00598     return container;
00599 }
00600 
00601 inline Vector2d c1PixelToc2Pixel(const SE3& T_c1c2, const Vector2d& pixel1){
00602     Vector3d v = T_c1c2 * PanoImCoord::fromPixel(pixel1).getHomogenous();
00603     return PanoImCoord::fromHomogenous(v).getPixel();
00604 }
00605 
00606 
00607 /*------------------------------------------------------------------------------------------*/
00608 
00609 
00610 
00611 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines


pose_estimation
Author(s): Jiri Divis/jiridivis@gmail.com
autogenerated on Wed Mar 27 2013 21:00:12