Пример #1
0
template <typename PointSource, typename PointTarget> void
pcl::registration::TransformationEstimationSVD<PointSource, PointTarget>::getTransformationFromCorrelation (
    const Eigen::MatrixXf &cloud_src_demean,
    const Eigen::Vector4f &centroid_src,
    const Eigen::MatrixXf &cloud_tgt_demean,
    const Eigen::Vector4f &centroid_tgt,
    Eigen::Matrix4f &transformation_matrix)
{
  transformation_matrix.setIdentity ();

  // Assemble the correlation matrix H = source * target'
  Eigen::Matrix3f H = (cloud_src_demean * cloud_tgt_demean.transpose ()).topLeftCorner<3, 3>();

  // Compute the Singular Value Decomposition
  Eigen::JacobiSVD<Eigen::Matrix3f> svd (H, Eigen::ComputeFullU | Eigen::ComputeFullV);
  Eigen::Matrix3f u = svd.matrixU ();
  Eigen::Matrix3f v = svd.matrixV ();

  // Compute R = V * U'
  if (u.determinant () * v.determinant () < 0)
  {
    for (int x = 0; x < 3; ++x)
      v (x, 2) *= -1;
  }

  Eigen::Matrix3f R = v * u.transpose ();

  // Return the correct transformation
  transformation_matrix.topLeftCorner<3, 3> () = R;
  Eigen::Vector3f Rc = R * centroid_src.head<3> ();
  transformation_matrix.block <3, 1> (0, 3) = centroid_tgt.head<3> () - Rc;
}
/** Extract rotation (R) and translation (t) from a given essential matrix and triangulate feature matches.
 * @param Eigen::Matrix3f essential matrix
 * @param std::vector<Match> vector with matches
 * @param Eigen::Matrix3f output rotation matrix
 * @param Eigen::Vector3f output translation vector
 * @param Eigen::Matrix<float, 4, Eigen::Dynamic> output matrix with computed 3D points
 * @return void */
void MonoOdometer5::E2Rt(Eigen::Matrix3f E, std::vector<Match> matches, Eigen::Matrix3f &R, Eigen::Vector3f &t, Eigen::Matrix<float, 4, Eigen::Dynamic> &points3D)
{
    Eigen::Matrix3f W, Z;
    W << 0, -1, 0, 1, 0, 0, 0, 0, 1;
    Z << 0, 1, 0, -1, 0, 0, 0, 0, 0;
    
	// singular values decomposition of E
    Eigen::JacobiSVD<Eigen::Matrix3f> svdE(E, Eigen::ComputeFullU | Eigen::ComputeFullV);
    
	// get skew symmetric matrix of translation vector
    Eigen::Matrix3f S = svdE.matrixU() * Z * (svdE.matrixU()).transpose();
	
	// get possible rotation matrices
    Eigen::Matrix3f Ra = svdE.matrixU() * W * (svdE.matrixV()).transpose();
    Eigen::Matrix3f Rb = svdE.matrixU() * W.transpose() * (svdE.matrixV()).transpose();

	// get translation vetor from skew symmetric matrix
    t << S(2, 1), S(0, 2), S(1, 0);
    
	// correct signal of both rotation matrices
    if(Ra.determinant() < 0)
    {
        Ra = -Ra;
    }
    if(Rb.determinant() < 0)
    {
        Rb = -Rb;
    }
    
	// 4 possible combinations of R,t
    std::vector<Eigen::Matrix3f> solutionsR;
    std::vector<Eigen::Vector3f> solutionst;    
    solutionsR.push_back(Ra); solutionst.push_back(t);
    solutionsR.push_back(Ra); solutionst.push_back(-t);
    solutionsR.push_back(Rb); solutionst.push_back(t);
    solutionsR.push_back(Rb); solutionst.push_back(-t);
    
	// test Chirality constraint for all 4 solutions
    Eigen::Matrix<float, 4, Eigen::Dynamic> points3DCurr;
    int maxInliers = 0;
    for(int i=0; i<4; i++)
    {
        int nInliers = triangulate(matches, solutionsR[i], solutionst[i], points3DCurr);

		// solution with the most inliers wins
		if(nInliers > maxInliers)
        {
            maxInliers = nInliers;
            points3D = points3DCurr;
            R = solutionsR[i];
            t = solutionst[i];
        }
    }
}
Пример #3
0
/**
 * estimateRigidTransformationSVD
 */
