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));
In case anyone is interested
There were 2 problems in the code
Thank you for posting the code, it helped me to finish this quickly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With