首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用加速度计和陀螺仪(MPU6050)计算位移

用加速度计和陀螺仪(MPU6050)计算位移
EN

Stack Overflow用户
提问于 2014-10-20 23:15:44
回答 5查看 53.5K关注 0票数 12

我是一名计算机科学专业的学生,正在从事一个电子项目,需要计算偏航,俯仰,滚转和X,Y,Z位移。我想把IMU装在枪上,跟踪它的方位和位移。我能够得到偏航,俯仰和滚动,但不幸的是无法理解如何计算位移或我的枪的位置。我正在使用一个10自由度GY-87传感器,其中包含MPU-6050.

我得到g和m/s2格式的值。从我已经研究过的研究来看,我需要得到加速/时间2,然后把所有的值加起来。但我不明白我应该用什么时差。参考文献:基于电话加速度的距离计算方法

代码语言:javascript
复制
#include "I2Cdev.h"
#include "MPU6050.h"

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 accelgyro;
//MPU6050 accelgyro(0x69); // <-- use for AD0 high

int16_t ax, ay, az;
float dx, dy, dz = 0;
int16_t gx, gy, gz;





#define LED_PIN 13
bool blinkState = false;

void setup() {
    // join I2C bus (I2Cdev library doesn't do this automatically)
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif

    Serial.begin(38400);

    Serial.println("Initializing I2C devices...");
    accelgyro.initialize();

    Serial.println("Testing device connections...");
    Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");

    Serial.println("Updating internal sensor offsets...");

    accelgyro.setXGyroOffset(85);
    accelgyro.setYGyroOffset(1);
    accelgyro.setZGyroOffset(-4);
    accelgyro.setXAccelOffset(-4269);
    accelgyro.setYAccelOffset(-4836);
    accelgyro.setZAccelOffset(1080);

    pinMode(LED_PIN, OUTPUT);
}

void loop() {

        accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

        dx=dx+(float)(((float)ax/(float)16384)*9.8*0.05*0.05);
        dy=dy+(float)(((float)ay/(float)16384)*9.8*0.05*0.05);
        dz=dz+(float)(((float)az/(float)16384)*9.8*0.05*0.05);
        Serial.print(dx); Serial.print("\t");
        Serial.print(dy); Serial.print("\t");
        Serial.print(dz); Serial.print("\t\n");


delay(1000);
    // blink LED to indicate activity
    blinkState = !blinkState;
    digitalWrite(LED_PIN, blinkState);
}

我想跟踪对象,如下面的youtube视频所示。

http://www.youtube.com/watch?v=ZYyyaJgKsDg

如果你们中的任何人能在这方面指导我,我将不胜感激。谢谢

对不起,我的英语很差,而且使用非技术术语。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2015-01-23 20:21:59

恐怕答案不是你想听到的。从IMU单元计算位置是非常非常困难的。这个来自Google的视频是一个很好的参考,为什么(转到24分钟的详细解释)。基本上,你需要整合两次加速度才能定位。你也需要从你的IMU所看到的加速度中移除重力。如果这件事做得不好,那么这些错误就会很快地累积起来。

你引用的视频使用了球在桌子上滚动的信息来通知他们的模型。他们可以跟踪传感器的方向,知道球在往哪个方向滚动。他们用球的半径和板上的角度变化来追踪x和y中的球。如果你把他们的球从桌子上摘下来,那就根本行不通了。

如果你需要跟踪什么东西,你应该寻找一些传感器,可以给你信息的位置,你的对象(GPS,视频分析)。然后,您可以使用卡尔曼滤波结合IMU数据,以获得良好的定位精度。

祝你的项目好运。

票数 13
EN

Stack Overflow用户

发布于 2018-08-05 01:32:03

我知道这是一个旧的邮报,但我想我会张贴一些修正的实验,我已经做了MPU 6050和arduino。

首先,你用来找位移的方程式是不正确的,你需要用一个运动学方程。然而,方程Xf = 1/2a_t^2 + Vo_t + Xo也是不正确的,因为它只适用于常数加速度。在这种情况下,加速度是变化的,所以您可以获取两个数据集点之间的平均加速度,并将其插入到前面的方程中,或者使用以下公式:

