首页 > 解决方案 > 旋转精度误差建立得太快?

问题描述

当一个接一个地应用旋转时,精度误差会累积。

但我对错误的累积速度感到惊讶。

在这个例子中,我比较了 2 个理论上等效的变换。

在实践中,我只做 2 次而不是 1 次旋转就会得到 0.02 度的误差。

我期望错误会更低。

有没有办法让这两个转换的结果更接近?除了使用双精度变量。

#include <glm/gtx/rotate_vector.hpp>

double RadToDeg(double rad) 
{
    return rad * 180.0 / M_PI;
}

const glm::vec3 UP(0, 0, 1);

void CompareRotations()
{
    glm::vec3 v0 = UP;
    glm::vec3 v1 = glm::normalize((glm::vec3(0.0491, 0.0057, 0.9987)));
    glm::vec3 v2 = glm::normalize((glm::vec3(0.0493, 0.0057, 0.9987)));

    glm::vec3 axis_0_to_1 = glm::cross(v0, v1);
    glm::vec3 axis_1_to_2 = glm::cross(v1, v2);
    glm::vec3 axis_global = glm::cross(v0, v2);

    float angle_0_to_1 = RadToDeg(acos(glm::dot(v0, v1)));
    float angle_1_to_2 = RadToDeg(acos(glm::dot(v1, v2)));
    float angle_global = RadToDeg(acos(glm::dot(v0, v2)));

    glm::vec3 v_step = UP;
    v_step = glm::rotate(v_step, angle_0_to_1, axis_0_to_1);
    v_step = glm::rotate(v_step, angle_1_to_2, axis_1_to_2);

    glm::vec3 v_glob = UP;
    v_glob = glm::rotate(v_glob, angle_global, axis_global);

    float angle = RadToDeg(acos(glm::dot(v_step, v_glob)));
    if (angle > 0.01)
    {
       printf("error");
    }
}

标签: c++openglglm-math

解决方案


如果您只想继续沿同一轴旋转,那么最好只增加围绕该轴的旋转角度并每次从该角度重新计算一个新矩阵。请注意,您可以直接计算一个矩阵以围绕任意轴旋转。例如,从欧拉角构建旋转通常既不需要也不是很好的解决方案(奇点,数值上不理想,行为不是很直观)。有一个重载glm::rotate()需要一个轴和一个角度,你可以使用它。

如果您确实必须围绕任意轴连接许多任意旋转,那么使用四元数来表示您的旋转可能在数值上更稳定。由于您已经在使用 GLM,您可以只使用其中的四元数。您可能会发现本教程很有用。


推荐阅读