Вращение объекта в касательном пространстве земного шара - PullRequest
3 голосов
/ 07 октября 2019

Учитывая два следующих входа:

  • точка на сфере (как наблюдатель на Земле);
  • и матрица мираобъекта в космосе (положение и ориентация спутника),

как получить азимут и угол места объекта в касательном пространстве точки на сфере (высота и азимут, на которые должен смотреть наблюдатель)? В частности, когда объект находится точно в зените, поворот рыскания (вращение вокруг вертикальной оси) должен учитывать азимут (так что, хотя наблюдатель смотрит прямо вверх, его плечи будут смотреть на тот же азимут, что и объект).

Математика, которую я до сих пор пробовал:

  1. , чтобы поместить спутник в касательное пространство (умножить его мировую матрицу на обратную матрицу касательного пространства наГлобус). Или то же самое с кватернионами. Поворот эйлера затем выводится из результирующей матрицы (или результирующего кватерниона) с приоритетом "ZXY", а Z и X интерпретируются как азимут и угол места. Но это дает неправильные числа, так как часть вращения, кажется, часто интерпретируется как крен (вращение оси Y), который я хочу равным нулю.
  2. Интуитивный подход также состоит в том, чтобы вычислить угол между вектором наблюдателя и положением объекта с вертикальной осью, чтобы вывести высоту;в то время как азимут задается углом между касательным севером и предполагаемым положением объекта на «касательной земле» (плюс еще немного математики, чтобы отточить этот конкретный вывод). Но этот подход не работает для случая объекта в зените.

Ресурсы существуют онлайн, но не с этими конкретными входными данными и необходимостью поддержки случая зенита.


Между прочим, программа написана на машинописном языке для three.js, поэтому для первого решения, описанного выше, код выглядит следующим образом:

function getRotationAtPoint(
    object: THREE.Object3D,
    point: THREE.Vector3
): { azimuth: number, elevation: number } {
    // 1. Get the matrix of the tangent space of the observer.
    const tangentSpaceMatrix = new THREE.Matrix4();
    const baseTangentSpaceAxes = getBaseTangentAxesOnSphere(point);
    tangentSpaceMatrix.makeBasis(...baseTangentSpaceAxes);

    // 2. Tranform the object's matrix in tangent space of observer.
    const inverseMatrix = new THREE.Matrix4().getInverse(tangentSpaceMatrix);
    const objectMatrix = object.matrixWorld.clone().multiply(inverseMatrix);

    // 3. Get the angles.
    const euler = new THREE.Euler().setFromRotationMatrix(objectMatrix);
    return {
        azimuth: euler.z,
        elevation: euler.x
    };
}

Кроме того, Three.js предлагает ссылки на верхнюю ось * 1031. * в некоторых случаях, однако программа, с которой я имею дело, вычисляет все непосредственно в матрицах объектов, и оси вверх нельзя доверять.

...