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
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
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
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
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
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
00203 stereo_camera_model.fromCameraInfo(l_info_msg, r_info_msg);
00204
00205
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
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
00292 pcl::PassThrough<Point> pass;
00293
00294
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
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
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
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
00323
00324
00325
00326
00327
00328
00329 }
00330 };
00331
00332 }
00333
00334 #endif // TOOLS