Angle between two 3D vectors in 3D rotated by a quaternion -
i have 3d unit quaternion = {w,x,y,z} coming sensor device. want amount of angles(ax,ay,az) x, y , z axes ( angles should independent, 1 should not change when other changes). have come across, quaternion euler angle conversion, have gimbal lock problem & dependents. i'm thinking take different approach.
take 3d vectors x = [1,0,0], y = [0,1,0] , z = [0,0,1]. if rotate these vectors x, y , z quaternion, 3 vectors xx, yy , zz. calculate angle between x, xx vectors. angle between y, yy , z, zz. seems not working. following c# code i've written. angle range should -180 180 or 0 360deg. acos not preferred has precision problems.
how done ? there standard approaches ? how decompose 3d quaternion 3 quaternions individual x, y , z axes ?
vector3d rotvecx = quatvecrotation(quaternion, new vector3d(1,0,0)); vector3d rotvecy = quatvecrotation(quaternion, new vector3d(0,1,0)); vector3d rotvecz = quatvecrotation(quaternion, new vector3d(0,0,1)); float ax = (float)getxangle(new vector3d(1, 0, 0), rotvec1); float ay = (float)getyangle(new vector3d(0, 1, 0), rotvec2); float az = (float)getzangle(new vector3d(0, 0, 1), rotvec3);
vector3d quatvecrotation(quaternion quat, vector3d vec) { quaternion qvec = new quaternion(0,vec.x,vec.y,vec.z); quaternion qvecr = quaternion.multiply(quat, qvec); quaternion qinv = new quaternion( quat.w, -quat.x, -quat.y, -quat.z); // conjugate or inverse quaternion qr = quaternion.multiply(qvecr, qinv); vector3d resultvec = new vector3d(qr.x, qr.y, qr.z); resultvec.normalize(); return resultvec; } public double getxangle(vector3d vec1, vector3d vec2) { vector3d axis = vector3d.crossproduct(vec1, vec2); double angle = rad2deg((float)math.atan2(axis.length, vector3d.dotproduct(vec1, vec2))); double dir = vector3d.dotproduct(vector3d.crossproduct(axis, vec1), new vector3d(0, 1, 1)); if(dir<0) angle = angle * math.sign(dir); return angle; }
use dot product:
x·xx = |x||xx|cos(angle)
so:
angle = acos( x·xx / ( |x||xx| ) )
Comments
Post a Comment