作為從未學過慣性導航的小白,四元數折磨了我很長時間,至今也是似懂非懂的。下面說的不正確的,希望大神指點。
四元數說起來很好理解,即表示繞着瞬時軸n旋轉θ角度。瞬時軸n=cosαi+cosγj+cosβk。
四元數的表示即Q=cos(θ/2)+sin(θ/2)(cosαi+cosγj+cosβk)=q0+q1i+q2j+q3k。姿態矩陣是如何和四元數對應的呢?θ和n是多少呢?
先擺出一個很重要的性質:坐標系旋轉,矢量固定不變。坐標系OXYZ按照四元數Q轉動,得到新坐標系OXbYbZb,設矢量V在兩坐標系中的坐標分別為Ve,Vb。那么有,Vb=Q-1VeQ。具體見http://www.doc88.com/p-893241688972.html

這就是四元數得到旋轉矩陣的由來。



這篇文章寫的太好了,我就直接復制過來了,感謝作者。
四元數表示旋轉矩陣,四元數的微分都說的很清楚了,然而我還是不知道q0,q1,q2,q3跟姿態角到底有什么關系。我想了很久,不知道下面的理解是不是對的。
n的方向就是陀螺儀測得的(wx,wy,wz)矢量和的方向,θ就是(wx,wy,wz)矢量和的長度!!!
wx,wy,wz是飛機繞三個軸旋轉的角速度,飛機我們認為是分步驟繞三個軸旋轉后到達最終位置的,四元數旋轉我們認為是一步旋轉到最終位置的。那么這兩種旋轉肯定有關系啊!四元數是繞一個向量旋轉,n表示的是旋轉方向,θ表示的是旋轉量。wx,wy,wz的旋轉其實也是繞三個向量旋轉,即(wx,0,0)(0,wy,0)(0,0,wz)。它們最終都到達了同一個位置,那么n當然是(wx,0,0)(0,wy,0)(0,0,wz)三個向量的矢量和啦!
在這里我們一定要認清,向量是與坐標系沒有關系的!向量就是向量,是固定的!它只是在不同的坐標系表示的坐標不同罷了!
我們被很多書上的圖誤導了

就像這樣的圖,先入為主的認為n是在地理坐標系的,然后去想飛機是怎么旋轉的,怎么想也想不明白!當我們談到向量,我們一定要認為他是獨立的存在空間的,跟坐標系什么關系都沒有!
四元數的本質就是,飛機可以看成繞三個向量x,y,z三步旋轉到最終位置,也可以看成繞一個向量n一步旋轉到最終位置。那么當然n=x+y+z啦,這里是矢量和。
我們始終要牢記:向量是獨立的!跟坐標系沒有任何關系!
n、θ和歐拉角的關系,我一直講的是角速度,其實應該是角度的增量。θ應該是三個角度增量的長度。下面是PX4的代碼。
// Convert the rotation vector to its equivalent quaternion
rotationMag = correctedDelAng.length();
if (rotationMag < 1e-12f)
{
deltaQuat[0] = 1.0;
deltaQuat[1] = 0.0;
deltaQuat[2] = 0.0;
deltaQuat[3] = 0.0;
}
else
{
// We are using double here as we are unsure how small
// the angle differences are and if we get into numeric
// issues with float. The runtime impact is not measurable
// for these quantities.
deltaQuat[0] = cos(0.5*(double)rotationMag);
float rotScaler = (sin(0.5*(double)rotationMag))/(double)rotationMag;
deltaQuat[1] = correctedDelAng.x*rotScaler;
deltaQuat[2] = correctedDelAng.y*rotScaler;
deltaQuat[3] = correctedDelAng.z*rotScaler;
}
// Update the quaternions by rotating from the previous attitude through
// the delta angle rotation quaternion
qUpdated[0] = states[0]*deltaQuat[0] - states[1]*deltaQuat[1] - states[2]*deltaQuat[2] - states[3]*deltaQuat[3];
qUpdated[1] = states[0]*deltaQuat[1] + states[1]*deltaQuat[0] + states[2]*deltaQuat[3] - states[3]*deltaQuat[2];
qUpdated[2] = states[0]*deltaQuat[2] + states[2]*deltaQuat[0] + states[3]*deltaQuat[1] - states[1]*deltaQuat[3];
qUpdated[3] = states[0]*deltaQuat[3] + states[3]*deltaQuat[0] + states[1]*deltaQuat[2] - states[2]*deltaQuat[1];
// Normalise the quaternions and update the quaternion states
quatMag = sqrtf(sq(qUpdated[0]) + sq(qUpdated[1]) + sq(qUpdated[2]) + sq(qUpdated[3]));
if (quatMag > 1e-16f)
{
float quatMagInv = 1.0f/quatMag;
states[0] = quatMagInv*qUpdated[0];
states[1] = quatMagInv*qUpdated[1];
states[2] = quatMagInv*qUpdated[2];
states[3] = quatMagInv*qUpdated[3];
}
correctedDelAng是實時測量的角速度乘以采樣周期T。
這里Q的更新采用的是Q=QXΔQ。依據如下:

即兩個四元數相乘,表示兩次旋轉。初始的旋轉加上此次的旋轉增量,即為此刻的旋轉矩陣了。
5.今天又看到另外一種求四元數與姿態角的關系的。感覺這種方法更直觀。
把姿態角的三次旋轉就看成三次四元數旋轉,然后q1q2q3就是四元數最終旋轉矩陣了。


cosRoll = cosf(initialRoll * 0.5f);
sinRoll = sinf(initialRoll * 0.5f);
cosPitch = cosf(initialPitch * 0.5f);
sinPitch = sinf(initialPitch * 0.5f);
cosHeading = cosf(initialHdg * 0.5f);
sinHeading = sinf(initialHdg * 0.5f);
initQuat[0] = cosRoll * cosPitch * cosHeading + sinRoll * sinPitch * sinHeading;
initQuat[1] = sinRoll * cosPitch * cosHeading - cosRoll * sinPitch * sinHeading;
initQuat[2] = cosRoll * sinPitch * cosHeading + sinRoll * cosPitch * sinHeading;
initQuat[3] = cosRoll * cosPitch * sinHeading - sinRoll * sinPitch * cosHeading;
這是PX4給Q賦初值的代碼,就是采用的5這種方法。按理來說這才是最合理的。一開始就把三次旋轉就用四元數表示了。至於上面的那種辦法,合並旋轉軸,也是對的。
