从加速度数据创建四元数

所以我有一个加速度传感器,可以提供加速度数据。设备当前停在某个位置,因此数据如下所示(每个轴都有一些噪音):


ACCELX = 264

ACCELY = -43

ACCELZ = 964

然后是一个代表设备的 3D 模型,“我想要的”就是这个 3D 模型来表示真实设备的方向。在我试图了解.NET中四元数的用法时,这是我狼吞虎咽的代码:


/* globals */

Vector3D PrevVector = new Vector3D(0, 0, 0);

ModelVisual3D model; // initialized and model file loaded


private async void TimerEvent() 

{

    RotateTransform3D rot = new RotateTransform3D();

    QuaternionRotation3D q = new QuaternionRotation3D();


    double x = 0, y = 0, z = 0;


    List<Reading> results = await Device.ReadSensor();


    foreach (Reading r in results)

    {

        switch (r.Type)

        {

            case "RPF_SEN_ACCELX":

                x = r.Value;

                break;


            case "RPF_SEN_ACCELY":

                y = r.Value;

                break;


            case "RPF_SEN_ACCELZ":

                z = r.Value;

                break;

        }

    }


    double angle = Vector3D.AngleBetween(new Vector3D(x, y, z), PrevVector);


    q.Quaternion = new Quaternion(new Vector3D(x, y, z), angle);


    rot.Rotation = q;

    model.Transform = rot;


    PrevVector = new Vector3D(x, y, z); 

}

移动我的真实设备确实会导致报告值发生变化,但屏幕上的模型只是在我看来随机的方向上抽搐,与噪音相差无几,似乎与我如何旋转真实设备无关。我很确定我正在错误地构建和使用四元数。我该怎么做才对?


这是带有 WPF 的 .NET。还有HelixToolkit.WPF可用,但我还没有看到任何从那里的加速度数据创建四元数的函数。更高级别的框架(例如 Unreal Engine 或 Unity)不适用于此项目。


明月笑刀无情
浏览 248回答 2
2回答

DIEA

事实证明我的问题具有完全不同的性质:我必须使用一个名为Transform3DGroup. 这是必须更改代码以启用绕 Z 轴旋转的方式:/* globals */ModelVisual3D model; // initialized and model file loadedTransform3DGroup tg = new Transform3DGroup();private async void TimerEvent()&nbsp;{&nbsp; &nbsp; RotateTransform3D rot = new RotateTransform3D();&nbsp; &nbsp; QuaternionRotation3D q = new QuaternionRotation3D();&nbsp; &nbsp; double x = 0, y = 0, z = 0;&nbsp; &nbsp; List<Reading> results = await Device.ReadSensor();&nbsp; &nbsp; foreach (Reading r in results)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; switch (r.Type)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "RPF_SEN_ACCELX":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = r.Value;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "RPF_SEN_ACCELY":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y = r.Value;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case "RPF_SEN_ACCELZ":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; z = r.Value;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; angle = GetAngle(x, y).ToDegrees();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; q.Quaternion = new Quaternion(new Vector3D(0, 0, 1), angle);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; rot.Rotation = q;&nbsp; &nbsp; &nbsp; &nbsp; tg.Children.Clear();&nbsp; &nbsp; &nbsp; &nbsp; tg.Children.Add(rot);&nbsp; &nbsp; &nbsp; &nbsp; model.Transform = tg; // Use Transform3DGroup!&nbsp; &nbsp; }}我还没有找到任何关于强制使用Transform3DGroup.为了完整起见,以下是Bill Wallis 在 Math Overflow 上GetAngle()得出的内部结构:private double GetAngle(double x, double y){&nbsp; &nbsp; if (x > 0)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return 2 * Math.PI - Math.Atan(y / x);&nbsp; &nbsp; }&nbsp; &nbsp; else if (x < 0)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return Math.PI - Math.Atan(y / x);&nbsp; &nbsp; }&nbsp; &nbsp; else // x == 0&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return 2 * Math.PI - Math.Sign(y) * Math.PI / 2;&nbsp; &nbsp; }}以及 double 类型的扩展以在弧度和度数之间转换双精度数(类外,命名空间内):public static class NumericExtensions{&nbsp; &nbsp; public static double ToRadians(this double val)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return (Math.PI / 180) * val;&nbsp; &nbsp; }&nbsp; &nbsp; public static double ToDegrees(this double val)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return (180 / Math.PI) * val;&nbsp; &nbsp; }}

沧海一幻觉

您的传感器输出旋转值是累积的还是差异的?有时输出旋转是差异,您需要先前的旋转值加上差异来计算当前的新旋转值。您可以尝试保存之前的四元数并将当前四元数与之前的四元数相加,以获得新的累积旋转。
打开App,查看更多内容
随时随地看视频慕课网APP