void RigidTransformationRANSAC::estimateRigidTransformationSVD(
      const std::vector<Eigen::Vector3f > &srcPts,
      const std::vector<int> &srcIndices,
      const std::vector<Eigen::Vector3f > &tgtPts,
      const std::vector<int> &tgtIndices,
      Eigen::Matrix4f &transform)
{
  Eigen::Vector3f srcCentroid, tgtCentroid;

  // compute the centroids of source, target
  ComputeCentroid (srcPts, srcIndices, srcCentroid);
  ComputeCentroid (tgtPts, tgtIndices, tgtCentroid);

  // Subtract the centroids from source, target
  Eigen::MatrixXf srcPtsDemean;
  DemeanPoints(srcPts, srcIndices, srcCentroid, srcPtsDemean);

  Eigen::MatrixXf tgtPtsDemean;
  DemeanPoints(tgtPts, tgtIndices, tgtCentroid, tgtPtsDemean);

  // Assemble the correlation matrix H = source * target'
  Eigen::Matrix3f H = (srcPtsDemean * tgtPtsDemean.transpose ()).topLeftCorner<3, 3>();

  // Singular Value Decomposition
  Eigen::JacobiSVD<Eigen::Matrix3f> svd (H, Eigen::ComputeFullU | Eigen::ComputeFullV);
  Eigen::Matrix3f u = svd.matrixU ();
  Eigen::Matrix3f v = svd.matrixV ();

  // Compute R = V * U'
  if (u.determinant () * v.determinant () < 0)
  {
    for (int x = 0; x < 3; ++x)
      v (x, 2) *= -1;
  }

  // Return the transformation
  Eigen::Matrix3f R = v * u.transpose ();
  Eigen::Vector3f t = tgtCentroid - R * srcCentroid;

  // set rotation
  transform.block(0,0,3,3) = R;
  // set translation
  transform.block(0,3,3,1) = t;
  transform.block(3, 0, 1, 3).setZero();  
  transform(3,3) = 1.;
}
Пример #4
0
template <typename PointT> void
pcl::SampleConsensusModelRegistration<PointT>::estimateRigidTransformationSVD (
    const pcl::PointCloud<PointT> &cloud_src, 
    const std::vector<int> &indices_src, 
    const pcl::PointCloud<PointT> &cloud_tgt,
    const std::vector<int> &indices_tgt, 
    Eigen::VectorXf &transform)
{
  transform.resize (16);
  Eigen::Vector4f centroid_src, centroid_tgt;
  // Estimate the centroids of source, target
  compute3DCentroid (cloud_src, indices_src, centroid_src);
  compute3DCentroid (cloud_tgt, indices_tgt, centroid_tgt);

  // Subtract the centroids from source, target
  Eigen::MatrixXf cloud_src_demean;
  demeanPointCloud (cloud_src, indices_src, centroid_src, cloud_src_demean);

  Eigen::MatrixXf cloud_tgt_demean;
  demeanPointCloud (cloud_tgt, indices_tgt, centroid_tgt, cloud_tgt_demean);

  // Assemble the correlation matrix H = source * target'
  Eigen::Matrix3f H = (cloud_src_demean * cloud_tgt_demean.transpose ()).topLeftCorner<3, 3>();

  // Compute the Singular Value Decomposition
  Eigen::JacobiSVD<Eigen::Matrix3f> svd (H, Eigen::ComputeFullU | Eigen::ComputeFullV);
  Eigen::Matrix3f u = svd.matrixU ();
  Eigen::Matrix3f v = svd.matrixV ();

  // Compute R = V * U'
  if (u.determinant () * v.determinant () < 0)
  {
    for (int x = 0; x < 3; ++x)
      v (x, 2) *= -1;
  }

  Eigen::Matrix3f R = v * u.transpose ();

  // Return the correct transformation
  transform.segment<3> (0) = R.row (0); transform[12]  = 0;
  transform.segment<3> (4) = R.row (1); transform[13]  = 0;
  transform.segment<3> (8) = R.row (2); transform[14] = 0;

  Eigen::Vector3f t = centroid_tgt.head<3> () - R * centroid_src.head<3> ();
  transform[3] = t[0]; transform[7] = t[1]; transform[11] = t[2]; transform[15] = 1.0;
}
Пример #5
0
void Element::CalculateStiffnessMatrix(const Eigen::Matrix3f& D, std::vector<Eigen::Triplet<float> >& triplets)
{
	Eigen::Vector3f x, y;
	x << nodesX[nodesIds[0]], nodesX[nodesIds[1]], nodesX[nodesIds[2]];
	y << nodesY[nodesIds[0]], nodesY[nodesIds[1]], nodesY[nodesIds[2]];
	
	Eigen::Matrix3f C;
	C << Eigen::Vector3f(1.0f, 1.0f, 1.0f), x, y;
	
	Eigen::Matrix3f IC = C.inverse();

	for (int i = 0; i < 3; i++)
	{
		B(0, 2 * i + 0) = IC(1, i);
		B(0, 2 * i + 1) = 0.0f;
		B(1, 2 * i + 0) = 0.0f;
		B(1, 2 * i + 1) = IC(2, i);
		B(2, 2 * i + 0) = IC(2, i);
		B(2, 2 * i + 1) = IC(1, i);
	}
	Eigen::Matrix<float, 6, 6> K = B.transpose() * D * B * C.determinant() / 2.0f;

	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			Eigen::Triplet<float> trplt11(2 * nodesIds[i] + 0, 2 * nodesIds[j] + 0, K(2 * i + 0, 2 * j + 0));
			Eigen::Triplet<float> trplt12(2 * nodesIds[i] + 0, 2 * nodesIds[j] + 1, K(2 * i + 0, 2 * j + 1));
			Eigen::Triplet<float> trplt21(2 * nodesIds[i] + 1, 2 * nodesIds[j] + 0, K(2 * i + 1, 2 * j + 0));
			Eigen::Triplet<float> trplt22(2 * nodesIds[i] + 1, 2 * nodesIds[j] + 1, K(2 * i + 1, 2 * j + 1));

			triplets.push_back(trplt11);
			triplets.push_back(trplt12);
			triplets.push_back(trplt21);
			triplets.push_back(trplt22);
		}
	}
}
  void onGMM(const gaussian_mixture_model::GaussianMixture & mix)
  {
    visualization_msgs::MarkerArray msg;
    ROS_INFO("gmm_rviz_converter: Received message.");

    uint i;

    for (i = 0; i < mix.gaussians.size(); i++)
    {
      visualization_msgs::Marker marker;

      marker.header.frame_id = m_frame_id;
      marker.header.stamp = ros::Time::now();
      marker.ns = m_rviz_namespace;
      marker.id = i;
      marker.type = visualization_msgs::Marker::SPHERE;
      marker.action = visualization_msgs::Marker::ADD;
      marker.lifetime = ros::Duration();

      Eigen::Vector3f coords;
      for (uint ir = 0; ir < NUM_OUTPUT_COORDINATES; ir++)
        coords[ir] = m_conversion_mask[ir]->GetMean(m_conversion_mask,mix.gaussians[i]);
      marker.pose.position.x = coords.x();
      marker.pose.position.y = coords.y();
      marker.pose.position.z = coords.z();

      Eigen::Matrix3f covmat;
      for (uint ir = 0; ir < NUM_OUTPUT_COORDINATES; ir++)
        for (uint ic = 0; ic < NUM_OUTPUT_COORDINATES; ic++)
          covmat(ir,ic) = m_conversion_mask[ir]->GetCov(m_conversion_mask,mix.gaussians[i],ic);

      Eigen::EigenSolver<Eigen::Matrix3f> evsolver(covmat);

      Eigen::Matrix3f eigenvectors = evsolver.eigenvectors().real();
      if (eigenvectors.determinant() < 0.0)
        eigenvectors.col(0) = - eigenvectors.col(0);
      Eigen::Matrix3f rotation = eigenvectors;
      Eigen::Quaternionf quat = Eigen::Quaternionf(Eigen::AngleAxisf(rotation));

      marker.pose.orientation.x = quat.x();
      marker.pose.orientation.y = quat.y();
      marker.pose.orientation.z = quat.z();
      marker.pose.orientation.w = quat.w();

      Eigen::Vector3f eigenvalues = evsolver.eigenvalues().real();
      Eigen::Vector3f scale = Eigen::Vector3f(eigenvalues.array().abs().sqrt());
      if (m_normalize)
        scale.normalize();
      marker.scale.x = mix.weights[i] * scale.x() * m_scale;
      marker.scale.y = mix.weights[i] * scale.y() * m_scale;
      marker.scale.z = mix.weights[i] * scale.z() * m_scale;

      marker.color.a = 1.0;
      rainbow(float(i) / float(mix.gaussians.size()),marker.color.r,marker.color.g,marker.color.b);

      msg.markers.push_back(marker);
    }

    // this a waste of resources, but we need to delete old markers in some way
    // someone should add a "clear all" command to rviz
    // (using expiration time is not an option, here)
    for ( ; i < m_max_markers; i++)
    {
      visualization_msgs::Marker marker;
      marker.id = i;
      marker.action = visualization_msgs::Marker::DELETE;
      marker.lifetime = ros::Duration();
      marker.header.frame_id = m_frame_id;
      marker.header.stamp = ros::Time::now();
      marker.ns = m_rviz_namespace;
      msg.markers.push_back(marker);
    }

    m_pub.publish(msg);
    ROS_INFO("gmm_rviz_converter: Sent message.");
  }
