Cesium中的相机—HeadingPitchRoll
在Cesium中,常常使用HeadingPitchRoll三個角度來定義相機坐標系相對某基準坐標系的方位。
在詳細闡述這個概念之前,先闡述在航空飛行中常用的yaw/pitch/roll。
偏航(yaw)/俯仰(pitch)/滾動(roll)
在航空中,常用yaw,pitch,roll這三個詞來表示飛機的俯仰、偏航、和滾動。為了避免混淆,這里暫時不用坐標系x,y,z軸來表示具體的旋轉軸,而只是用描述性的語言。
首先看這三個詞的翻譯:
- yaw:(火箭、飛機、宇宙飛船等)偏航
yaw是偏航的意思,如果要改變航向,飛機必定是繞著重力方向為軸; - pitch: 傾斜;投擲;搭帳篷;墜落
pitch有傾斜、墜落的意思。飛機在墜落時,必定會一頭栽下去,以翅膀所在的直線為軸。常翻譯為俯仰。 - roll: 卷;滾動,轉動;輾
roll的意思是翻滾,中文中飛機的翻滾是什么,就是繞著機身所在的那個軸。
再來看看簡單的動畫來描述yaw/pitch/roll
使用單獨一副圖來描述飛機的yaw/pitch/roll.
Cesium中的Heading/Pitch/Roll的定義
注意,在上面描述飛機三個方向的旋轉時,我們并沒有將yaw/pitch/roll與具體的x,y,z軸關聯,也沒有指定yaw/pitch/roll的前后順序,這主要是因為并沒有一個具體的標準。
重點來了:
在Cesium中,Heading就是yaw,即偏航的意思。則相機的Heading/pitch/roll與飛機類似:
- Heading=yaw,表示相機繞Up軸旋轉,Up軸為+Z軸,且定義繞-Z軸旋轉為正。
- Pitch,表示相機繞Right軸旋轉,Right軸為-Y軸,且定義繞-Y軸旋轉為正。
- Roll,表示相機繞Direction軸(視線方向)旋轉,Direction軸為+X軸,且繞+X軸旋轉為正。
相機的三個旋轉方向見下圖示意,同時給出了Cesium中相機的Up/Right/Direction三個軸與X/Y/Z軸的關系。
下面給出Heading/Pitch/Roll的旋轉順序:
初始時刻,相機以坐標系o?xyzo-xyzo?xyz為參考基準,相機坐標系o?XYZo-XYZo?XYZ與之重合。
即相機坐標系經過三次基本的歐拉旋轉,旋轉到最終的坐標系o?XYZo-XYZo?XYZ(下圖紅色),歐拉轉序為321(ZYX),旋轉的角度遵循右手定則。
注意,在Cesium中,常使用對象headingPitchRoll來表示相機的三次旋轉角度,使用heading屬性表示繞z軸旋轉的角度(繞-z軸為正);使用pitch表示繞y軸旋轉的角度(繞-y軸為正);使用roll表示繞x軸旋轉角度(繞+x軸為正);旋轉順序仍為321(ZYX)。
因此,對比ψθ?\psi\theta\phiψθ?,有以下關系:
ψ=?headingθ=?pitch?=roll\psi = -heading \\ \theta = -pitch \\ \phi = roll ψ=?headingθ=?pitch?=roll
旋轉矩陣的表示
因此,以后再考慮HeadingPitchRoll旋轉時,可正常按照321轉序,歐拉角為ψ、θ、?\psi、 \theta 、\phiψ、θ、?,只要注意前兩個角度需要添加負號。
相機坐標系經過三次基本旋轉(ZYX)后,以[X,Y,Z]T\begin{bmatrix} X,Y,Z\end{bmatrix}^{T}[X,Y,Z?]T表示點P在相機坐標系o?XYZo-XYZo?XYZ中的坐標分量(始終不變),[x,y,z]T\begin{bmatrix} x,y,z\end{bmatrix}^{T}[x,y,z?]T表示點P隨相機旋轉后在原坐標系o?xyzo-xyzo?xyz中的坐標分量,則有:
[xyz]=M(ψ,θ,?)[XYZ]=Mz(ψ)?My(θ)?Mx(?)?[XYZ]=[cos?ψ?sin?ψ0sin?ψcos?ψ0001][cos?θ0sin?θ010?sin?θ0cos?θ][1000cos?θ?sin?θ0sin?θcos?θ][XYZ]=[cos?θcos?ψ?cos??sin?ψ+sin??sin?θcos?ψsin??sin?ψ+cos??sin?θcos?ψcos?θsin?ψcos??cos?ψ+sin??sin?θsin?ψ?sin??cos?ψ+cos??sin?θsin?ψ?sin?θsin??cos?θcos??cos?θ][XYZ](1)\begin{bmatrix} {x}\\{y} \\{z} \end{bmatrix}=M(\psi,\theta,\phi) \begin{bmatrix} X \\Y \\Z \end{bmatrix} = M_z(\psi)\cdot M_y(\theta)\cdot M_x(\phi)\cdot \begin{bmatrix} X \\Y \\Z \end{bmatrix} \\= \begin{bmatrix} \cos\psi &-\sin\psi & 0 \\ \sin\psi &\cos\psi & 0\\ 0 & 0 &1 \end{bmatrix} \begin{bmatrix} \cos\theta &0 &\sin\theta\\ 0 & 1 &0\\ -\sin\theta &0 &\cos\theta\\ \end{bmatrix} \begin{bmatrix} 1 & 0 &0 \\ 0 &\cos\theta &-\sin\theta \\ 0 &\sin\theta &\cos\theta \end{bmatrix} \begin{bmatrix} X \\Y \\Z \end{bmatrix} \\= \begin{bmatrix} \cos\theta\cos\psi &-\cos\phi\sin\psi+\sin\phi\sin\theta\cos\psi &\sin\phi\sin\psi+\cos\phi\sin\theta\cos\psi \\ \cos\theta\sin\psi &\cos\phi\cos\psi+\sin\phi\sin\theta\sin\psi &-\sin\phi\cos\psi+\cos\phi\sin\theta\sin\psi \\ -\sin\theta &\sin\phi\cos\theta &\cos\phi\cos\theta \end{bmatrix} \begin{bmatrix} X \\Y \\Z \end{bmatrix} \qquad(1) ???xyz????=M(ψ,θ,?)???XYZ????=Mz?(ψ)?My?(θ)?Mx?(?)????XYZ????=???cosψsinψ0??sinψcosψ0?001???????cosθ0?sinθ?010?sinθ0cosθ???????100?0cosθsinθ?0?sinθcosθ???????XYZ????=???cosθcosψcosθsinψ?sinθ??cos?sinψ+sin?sinθcosψcos?cosψ+sin?sinθsinψsin?cosθ?sin?sinψ+cos?sinθcosψ?sin?cosψ+cos?sinθsinψcos?cosθ???????XYZ????(1)
旋轉矩陣M(ψ,θ,?)M(\psi,\theta,\phi)M(ψ,θ,?)是將點P在相機坐標系中的坐標分量轉換到相機旋轉前的原坐標系中的坐標分量。
Cesium中,使用Matrix3對象表示3×3矩陣,其中表示相機HeadingPitchRoll的旋轉矩陣(M(ψ,θ,?)M(\psi,\theta,\phi)M(ψ,θ,?))代碼如下:
/*** Computes a 3x3 rotation matrix from the provided headingPitchRoll. (see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles )** @param {HeadingPitchRoll} headingPitchRoll the headingPitchRoll to use.* @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.* @returns {Matrix3} The 3x3 rotation matrix from this headingPitchRoll.*/Matrix3.fromHeadingPitchRoll = function(headingPitchRoll, result) {//>>includeStart('debug', pragmas.debug);Check.typeOf.object('headingPitchRoll', headingPitchRoll);//>>includeEnd('debug');// 注意此處,為了使用正常的321轉序,此處需將heding和pitch的角度加上負號var cosTheta = Math.cos(-headingPitchRoll.pitch);var cosPsi = Math.cos(-headingPitchRoll.heading);var cosPhi = Math.cos(headingPitchRoll.roll);var sinTheta = Math.sin(-headingPitchRoll.pitch);var sinPsi = Math.sin(-headingPitchRoll.heading);var sinPhi = Math.sin(headingPitchRoll.roll);// 第1行矩陣元素var m00 = cosTheta * cosPsi;var m01 = -cosPhi * sinPsi + sinPhi * sinTheta * cosPsi;var m02 = sinPhi * sinPsi + cosPhi * sinTheta * cosPsi;// 第2行矩陣元素var m10 = cosTheta * sinPsi;var m11 = cosPhi * cosPsi + sinPhi * sinTheta * sinPsi;var m12 = -sinPhi * cosPsi + cosPhi * sinTheta * sinPsi;// 第3行矩陣元素var m20 = -sinTheta;var m21 = sinPhi * cosTheta;var m22 = cosPhi * cosTheta;if (!defined(result)) {return new Matrix3(m00, m01, m02,m10, m11, m12,m20, m21, m22);}result[0] = m00;result[1] = m10;result[2] = m20;result[3] = m01;result[4] = m11;result[5] = m21;result[6] = m02;result[7] = m12;result[8] = m22;return result;};四元素的表示
參考Cesium中的相機—四元素一文中連續旋轉的四元素乘法規則,相機從原坐標系o?xyzo-xyzo?xyz歷經321(ZYX)三次旋轉的四元素表示為:
q(ψ,θ,?)=qz(ψ)?qy(θ)?qx(?)=[cos?(ψ/2)00sin?(ψ/2)][cos?(θ/2)0sin?(θ/2)0][cos?(?/2)sin?(?/2)00]=[cos?(?/2)cos?(θ/2)cos?(ψ/2)+sin?(?/2)sin?(θ/2)sin?(ψ/2)sin?(?/2)cos?(θ/2)cos?(ψ/2)?cos?(?/2)sin?(θ/2)sin?(ψ/2)cos?(?/2)sin?(θ/2)cos?(ψ/2)+sin?(?/2)cos?(θ/2)sin?(ψ/2)cos?(?/2)cos?(θ/2)sin?(ψ/2)?sin?(?/2)sin?(θ/2)cos?(ψ/2)](2)q(\psi,\theta,\phi)=q_z(\psi)\cdot q_y(\theta) \cdot q_x(\phi)= \begin{bmatrix}\cos(\psi/2) \\0 \\0 \\ \sin(\psi/2) \end{bmatrix} \begin{bmatrix}\cos(\theta/2) \\0 \\ \sin(\theta/2) \\0 \end{bmatrix} \begin{bmatrix}\cos(\phi/2) \\ \sin(\phi/2) \\0 \\0 \end{bmatrix} \\= \begin{bmatrix} \cos(\phi/2)\cos(\theta/2)\cos(\psi/2)+\sin(\phi/2)\sin(\theta/2)\sin(\psi/2)\\ \sin(\phi/2)\cos(\theta/2)\cos(\psi/2)-\cos(\phi/2)\sin(\theta/2)\sin(\psi/2)\\ \cos(\phi/2)\sin(\theta/2)\cos(\psi/2)+\sin(\phi/2)\cos(\theta/2)\sin(\psi/2)\\ \cos(\phi/2)\cos(\theta/2)\sin(\psi/2)-\sin(\phi/2)\sin(\theta/2)\cos(\psi/2) \end{bmatrix} \qquad(2)q(ψ,θ,?)=qz?(ψ)?qy?(θ)?qx?(?)=?????cos(ψ/2)00sin(ψ/2)???????????cos(θ/2)0sin(θ/2)0???????????cos(?/2)sin(?/2)00??????=?????cos(?/2)cos(θ/2)cos(ψ/2)+sin(?/2)sin(θ/2)sin(ψ/2)sin(?/2)cos(θ/2)cos(ψ/2)?cos(?/2)sin(θ/2)sin(ψ/2)cos(?/2)sin(θ/2)cos(ψ/2)+sin(?/2)cos(θ/2)sin(ψ/2)cos(?/2)cos(θ/2)sin(ψ/2)?sin(?/2)sin(θ/2)cos(ψ/2)??????(2)
上式中,qz(ψ)q_z(\psi)qz?(ψ)表示繞Z軸旋轉ψ\psiψ角度的四元素,其它類似。
參考Cesium中的相機—四元素文中式(5),將四元素q(ψ,θ,?)q(\psi,\theta,\phi)q(ψ,θ,?)可表示為旋轉矩陣,則本文中,式(1)和式(2)相等。
Cesium中,使用對象Quaternion表示四元素,則由表示相機HeadingPitchRoll的表示的四元素源代碼如下:
// 臨時四元素對象存儲var scratchHPRQuaternion = new Quaternion();var scratchHeadingQuaternion = new Quaternion();var scratchPitchQuaternion = new Quaternion();var scratchRollQuaternion = new Quaternion();/*** Computes a rotation from the given heading, pitch and roll angles. Heading is the rotation about the* negative z axis. Pitch is the rotation about the negative y axis. Roll is the rotation about* the positive x axis.** @param {HeadingPitchRoll} headingPitchRoll The rotation expressed as a heading, pitch and roll.* @param {Quaternion} [result] The object onto which to store the result.* @returns {Quaternion} The modified result parameter or a new Quaternion instance if none was provided.*/Quaternion.fromHeadingPitchRoll = function(headingPitchRoll, result) {//>>includeStart('debug', pragmas.debug);Check.typeOf.object('headingPitchRoll', headingPitchRoll);//>>includeEnd('debug');// 注意此處,為了使用正常的321轉序,此處需將heding和pitch的角度加上負號// 最終的四元素=qz?qy?qxscratchRollQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_X, headingPitchRoll.roll, scratchHPRQuaternion);scratchPitchQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Y, -headingPitchRoll.pitch, result);result = Quaternion.multiply(scratchPitchQuaternion, scratchRollQuaternion, scratchPitchQuaternion);scratchHeadingQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Z, -headingPitchRoll.heading, scratchHPRQuaternion);return Quaternion.multiply(scratchHeadingQuaternion, result, result);};小結
Cesium中,使用Heading /Pitch /Roll來分別表示相機坐標系繞Z、Y、X軸的3次連續旋轉,需要注意的是,Heading和Pitch的旋轉角度與普通右手旋轉的符號相反,因此在計算中需要在前兩個角度加上負號,再進行321轉序的旋轉。
Cesium采用的是第二種旋轉方式,因此連續旋轉時,最先旋轉的矩陣(或四元素)在最左邊。
由HeadingPitchRoll創建的旋轉矩陣Matrix3(或者四元素表示的)是把相機坐標系中的點坐標轉換為原坐標系中(不一定是世界坐標系)的坐標。
總結
以上是生活随笔為你收集整理的Cesium中的相机—HeadingPitchRoll的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【贪玩巴斯】带你一起攻克英语语法长难句—
- 下一篇: 浏览器测试