问题
I am writing a code to control robotic arm in 3D space. The robotic arm handle the rotation by quaternion but I want user to control it by changing yaw, pitch and roll since its more sensible for human to use these.
I wrote function to get the amount that user wants to rotate the arm in each of directions(roll, pitch, yaw) and output the new quaternion. I saved the current_quaternion as a global variable.
I am using C++ and Eigen.
Eigen::Quaterniond euler2Quaternion( const double roll,
const double pitch,
const double yaw)
{
Eigen::AngleAxisd rollAngle(roll,Eigen::Vector3d::UnitX());
Eigen::AngleAxisd pitchAngle(pitch,Eigen::Vector3d::UnitY());
Eigen::AngleAxisd yawAngle(yaw,Eigen::Vector3d::UnitZ());
Eigen::Quaterniond q = rollAngle*pitchAngle*yawAngle;
current_q=q*current_q;
return current_q;
}
I tried many things changing the order of multiplying angles and multiplying UnitX(), UnitY() and UnitZ() by current_q.toRotationMatrix() but non of them worked.
回答1:
Your example is almost identical to the example
Matrix3f m;
m = AngleAxisf(0.25*M_PI, Vector3f::UnitX())
* AngleAxisf(0.5*M_PI, Vector3f::UnitY())
* AngleAxisf(0.33*M_PI, Vector3f::UnitZ());
Have you tried printing the result of that combined rotation matrix? I will bet it is diagonal 1,1,1 when the angles are zero.
I'm confused about your use of current_q. If roll, pitch, yaw corresponds to some fixed reference direction, then q will be the whole rotation. In that case, this:
current_q=q*current_q;
return current_q;
should just be
current_q=q;
return current_q;
if roll, pitch, yaw
are meant as changes to the current euler rotation angles (which start from some fixed reference direction), it's easier to store these angles and change them accordingly:
double m_roll=0, m_pitch=0, m_yaw=0;
. . .
Eigen::Quaterniond euler2Quaternion(double roll,
double pitch,
double yaw)
{
m_roll+=roll;
m_pitch+=pitch;
m_yaw+=yaw;
Eigen::AngleAxisd rollAngle(m_roll,Eigen::Vector3d::UnitX());
Eigen::AngleAxisd pitchAngle(m_pitch,Eigen::Vector3d::UnitY());
Eigen::AngleAxisd yawAngle(m_yaw,Eigen::Vector3d::UnitZ());
Eigen::Quaterniond q = rollAngle*pitchAngle*yawAngle;
current_q=q;
return current_q;
}
This is also suggested in a comment by sbabbi
回答2:
Why not build the quaternions directly?
Eigen::Quaterniond rollQuaternion(cos(0.5*roll), sin(0.5*roll), 0.0, 0.0);
Eigen::Quaterniond pitchQuaternion(cos(0.5*roll), 0.0, sin(0.5*roll), 0.0);
Eigen::Quaterniond yawQuaternion(cos(0.5*roll), 0.0, 0.0, sin(0.5*roll));
Eigen::Quaterniond finalOrientation = rollQuaternion*pitchQuaternion*yawQuaternion*current_q;
来源:https://stackoverflow.com/questions/29830109/rotate-a-quaternion-by-euler-angles-input