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...