从陀螺仪和加速度计获得倾斜角度wp8

时间:2013-07-15 09:53:34

标签: c# windows-phone-8 accelerometer gyroscope

当我在赛道上骑摩托车时,我想计算倾斜角度,并考虑使用我的lumia 920。引起我兴趣的产品是http://leanometer.com。我发现仅使用陀螺仪是不好的,因为它会随着时间的推移而漂移,所以使用带加速度计的互补滤波器似乎是可行的方法。我从http://www.pieter-jan.com/node/11发现了这段代码:

#define ACCELEROMETER_SENSITIVITY 8192.0
#define GYROSCOPE_SENSITIVITY 65.536

#define M_PI 3.14159265359      

#define dt 0.01                         // 10 ms sample rate!    

void ComplementaryFilter(short accData[3], short gyrData[3], float *pitch, float *roll)
{
    float pitchAcc, rollAcc;               

    // Integrate the gyroscope data -> int(angularSpeed) = angle
    *pitch += ((float)gyrData[0] / GYROSCOPE_SENSITIVITY) * dt; // Angle around the X-axis
    *roll -= ((float)gyrData[1] / GYROSCOPE_SENSITIVITY) * dt;    // Angle around the Y-axis

    // Compensate for drift with accelerometer data if !bullshit
    // Sensitivity = -2 to 2 G at 16Bit -> 2G = 32768 && 0.5G = 8192
    int forceMagnitudeApprox = abs(accData[0]) + abs(accData[1]) + abs(accData[2]);
    if (forceMagnitudeApprox > 8192 && forceMagnitudeApprox < 32768)
    {
    // Turning around the X axis results in a vector on the Y-axis
        pitchAcc = atan2f((float)accData[1], (float)accData[2]) * 180 / M_PI;
        *pitch = *pitch * 0.98 + pitchAcc * 0.02;

    // Turning around the Y axis results in a vector on the X-axis
        rollAcc = atan2f((float)accData[0], (float)accData[2]) * 180 / M_PI;
        *roll = *roll * 0.98 + rollAcc * 0.02;
    }
} 

我已将此代码转换为c#,但我遇到问题需要准确一些。有一件事是我不知道陀螺仪/加速度计的灵敏度或如何获得它。过了一会儿,我开始更多关于acclerometer和角度的google,并发现:http://www.hobbytronics.co.uk/accelerometer-info这与加速度计上方的角度略有不同,但似乎有效。当使用来自hobbytronics的算法并将其放入上面的代码中时,我得到了一个奇怪的行为,所以它总是试图接近-1.4度角。

我在另一台计算机上获得了真正的代码,但这就是我的工作方式:

var lastReading = new DateTime();
var angleX = 0.0; 
var gyro = new Gyroscope();
gyro.TimeBetweenUpdates = 20ms;
gyro.CurrentValueChanged += ValueChanged;
var acc = new Accelerometer();
acc.TimeBetweenUpdates = 20ms;
gyro.Start(); acc.Start();

void ValueChanged(SensorReading reading)
{
    if(lastReading < 1 sec old)
    {
        var dt = lastReading - reading.Timestamp;
        if(reading.X > 0.05 || Reading.X < -0.05) // Got so much errors if I did not use this, maybe too high?
        {
           var x = reading.X * dt.TotalSeconds;
           var accData = acc.CurrentValue(); 
           var accX = atan(accData.X / Math.Sqrt(accData.Y*accData.Y+accData.Z*accData.Z));
           angleX = 0.98*(angleX + x *180 / Math.PI) + 0.02 * (accX *180 /Math.PI);
           TxtAngleX.Text = "x:" + angleX.ToString("F");
        }
    }
    lastReading = reading.Timestamp;
 }

我错过了什么?一种使其更好的方法可能是仅设置加速度计的角度,当lastReading更长,然后一秒但我知道那不是问题

0 个答案:

没有答案