|
@@ -35,7 +35,7 @@
|
|
|
* on Robotics and Automation (ICRA), 2008
|
|
|
*/
|
|
|
|
|
|
-#include <laser_scan_matcher.h>
|
|
|
+#include "laser_scan_matcher.h"
|
|
|
#include <pcl_conversions/pcl_conversions.h>
|
|
|
#include <pcl/common/transforms.h>
|
|
|
#include <pcl/registration/icp.h>
|
|
@@ -193,7 +193,7 @@ void LaserScanMatcher::initParams()
|
|
|
// 1) Order the errors.
|
|
|
// 2) Choose the percentile according to outliers_adaptive_order.
|
|
|
// (if it is 0.7, get the 70% percentile)
|
|
|
- // 3) Define an adaptive threshold multiplying outliers_adaptive_mult
|
|
|
+ // 3) Define an adaptive threshold multiplying outliers_adaptive_multinput_
|
|
|
// with the value of the error at the chosen percentile.
|
|
|
// 4) Discard correspondences over the threshold.
|
|
|
// This is useful to be conservative; yet remove the biggest errors.
|
|
@@ -249,7 +249,7 @@ void LaserScanMatcher::scanCallback (const sensor_msgs::LaserScan::ConstPtr& sca
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- laserScanToLDP(scan_msg, prev_ldp_scan_, scan_msg->ranges.size());
|
|
|
+ laserScanToLDP(scan_msg, prev_ldp_scan_, scan_msg->angle_min, scan_msg->angle_max);
|
|
|
last_icp_time_ = scan_msg->header.stamp;
|
|
|
initialized_ = true;
|
|
|
|
|
@@ -286,20 +286,19 @@ void LaserScanMatcher::scanCallback (const sensor_msgs::LaserScan::ConstPtr& sca
|
|
|
|
|
|
//printf("min_ang, max_ang, ang_inc: %.3f %.3f %.3f\n",scan_msg->angle_min, scan_msg->angle_max, scan_msg->angle_increment);
|
|
|
}
|
|
|
- LDP curr_ldp_scan;
|
|
|
- laserScanToLDP(scan_msg, curr_ldp_scan, scan_msg->ranges.size()/2);
|
|
|
+ laserScanToLDP(scan_msg, curr_ldp_scan_, -M_PI_2, M_PI_2);
|
|
|
|
|
|
//for cloud display
|
|
|
- pc_curr_.width = curr_ldp_scan->nrays;
|
|
|
+ pc_curr_.width = curr_ldp_scan_->nrays;
|
|
|
pc_curr_.height = 1;
|
|
|
- pc_curr_.resize(curr_ldp_scan->nrays);
|
|
|
- for (int i = 0; i < curr_ldp_scan->nrays; i++)
|
|
|
+ pc_curr_.resize(curr_ldp_scan_->nrays);
|
|
|
+ for (int i = 0; i < curr_ldp_scan_->nrays; i++)
|
|
|
{
|
|
|
- // printf("curr i, valid[i]: %d, %d\n",i,curr_ldp_scan->valid[i]);
|
|
|
- if (curr_ldp_scan->valid[i])
|
|
|
+ // printf("curr i, valid[i]: %d, %d\n",i,curr_ldp_scan_->valid[i]);
|
|
|
+ if (curr_ldp_scan_->valid[i])
|
|
|
{
|
|
|
- dist = curr_ldp_scan->readings[i];
|
|
|
- theta = curr_ldp_scan->theta[i];
|
|
|
+ dist = curr_ldp_scan_->readings[i];
|
|
|
+ theta = curr_ldp_scan_->theta[i];
|
|
|
pc_curr_.points[i].x = dist * cos(theta);
|
|
|
pc_curr_.points[i].y = dist * sin(theta);
|
|
|
pc_curr_.points[i].z = 0;
|
|
@@ -312,12 +311,70 @@ void LaserScanMatcher::scanCallback (const sensor_msgs::LaserScan::ConstPtr& sca
|
|
|
}
|
|
|
// printf("curr x,y,z: %.3f, %.3f, %.3f\n", pc_curr_.points[i].x, pc_curr_.points[i].y, pc_curr_.points[i].z);
|
|
|
}
|
|
|
- processScan(curr_ldp_scan, scan_msg->header.stamp);
|
|
|
+ // tf::Transform t;
|
|
|
+ // icp_process(pc_origin_, pc_curr_, t);
|
|
|
+ processScan(curr_ldp_scan_, scan_msg->header.stamp);
|
|
|
+
|
|
|
}
|
|
|
+void LaserScanMatcher::icp_process(const pcl::PointCloud<pcl::PointXYZ> frame_left, const pcl::PointCloud<pcl::PointXYZ> frame_right, tf::Transform transform)
|
|
|
+{
|
|
|
+ ros::WallTime start = ros::WallTime::now();
|
|
|
+ LDP prev, curr;
|
|
|
+ pointCloudToLDP(frame_left.makeShared(), prev, -M_PI, M_PI);
|
|
|
+ pointCloudToLDP(frame_right.makeShared(), curr, -M_PI/2.0, M_PI/2.0);
|
|
|
+ prev->odometry[0] = 0.0;
|
|
|
+ prev->odometry[1] = 0.0;
|
|
|
+ prev->odometry[2] = 0.0;
|
|
|
+
|
|
|
+ prev->estimate[0] = 0.0;
|
|
|
+ prev->estimate[1] = 0.0;
|
|
|
+ prev->estimate[2] = 0.0;
|
|
|
+
|
|
|
+ prev->true_pose[0] = 0.0;
|
|
|
+ prev->true_pose[1] = 0.0;
|
|
|
+ prev->true_pose[2] = 0.0;
|
|
|
+
|
|
|
+ input_.laser_ref = prev;
|
|
|
+ input_.laser_sens = curr;
|
|
|
+
|
|
|
+ input_.first_guess[0] = f2b_.getOrigin().getX();
|
|
|
+ input_.first_guess[1] = f2b_.getOrigin().getY();
|
|
|
+ input_.first_guess[2] = tf::getYaw(f2b_.getRotation());
|
|
|
+
|
|
|
+ // If they are non-Null, free covariance gsl matrices to avoid leaking memory
|
|
|
+ //清空GNU科学计算库协方差矩阵
|
|
|
+ if (output_.cov_x_m)
|
|
|
+ {
|
|
|
+ gsl_matrix_free(output_.cov_x_m);
|
|
|
+ output_.cov_x_m = 0;
|
|
|
+ }
|
|
|
+ if (output_.dx_dy1_m)
|
|
|
+ {
|
|
|
+ gsl_matrix_free(output_.dx_dy1_m);
|
|
|
+ output_.dx_dy1_m = 0;
|
|
|
+ }
|
|
|
+ if (output_.dx_dy2_m)
|
|
|
+ {
|
|
|
+ gsl_matrix_free(output_.dx_dy2_m);
|
|
|
+ output_.dx_dy2_m = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ ros::WallTime end0 = ros::WallTime::now();
|
|
|
+ // ******************** csm ICP配准 ********************
|
|
|
+ sm_icp(&input_, &output_);
|
|
|
|
|
|
+ ros::WallTime end1 = ros::WallTime::now();
|
|
|
+ double dur1 = (end1 - end0).toSec() * 1e3;
|
|
|
+ ROS_INFO("Scan matcher total duration: %.2f ms", dur1);
|
|
|
+ printf("icp_process transform x,y,theta: %.3f, %.3f, %.3f\n",output_.x[0],output_.x[1],output_.x[2]);
|
|
|
+ transform.setOrigin(tf::Vector3(output_.x[0], output_.x[1], 0.0));
|
|
|
+ tf::Quaternion q;
|
|
|
+ q.setRPY(0.0, 0.0, output_.x[2]);
|
|
|
+ transform.setRotation(q);
|
|
|
+}
|
|
|
void LaserScanMatcher::processScan(LDP& curr_ldp_scan, const ros::Time& time)
|
|
|
{
|
|
|
- // 发布tf模板
|
|
|
+ // // 发布tf模板
|
|
|
// tf::TransformBroadcaster tf_broadcaster_;
|
|
|
// tf::Transform transform;
|
|
|
// transform.setOrigin( tf::Vector3(0.0, 0.0, 0.0));
|
|
@@ -432,7 +489,7 @@ void LaserScanMatcher::processScan(LDP& curr_ldp_scan, const ros::Time& time)
|
|
|
//Setting Resolution of NDT grid structure (VoxelGridCovariance).
|
|
|
ndt.setResolution (0.5);
|
|
|
// Setting max number of registration iterations.
|
|
|
- ndt.setMaximumIterations (60);
|
|
|
+ ndt.setMaximumIterations (50);
|
|
|
// Setting point cloud to be aligned.
|
|
|
ndt.setInputSource (cur_ptr);
|
|
|
// Setting point cloud to be aligned to.
|
|
@@ -442,10 +499,10 @@ void LaserScanMatcher::processScan(LDP& curr_ldp_scan, const ros::Time& time)
|
|
|
ndt_omp->setInputTarget(ori_ptr);
|
|
|
ndt_omp->setInputSource(cur_ptr);
|
|
|
ndt_omp->setNumThreads(n);
|
|
|
- ndt_omp->setTransformationEpsilon(0.0001);
|
|
|
- ndt_omp->setStepSize(0.05);
|
|
|
+ ndt_omp->setTransformationEpsilon(0.00001);
|
|
|
+ ndt_omp->setStepSize(0.1);
|
|
|
ndt_omp->setResolution(0.5);
|
|
|
- ndt_omp->setMaximumIterations(35);
|
|
|
+ ndt_omp->setMaximumIterations(40);
|
|
|
ndt_omp->setNeighborhoodSearchMethod(pclomp::DIRECT7);
|
|
|
|
|
|
// Set initial alignment estimate found using robot odometry.
|
|
@@ -467,7 +524,7 @@ void LaserScanMatcher::processScan(LDP& curr_ldp_scan, const ros::Time& time)
|
|
|
|
|
|
Eigen::Matrix4f pcl_trans= ndt_omp->getFinalTransformation();
|
|
|
//输出最终的变换矩阵(4x4)
|
|
|
- printf("pcl transform x,y,theta: %.3f, %.3f, %.3f\n",pcl_trans(0,3),pcl_trans(1,3),atan2(-pcl_trans(0,1), pcl_trans(0,0)));
|
|
|
+ // printf("pcl transform x,y,theta: %.3f, %.3f, %.3f\n",pcl_trans(0,3),pcl_trans(1,3),atan2(-pcl_trans(0,1), pcl_trans(0,0)));
|
|
|
// std::cout << pcl_trans << std::endl;
|
|
|
ros::WallTime end2 = ros::WallTime::now();
|
|
|
double dur2 = (end2 - end1).toSec() * 1e3;
|
|
@@ -561,26 +618,26 @@ void LaserScanMatcher::processScan(LDP& curr_ldp_scan, const ros::Time& time)
|
|
|
|
|
|
// **** swap old and new
|
|
|
|
|
|
- if (newKeyframeNeeded(corr_ch))
|
|
|
- {
|
|
|
- // generate a keyframe
|
|
|
- ld_free(prev_ldp_scan_);
|
|
|
- prev_ldp_scan_ = curr_ldp_scan;
|
|
|
- f2b_kf_ = f2b_;
|
|
|
- std::cout<<"new key generated.............."<<std::endl;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
+ // if (newKeyframeNeeded(corr_ch))
|
|
|
+ // {
|
|
|
+ // // generate a keyframe
|
|
|
+ // ld_free(prev_ldp_scan_);
|
|
|
+ // prev_ldp_scan_ = curr_ldp_scan;
|
|
|
+ // f2b_kf_ = f2b_;
|
|
|
+ // std::cout<<"new key generated.............."<<std::endl;
|
|
|
+ // }
|
|
|
+ // else
|
|
|
+ // {
|
|
|
ld_free(curr_ldp_scan);
|
|
|
// ld_free(ldp_prev);
|
|
|
- }
|
|
|
+ // }
|
|
|
|
|
|
last_icp_time_ = time;
|
|
|
|
|
|
// **** statistics
|
|
|
ros::WallTime end3 = ros::WallTime::now();
|
|
|
double dur3 = (end3 - start).toSec() * 1e3;
|
|
|
- std::cout<<"time consumption(csm, p1 p2 pcl and total): "<<dur1<<", "/* <<dur1_1<<", "<<dur1_2<<", "*/<<dur2<<", "<<dur3<<std::endl;
|
|
|
+ // std::cout<<"time consumption(csm, p1 p2 pcl and total): "<<dur1<<", "/* <<dur1_1<<", "<<dur1_2<<", "*/<<dur2<<", "<<dur3<<std::endl;
|
|
|
}
|
|
|
|
|
|
bool LaserScanMatcher::newKeyframeNeeded(const tf::Transform& d)
|
|
@@ -595,39 +652,154 @@ bool LaserScanMatcher::newKeyframeNeeded(const tf::Transform& d)
|
|
|
}
|
|
|
|
|
|
void LaserScanMatcher::laserScanToLDP(const sensor_msgs::LaserScan::ConstPtr& scan_msg,
|
|
|
- LDP& ldp, unsigned int count)
|
|
|
+ LDP& ldp, double angle_min, double angle_max)
|
|
|
{
|
|
|
unsigned int n = scan_msg->ranges.size();
|
|
|
- if(count>n || count<0)
|
|
|
+ int left=0,right=0;
|
|
|
+ if(angle_min>=-M_PI-1e04 && angle_min<=M_PI*2+1e04 && angle_max>=-M_PI-1e04 && angle_max<=M_PI*2+1e04 && angle_min<=angle_max){
|
|
|
+ if (angle_min >= scan_msg->angle_min && angle_max <= scan_msg->angle_max)
|
|
|
+ {
|
|
|
+ left = int((angle_min - scan_msg->angle_min) / scan_msg->angle_increment);
|
|
|
+ right = int((angle_max - scan_msg->angle_min) / scan_msg->angle_increment);
|
|
|
+ n = right - left + 1;
|
|
|
+ }else if((angle_min+M_PI*2) <= scan_msg->angle_max){
|
|
|
+ left = int((angle_min+M_PI*2 - scan_msg->angle_min) / scan_msg->angle_increment);
|
|
|
+ right = int((angle_max - scan_msg->angle_min) / scan_msg->angle_increment);
|
|
|
+ n = right + scan_msg->ranges.size()-left;
|
|
|
+ }else{
|
|
|
+ std::cout<<"angle limit"<<std::endl;
|
|
|
+ ldp = ld_alloc_new(0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ std::cout<<"angle not included."<<angle_min<<","<<angle_max<<std::endl;
|
|
|
+ ldp = ld_alloc_new(0);
|
|
|
return;
|
|
|
+ }
|
|
|
+ // if(count>n || count<0)
|
|
|
+ // return;
|
|
|
ldp = ld_alloc_new(n);
|
|
|
+ int index = 0;
|
|
|
//printf("n, ang_lim: %d, %.3f\n",n,scan_msg->angle_min + n * scan_msg->angle_increment);
|
|
|
for (unsigned int i = 0; i < n; i++)
|
|
|
{
|
|
|
+ if (left <= right)
|
|
|
+ {
|
|
|
+ index = left + i;
|
|
|
+ }
|
|
|
+ else if (left > right)
|
|
|
+ {
|
|
|
+ if (i <= right)
|
|
|
+ index = i;
|
|
|
+ else
|
|
|
+ index = left + i - right;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
// calculate position in laser frame
|
|
|
-
|
|
|
- double r = scan_msg->ranges[i];
|
|
|
-
|
|
|
- if (r > scan_msg->range_min && r < scan_msg->range_max && i<=count)
|
|
|
+ double r = scan_msg->ranges[index];
|
|
|
+ if (r > scan_msg->range_min && r < scan_msg->range_max)
|
|
|
{
|
|
|
// fill in laser scan data
|
|
|
-
|
|
|
ldp->valid[i] = 1;
|
|
|
ldp->readings[i] = r;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
ldp->valid[i] = 0;
|
|
|
- ldp->readings[i] = -1; // for invalid range -1
|
|
|
+ ldp->readings[i] = -1; // for invalid range -1
|
|
|
}
|
|
|
+ ldp->theta[i] = scan_msg->angle_min + index * scan_msg->angle_increment;
|
|
|
+ ldp->cluster[i] = -1;
|
|
|
+ }
|
|
|
|
|
|
- ldp->theta[i] = scan_msg->angle_min + i * scan_msg->angle_increment;
|
|
|
+ ldp->min_theta = ldp->theta[0];
|
|
|
+ ldp->max_theta = ldp->theta[n - 1];
|
|
|
|
|
|
- ldp->cluster[i] = -1;
|
|
|
+ ldp->odometry[0] = 0.0;
|
|
|
+ ldp->odometry[1] = 0.0;
|
|
|
+ ldp->odometry[2] = 0.0;
|
|
|
+
|
|
|
+ ldp->true_pose[0] = 0.0;
|
|
|
+ ldp->true_pose[1] = 0.0;
|
|
|
+ ldp->true_pose[2] = 0.0;
|
|
|
+}
|
|
|
+void LaserScanMatcher::pointCloudToLDP(const pcl::PointCloud<pcl::PointXYZ>::Ptr &point_cloud_msg,
|
|
|
+ LDP &ldp, double angle_min, double angle_max)
|
|
|
+{
|
|
|
+ pcl::PointCloud<pcl::PointXYZ> laserCloudIn = *point_cloud_msg;
|
|
|
+ // pcl::fromROSMsg(*point_cloud_msg, laserCloudIn);
|
|
|
+ // std::vector<int> indices;
|
|
|
+ // pcl::removeNaNFromPointCloud(laserCloudIn, laserCloudIn, indices);
|
|
|
+ double theta_min = atan2(laserCloudIn.points[0].y, laserCloudIn.points[0].x);
|
|
|
+ unsigned int n = laserCloudIn.points.size();
|
|
|
+ double theta_max = atan2(laserCloudIn.points[n-1].y, laserCloudIn.points[n-1].x);
|
|
|
+ std::cout<<laserCloudIn.points[0].x<<", "<<laserCloudIn.points[0].y<<std::endl;
|
|
|
+ std::cout<<laserCloudIn.points[n-1].x<<", "<<laserCloudIn.points[n-1].y<<std::endl;
|
|
|
+ if (theta_max <= 1e-4)
|
|
|
+ theta_max += M_PI * 2;
|
|
|
+ double angle_increment = (theta_max - theta_min) / n;
|
|
|
+ int left=0,right=0;
|
|
|
+
|
|
|
+ if(angle_min>=-M_PI-1e04 && angle_min<=M_PI*2+1e04 && angle_max>=-M_PI-1e04 && angle_max<=M_PI*2+1e04 && angle_min<=angle_max){
|
|
|
+ if (angle_min >= theta_min && angle_max <= theta_max)
|
|
|
+ {
|
|
|
+ left = int((angle_min - theta_min) / angle_increment);
|
|
|
+ right = int((angle_max - theta_min) / angle_increment);
|
|
|
+ n = right - left + 1;
|
|
|
+ }else if((angle_min+M_PI*2) <= theta_max){
|
|
|
+ left = int((angle_min+M_PI*2 - theta_min) / angle_increment);
|
|
|
+ right = int((angle_max - theta_min) / angle_increment);
|
|
|
+ n = right + n-left;
|
|
|
+ }else{
|
|
|
+ printf("a min max, theta min max: %.3f, %.3f, %.3f, %.3f",angle_min, angle_max, theta_min, theta_max);
|
|
|
+ std::cout<<"cloud angle limit"<<std::endl;
|
|
|
+ ldp = ld_alloc_new(0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ std::cout<<"cloud angle not included."<<angle_min<<","<<angle_max<<std::endl;
|
|
|
+ ldp = ld_alloc_new(0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ ldp = ld_alloc_new(n);
|
|
|
+ int index = 0;
|
|
|
+ //printf("n, ang_lim: %d, %.3f\n",n,scan_msg->angle_min + n * scan_msg->angle_increment);
|
|
|
+ for (unsigned int i = 0; i < n; i++)
|
|
|
+ {
|
|
|
+ if (left <= right)
|
|
|
+ {
|
|
|
+ index = left + i;
|
|
|
+ }
|
|
|
+ else if (left > right)
|
|
|
+ {
|
|
|
+ if (i <= right)
|
|
|
+ index = i;
|
|
|
+ else
|
|
|
+ index = left + i - right;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ldp = ld_alloc_new(0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // calculate position in laser frame
|
|
|
+ double r = sqrt(pow(laserCloudIn.points[index].x,2)+pow(laserCloudIn.points[index].y,2));
|
|
|
+ // fill in laser scan data
|
|
|
+ ldp->valid[i] = 1;
|
|
|
+ ldp->readings[i] = r;
|
|
|
+ ldp->theta[i] = theta_min + index * angle_increment;
|
|
|
+ ldp->cluster[i] = -1;
|
|
|
}
|
|
|
|
|
|
ldp->min_theta = ldp->theta[0];
|
|
|
- ldp->max_theta = ldp->theta[n-1];
|
|
|
+ ldp->max_theta = ldp->theta[n - 1];
|
|
|
|
|
|
ldp->odometry[0] = 0.0;
|
|
|
ldp->odometry[1] = 0.0;
|
|
@@ -637,7 +809,6 @@ void LaserScanMatcher::laserScanToLDP(const sensor_msgs::LaserScan::ConstPtr& sc
|
|
|
ldp->true_pose[1] = 0.0;
|
|
|
ldp->true_pose[2] = 0.0;
|
|
|
}
|
|
|
-
|
|
|
void LaserScanMatcher::createCache (const sensor_msgs::LaserScan::ConstPtr& scan_msg)
|
|
|
{
|
|
|
a_cos_.clear();
|