Cesiumjs从矢量开始计算俯仰,偏航

时间:2018-06-23 01:25:01

标签: javascript rotation linear-algebra quaternions cesium

我已经将Cesium的一个模型加载到场景中,并且我想使用两个点来计算模型的方向,这就是我创建的功能。

// calculate the direction which the model is facing
calculateOrientation({ position, nextPosition }) {

    let dir = new Cesium.Cartesian3();
    let normalizedDir = new Cesium.Cartesian3();

    Cesium.Cartesian3.subtract(nextPosition, position, dir);
    Cesium.Cartesian3.normalize(dir, normalizedDir);

    var heading = Math.acos(normalizedDir.x);
    var pitch = Math.acos(normalizedDir.y);
    var roll = 0;

    var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
    var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);
    return orientation;
}

但是我得到的轮换没有任何意义。我的数学错了吗?

更新

在@Keshet给出的第一个答案之后,我抬起头来如何找到平面与矢量之间的夹角。我想知道是否能找到每个平面的法线与-90之间的角度,我应该得到正确的角度,但是我不确定这是否正确。

我也不知道Cesium Axis的工作原理,也找不到任何描述它的文档。例如XY平面等。

    let dir = new Cesium.Cartesian3();
    let xyNormal = new Cesium.Cartesian3(0,0,1);
    let xzNormal = new Cesium.Cartesian3(0,1,0);
    let yzNormal = new Cesium.Cartesian3(1,0,0);

    Cesium.Cartesian3.subtract(nextPosition, position, dir);

    let xyAngle = Cesium.Math.PI_OVER_TWO - Cesium.Cartesian3.angleBetween(dir, xyNormal);
    let xzAngle = Cesium.Math.PI_OVER_TWO - Cesium.Cartesian3.angleBetween(dir, xzNormal);
    let yzAngle = Cesium.Math.PI_OVER_TWO - Cesium.Cartesian3.angleBetween(dir, yzNormal);

更新2

使用atan2进行@IIan建议后,代码如下:

    Cesium.Cartesian3.subtract(position, nextPosition, dir);

    // create the mapped to plane vectors, and get the 
    // normalized versions
    let xyMappedVectorNormalized = new Cesium.Cartesian3(0, 0, 0);
    let xyMappedVector = new Cesium.Cartesian3(dir.x, dir.y, 0);

    let xzMappedVectorNormalized = new Cesium.Cartesian3(0, 0, 0);
    let xzMappedVector = new Cesium.Cartesian3(dir.x, 0, dir.z);

    let yzMappedVectorNormalized = new Cesium.Cartesian3(0, 0, 0);
    let yzMappedVector = new Cesium.Cartesian3(0, dir.y, dir.z);

    Cesium.Cartesian3.normalize(xyMappedVector, xyMappedVectorNormalized);
    Cesium.Cartesian3.normalize(xzMappedVector, xzMappedVectorNormalized);
    Cesium.Cartesian3.normalize(yzMappedVector, yzMappedVectorNormalized);

    // calculate the angles
    let xyAngle = Math.atan2(xyMappedVectorNormalized.y, xyMappedVectorNormalized.x);
    let xzAngle = Math.atan2(xzMappedVectorNormalized.z, xzMappedVectorNormalized.x);
    let yzAngle = Math.atan2(yzMappedVectorNormalized.z, yzMappedVectorNormalized.y);

1 个答案:

答案 0 :(得分:0)

首先,我们需要解释航向角,俯仰角和侧倾角代表什么。

  1. 航向角表示相对于XY平面的弧度角
  2. 俯仰角表示相对于XZ平面的弧度角
  3. 侧倾角表示相对于YZ平面的弧度角

您不能简单地使用x / y来计算航向/俯仰

var heading = Math.acos(normalizedDir.x);
var pitch = Math.acos(normalizedDir.y);

您需要获取每个平面上的总角度。

在XY平面上,将使用归一化||(X,Y)| 在XZ平面上,您将使用归一化|(X,Z)| 在YZ平面上,您将使用归一化|(Y,Z)|


更新

|(X,Y)|代表单位圆上的一个点。

其中(sin(theta),cos(theta))= |(X,Y)|

IE,当theta = 0时,|(X,Y)| =(1,0) 当theta = PI / 2时,|(X,Y)| =(0,1)

这个theta就是您用于航向的角度


然后,您可以调用arctan2函数来计算相对于平面的角度。

atan2(y,x)= theta其中[x,y]是使用相应的归一化2D向量从上方计算的

请注意:atan2给出了以(-PI,PI]为边界的角度

示例

如果您的3D矢量是(1、2、3)-在XY平面上X = 1,Y =2。

然后将(1,2)归一化=>(1 / sqrt(5),2 / sqrt(5))

然后,您可以使用atan2(2 / sqrt(5),1 / sqrt(5)来计算航向的弧度角