Exemple #1
0
 PointCloudPtr downsampleCloud(const PointCloudConstPtr input_cloud_ptr, const float leaf_size)
 {
   pcl17::VoxelGrid<PointType> sor;
   PointCloudPtr output_cloud_ptr (new PointCloud);
   sor.setInputCloud (input_cloud_ptr);
   sor.setLeafSize (leaf_size, leaf_size, leaf_size);
   sor.filter (*output_cloud_ptr);
   return output_cloud_ptr;
 }
void NDTScanMatching::scan_matching_callback(const sensor_msgs::PointCloud2::ConstPtr& points,
        const geometry_msgs::PoseStamped::ConstPtr& pose)
{
    ros::Time scan_time = ros::Time::now();

    pcl::PointXYZI p;
    pcl::PointCloud<pcl::PointXYZI> scan;

    pcl::PointCloud<pcl::PointXYZI>::Ptr transformed_scan_ptr (new pcl::PointCloud<pcl::PointXYZI>());
    tf::Quaternion q;
    Eigen::Matrix4f t(Eigen::Matrix4f::Identity());

    tf::Transform transform;

    pcl::fromROSMsg(*points, scan);

    pcl::PointCloud<pcl::PointXYZI>::Ptr scan_ptr(new pcl::PointCloud<pcl::PointXYZI>(scan));

    if(initial_scan_loaded_ == 0)
    {
        last_scan_ = *scan_ptr;
        last_pose_ = *pose;
        initial_scan_loaded_ = 1;
        return;
    }
    // Filtering input scan to roughly 10% of original size to increase speed of registration.
    pcl::PointCloud<pcl::PointXYZI>::Ptr filtered_cloud_ptr (new pcl::PointCloud<pcl::PointXYZI>);
    pcl::ApproximateVoxelGrid<pcl::PointXYZI> approximate_voxel_filter;
    approximate_voxel_filter.setLeafSize (2.0, 2.0, 2.0);
    approximate_voxel_filter.setInputCloud (scan_ptr);
    approximate_voxel_filter.filter (*filtered_cloud_ptr);

    // Setting scale dependent NDT parameters
    // Setting minimum transformation difference for termination condition.
    ndt_.setTransformationEpsilon (0.01);
    // Setting maximum step size for More-Thuente line search.
    ndt_.setStepSize (0.1);
    //Setting Resolution of NDT grid structure (VoxelGridCovariance).
    ndt_.setResolution (1.0);

    // Setting max number of registration iterations.
    ndt_.setMaximumIterations (30);

    // Setting point cloud to be aligned.
    ndt_.setInputSource (filtered_cloud_ptr);

    pcl::PointCloud<pcl::PointXYZI>::Ptr last_scan_ptr(new pcl::PointCloud<pcl::PointXYZI>(last_scan_));

    // Setting point cloud to be aligned to.
    ndt_.setInputTarget (last_scan_ptr);

    tf::Matrix3x3 init_rotation;

    // 一個前のposeと引き算してx, y ,zの偏差を出す
    offset_x_ = pose->pose.position.x - last_pose_.pose.position.x;
    offset_y_ = pose->pose.position.y - last_pose_.pose.position.y;
    double roll, pitch, yaw = 0;
    getRPY(pose->pose.orientation, roll, pitch, yaw);
    offset_yaw_ = yaw - last_yaw_;

    guess_pos_.x = previous_pos_.x + offset_x_;
    guess_pos_.y = previous_pos_.y + offset_y_;
    guess_pos_.z = previous_pos_.z;

    guess_pos_.roll = previous_pos_.roll;
    guess_pos_.pitch = previous_pos_.pitch;
    guess_pos_.yaw = previous_pos_.yaw + offset_yaw_;

    Eigen::AngleAxisf init_rotation_x(guess_pos_.roll, Eigen::Vector3f::UnitX());
    Eigen::AngleAxisf init_rotation_y(guess_pos_.pitch, Eigen::Vector3f::UnitY());
    Eigen::AngleAxisf init_rotation_z(guess_pos_.yaw, Eigen::Vector3f::UnitZ());

    Eigen::Translation3f init_translation(guess_pos_.x, guess_pos_.y, guess_pos_.z);

    Eigen::Matrix4f init_guess = (init_translation * init_rotation_z * init_rotation_y * init_rotation_x).matrix();

    pcl::PointCloud<pcl::PointXYZI>::Ptr output_cloud_ptr(new pcl::PointCloud<pcl::PointXYZI>);

    ros::Time ndt_start = ros::Time::now();
    ndt_.align (*output_cloud_ptr, init_guess);
    ros::Duration ndt_delta_t = ros::Time::now() - ndt_start;

    std::cout << "Normal Distributions Transform has converged:" << ndt_.hasConverged ()
              << " score: " << ndt_.getFitnessScore () << std::endl;

    t = ndt_.getFinalTransformation();

    // Transforming unfiltered, input cloud using found transform.
    pcl::transformPointCloud (*scan_ptr, *output_cloud_ptr, t);

    tf::Matrix3x3 tf3d;
    tf3d.setValue(
        static_cast<double>(t(0, 0)), static_cast<double>(t(0, 1)), static_cast<double>(t(0, 2)),
        static_cast<double>(t(1, 0)), static_cast<double>(t(1, 1)), static_cast<double>(t(1, 2)),
        static_cast<double>(t(2, 0)), static_cast<double>(t(2, 1)), static_cast<double>(t(2, 2)));

    current_pos_.x = t(0, 3);
    current_pos_.y = t(1, 3);
    current_pos_.z = t(2, 3);

    std::cout << "/////////////////////////////////////////////" << std::endl;
    std::cout << "count : " << count_ << std::endl;
    std::cout << "Process time : " << ndt_delta_t.toSec() << std::endl;
    std::cout << "x : " << current_pos_.x << std::endl;
    std::cout << "y : " << current_pos_.y << std::endl;
    std::cout << "z : " << current_pos_.z << std::endl;
    std::cout << "/////////////////////////////////////////////" << std::endl;

    tf3d.getRPY(current_pos_.roll, current_pos_.pitch, current_pos_.yaw, 1);

    transform.setOrigin(tf::Vector3(current_pos_.x, current_pos_.y, current_pos_.z));
    q.setRPY(current_pos_.roll, current_pos_.pitch, current_pos_.yaw);
    transform.setRotation(q);


    // "map"に対する"base_link"の位置を発行する
    br_.sendTransform(tf::StampedTransform(transform, scan_time, "map", "ndt_base_link"));

    sensor_msgs::PointCloud2 scan_matched;
    pcl::toROSMsg(*output_cloud_ptr, scan_matched);

    scan_matched.header.stamp = scan_time;
    scan_matched.header.frame_id = "matched_point_cloud";

    point_cloud_pub_.publish(scan_matched);

    // Update position and posture. current_pos -> previous_pos
    previous_pos_ = current_pos_;

    // save current scan
    last_scan_ += *output_cloud_ptr;
    last_pose_ = *pose;
    last_yaw_ = yaw;
    // geometry_msgs::TransformStamped ndt_trans;
    // ndt_trans.header.stamp = scan_time;
    // ndt_trans.header.frame_id = "map";
    // ndt_trans.child_frame_id = "base_link";

    // ndt_trans.transform.translation.x = curren_pos.x;
    // ndt_trans.transform.translation.y = curren_pos.y;
    // ndt_trans.transform.translation.z = curren_pos.z;
    // ndt_trans.transform.rotation = q;

    // ndt_broadcaster_.sendTransform(ndt_trans);
    count_++;
}