Xf = 1/4(Af + Ao)_t^2 + Vo_t + Xo

其中Xf是以米为单位的最终距离,Af是m/s^2的最终电流加速度,Ao是m/s^2中最后一组数据集的前一次加速度,t是Af和Ao数据集之间的时间变化(以秒为单位),Vo是以m/s为单位的最后一组数据集的瞬时速度,Xo是最后一次数据集的最后距离或所有以前距离的总和。Vo需要使用以前的加速度和使用以下运动学方程的前两个数据集或Ao-1中的加速度来计算:

Vo = 1/2(Ao + Ao-1)*t + Vo-1

其中,Vo是m/s中的前一个瞬时速度,Ao是m/s^2中的前一个加速度,Ao-1是在m/s^2中来自两个数据集的加速度,t是Ao和Ao-1数据集在秒内的时间变化,而Vo-1是Ao-1数据集或两个数据集的m/s的瞬时速度。

其次,你需要使用一个更可靠的时钟。我建议使用micros()函数,并记住t是数据集之间时间的变化。我不确定它的可靠性,但它是我能想到的最好的。使用规定的公式时,请确保从微秒转换为秒。

第三,我建议您将代码与Luisódenas这样的校准草图结合起来,在代码开始时经常甚至每次校准偏移量。您可以将其放置在setup()例程中,并可以使用一个小的缓冲区大小值或200或300这样的数据集来确保您不会在两次实验之间等待太久。

第四,您可以使用两个数据集加速之间的平均值操作(这就是我们前面所做的),或者更进一步,使用各种数据集的平均值,例如使用fifo缓冲区数组来存储各种加速值,并获取缓冲区中所有值的平均值。Fifo缓冲区要求它们始终保留一定数量的值,但是随着新值的进入,旧的值会离开。fifo越大,您的距离计算就越不准确,但是fifo缓冲区将允许异常值加速值不会对您的数据造成太大影响。缓冲区的大小要求您在加速度值的准确性和孤立值之间找到一个甜蜜点。如果您确实使用fifo缓冲区作为加速值,那么使用以下公式:

Xf = 1/2A_t^2 + Vo_t + Xo

Vo = Aold *t + Vo-1

其中A是由假设FIFO缓冲器导出的新的平均加速度,Aold是上一个FIFO平均值的旧平均加速度,t是两个单独数据集点之间的时间变化。所有的标准单位,当然,m/s等等。

通过除以16384,再乘以9.8m/s^2,将原始加速值转换为m/s^2的工作做得很好。16384值取决于+-2g的标准灵敏度设置,如果您选择+-4g之类的另一个设置,则可以更改。

最后,即使有以上所有的变化,由于温度等许多不同的因素,很难得到一个准确的读数。使用风扇或任何东西来保持陀螺仪/加速度计在室温或25摄氏度时,为你的加速度计保持一个受控环境是很重要的。我相信,在Jeff的MPU6050库中有一个函数可以得到当前的温度,mpu.getTemperature()

即使有了这些变化,由于数学上的原因和微小的不准确,仍然很难获得一个好的准确的读数。您可以尝试将您的陀螺仪设置为不太敏感的设置,因为我知道mpu 6050设置在默认的+-2g设置中,较高的设置可以防止许多问题影响您的读数,但它会变得对小位移不太敏感。

总是有更多的方法可以优化你的陀螺仪/加速度计的值,一种方法是如果你增加MPU数据的频率,以便在一段时间内接收更多的数据,这可以让你收到更精确的读数。我相信在Jeff库中有一个函数允许这样做。

票数 6
EN

Stack Overflow用户

发布于 2015-04-20 11:55:12

是的..在循环()中有延迟(1000);

这意味着你的三角时间是1秒,不是50毫秒。

在循环()中尝试这样做:

代码语言:javascript
复制
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

    double t2 = millis() - pms;
    t2 /= 1000;  // convert ms to s
    t2 *=t2;


    // your Math and Serial here... 


    pms = millis(); 
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26476467

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档