I have a point cloud that is known to contain the floor. This is oriented in some unknown direction and is not at the origin (0,0,0). I have to
floor_plane
to XY plane, so that the floor_plane
lies on XY planefloor_plane
to the origin (0,0,0)
.My approach for the above is:
floor_plane
from RANSAC. First three coefficients correspond to the floor_plane
's normal. theta=acos(C/sqrt(A^2+B^2+C^2)
where A, B, C are first three coefficients of floor_plane
. floor_plane
. Negate them to generate the translationMy code using PointCloud Library goes as follows. It is unable to perform the required transformation, and I am not sure why. Any clues?
// Find the planar coefficients for floor plane
pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
pcl::PointIndices::Ptr floor_inliers (new pcl::PointIndices);
pcl::SACSegmentation<pcl::PointXYZRGB> seg;
seg.setOptimizeCoefficients (true);
seg.setModelType (pcl::SACMODEL_PLANE);
seg.setMethodType (pcl::SAC_RANSAC);
seg.setDistanceThreshold (0.01);
seg.setInputCloud (floor_plane);
seg.segment (*floor_inliers, *coefficients);
std::cerr << "Floor Plane Model coefficients: " << coefficients->values[0] << " "
<< coefficients->values[1] << " "
<< coefficients->values[2] << " "
<< coefficients->values[3] << std::endl;
Eigen::Matrix<float, 1, 3> floor_plane_normal_vector, xy_plane_normal_vector, rotation_vector;
floor_plane_normal_vector[0] = coefficients->values[0];
floor_plane_normal_vector[1] = coefficients->values[1];
floor_plane_normal_vector[2] = coefficients->values[2];
std::cout << floor_plane_normal_vector << std::endl;
xy_plane_normal_vector[0] = 0.0;
xy_plane_normal_vector[1] = 0.0;
xy_plane_normal_vector[2] = 1.0;
std::cout << xy_plane_normal_vector << std::endl;
rotation_vector = xy_plane_normal_vector.cross (floor_plane_normal_vector);
std::cout << "Rotation Vector: "<< rotation_vector << std::endl;
float theta = acos(floor_plane_normal_vector.dot(xy_plane_normal_vector)/sqrt( pow(coefficients->values[0],2)+ pow(coefficients->values[1],2) + pow(coefficients->values[2],2)));
Eigen::Affine3f transform_2 = Eigen::Affine3f::Identity();
transform_2.translation() << 0, 0, 30;
transform_2.rotate (Eigen::AngleAxisf (theta, rotation_vector));
std::cout << "Transformation matrix: " << std::endl << transform_2.matrix() << std::endl;
pcl::transformPointCloud (*cloud, *centeredCloud, transform_2);
Do the translation first, then do the rotation.
Check the sign of theta
Eigen::Vector3f rotation_vector = xy_plane_normal_vector.cross(floor_plane_normal_vector);
float theta = -atan2(rotation_vector.norm(), xy_plane_normal_vector.dot(floor_plane_normal_vector));