Reputation: 13
I am trying to visualize a cylinder that I fit to a point cloud using the PCL RANSAC functions. When I fit the model I am given a pcl::ModelCoefficients
object and this has the following coefficients point_on_axis, axis_direction, cylinder_radius_R, see documentation here.
As I understand it, the axis direction values (values 3, 4 and 5 of the coefficient object values member) are the x,y and z components of the cylinder axis vector, respectively. To display this vector in RVIZ using a marker object, I need to convert this vector to a quarternion. I have been doing this using the following c++ code:
//Convert axis vector to quarternion format
double axis_pitch = atan2(coefficients_cylinder.values[5],coefficients_cylinder.values[4]);
double axis_roll = atan2(coefficients_cylinder.values[3],coefficients_cylinder.values[5]);
double axis_yaw = atan2(coefficients_cylinder.values[3],coefficients_cylinder.values[4]);
tf2::Quaternion axis_quarternion;
axis_quarternion.setRPY( axis_roll, axis_pitch, axis_yaw );
axis_quarternion.normalize();
However, whenever I view the cylinder markers overlayed on the original point cloud they have the wrong orientation.
What is causing this? Am I missing a step in the conversion or is my approach completely off?
Thanks for the help!
EDIT:
I found the following code to work quite well:
//Convert axis vector to quarternion format
double axis_roll = atan2(coefficients_cylinder->values[5],coefficients_cylinder->values[4]);
double axis_pitch = -1.0 * atan2(coefficients_cylinder->values[5],coefficients_cylinder->values[3]);
double axis_yaw = atan2(coefficients_cylinder->values[4],coefficients_cylinder->values[3]);
tf2::Quaternion axis_quarternion;
axis_quarternion.setRPY( 0.0, -0.5*M_PI + axis_pitch, axis_yaw);
// axis_quarternion.setRPY( axis_roll, axis_pitch, axis_yaw);
axis_quarternion.normalize();
I had made some incorrect assumptions on the axis directions (see mgrova's answer) and not taken into account that by default the rviz cylinder marker is aligned with the z-axis.
Upvotes: 0
Views: 429
Reputation: 11
I think that one problem is that PCL works with an optical axis frame (right hand definition: x=down, y=left, z=forward).
That's why the best way that I find to be able to represent this orientation is obtaining the Eigen::QuaternionX from the Eigen::AngleAxis giving an angle and the axis where it was measured.
Try with this function to convert from RANSAC cylinder model to geometry_msgs/Quaternion. This orientation will be used to display the cylinder marker in Rviz.
#include <tf2_eigen/tf2_eigen.h>
inline Eigen::Quaterniond obtainCylinderOrientationFromModel(
const pcl::ModelCoefficients::ConstPtr& coefficients)
{
Eigen::Vector3d axis_vector(coefficients->values[3],
coefficients->values[4],
coefficients->values[5]);
Eigen::Vector3d up_vector(0.0, 0.0, -1.0);
Eigen::Vector3d right_vector = axis_vector.cross(up_vector);
right_vector.normalized();
Eigen::Quaterniond q(Eigen::AngleAxisd(-1.0 * std::acos(axis_vector.dot(up_vector)),
right_vector));
q.normalize();
return q;
}
...
// Obtain geometry_msgs/Quaternion from model coefficients
pcl::ModelCoefficients::Ptr coeffs(new pcl::ModelCoefficients);
const auto q = obtainCylinderOrientationFromModel(coeffs);
geometry_msgs::Quaternion cyl_q = tf2::toMsg(q);
I hope this would help you!
Upvotes: 0