javascript - Cesiumjs 从矢量计算俯仰、偏航、航向

标签 javascript rotation linear-algebra quaternions cesiumjs

我将 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 给出第一个答案后,我查找了如何找到平面和矢量之间的 Angular 。我想如果我找到每个平面的法线和 -90 之间的 Angular ,我应该得到正确的 Angular ,但我不确定这是否正确。

我也不知道 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

根据@IIan 建议使用 atan2,这里是代码:

    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);

最佳答案

首先,我们需要解释航向 Angular 、俯仰 Angular 和横滚 Angular 代表什么。

  1. 航向 Angular 表示相对于 XY 平面的弧度 Angular
  2. 俯仰 Angular 表示相对于 XZ 平面的弧度 Angular
  3. 滚动 Angular 表示相对于 YZ 平面的弧度 Angular

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

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

您需要获得每个平面上的总 Angular 。

在 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 将是您用于航向的 Angular


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

atan2(y, x) = theta 其中 [x, y] 是使用相应的归一化二维向量从上面计算得出的

注意:atan2 给出的 Angular 范围为 (-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) 来计算航向的弧度 Angular

关于javascript - Cesiumjs 从矢量计算俯仰、偏航、航向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50997196/

相关文章:

javascript - 使用 Mandrill 发送 Meteor Email.send

javascript - GWT java.util.Date 序列化

CSS 边框旋转

python - 如何在 Python 中计算分解 A=P[I_r,0;0,0]Q?

python - 为什么 numpy 的 einsum 比 numpy 的内置函数慢?

javascript - AJAX成功回调是同步的吗?

javascript - 这两个 JavaScript 作用域链示例有什么区别?

css3 样式在 ie 中旋转,有人知道如何实现吗?

ios - 在不设置自动旋转的情况下强制进入横向模式

javascript - 在javascript中创建 "m x n"二维数组