15 #include <pcl/common/io.h> 
   17 #include <pcl/common/transforms.h> 
   28 #include <boost/bind.hpp> 
   63   , plot_all_movements(true)
 
   64   , calibration_wanted(true)
 
   69   , add_to_data_set(false)
 
   86   latest_to_draw.reset();
 
   92   double pos_x, 
double pos_y, 
double pos_z
 
   93   , 
double phi, 
double theta, 
double psi
 
   96   const double width = 20;
 
   97   std::cout << std::endl
 
   98             << std::setw( width ) << std::left << name << 
":" << std::endl
 
  100             << std::setw( width ) << std::right << 
"x" << 
" " << pos_x << std::endl
 
  101             << std::setw( width ) << std::right << 
"y" << 
" " << pos_y << std::endl
 
  102             << std::setw( width ) << std::right << 
"z" << 
" " << pos_z << std::endl
 
  103             << std::setw( width ) << std::right << 
"phi" << 
" " << 
math::c_RAD_TO_DEG * phi << std::endl
 
  104             << std::setw( width ) << std::right << 
"theta" << 
" " << 
math::c_RAD_TO_DEG * theta << std::endl
 
  105             << std::setw( width ) << std::right << 
"psi" << 
" " << 
math::c_RAD_TO_DEG * psi << std::endl
 
  111   Eigen::Affine3d* transformation_to_print
 
  114   print(&transformation_to_print->matrix(), name);
 
  119   Eigen::Matrix4d* transformation_to_print
 
  122   double d_x, d_y, d_z, phi, theta, psi;
 
  123   pcl::getTranslationAndEulerAngles(
 
  124     Eigen::Affine3d(*transformation_to_print), d_x, d_y, d_z, phi, theta, psi);
 
  125   print(d_x, d_y, d_z, phi, theta, psi, name);
 
  130   const std::string& name)
 
  133   return (stat (name.c_str(), &buffer) == 0);
 
  140   , std::string filename)
 
  142   std::string folder = 
"../log/plots/";
 
  143   std::string extension = 
".csv";
 
  145   std::stringstream plot_file_ss;
 
  146   plot_file_ss << folder << filename << extension;
 
  147   std::string plot_file_s = plot_file_ss.str();
 
  149   std::fstream plot_file;
 
  151   if (exists(plot_file_s)) {
 
  154       , std::fstream::in | std::fstream::out | std::fstream::app);
 
  159       , std::fstream::in | std::fstream::out | std::fstream::app);
 
  160     plot_file << header << std::endl;
 
  162   plot_file << data << std::endl;
 
  170   , pointCloud::Ptr latest)
 
  172   Eigen::Affine3d T_movement;
 
  208   return T_movement.matrix();
 
  214   , pointCloud::Ptr latest
 
  215   , 
