45 #include <boost/assign.hpp>
52 nh_private_(nh_private),
54 received_odom_(
false),
56 initialpose_valid_(
false),
60 ROS_INFO(
"Starting LaserScanMatcher");
74 B_odom_ = gsl_matrix_calloc(3, 5);
75 gsl_matrix_set(
B_odom_, 2, 4, 1.0);
82 I1_ = gsl_matrix_alloc(5, 3);
83 I2_ = gsl_matrix_alloc(3, 3);
84 P2_ = gsl_permutation_alloc (3);
86 xvec_ = gsl_vector_alloc(3);
87 yvec_ = gsl_vector_alloc(3);
100 "lsm_localization/constructed_scan", 5);
106 "lsm_localization/pose2D", 5);
112 "lsm_localization/pose_stamped", 5);
118 "lsm_localization/pose_with_covariance", 5);
124 "lsm_localization/pose", 5);
140 "lsm_localization/debug/odom_delta", 5);
142 "lsm_localization/debug/laser_delta", 5);
144 "lsm_localization/debug/odom_reference", 5);
146 "lsm_localization/debug/odom_current", 5);
159 ROS_INFO(
"using map-based matching");
164 ROS_INFO(
"using frame-to-frame matching");
173 ROS_INFO(
"Destroying LaserScanMatcher");
178 gsl_matrix_free(
I1_);
179 gsl_matrix_free(
I2_);
180 gsl_permutation_free(
P2_);
184 gsl_vector_free(
xvec_);
185 gsl_vector_free(
yvec_);
190 ROS_INFO(
"LaserScanMatcher state cleared");
414 if (o->header.stamp <= time)
423 if (o->header.stamp == time) {
426 }
else if (o->header.stamp < time) {
449 if (!latest_before) {
450 ROS_WARN(
"missing latest odom before t=%.3f (is odom topic alive)",
454 nav_msgs::Odometry o = *latest_before;
455 o.header.stamp = time;
458 double delta_t = (time - latest_before->header.stamp).toSec();
461 o.pose.pose.position.x = latest_before->pose.pose.position.x +
462 delta_t * latest_before->twist.twist.linear.x;
463 o.pose.pose.position.y = latest_before->pose.pose.position.y +
464 delta_t * latest_before->twist.twist.linear.y;
465 o.pose.pose.position.z = latest_before->pose.pose.position.z +
466 delta_t * latest_before->twist.twist.linear.z;
468 delta_q.
setRPY(delta_t * latest_before->twist.twist.angular.x,
469 delta_t * latest_before->twist.twist.angular.y,
470 delta_t * latest_before->twist.twist.angular.z);
472 latest_before->pose.pose.orientation.y,
473 latest_before->pose.pose.orientation.z,
474 latest_before->pose.pose.orientation.w);
476 o.pose.pose.orientation.x = q.x();
477 o.pose.pose.orientation.y = q.y();
478 o.pose.pose.orientation.z = q.z();
479 o.pose.pose.orientation.w = q.w();
488 return (o->header.stamp -
odom_history_.front().header.stamp).toSec();
533 gsl_matrix_set(
B_odom_, 0, 0, cos0);
534 gsl_matrix_set(
B_odom_, 0, 1, -sin0);
535 gsl_matrix_set(
B_odom_, 1, 0, sin0);
536 gsl_matrix_set(
B_odom_, 1, 1, cos0);
537 gsl_matrix_set(
B_odom_, 0, 2, cos90);
538 gsl_matrix_set(
B_odom_, 0, 3, -sin90);
539 gsl_matrix_set(
B_odom_, 1, 2, sin90);
540 gsl_matrix_set(
B_odom_, 1, 3, cos90);
555 boost::mutex::scoped_lock(
mutex_);
574 assert (delta_t >= 0.0);
601 double laser_x = predicted_laser_pose_in_pcl.
getOrigin().getX();
602 double laser_y = predicted_laser_pose_in_pcl.
getOrigin().getY();
604 ROS_DEBUG(
"%s: laser_x=%f, laser_y=%f laser_yaw (deg)=%f", __func__,
605 laser_x, laser_y, 180.0 * laser_yaw /
M_PI);
606 ROS_DEBUG(
"%s: range=[%f,%f], angle=[%f,%f]@%f", __func__,
620 sensor_msgs::LaserScan::Ptr scan_msg;
621 scan_msg = boost::make_shared<sensor_msgs::LaserScan>();
622 scan_msg->range_min =
params.range_min;
623 scan_msg->range_max =
params.range_max;
624 scan_msg->angle_min =
params.angle_min;
625 scan_msg->angle_max =
params.angle_max;
626 scan_msg->angle_increment =
params.angle_inc;
629 scan_msg->header.stamp = time;
631 scan_msg->ranges.assign(
633 scan_msg->intensities.assign(
642 boost::mutex::scoped_lock(
mutex_);
653 if (
syncOdom(pose_msg->header.stamp) < 0.0) {
662 pose.
setOrigin(tf::Vector3(pose_msg->pose.pose.position.x,
663 pose_msg->pose.pose.position.y,
664 pose_msg->pose.pose.position.z));
666 pose_msg->pose.pose.orientation.y,
667 pose_msg->pose.pose.orientation.z,
668 pose_msg->pose.pose.orientation.w));
670 ROS_WARN(
"incorrect frame for initial pose: '%s' vs. '%s'",
671 pose_msg->header.frame_id.c_str(),
fixed_frame_.c_str());
687 boost::mutex::scoped_lock(
mutex_);
692 map_params.
map_res = map_msg->info.resolution;
693 map_params.
map_width = map_msg->info.width;
696 map_msg->info.origin.position.y,
697 map_msg->info.origin.position.z));
699 map_msg->info.origin.orientation.y,
700 map_msg->info.origin.orientation.z,
701 map_msg->info.origin.orientation.w));
708 for (
auto row=map_grid.begin(); row < map_grid.end(); row++) {
710 for (
auto element=row->begin(); element < row->end(); element++)
711 *element = map_msg->data[i++];
723 boost::mutex::scoped_lock(
mutex_);
728 ROS_INFO(
"first scan observed, initializing");
758 if ((delta_t =
syncOdom(scan_msg->header.stamp)) < 0.0) {
768 LDP ref_pose_ldp_scan;
772 r =
processScan(curr_ldp_scan, ref_pose_ldp_scan, scan_msg->header.stamp);
786 "initial pose not received yet, scan processing skipped"
790 r =
processScan(curr_ldp_scan, scan_msg->header.stamp);
794 ROS_DEBUG(
"complete scan processing total duration: %.1f ms", dur);
800 geometry_msgs::PoseStamped::Ptr pose_stamped_msg;
801 pose_stamped_msg = boost::make_shared<geometry_msgs::PoseStamped>();
802 pose_stamped_msg->header.stamp = time;
803 pose_stamped_msg->header.frame_id = frame;
805 publisher.
publish(pose_stamped_msg);
811 geometry_msgs::PoseWithCovarianceStamped::Ptr pose_with_covariance_stamped_msg;
812 pose_with_covariance_stamped_msg = boost::make_shared<geometry_msgs::PoseWithCovarianceStamped>();
814 pose_with_covariance_stamped_msg->header.stamp = time;
815 pose_with_covariance_stamped_msg->header.frame_id =
fixed_frame_;
819 pose_with_covariance_stamped_msg->pose.covariance = boost::assign::list_of
834 geometry_msgs::Pose2D::Ptr pose_msg;
835 pose_msg = boost::make_shared<geometry_msgs::Pose2D>();
843 geometry_msgs::PoseStamped::Ptr pose_stamped_msg;
844 pose_stamped_msg = boost::make_shared<geometry_msgs::PoseStamped>();
846 pose_stamped_msg->header.stamp = time;
855 geometry_msgs::PoseWithCovariance::Ptr pose_with_covariance_msg;
856 pose_with_covariance_msg = boost::make_shared<geometry_msgs::PoseWithCovariance>();
859 pose_with_covariance_msg->covariance = boost::assign::list_of
870 geometry_msgs::PoseWithCovarianceStamped::Ptr pose_with_covariance_stamped_msg;
871 pose_with_covariance_stamped_msg = boost::make_shared<geometry_msgs::PoseWithCovarianceStamped>();
873 pose_with_covariance_stamped_msg->header.stamp = time;
874 pose_with_covariance_stamped_msg->header.frame_id =
fixed_frame_;
878 pose_with_covariance_stamped_msg->pose.covariance = boost::assign::list_of
889 geometry_msgs::PoseWithCovarianceStamped::Ptr pose_with_covariance_stamped_msg;
890 pose_with_covariance_stamped_msg = boost::make_shared<geometry_msgs::PoseWithCovarianceStamped>();
892 pose_with_covariance_stamped_msg->header.stamp = time;
893 pose_with_covariance_stamped_msg->header.frame_id =
fixed_frame_;
897 pose_with_covariance_stamped_msg->pose.covariance = boost::assign::list_of
936 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans,
942 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans,
947 if (measured_pose_yaw < -M_PI/2.0 && predicted_pose_yaw >
M_PI/2.0)
948 measured_pose_yaw += 2*
M_PI;
949 else if (measured_pose_yaw >
M_PI/2.0 && predicted_pose_yaw < -
M_PI/2.0)
950 predicted_pose_yaw += 2*
M_PI;
954 gsl_vector_set(
xvec_, 2, measured_pose_yaw);
959 gsl_vector_set(
xvec_, 2, predicted_pose_yaw);
962 ROS_DEBUG(
"kalman_gain:\n%e %e %e\n%e %e %e\n%e %e %e",
973 gsl_vector_get(
yvec_, 0),
974 gsl_vector_get(
yvec_, 1),
975 gsl_vector_get(
yvec_, 2));
1019 if (e == GSL_EDOM) {
1020 ROS_ERROR(
"sm_icp failed, probably singular matrix");
1030 ROS_DEBUG(
"found correlation transform: x=%f, y=%f, yaw=%f",
1058 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0,
1060 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0,
trans_sigma_,
1062 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0,
1064 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0,
trans_sigma_,
1081 "not publishing. (%d poses skipped)",
1088 ROS_WARN(
"Error in scan matching");
1125 double pr_ch_x, pr_ch_y, pr_ch_a;
1185 ROS_WARN(
"Error in scan matching");
1207 ROS_DEBUG(
"Scan matcher total duration: %.1f ms", dur);
1215 double x =
d.getOrigin().getX();
1216 double y =
d.getOrigin().getY();
1225 unsigned int n = scan_msg->ranges.size();
1228 for (
unsigned int i = 0; i < n; i++)
1232 double r = scan_msg->ranges[i];
1234 if (r > scan_msg->range_min && r < scan_msg->range_max &&
1248 ldp->
theta[i] = scan_msg->angle_min + i * scan_msg->angle_increment;
1270 for (
int i = 0; i < n; i++) {
1305 ROS_WARN(
"Could not get initial transform from base to laser frame, %s", ex.what());
1328 ROS_WARN(
"Could not get initial transform from footprint to base frame, %s", ex.what());
1340 double& pr_ch_a,
double dt)
1342 boost::mutex::scoped_lock(
mutex_);
1360 if (pr_ch_a >=
M_PI) pr_ch_a -= 2.0 *
M_PI;
1361 else if (pr_ch_a < -
M_PI) pr_ch_a += 2.0 *
M_PI;
1375 q.
setRPY(0.0, 0.0, theta);