用倾角计算重力

Tho*_*ian 12 c# physics accelerometer windows-phone-8

如何将倾角仪(俯仰,偏航和滚转)转换为系统中预期的重力[X,Y,Z]

处于某个俯仰角,俯仰角和俯仰角的静止系统应该在某个位置拉到地面[X*g,Y*g,Z*g],假设这是出于模拟目的.我想创建一个输入是Pitch,Yaw和Roll的函数,输出是一个Vector3(X,Y,Z)下降时刻.

意味着一个物体静止,它向后向下会输出类似于[0,-1,0]加速度计和a的东西[pitch,yaw,roll]->[0,-1,0],其中[0,-1,0]减去了[0,-1,0]结果[0,0,0].或者如果我们以1g的速度向左拉,我们有一个加速度计显示[1,-1,0]新的值[1,0,0].

系统背面[俯仰,偏航,滚动] - > [0,-1,0]功能是我所追求的

Vector3 OriToXYZ(float pitch, float yaw, float roll){
    Vector3 XYZ = Vector.Zero;
    //Simulate what the XYZ should be on a object in this orientation
    //oriented against gravity
    ...
    return XYZ;
}
Run Code Online (Sandbox Code Playgroud)

是的我知道,因为下面的解释显示我无法检测系统是否颠倒或不基于滚动仅作为滚动给出(-90到90)但这是一个不同的问题).

这就是方向的布局方式. 倾斜度

有关使用此信息的原因,内容和方式的更多信息,请继续阅读.

计划是使用测斜仪作为陀螺仪的替代方案,通过模拟/计算方向上的重力预期值(俯仰,偏航,滚动)来将重力分量移除到加速度计数据.

由于加速度计(XYZ)是重力(XYZ)和运动(XYZ)两个组件的组合,我假设gravity(XYZ)-calc_g(XYZ) = 0,允许我执行accelerometer(XYZ)- calc_g(XYZ) =movement(XYZ)

说明为什么我认为这是可能的.当我绘制手机的数值并将手机侧向移动时略微摆动,看起来像正弦/余弦运动的线条是倾斜的,其他线条是XYZ加速度计:

  • red =(Pitch&accell-X)
  • 绿色=(Yaw&accell-Y)
  • blue =(Roll&accell-Z)

加速度值乘以90,因为它的范围为(-2到2),因此它在图纸中的范围从-180到180,俯仰偏航和滚转范围如上面的指示所示.图像的中间是Y = 0,左边是X = 0(X =时间)

传感器测量

Romasz解决了解决方案

VectorX = Cos(Pitch)*Sin(Roll);
VectorY = -Sin(Pitch);
VectorZ = -Cos(Pitch)*Cos(Roll);
Run Code Online (Sandbox Code Playgroud)

结果 在此输入图像描述

*图表不是来自同一测量.

Rom*_*asz 4

(在评论后(完全)编辑)

如果您想计算倾斜方向上的重力分量,那么您只需要俯仰和滚动(按照 WP 约定)-绕 Z 轴(偏航)的旋转对加速度计没有影响。公式应如下所示:

VectorX = Cos(Pitch)*Sin(Roll);
VectorY = -Sin(Pitch);
VectorZ = -Cos(Pitch)*Cos(Roll);
Run Code Online (Sandbox Code Playgroud)

(您可以在此处此处找到类似的公式)

由于多种原因,可能会出现一些准确性问题:

  • 倾角为单精度,加速度为双精度
  • 倾斜仪可能需要一段时间才能稳定
  • 从倾斜计和加速度计执行读数时的计时不同(请注意,因为这些传感器具有不同的最小报告间隔)
  • 加速度计根据其位置具有不同的精度

另请注意,因为加速度计可能会过载(其范围为 +-2g) - 例如,如果您折断手机。


为了测试它,我编写了一个简单的应用程序(您可以在此处下载) - 比较加速度计指示的值和通过倾斜计算的值。因为加速度计的值与重力有关,所以它很简单:
在 XAML 中 - 几个 TextBlock:

<Grid x:Name="LayoutRoot" Background="Transparent" Margin="20">
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0" VerticalAlignment="Center" Orientation="Horizontal">
            <TextBlock Text="Incliation:" FontSize="16"/>
            <TextBlock Name="incXTB" Margin="10"/>
            <TextBlock Name="incYTB" Margin="10"/>
        </StackPanel>
        <StackPanel Grid.Row="1" VerticalAlignment="Center" Orientation="Horizontal">
            <TextBlock Text="Accelerometers:" FontSize="16"/>
            <TextBlock Name="accXTB" Margin="10"/>
            <TextBlock Name="accYTB" Margin="10"/>
            <TextBlock Name="accZTB" Margin="10"/>
        </StackPanel>
        <StackPanel Grid.Row="2" VerticalAlignment="Center" Orientation="Horizontal">
            <TextBlock Text="Through Inc:" FontSize="16"/>
            <TextBlock Name="accincXTB" Margin="10"/>
            <TextBlock Name="accincYTB" Margin="10"/>
            <TextBlock Name="accincZTB" Margin="10"/>
        </StackPanel>
</Grid>
Run Code Online (Sandbox Code Playgroud)

在后面的代码中:

public partial class MainPage : PhoneApplicationPage
{
    private Inclinometer myIncMeter = null;
    private float inclX = 0;
    private float inclY = 0;

    private Accelerometer myAccel = null;
    private double accX = 0;
    private double accY = 0;
    private double accZ = 0;

    public MainPage()
    {
        InitializeComponent();
        this.DataContext = this;
        myIncMeter = Inclinometer.GetDefault();
        myIncMeter.ReportInterval = myIncMeter.MinimumReportInterval;
        myAccel = Accelerometer.GetDefault();
        myAccel.ReportInterval = myIncMeter.MinimumReportInterval;

        CompositionTarget.Rendering += CompositionTarget_Rendering;
    }

    private void CompositionTarget_Rendering(object sender, EventArgs e)
    {
        InclinometerReading incRead = myIncMeter.GetCurrentReading();
        AccelerometerReading accRead = myAccel.GetCurrentReading();

        accX = accRead.AccelerationX;
        accY = accRead.AccelerationY;
        accZ = accRead.AccelerationZ;

        inclX = incRead.RollDegrees;
        inclY = incRead.PitchDegrees;

        incXTB.Text = "X: " + inclX.ToString("0.00");
        incYTB.Text = "Y: " + inclY.ToString("0.00");

        accXTB.Text = "X: " + accX.ToString("0.00");
        accYTB.Text = "Y: " + accY.ToString("0.00");
        accZTB.Text = "Z: " + accZ.ToString("0.00");

        accincXTB.Text = "X: " + ((Math.Cos(inclY * Math.PI / 180) * Math.Sin(inclX * Math.PI / 180))).ToString("0.00");
        accincYTB.Text = "Y: " + (-Math.Sin(inclY * Math.PI / 180)).ToString("0.00");
        accincZTB.Text = "Z: " + (-(Math.Cos(inclX * Math.PI / 180) * Math.Cos(inclY * Math.PI / 180))).ToString("0.00");
    }
}
Run Code Online (Sandbox Code Playgroud)