double* icp_fitness_score
 
  218   Eigen::Matrix4d transformationBetweenScans;
 
  220   pcl::copyPointCloud(*last, *last_to_draw);
 
  227   if (bilateral_filtering) {
 
  232   if (calculate_normals || covariance_sampling || initial_aligning) {
 
  236     if (covariance_sampling) {
 
  241     if (initial_aligning) {
 
  242       pcl::PointCloud< pcl::FPFHSignature33 >::Ptr last_descriptors
 
  244       pcl::PointCloud< pcl::FPFHSignature33 >::Ptr latest_descriptors
 
  248                                    , latest, latest_descriptors);
 
  252   pcl::copyPointCloud(*last, *last_to_draw);
 
  256     transformationBetweenScans = 
filter::icp(last, latest, icp_fitness_score, iterations);
 
  258   case E_LEVENBERG_MARQUARDT:
 
  259     transformationBetweenScans = 
filter::icpLM(last, latest, icp_fitness_score, iterations);
 
  262   return transformationBetweenScans;
 
  266   pointCloud::Ptr first
 
  267   , pointCloud::Ptr second
 
  276   const unsigned int iterate_once = 0;
 
  277   double icp_fitness_score = 0.0;
 
  279   Eigen::Affine3d T_mounting_pose;
 
  280   pcl::getTransformation(pos_x, pos_y, pos_z, phi, theta, psi, T_mounting_pose);
 
  284   pcl::copyPointCloud(*first, *temp_first);
 
  286   pcl::copyPointCloud(*second, *temp_second);
 
  289   pcl::transformPointCloud(*temp_first, *temp_first, T_mounting_pose);
 
  290   pcl::transformPointCloud(*temp_second, *temp_second, T_mounting_pose);
 
  293   Eigen::Affine3d T_movement = Eigen::Affine3d(getMovementFrom(temp_first, temp_first));
 
  294   pcl::transformPointCloud(*temp_first, *temp_first, T_movement);
 
  297   getScanTransformationFrom(
 
  302   return icp_fitness_score;
 
  312   const std::vector<last_and_latest> *curr_data_set
 
  313     = 
reinterpret_cast<const std::vector<last_and_latest>* 
>(data);
 
  314   unsigned int nr_scan_pairs = curr_data_set->size();
 
  316   double score_sum = 0.0;
 
  318   for (
int i = 0; i < nr_scan_pairs; ++i) {
 
  320     double icp_fitness_score
 
  321       = evaluateICPFitnessScore(
 
  322           curr_data_set->at(i).first, curr_data_set->at(i).second
 
  323           , par[0], par[1], par[2], par[3], par[4], par[5]);
 
  325     fvec[i] = icp_fitness_score;
 
  326     if (fvec[i] > worst_score) {
 
  328       worst_score = fvec[i];
 
  330     score_sum += fvec[i];
 
  332     std::string pose_header = 
"data_pair;d_x;d_y;d_z;phi;theta;psi;icp_fitness_score";
 
  333     std::stringstream pose;
 
  335          << par[0] << 
";" << par[1] << 
";" << par[2] << 
";" 
  336          << par[3] << 
";" << par[4] << 
";" << par[5] << 
";" 
  337          << icp_fitness_score;
 
  338     plot(pose_header, pose.str(), 
"estimated_mounting_pose");
 
  340   std::cout << ++
iterations << 
"\r" << std::flush;
 
  341   avr_cal_err = score_sum / nr_scan_pairs;
 
  344 const pointCloud::Ptr
 
  347   return latest_to_draw;
 
  350 const pointCloud::Ptr
 
  359   downsampling = new_state;
 
  371   bilateral_filtering = new_state;
 
  377   return bilateral_filtering;
 
  383   calculate_normals = new_state;
 
  389   return calculate_normals;
 
  395   covariance_sampling = new_state;
 
  401   return covariance_sampling;
 
  407   initial_aligning = new_state;
 
  413   return initial_aligning;
 
  419   add_to_data_set = 
true;
 
  431   std::swap(data_set[worst_pair], data_set.back());
 
  437   unsigned int scans_between_last_and_latest)
 
  439   this->scans_between_last_and_latest = scans_between_last_and_latest;
 
  446   if (plot_all_movements) {
 
  447     if (0 == scan_counter) {
 
  448       if (cloud_to_draw && !cloud_to_draw->points.empty()) {
 
  449         pcl::copyPointCloud(*cloud_to_draw, *last);
 
  455     else if (scans_between_last_and_latest == scan_counter) {
 
  456       if (cloud_to_draw && !cloud_to_draw->points.empty()) {
 
  457         pcl::copyPointCloud(*cloud_to_draw, *latest);
 
  460         double d_x, d_y, d_z, d_phi, d_theta, d_psi;
 
  461         pcl::getTranslationAndEulerAngles(
 
  462           Eigen::Affine3d(getMovementFrom(last, latest)), d_x, d_y, d_z, d_phi, d_theta, d_psi);
 
  463         if (sampled_scans == 170 || sampled_scans == 200 || sampled_scans == 75
 
  464             || sampled_scans == 140 || sampled_scans == 60 || sampled_scans == 190) {
 
  467           pcl::copyPointCloud(*last, *temp_last);
 
  468           pcl::copyPointCloud(*latest, *temp_latest);
 
  516   if (nr_scan_pairs >= nr_unknowns && calibration_wanted) {
 
  519       mounting_pose[0] = pos_x;
 
  520       mounting_pose[1] = pos_y;
 
  521       mounting_pose[2] = pos_z;
 
  522       mounting_pose[3] = phi;
 
  523       mounting_pose[4] = theta;
 
  524       mounting_pose[5] = psi;
 
  539     printf( 
"Fitting:\n" );
 
  540     lmmin( nr_unknowns, mounting_pose, nr_scan_pairs, (
const void*)&data_set
 
  542            , &control, &status );
 
  544     std::cout << 
"Iterations: " << status.
nfev << std::endl;
 
  547       mounting_pose[0], mounting_pose[1], mounting_pose[2]
 
  548       , mounting_pose[3], mounting_pose[4], mounting_pose[5]
 
  551     plot_all_movements = 
false;
 
  554     if (avr_cal_err > 10.0) {
 
  557       Eigen::Affine3d T_new_init;
 
  558       Eigen::Affine3d T_scan_pairs;
 
  559       double smallest_score = 100.0;
 
  560       double scan_pairs_score = 100.0;
 
  561       for (
unsigned int i = 0; i < nr_scan_pairs; ++i) {
 
  562         T_scan_pairs = getScanTransformationFrom(
 
  564                          , data_set.at(i).second
 
  567         if (scan_pairs_score < smallest_score) {
 
  568           smallest_score = scan_pairs_score;
 
  569           T_new_init = T_scan_pairs;
 
  572       pcl::getTranslationAndEulerAngles(
 
  574         , mounting_pose[0], mounting_pose[1], mounting_pose[2]
 
  575         , mounting_pose[3], mounting_pose[4], mounting_pose[5]);
 
  577       print(&T_new_init, 
"new-init");
 
  579       calibration_wanted = 
false;
 
double epsilon
Step used to calculate the Jacobian. 
 
static bool bilateral_filtering
When true: bilateral-filtering is used (computes fpfh-features!) 
 
Declarations for Levenberg-Marquardt minimization. 
 
void print(double pos_x, double pos_y, double pos_z, double phi, double theta, double psi, std::string name="Transformation")
Print the given transformation on command-line-interface. 
 
void bilateralFiltering(pointCloud::Ptr organized_cloud)
Use bilateral filtering. 
 
void resetDataSet(void)
Reset/Remove all point-cloud-pairs from the data-set. 
 
Collection of input parameters for fit control. 
 
static void getMountingPose(const double *par, int m_dat, const void *data, double *fvec, int *info)
Optimized the mounting-pose as part of the Levenberg-Marquardt. 
 
const pointCloud::Ptr getLastCloud(void) const 
Returns the last stable cloud. 
 
static bool exists(const std::string &name)
Checks if the given filename-at-path exists. 
 
This file implements all the filter and registration methods for point-cloud data using wrappers for ...
 
bool getInitialAligning(void)
Retrieves if the initial alignment is activated. 
 
double pos_x
Class-wide latest position (this is altered after optimization) 
 
static bool initial_aligning
When true: Initial Alignment is calculated using Sample-Consensus (untested) 
 
bool getBilateralFiltering(void)
Retrieves if the bilateral filter is activated. 
 
static e_registrationMethod ICPMethod
Selector for the calibration-method (not supported atm) 
 
static Eigen::Matrix4d getMovementFrom(pointCloud::Ptr last, pointCloud::Ptr latest)
Retrieves the movement of the Navigation-Data between the last and latest point-cloud. 
 
e_registrationMethod
Selector for the calibration-method (not supported atm) 
 
This file introduces the class LaserNAVCalibration which is used to calibrate the laser-pose with nav...
 
Eigen::Matrix4d icpLM(const pointCloud::Ptr source, const pointCloud::Ptr target, double *fitness_score, const double iterations)
Calls the pcl iterativeClosestPoint-algorithm levenberg-marquardt alternative (internally) ...
 
std::pair< pointCloud::Ptr, pointCloud::Ptr > last_and_latest
Typedef for shorter call (used as data-set for the levenberg-marquardt data) 
 
pcl::PointCloud< pcl::PointNormal > pointCloud
Typedef for shorter call of point-cloud-pointer-type. 
 
const lm_control_struct lm_control_double
Preset (and recommended) control parameter settings. 
 
Collection of output parameters for status info. 
 
void setCovarianceSampling(bool new_state)
Sets the covariance-sampling of point-normals. 
 
virtual ~LaserNAVCalibration()
Virtual std. dtor. 
 
int verbosity
Controls the ouput verbosity. 
 
void setInitialAligning(bool new_state)
Sets the initial alignment of point-normals. 
 
static double worst_score
Holds the worst ICP-fitness-score for the according point-cloud-pair. 
 
pcl::PointCloud< pcl::FPFHSignature33 >::Ptr fastPointFeatureHistogram(const pointCloud::Ptr input)
Extracts all (F)PFHs. 
 
virtual void update(pointCloud::Ptr cloud_to_draw)
Updates the mounting-pose using Levenberg-Marquardt non-linear optimization. 
 
void setBilateralFiltering(bool new_state)
Sets the bilateral filter. 
 
static unsigned int scans_between_last_and_latest
Number of scans between point-cloud-pairs (those are simply dropped) 
 
void setDownsampling(bool new_state)
Sets the filter voxel-grid. 
 
static bool downsampling
When true: all point-clouds are downsampled using Voxel-Grids. 
 
bool getCalculateNormals(void)
Retrieves if the bilateral filter is activated. 
 
void covarianceDownsampling(pointCloud::Ptr cloud)
Use covariances for downsampling. 
 
void computeSurfaceNormals(pointCloud::Ptr cloud)
Compute the surface normals. 
 
bool getDownsampling(void)
Retrieves if the voxel-grid filter is activated. 
 
static bool calculate_normals
When true: calculate normals (basis for covariance-sampling and initial-alignment) ...
 
static void plot(std::string header, std::string data, std::string filename)
Plot the given header + data to file. 
 
static size_t worst_pair
Index of the point-cloud-pair with the worst ICP-fitness-score. 
 
static Eigen::Matrix4d getScanTransformationFrom(pointCloud::Ptr last, pointCloud::Ptr latest, double *icp_fitness_score, double iterations)
Retrieves the transformation from last to latest point-cloud. 
 
void downsample(pointCloud::Ptr cloud)
Simple Voxel-Grid downsampling. 
 
LaserNAVCalibration(double pos_x=0.0, double pos_y=0.0, double pos_z=0.0, double phi=math::c_DEG_TO_RAD *0.0, double theta=math::c_DEG_TO_RAD *0.0, double psi=math::c_DEG_TO_RAD *0.0)
std. ctor. 
 
bool getCovarianceSampling(void)
Retrieves if the covariance-sampling is activated. 
 
void setCalculateNormals(bool new_state)
Sets the calculation of point-normals. 
 
static double avr_cal_err
Mean of the summed ICP-fitness-score's (updated each iteration) 
 
void lmmin(int n, double *x, int m, const void *data, void(*evaluate)(const double *par, int m_dat, const void *data,                                                                                                               double *fvec, int *userbreak), const lm_control_struct *C, lm_status_struct *S)
Levenberg-Marquardt minimization. 
 
const pointCloud::Ptr getLatestCloud(void) const 
Returns the latest stable cloud. 
 
Eigen::Matrix4d initialAlignment(pointCloud::Ptr source, pcl::PointCloud< pcl::FPFHSignature33 >::Ptr source_descriptors, pointCloud::Ptr target, pcl::PointCloud< pcl::FPFHSignature33 >::Ptr target_descriptors)
Aligns the point-clouds initially using Sample Consensus. 
 
void optimizeDataSet(void)
Deletes the worst-pair according to its ICP-fitness-score. 
 
Eigen::Matrix4d icp(const pointCloud::Ptr source, const pointCloud::Ptr target, double *fitness_score, const double iterations)
Calls the pcl iterativeClosestPoint-algorithm. 
 
static double evaluateICPFitnessScore(pointCloud::Ptr first, pointCloud::Ptr second, double pos_x, double pos_y, double pos_z, double phi, double theta, double psi)
 
void addToDataSet(void)
Sets the boolean to add the point-clouds at the active index to the data-set-pairs. 
 
int nfev
actual number of iterations. 
 
static pointCloud::Ptr latest_to_draw
Cloud-ptr that stores the latest point-cloud that will be drawn (stable, switched after registration-...
 
static bool covariance_sampling
When true: Samples the point-cloud using covariance-matrices. 
 
void setScansBetweenLastAndLatest(unsigned int scans_between_last_and_latest)
Sets the number of scans to skip between one registration. 
 
static pointCloud::Ptr last_to_draw
Cloud-ptr that stores the last point-cloud that will be drawn (stable, switched after registration-pr...