void cloud_cb (const sensor_msgs::PointCloud2ConstPtr& input)
{
  // Create a container for the data.
  pcl::PointCloud<pcl::PointXYZRGBNormal> cloud;
  pcl::PointCloud<pcl::PointXYZRGBNormal> cloud_fast;
  pcl::fromROSMsg(*input, cloud);
  for (size_t i=0; i < cloud.points.size(); i++) {
    pcl::PointXYZRGBNormal point_temp = cloud.points[i];
    if (sqrt(point_temp.normal_x*point_temp.normal_x+point_temp.normal_y*point_temp.normal_y+point_temp.normal_z*point_temp.normal_z) > 0.02) {
      cloud_fast.points.push_back(cloud.points[i]);
    }
  }

  cloud_fast.width=cloud_fast.points.size();
  cloud_fast.height=1;
  ROS_INFO("done extract fast size %d", cloud_fast.points.size());
  unsigned int max_inliers = 0;
  Eigen::Matrix3f R_best;
  Eigen::Vector3f t_best;
  pcl::PointCloud<pcl::PointXYZRGBNormal> point_best;
  point_best.points.resize(3); point_best.width = 3; point_best.height = 1;
  bool apply_sac;
  int mirror_num = 0;
  if (cloud_fast.points.size() > 50) {
    omp_lock_t writelock;
    omp_init_lock(&writelock);
#ifdef _OPENMP
#pragma omp parallel for
#endif
    for (size_t i=0; i < 2000; i++) {
      unsigned int rand_nums[3];
      while (true) {
        rand_nums[0] = rand() % cloud_fast.width;
        rand_nums[1] = rand() % cloud_fast.width;
        rand_nums[2] = rand() % cloud_fast.width;
        if (rand_nums[0] != rand_nums[1] && rand_nums[1] != rand_nums[2] && rand_nums[2] != rand_nums[0])
          break;
      }
      Eigen::Vector3f v_before[3];
      Eigen::Vector3f v_after[3];
      for (size_t j=0; j < 3; j++) {
        pcl::PointXYZRGBNormal point_temp = cloud_fast.points[rand_nums[j]];
        v_before[j] = Eigen::Vector3f(point_temp.x, point_temp.y, point_temp.z);
        v_after[j] = v_before[j] + Eigen::Vector3f(point_temp.normal_x, point_temp.normal_y, point_temp.normal_z);
      }
      Eigen::Vector3f v_before_ave = (v_before[0] + v_before[1] + v_before[2]) / 3.0;
      Eigen::Vector3f v_after_ave = (v_after[0] + v_after[1] + v_after[2]) / 3.0;
      Eigen::Vector3f v_before_relative[3];
      Eigen::Vector3f v_after_relative[3];
      Eigen::MatrixXf m_before_ave = Eigen::MatrixXf::Zero(3, 3);
      Eigen::MatrixXf m_after_ave = Eigen::MatrixXf::Zero(3, 3);
      for (size_t j=0; j < 3; j++) {
        v_before_relative[j] = v_before[j] - v_before_ave;
        v_after_relative[j] = v_after[j] - v_after_ave;
        m_before_ave.col(j) = v_before_relative[j];
        m_after_ave.col(j) = v_after_relative[j];
      }
      
      Eigen::Matrix3f Q = m_after_ave * m_before_ave.transpose();
      JacobiSVD<Eigen::Matrix3f> svd(Q, ComputeFullU | ComputeFullV);
      Eigen::Matrix3f R = svd.matrixV() * svd.matrixU().transpose();
      if (R.determinant() < 0.0) {mirror_num++; continue;}
      Eigen::Vector3f t = v_after_ave - R * v_before_ave;
      unsigned int inliers = 0;
      for (size_t j=0; j < cloud_fast.points.size(); j++) {
        pcl::PointXYZRGBNormal point_temp = cloud_fast.points[j];
        Eigen::Vector3f v_before_temp = Eigen::Vector3f(point_temp.x, point_temp.y, point_temp.z);
        Eigen::Vector3f v_after_temp = v_before_temp + Eigen::Vector3f(point_temp.normal_x, point_temp.normal_y, point_temp.normal_z);
        Eigen::Vector3f v_after_temp_estimated = R * v_before_temp + t;
        float error = (v_after_temp_estimated - v_after_temp).norm();
        if (error < 0.03){
          inliers ++;
        }
      }
      omp_set_lock(&writelock);
      if (max_inliers < inliers) {
        max_inliers = inliers;
        R_best = R;
        t_best = t;
        for (size_t j=0; j < 3; j++) {
          point_best.points[j]=cloud_fast.points[rand_nums[j]];
        }
      }
      omp_unset_lock(&writelock);
    }
    ROS_INFO("Done sac, total moving: %d, max_i: %d", cloud_fast.points.size(), max_inliers);
    apply_sac = true;
    ROS_INFO("determinant %f", R_best.determinant());
    //ROS_INFO("mirror num %d", mirror_num);
  } else{
    ROS_INFO("No moving points");
    apply_sac = false;
  }
  sensor_msgs::PointCloud2 ros_out;
  pcl::toROSMsg(cloud_fast, ros_out);
  ros_out.header = input->header;
  pub_result_cloud_fast_.publish(ros_out); 
  if (apply_sac){
    pcl::PointCloud<pcl::PointXYZRGBNormal> cloud_sac, cloud_sac2, cloud_sac3, cloud_sac4;
    for (size_t j=0; j < cloud.points.size(); j++) {
      pcl::PointXYZRGBNormal point_temp = cloud.points[j];
      Eigen::Vector3f v_before_temp = Eigen::Vector3f(point_temp.x, point_temp.y, point_temp.z);
      Eigen::Vector3f v_after_temp = v_before_temp + Eigen::Vector3f(point_temp.normal_x, point_temp.normal_y, point_temp.normal_z);
      Eigen::Vector3f v_after_temp_estimated = R_best * v_before_temp + t_best;
      float error = (v_after_temp_estimated - v_after_temp).norm();
      if (error < 0.03){
        cloud_sac.points.push_back(cloud.points[j]);

        pcl::PointXYZRGBNormal point_temp2;
        point_temp2.x = v_after_temp_estimated[0];
        point_temp2.y = v_after_temp_estimated[1];
        point_temp2.z = v_after_temp_estimated[2];
        cloud_sac2.points.push_back(point_temp2);
        
        v_after_temp_estimated = R_best * v_after_temp_estimated + t_best;
        pcl::PointXYZRGBNormal point_temp3;
        point_temp3.x = v_after_temp_estimated[0];
        point_temp3.y = v_after_temp_estimated[1];
        point_temp3.z = v_after_temp_estimated[2];
        cloud_sac3.points.push_back(point_temp3);

        v_after_temp_estimated = R_best * v_after_temp_estimated + t_best;
        pcl::PointXYZRGBNormal point_temp4;
        point_temp4.x = v_after_temp_estimated[0];
        point_temp4.y = v_after_temp_estimated[1];
        point_temp4.z = v_after_temp_estimated[2];
        cloud_sac4.points.push_back(point_temp4);
        // if (j == 20) {
        //   Eigen::Vector3f v_a_b = v_after_temp_estimated4;
        //   for (int k=0; k<10; k++){
        //     v_a_b = R_best * v_a_b + t_best;
        //     ROS_INFO("v_a_b, x:%f, y:%f, z:%f", v_a_b[0], v_a_b[1], v_a_b[2]);
        //   }
        // }
      }
    }
    cloud_sac.width=cloud_sac2.width=cloud_sac3.width=cloud_sac4.width=cloud_sac.points.size();
    cloud_sac.height=cloud_sac2.height=cloud_sac3.height=cloud_sac4.height=1;

    pcl::toROSMsg(cloud_sac, ros_out);
    ros_out.header = input->header;
    pub_result_cloud_sac_.publish(ros_out);

    pcl::toROSMsg(cloud_sac2, ros_out);
    ros_out.header = input->header;
    pub_result_cloud_sac2_.publish(ros_out);

    pcl::toROSMsg(cloud_sac3, ros_out);
    ros_out.header = input->header;
    pub_result_cloud_sac3_.publish(ros_out);

    pcl::toROSMsg(cloud_sac4, ros_out);
    ros_out.header = input->header;
    pub_result_cloud_sac4_.publish(ros_out);

    pcl::toROSMsg(point_best, ros_out);
    ros_out.header = input->header;
    pub_result_cloud_seed_.publish(ros_out);
    
    visualization_msgs::MarkerArray marker_array_best;
    for (int i=0; i<3; i++) {
      visualization_msgs::Marker marker_best;
      geometry_msgs::Point point;

      marker_best.header = input->header;
      marker_best.type = visualization_msgs::Marker::ARROW;
      point.x = point_best.points[i].x;
      point.y = point_best.points[i].y;
      point.z = point_best.points[i].z;
      marker_best.points.push_back(point);
      point.x = point_best.points[i].x + point_best.points[i].normal_x;
      point.y = point_best.points[i].y + point_best.points[i].normal_y;
      point.z = point_best.points[i].z + point_best.points[i].normal_z;
      marker_best.points.push_back(point);
      marker_best.id = i;
      marker_best.ns = std::string("debug_point_array: ");
      marker_best.scale.x = 0.01;
      marker_best.scale.y = 0.02;
      marker_best.scale.z = 0.01;
      marker_best.color.r = 1.0;
      marker_best.color.a = 1.0;
      marker_array_best.markers.push_back(marker_best);
    }
    pub_result_pose_seed_.publish(marker_array_best);
  }
}