00001 #include "laser_icp_alg_node.h"
00002
00003 LaserIcpAlgNode::LaserIcpAlgNode(void) :
00004 algorithm_base::IriBaseAlgorithm<LaserIcpAlgorithm>()
00005 {
00006 ROS_INFO("Laser ICP: Warming up..");
00007
00008
00009
00010
00011
00012
00013
00014
00015 this->get_relative_pose_server_ = this->public_node_handle_.advertiseService("get_relative_pose", &LaserIcpAlgNode::get_relative_poseCallback, this);
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 initParams();
00026
00027
00028
00029 input_.laser[0] = 0.0;
00030 input_.laser[1] = 0.0;
00031 input_.laser[2] = 0.0;
00032
00033 }
00034
00035 LaserIcpAlgNode::~LaserIcpAlgNode(void)
00036 {
00037
00038 }
00039
00040 void LaserIcpAlgNode::mainNodeThread(void)
00041 {
00042
00043
00044
00045
00046
00047
00048
00049 }
00050
00051
00052
00053
00054 bool LaserIcpAlgNode::get_relative_poseCallback(
00055 iri_laser_icp::GetRelativePose::Request &req,
00056 iri_laser_icp::GetRelativePose::Response &res)
00057 {
00058 ROS_DEBUG("Laser ICP: New Request");
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 input_.min_reading = std::max(float(min_laser_range_), std::min(req.scan_ref.range_min,req.scan_sens.range_min));
00070 input_.max_reading = std::min(float(max_laser_range_), std::max(req.scan_ref.range_max,req.scan_sens.range_max));
00071 laserScanToLDP(req.scan_ref, ref_ldp_scan_);
00072 laserScanToLDP(req.scan_sens, sens_ldp_scan_);
00073
00074
00075 input_.first_guess[0] = req.prior_d.position.x;
00076 input_.first_guess[1] = req.prior_d.position.y;
00077 if (req.prior_d.orientation.x != 0 || req.prior_d.orientation.y != 0 || req.prior_d.orientation.z != 0 || req.prior_d.orientation.w != 0)
00078 input_.first_guess[2] = tf::getYaw(req.prior_d.orientation);
00079 else
00080 input_.first_guess[2] = 0;
00081
00082 processScans();
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 if (output_.valid)
00131 {
00132 res.pose_rel.pose.pose.position.x = output_.x[0];
00133 res.pose_rel.pose.pose.position.y = output_.x[1];
00134 res.pose_rel.pose.pose.orientation = tf::createQuaternionMsgFromYaw(output_.x[2]);
00135
00136 res.pose_rel.pose.covariance[0] = gsl_matrix_get(output_.cov_x_m, 0, 0);
00137 res.pose_rel.pose.covariance[1] = gsl_matrix_get(output_.cov_x_m, 0, 1);
00138 res.pose_rel.pose.covariance[5] = gsl_matrix_get(output_.cov_x_m, 0, 2);
00139 res.pose_rel.pose.covariance[6] = gsl_matrix_get(output_.cov_x_m, 1, 0);
00140 res.pose_rel.pose.covariance[7] = gsl_matrix_get(output_.cov_x_m, 1, 1);
00141 res.pose_rel.pose.covariance[11] = gsl_matrix_get(output_.cov_x_m, 1, 2);
00142 res.pose_rel.pose.covariance[30] = gsl_matrix_get(output_.cov_x_m, 2, 0);
00143 res.pose_rel.pose.covariance[31] = gsl_matrix_get(output_.cov_x_m, 2, 1);
00144 res.pose_rel.pose.covariance[35] = gsl_matrix_get(output_.cov_x_m, 2, 2);
00145
00146 res.success = true;
00147 }
00148 else
00149 {
00150 res.pose_rel.pose.pose.position.x = 0;
00151 res.pose_rel.pose.pose.position.y = 0;
00152 res.pose_rel.pose.pose.orientation = tf::createQuaternionMsgFromYaw(0);
00153
00154 res.pose_rel.pose.covariance[0] = 0;
00155 res.pose_rel.pose.covariance[1] = 0;
00156 res.pose_rel.pose.covariance[5] = 0;
00157 res.pose_rel.pose.covariance[6] = 0;
00158 res.pose_rel.pose.covariance[7] = 0;
00159 res.pose_rel.pose.covariance[11] = 0;
00160 res.pose_rel.pose.covariance[30] = 0;
00161 res.pose_rel.pose.covariance[31] = 0;
00162 res.pose_rel.pose.covariance[35] = 0;
00163
00164 res.success = false;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 return true;
00178 }
00179
00180
00181
00182
00183
00184 void LaserIcpAlgNode::node_config_update(Config &config, uint32_t level)
00185 {
00186 this->alg_.lock();
00187
00188 this->alg_.unlock();
00189 }
00190
00191 void LaserIcpAlgNode::addNodeDiagnostics(void)
00192 {
00193 }
00194
00195
00196 int main(int argc,char *argv[])
00197 {
00198 return algorithm_base::main<LaserIcpAlgNode>(argc, argv, "laser_icp_alg_node");
00199 }
00200
00201
00202 void LaserIcpAlgNode::initParams()
00203 {
00204
00205 if (!private_node_handle_.getParam ("min_laser_range", min_laser_range_))
00206 min_laser_range_ = 0.0;
00207
00208 if (!private_node_handle_.getParam ("max_laser_range", max_laser_range_))
00209 max_laser_range_ = 1.0e10;
00210
00211 if (!private_node_handle_.getParam ("use_alpha_beta", use_alpha_beta_))
00212 use_alpha_beta_ = false;
00213
00214 if (!private_node_handle_.getParam ("alpha", alpha_))
00215 alpha_ = 1.0;
00216
00217 if (!private_node_handle_.getParam ("beta", beta_))
00218 beta_ = 0.8;
00219
00220
00221
00222
00223 if (!private_node_handle_.getParam ("max_angular_correction_deg", input_.max_angular_correction_deg))
00224 input_.max_angular_correction_deg = 45.0;
00225
00226
00227 if (!private_node_handle_.getParam ("max_linear_correction", input_.max_linear_correction))
00228 input_.max_linear_correction = 0.50;
00229
00230
00231 if (!private_node_handle_.getParam ("max_iterations", input_.max_iterations))
00232 input_.max_iterations = 10;
00233
00234
00235 if (!private_node_handle_.getParam ("epsilon_xy", input_.epsilon_xy))
00236 input_.epsilon_xy = 0.000001;
00237
00238
00239 if (!private_node_handle_.getParam ("epsilon_theta", input_.epsilon_theta))
00240 input_.epsilon_theta = 0.000001;
00241
00242
00243 if (!private_node_handle_.getParam ("max_correspondence_dist", input_.max_correspondence_dist))
00244 input_.max_correspondence_dist = 0.3;
00245
00246
00247 if (!private_node_handle_.getParam ("sigma", input_.sigma))
00248 input_.sigma = 0.010;
00249
00250
00251 if (!private_node_handle_.getParam ("use_corr_tricks", input_.use_corr_tricks))
00252 input_.use_corr_tricks = 1;
00253
00254
00255 if (!private_node_handle_.getParam ("restart", input_.restart))
00256 input_.restart = 0;
00257
00258
00259 if (!private_node_handle_.getParam ("restart_threshold_mean_error", input_.restart_threshold_mean_error))
00260 input_.restart_threshold_mean_error = 0.01;
00261
00262
00263 if (!private_node_handle_.getParam ("restart_dt", input_.restart_dt))
00264 input_.restart_dt = 1.0;
00265
00266
00267 if (!private_node_handle_.getParam ("restart_dtheta", input_.restart_dtheta))
00268 input_.restart_dtheta = 0.1;
00269
00270
00271 if (!private_node_handle_.getParam ("clustering_threshold", input_.clustering_threshold))
00272 input_.clustering_threshold = 0.25;
00273
00274
00275 if (!private_node_handle_.getParam ("orientation_neighbourhood", input_.orientation_neighbourhood))
00276 input_.orientation_neighbourhood = 20;
00277
00278
00279 if (!private_node_handle_.getParam ("use_point_to_line_distance", input_.use_point_to_line_distance))
00280 input_.use_point_to_line_distance = 1;
00281
00282
00283 if (!private_node_handle_.getParam ("do_alpha_test", input_.do_alpha_test))
00284 input_.do_alpha_test = 0;
00285
00286
00287 if (!private_node_handle_.getParam ("do_alpha_test_thresholdDeg", input_.do_alpha_test_thresholdDeg))
00288 input_.do_alpha_test_thresholdDeg = 20.0;
00289
00290
00291
00292 if (!private_node_handle_.getParam ("outliers_maxPerc", input_.outliers_maxPerc))
00293 input_.outliers_maxPerc = 0.90;
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 if (!private_node_handle_.getParam ("outliers_adaptive_order", input_.outliers_adaptive_order))
00304 input_.outliers_adaptive_order = 0.7;
00305
00306 if (!private_node_handle_.getParam ("outliers_adaptive_mult", input_.outliers_adaptive_mult))
00307 input_.outliers_adaptive_mult = 2.0;
00308
00309
00310
00311
00312
00313 if (!private_node_handle_.getParam ("do_visibility_test", input_.do_visibility_test))
00314 input_.do_visibility_test = 0;
00315
00316
00317 if (!private_node_handle_.getParam ("outliers_remove_doubles", input_.outliers_remove_doubles))
00318 input_.outliers_remove_doubles = 1;
00319
00320
00321 if (!private_node_handle_.getParam ("do_compute_covariance", input_.do_compute_covariance))
00322 input_.do_compute_covariance = 0;
00323
00324
00325 if (!private_node_handle_.getParam ("debug_verify_tricks", input_.debug_verify_tricks))
00326 input_.debug_verify_tricks = 0;
00327
00328
00329
00330 if (!private_node_handle_.getParam ("use_ml_weights", input_.use_ml_weights))
00331 input_.use_ml_weights = 0;
00332
00333
00334
00335 if (!private_node_handle_.getParam ("use_sigma_weights", input_.use_sigma_weights))
00336 input_.use_sigma_weights = 0;
00337 }
00338
00339
00340 void LaserIcpAlgNode::processScans()
00341 {
00342 struct timeval start, end;
00343 gettimeofday(&start, NULL);
00344
00345
00346
00347 ref_ldp_scan_->odometry[0] = 0;
00348 ref_ldp_scan_->odometry[1] = 0;
00349 ref_ldp_scan_->odometry[2] = 0;
00350
00351 ref_ldp_scan_->estimate[0] = 0;
00352 ref_ldp_scan_->estimate[1] = 0;
00353 ref_ldp_scan_->estimate[2] = 0;
00354
00355 ref_ldp_scan_->true_pose[0] = 0;
00356 ref_ldp_scan_->true_pose[1] = 0;
00357 ref_ldp_scan_->true_pose[2] = 0;
00358
00359 input_.laser_ref = ref_ldp_scan_;
00360 input_.laser_sens = sens_ldp_scan_;
00361
00362
00363
00364 sm_icp(&input_, &output_);
00365
00366 ROS_DEBUG("Laser ICP:ProcessScans: output valid? %d", output_.valid);
00367
00368 if (output_.valid)
00369 {
00370
00371
00372 ROS_INFO_XYT("", output_.x[0], output_.x[1], output_.x[2]);
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 }
00383 else
00384 {
00385 ROS_ERROR("Laser ICP: Output invalid. Error in scan matching");
00386 }
00387
00388
00389
00390 ld_free(ref_ldp_scan_);
00391 ld_free(sens_ldp_scan_);
00392
00393
00394
00395 gettimeofday(&end, NULL);
00396 double dur_total = ((end.tv_sec * 1000000 + end.tv_usec ) -
00397 (start.tv_sec * 1000000 + start.tv_usec)) / 1000.0;
00398 ROS_DEBUG("Laser ICP: matching duration: %.1f ms", dur_total);
00399 }
00400
00401 void LaserIcpAlgNode::laserScanToLDP(const sensor_msgs::LaserScan& scan_msg,
00402 LDP& ldp)
00403 {
00404 unsigned int n = scan_msg.ranges.size();
00405 ldp = ld_alloc_new(n);
00406
00407 for (unsigned int i = 0; i < n; i++)
00408 {
00409
00410
00411 double r = scan_msg.ranges[i];
00412
00413 if (r > scan_msg.range_min && r < scan_msg.range_max)
00414 {
00415
00416
00417 ldp->valid[i] = 1;
00418 ldp->readings[i] = r;
00419 }
00420 else
00421 {
00422 ldp->valid[i] = 0;
00423 ldp->readings[i] = -1;
00424
00425 }
00426
00427 ldp->theta[i] = scan_msg.angle_min + i * scan_msg.angle_increment;
00428
00429 ldp->cluster[i] = -1;
00430 }
00431
00432 ldp->min_theta = ldp->theta[0];
00433 ldp->max_theta = ldp->theta[n-1];
00434
00435 ldp->odometry[0] = 0.0;
00436 ldp->odometry[1] = 0.0;
00437 ldp->odometry[2] = 0.0;
00438
00439 ldp->true_pose[0] = 0.0;
00440 ldp->true_pose[1] = 0.0;
00441 ldp->true_pose[2] = 0.0;
00442 }
00443
00444 void LaserIcpAlgNode::ROS_INFO_XYT(const std::string & str,const float & x,const float & y,const float & th)
00445 {
00446 ROS_DEBUG("Laser ICP: %s",str.c_str());
00447 ROS_DEBUG("\033[31mx:\033[0m%f \033[32my:\033[0m%f \033[34mth:\033[0m%f ",
00448 x,y,th);
00449 }
00450