Go to the documentation of this file.00001 #include <fstream>
00002 #include <memory>
00003
00004 #include "ros/ros.h"
00005 #include "ros/console.h"
00006
00007 #include "pointmatcher/PointMatcher.h"
00008
00009 #include "pointmatcher_ros/point_cloud.h"
00010 #include "pointmatcher_ros/transform.h"
00011 #include "pointmatcher_ros/get_params_from_server.h"
00012 #include "pointmatcher_ros/ros_logger.h"
00013
00014 #include "geometry_msgs/PoseWithCovarianceStamped.h"
00015 #include "nav_msgs/Odometry.h"
00016 #include "tf/transform_broadcaster.h"
00017 #include "tf_conversions/tf_eigen.h"
00018 #include "tf/transform_listener.h"
00019
00020 using namespace std;
00021 using namespace PointMatcherSupport;
00022
00023 class ExportVtk
00024 {
00025 typedef PointMatcher<float> PM;
00026 typedef PM::DataPoints DP;
00027
00028 ros::NodeHandle& n;
00029
00030 ros::Subscriber cloudSub;
00031 const string cloudTopic;
00032 const string mapFrame;
00033 const bool recordOnce;
00034 const string outputPath;
00035 string outputPrefix;
00036 string outputExtension;
00037
00038 tf::TransformListener tf_listener;
00039 std::shared_ptr<PM::Transformation> transformation;
00040
00041 void validateOutputExtension();
00042
00043 public:
00044 ExportVtk(ros::NodeHandle& n);
00045 void gotCloud(const sensor_msgs::PointCloud2& cloudMsg);
00046 };
00047
00048 ExportVtk::ExportVtk(ros::NodeHandle& n):
00049 n(n),
00050 cloudTopic(getParam<string>("cloudTopic", "/static_point_cloud")),
00051 mapFrame(getParam<string>("mapFrameId", "/map")),
00052 recordOnce(getParam<bool>("recordOnce", "false")),
00053 outputPath(getParam<string>("outputPath", "")),
00054 outputPrefix(getParam<string>("outputPrefix", "")),
00055 outputExtension(getParam<string>("outputExtension", ".vtk")),
00056 transformation(PM::get().TransformationRegistrar.create("RigidTransformation"))
00057 {
00058 if(outputPrefix.empty())
00059 {
00060 outputPrefix = cloudTopic;
00061 }
00062 validateOutputExtension();
00063
00064
00065 cloudSub = n.subscribe(cloudTopic, 100, &ExportVtk::gotCloud, this);
00066
00067
00068 }
00069
00070 void ExportVtk::validateOutputExtension()
00071 {
00072 if(!outputExtension.empty() && outputExtension.at(0) != '.')
00073 {
00074 outputExtension = "." + outputExtension;
00075 }
00076
00077 std::locale loc;
00078 for(std::string::size_type i=0; i < outputExtension.length(); ++i)
00079 {
00080 outputExtension[i] = std::tolower(outputExtension[i], loc);
00081 }
00082
00083 if(outputExtension.compare(".csv") != 0 &&
00084 outputExtension.compare(".vtk") != 0 &&
00085 outputExtension.compare(".ply") != 0 &&
00086 outputExtension.compare(".pcd") != 0)
00087 {
00088 outputExtension = ".vtk";
00089 }
00090 }
00091
00092
00093 void ExportVtk::gotCloud(const sensor_msgs::PointCloud2& cloudMsgIn)
00094 {
00095 const DP inCloud(PointMatcher_ros::rosMsgToPointMatcherCloud<float>(cloudMsgIn));
00096
00097 try
00098 {
00099 const PM::TransformationParameters tr(PointMatcher_ros::transformListenerToEigenMatrix<float>(tf_listener, mapFrame, cloudMsgIn.header.frame_id, cloudMsgIn.header.stamp));
00100
00101 const DP outCloud(transformation->compute(inCloud, tr));
00102
00103 if (outCloud.features.cols() == 0)
00104 {
00105 ROS_ERROR("I found no good points in the cloud");
00106 return;
00107 }
00108 else
00109 {
00110 ROS_INFO("Saving cloud");
00111 }
00112
00113 stringstream nameStream;
00114 if(outputPath.empty())
00115 {
00116 nameStream << ".";
00117 }
00118 else
00119 {
00120 nameStream << outputPath;
00121 }
00122 nameStream << outputPrefix << "_" << cloudMsgIn.header.seq << outputExtension;
00123
00124 outCloud.save(nameStream.str());
00125 if(recordOnce)
00126 {
00127 ros::shutdown();
00128 }
00129 }
00130 catch (tf::ExtrapolationException e)
00131 {
00132 ROS_WARN("Still build tf tree, skipping that scan");
00133 }
00134 }
00135
00136
00137 int main(int argc, char **argv)
00138 {
00139 ros::init(argc, argv, "pointCloudToVtk_node");
00140 ros::NodeHandle n;
00141 ExportVtk exporter(n);
00142 ros::spin();
00143
00144
00145 while(ros::ok()){}
00146
00147 return 0;
00148 }