【问题标题】:AxisAngleRotation3D to Quaternion gives unexpected resultAxisAngleRotation3D 到四元数给出了意想不到的结果
【发布时间】:2016-08-02 14:43:23
【问题描述】:

我正在 WPF 3D 中开发一个控制器(使用 C#),以便能够使用 Move()- 和 Pitch()-函数轻松移动和旋转 ProjectionCamera。我的控制器将变成一个Behavior<ProjectionCamera>,可以附加到ProjectionCamera。为了初始化控制器,我想计算相机的当前旋转,方法是查看相机当前的UpForward-vector,并将它们与默认相机方向(Up = [0 1 0]Forward = [0 0 -1])。换句话说,我想计算一个旋转,将相机默认方向转换为当前方向。

最终,我想将旋转表示为单个 Quaternion,但作为中间步骤,我首先计算 zNZ 形式的 Proper Euler Angle 旋转 表示作为AxisAngleRotation3D-values,遵循Wikipedia的默认定义:

var alphaRotation = CalculateRotation(z, x, N);
var betaRotation = CalculateRotation(N, z, Z);
var gammaRotation = CalculateRotation(Z, N, X);

CalculateRotation(Vector3D axisOfRotation, Vector3D from, Vector3D to) : AxisAngleRotation3D

根据一些单元测试,欧拉角旋转似乎计算正确。但是,当我将这些旋转转换为单个 Quaternion 时,生成的 Quaternion 表示与欧拉角旋转不同的旋转,我不知道为什么。

这就是我将欧拉角转换为单个四元数的方法:

var rotation =
    new Quaternion(alphaRotation.Axis, alphaRotation.Angle) *
    new Quaternion(betaRotation.Axis, betaRotation.Angle) *
    new Quaternion(gammaRotation.Axis, gammaRotation.Angle);

例如,当我用[1 0 0]UpDirection 初始化ProjectionCamera 时,这意味着它围绕LookDirection 轴([0 0 -1])旋转了90 度,计算出的欧拉角旋转如下:

alphaRotation -->  90 deg. around [0 1 0]
betaRotation  -->  90 deg. around [0 0 -1]
gammaRotation --> -90 deg. around [1 0 0]

我的测试证实,当按顺序应用时,这些旋转会将默认的Up-vector ([0 1 0]) 转换为当前的Up-vector ([1 0 0]),有效地将其旋转 90 度。围绕[0 0 -1] 轴。 (手动验证也很简单。)

但是,当我将计算出的QuaternionRotation 应用到默认的Up-vector 时,它被转换为向量[-1 0 0],这显然是错误的。我在单元测试中对这些结果进行了硬编码,得到了相同的结果:

    [TestMethod]
    public void ConversionTest()
    {
        var vector = new Vector3D(0, 1, 0);

        var alphaRotation = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 90);
        var betaRotation = new AxisAngleRotation3D(new Vector3D(0, 0, -1), 90);
        var gammaRotation = new AxisAngleRotation3D(new Vector3D(1, 0, 0), -90);

        var a = new Quaternion(alphaRotation.Axis, alphaRotation.Angle);
        var b = new Quaternion(betaRotation.Axis, betaRotation.Angle);
        var c = new Quaternion(gammaRotation.Axis, gammaRotation.Angle);
        var combinedRotation = a * b * c;

        var x = Apply(vector, alphaRotation, betaRotation, gammaRotation);
        var y = Apply(vector, combinedRotation);
    }

当您运行上面的测试时,您会看到 x 为您提供了预期的向量 ([1 0 0]),但 y 会有所不同,它应该是完全相同的旋转。

我错过了什么?

【问题讨论】:

  • @Sinatr:是的,我知道轮换的顺序很重要。你发现我的代码有什么错误吗?因为据我所知,欧拉角必须按 (alpha, beta, gamma) 的顺序应用,并且要将这个旋转序列表示为单个四元数,您还必须按这个顺序乘以旋转 (alpha * beta *伽玛)。

标签: c# wpf 3d rotation quaternions


【解决方案1】:

我解决了这个问题。显然,个人Quaternions 的乘法顺序应该颠倒。因此,要将欧拉角(或任何一组旋转)转换为单个 Quaternion.NET,您应该执行以下操作:

var rotation = gammaRotation * betaRotation * alphaRotation;

其中rotation 表示在几何上首先应用alphaRotation,然后是betaRotation,最后是gammaRotation。我只是希望他们已经记录了这一点,因为订单的含义取决于您正在使用的特定库....

【讨论】:

    猜你喜欢
    • 2019-05-19
    • 2017-01-05
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 2014-06-22
    • 2021-12-17
    • 2021-04-22
    • 2016-02-13
    相关资源
    最近更新 更多