tools.h
Go to the documentation of this file.
00001 #ifndef TOOLS
00002 #define TOOLS
00003 
00004 #include <ros/ros.h>
00005 #include <pcl/filters/voxel_grid.h>
00006 #include <pcl/filters/passthrough.h>
00007 #include <pcl/common/common.h>
00008 #include <image_geometry/stereo_camera_model.h>
00009 #include <sensor_msgs/image_encodings.h>
00010 #include <sensor_msgs/Image.h>
00011 #include <cv_bridge/cv_bridge.h>
00012 #include <nav_msgs/Odometry.h>
00013 #include "vertex.h"
00014 
00015 namespace enc = sensor_msgs::image_encodings;
00016 
00017 using namespace std;
00018 using namespace cv;
00019 
00020 namespace tools
00021 {
00022 
00023 class Tools
00024 {
00025 
00026 public:
00027 
00028   typedef pcl::PointXYZRGB        Point;
00029   typedef pcl::PointCloud<Point>  PointCloud;
00030 
00031   // Filter parameters
00032   struct FilterParams
00033   {
00034     double x_filter_min;
00035     double x_filter_max;
00036     double y_filter_min;
00037     double y_filter_max;
00038     double z_filter_min;
00039     double z_filter_max;
00040     double x_voxel_size;
00041     double y_voxel_size;
00042     double z_voxel_size;
00043 
00044     // Default settings
00045     FilterParams () {
00046       x_filter_min  = -2.0;
00047       x_filter_max  = 2.0;
00048       y_filter_min  = -2.0;
00049       y_filter_max  = 2.0;
00050       z_filter_min  = 0.2;
00051       z_filter_max  = 2.0;
00052       x_voxel_size  = 0.005;
00053       y_voxel_size  = 0.005;
00054       z_voxel_size  = 0.4;
00055     }
00056   };
00057 
00062   static Eigen::Isometry3d tfToIsometry(tf::Transform in)
00063   {
00064     tf::Vector3 t_in = in.getOrigin();
00065     tf::Quaternion q_in = in.getRotation();
00066     Eigen::Vector3d t_out(t_in.x(), t_in.y(), t_in.z());
00067     Eigen::Quaterniond q_out;
00068     q_out.setIdentity();
00069     q_out.x() = q_in.x();
00070     q_out.y() = q_in.y();
00071     q_out.z() = q_in.z();
00072     q_out.w() = q_in.w();
00073     Eigen::Isometry3d out = (Eigen::Isometry3d)q_out;
00074     out.translation() = t_out;
00075     return out;
00076   }
00077 
00082   static Eigen::Matrix4f tfToMatrix4f(tf::Transform in)
00083   {
00084     Eigen::Matrix4f out;
00085 
00086     tf::Vector3 t_in  = in.getOrigin();
00087     tf::Matrix3x3 rot = in.getBasis();
00088     tf::Vector3 r0    = rot.getRow(0);
00089     tf::Vector3 r1    = rot.getRow(1);
00090     tf::Vector3 r2    = rot.getRow(2);
00091 
00092     out << r0.x(), r0.y(), r0.z(), t_in.x(),
00093            r1.x(), r1.y(), r1.z(), t_in.y(),
00094            r2.x(), r2.y(), r2.z(), t_in.z(),
00095            0,     0,     0,     1;
00096 
00097     return out;
00098   }
00099 
00104   static tf::Transform isometryToTf(Eigen::Isometry3d in)
00105   {
00106     Eigen::Vector3d t_in = in.translation();
00107     Eigen::Quaterniond q_in = (Eigen::Quaterniond)in.rotation();
00108     tf::Vector3 t_out(t_in.x(), t_in.y(), t_in.z());
00109     tf::Quaternion q_out(q_in.x(), q_in.y(), q_in.z(), q_in.w());
00110     tf::Transform out(q_out, t_out);
00111     return out;
00112   }
00113 
00118   static tf::Transform matrix4fToTf(Eigen::Matrix4f in)
00119   {
00120     tf::Vector3 t_out;
00121     t_out.setValue(static_cast<double>(in(0,3)),static_cast<double>(in(1,3)),static_cast<double>(in(2,3)));
00122 
00123     tf::Matrix3x3 tf3d;
00124     tf3d.setValue(static_cast<double>(in(0,0)), static_cast<double>(in(0,1)), static_cast<double>(in(0,2)),
00125                   static_cast<double>(in(1,0)), static_cast<double>(in(1,1)), static_cast<double>(in(1,2)),
00126                   static_cast<double>(in(2,0)), static_cast<double>(in(2,1)), static_cast<double>(in(2,2)));
00127 
00128     tf::Quaternion q_out;
00129     tf3d.getRotation(q_out);
00130     tf::Transform out(q_out, t_out);
00131     return out;
00132   }
00133 
00139   static tf::Transform odomTotf(nav_msgs::Odometry odom_msg)
00140   {
00141     // Get the data
00142     double tx = odom_msg.pose.pose.position.x;
00143     double ty = odom_msg.pose.pose.position.y;
00144     double tz = odom_msg.pose.pose.position.z;
00145 
00146     double qx = odom_msg.pose.pose.orientation.x;
00147     double qy = odom_msg.pose.pose.orientation.y;
00148     double qz = odom_msg.pose.pose.orientation.z;
00149     double qw = odom_msg.pose.pose.orientation.w;
00150 
00151     // Sanity check
00152     if(qx == 0.0 && qy == 0.0 && qz == 0.0 && qw == 0.0)
00153     {
00154       tf::Transform odom;
00155       odom.setIdentity();
00156       return odom;
00157     }
00158     else
00159     {
00160       tf::Vector3 tf_trans(tx, ty, tz);
00161       tf::Quaternion tf_q (qx, qy, qz, qw);
00162       tf::Transform odom(tf_q, tf_trans);
00163       return odom;
00164     }
00165   }
00166 
00173   static bool imgMsgToMat(sensor_msgs::Image l_img_msg,
00174                           sensor_msgs::Image r_img_msg,
00175                           Mat &l_img, Mat &r_img)
00176   {
00177     // Convert message to Mat
00178     try
00179     {
00180       l_img = (cv_bridge::toCvCopy(l_img_msg, enc::BGR8))->image;
00181       r_img = (cv_bridge::toCvCopy(r_img_msg, enc::BGR8))->image;
00182     }
00183     catch (cv_bridge::Exception& e)
00184     {
00185       ROS_ERROR("[StereoSlam:] cv_bridge exception: %s", e.what());
00186       return false;
00187     }
00188     return true;
00189   }
00190 
00197   static bool getCameraModel(sensor_msgs::CameraInfo l_info_msg,
00198                              sensor_msgs::CameraInfo r_info_msg,
00199                              image_geometry::StereoCameraModel &stereo_camera_model,
00200                              Mat &camera_matrix)
00201   {
00202     // Get the stereo camera model
00203     stereo_camera_model.fromCameraInfo(l_info_msg, r_info_msg);
00204 
00205     // Get the projection/camera matrix
00206     const Mat P(3,4, CV_64FC1, const_cast<double*>(l_info_msg.P.data()));
00207     camera_matrix = P.colRange(Range(0,3)).clone();
00208 
00209     // Are the images scaled?
00210     int binning_x = l_info_msg.binning_x;
00211     int binning_y = l_info_msg.binning_y;
00212     if (binning_x > 1 || binning_y > 1)
00213     {
00214       camera_matrix.at<double>(0,0) = camera_matrix.at<double>(0,0) / binning_x;
00215       camera_matrix.at<double>(0,2) = camera_matrix.at<double>(0,2) / binning_x;
00216       camera_matrix.at<double>(1,1) = camera_matrix.at<double>(1,1) / binning_y;
00217       camera_matrix.at<double>(1,2) = camera_matrix.at<double>(1,2) / binning_y;
00218     }
00219   }
00220 
00225   static tf::Transform getVertexPose(slam::Vertex* v)
00226   {
00227     Eigen::Isometry3d pose_eigen = v->estimate();
00228     tf::Transform pose_tf = tools::Tools::isometryToTf(pose_eigen);
00229     return pose_tf;
00230   }
00231 
00237   static double poseDiff(tf::Transform pose_1, tf::Transform pose_2)
00238   {
00239     tf::Vector3 d = pose_1.getOrigin() - pose_2.getOrigin();
00240     return sqrt(d.x()*d.x() + d.y()*d.y() + d.z()*d.z());
00241   }
00242 
00248   static bool sortByDistance(const pair<int, double> d1, const pair<int, double> d2)
00249   {
00250     return (d1.second < d2.second);
00251   }
00252 
00257   static string isometryToString(Eigen::Isometry3d m)
00258   {
00259     char result[80];
00260     memset(result, 0, sizeof(result));
00261     Eigen::Vector3d xyz = m.translation();
00262     Eigen::Vector3d rpy = m.rotation().eulerAngles(0, 1, 2);
00263     snprintf(result, 79, "%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f",
00264         xyz(0), xyz(1), xyz(2),
00265         rpy(0) * 180/M_PI, rpy(1) * 180/M_PI, rpy(2) * 180/M_PI);
00266     return string(result);
00267   }
00268 
00273   static void showTf(tf::Transform input)
00274   {
00275     tf::Vector3 tran = input.getOrigin();
00276     tf::Matrix3x3 rot = input.getBasis();
00277     tf::Vector3 r0 = rot.getRow(0);
00278     tf::Vector3 r1 = rot.getRow(1);
00279     tf::Vector3 r2 = rot.getRow(2);
00280     ROS_INFO_STREAM("[StereoSlam:]\n" << r0.x() << ", " << r0.y() << ", " << r0.z() << ", " << tran.x() <<
00281                     "\n" << r1.x() << ", " << r1.y() << ", " << r1.z() << ", " << tran.y() <<
00282                     "\n" << r2.x() << ", " << r2.y() << ", " << r2.z() << ", " << tran.z());
00283   }
00284 
00289   static void filterPointCloud(PointCloud::Ptr cloud, tools::Tools::FilterParams params)
00290   {
00291     // NAN and limit filtering
00292       pcl::PassThrough<Point> pass;
00293 
00294       // X-filtering
00295       pass.setFilterFieldName("x");
00296       pass.setFilterLimits(params.x_filter_min, params.x_filter_max);
00297       pass.setInputCloud(cloud);
00298       pass.filter(*cloud);
00299 
00300       // Y-filtering
00301       pass.setFilterFieldName("y");
00302       pass.setFilterLimits(params.y_filter_min, params.y_filter_max);
00303       pass.setInputCloud(cloud);
00304       pass.filter(*cloud);
00305 
00306       // Z-filtering
00307       pass.setFilterFieldName("z");
00308       pass.setFilterLimits(params.z_filter_min, params.z_filter_max);
00309       pass.setInputCloud(cloud);
00310       pass.filter(*cloud);
00311 
00312       // Downsampling using voxel grid
00313       pcl::VoxelGrid<PointRGB> grid;
00314       grid.setLeafSize(params.x_voxel_size,
00315                        params.y_voxel_size,
00316                        params.z_voxel_size);
00317       grid.setDownsampleAllData(true);
00318       grid.setInputCloud(cloud);
00319       grid.filter(*cloud);
00320 
00321       /*
00322       // Remove isolated points
00323       pcl::StatisticalOutlierRemoval<PointRGB> sor;
00324       sor.setInputCloud (cloud);
00325       sor.setMeanK (50);
00326       sor.setStddevMulThresh (1.0);
00327       sor.filter(*cloud);
00328       */
00329   }
00330 };
00331 
00332 } // namespace
00333 
00334 #endif // TOOLS


stereo_slam
Author(s): Pep Lluis Negre
autogenerated on Thu Aug 27 2015 15:24:22