使用加速度计读取 android 手机的 x y z 坐标

Posted

技术标签:

【中文标题】使用加速度计读取 android 手机的 x y z 坐标【英文标题】:Read x y z coordinates of android phone using accelerometer 【发布时间】:2012-06-19 14:03:50 【问题描述】:

我要开发一个需要读取手机在 3D 空间上的 x,y,z 坐标android 应用程序。

我想写一个简单的代码并在设备上测试..

我在设备和模拟器上都使用姜饼。

【问题讨论】:

Using accelerometer, gyroscope and compass to calculate device's movement in 3D world 超集的可能副本,也要求旋转状态。 【参考方案1】:

要从加速度中获取位置,您需要对其进行两次积分。

积分加速度为您提供速度,积分速度为您提供位置。

请记住,集成噪声会产生漂移,而集成漂移会产生大量漂移,Android 传感器往往会产生大量噪声。

在我的 Galaxy S3 上,使用 Google 的线性加速度计复合传感器,我能够在 5 秒内将位置漂移降至 0.02 m。

我不确定您是否可以在姜饼上使用线性加速度计传感器。如果不能,则必须在积分之前消除重力。

如果您还没有,请在此处阅读所有内容 http://developer.android.com/guide/topics/sensors/sensors_motion.html

关于 android 中的运动传感器的精彩演讲

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

代码:

static final float NS2S = 1.0f / 1000000000.0f;
float[] last_values = null;
float[] velocity = null;
float[] position = null;
long last_timestamp = 0;

@Override
public void onSensorChanged(SensorEvent event) 
    if(last_values != null)
        float dt = (event.timestamp - last_timestamp) * NS2S;

        for(int index = 0; index < 3;++index)
            velocity[index] += (event.values[index] + last_values[index])/2 * dt;
            position[index] += velocity[index] * dt;
        
    
    else
        last_values = new float[3];
        velocity = new float[3];
        position = new float[3];
        velocity[0] = velocity[1] = velocity[2] = 0f;
        position[0] = position[1] = position[2] = 0f;
    
    System.arraycopy(event.values, 0, last_values, 0, 3);
    last_timestamp = event.timestamp;

现在您有了 3d 空间中的位置,请记住它假定手机在开始采样时是静止的。

如果你不消除重力,它很快就会很远。

这根本不会过滤数据,会产生很多漂移。

【讨论】:

产生漂移的不仅仅是传感器噪声。这种方法的主要限制是,从根本上不可能用加速度计检测恒定速度。因此,当您稍微摇晃手机时,集成似乎会产生合理的结果,但对于其他类型的运动,例如在驾驶或骑自行车时,漂移会很大。 你说得对。我正在使用加速度计来跟踪汽车,为此我实施了卡尔曼滤波器以进一步减少漂移。我还通过测量静止时的噪声来计算加速度计的精度,然后将其用于对滤波器中的数据进行加权。到目前为止,我取得了相当不错的成绩。 在这里你也会得到很多“漂移”,因为你用牛顿物理学计算所有这些,这是不准确的。做 Runge-kutta 或其他一些更准确的计算位置的方法以获得更好的结果。 @spontus 将您的代码与线性加速度传感器一起使用,我的位置值在设备静止在桌子上时,x 和 y 每秒增加约 1,z 每秒增加约 10。这是你所期望的吗?我知道这种方法不是很准确,但它应该这么糟糕吗? @DavidDoria 每秒约 10 是因为 9.8 m/s^2 重力加速度。正如答案所说,您需要以某种方式删除它。【参考方案2】:

阅读this tutorial。

上面给出的教程的简要总结::

首先获取SensorManager 和Sensor 的实例。 里面onCreate()::

mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);

在此之后,覆盖onSensorChanged(SensorEvent event) 并使用event.values[] 获取坐标。

@Override
public void onSensorChanged(SensorEvent event) 
    float x = event.values[0];
    float y = event.values[1];
    float z = event.values[2];

【讨论】:

以上是关于使用加速度计读取 android 手机的 x y z 坐标的主要内容,如果未能解决你的问题,请参考以下文章

Android 加速度计精度(惯性导航)

如何使用 Android 加速度计?

Android 加速度计在 z 轴上读数为 0 而没有变化

Android 加速度计分析

手机加速度计精度

如何在android studio 上用加速度传感器来得到x y z轴上的坐标?