使用线性加速度的积分近似室内定位

时间:2013-07-09 15:52:36

标签: android location android-sensors indoor-positioning-system

我正在尝试计算房间内Android手机的大致位置。我尝试了不同的方法,如位置(在室内很糟糕)和陀螺仪+指南针。我只需要在5-10秒之后知道行走后的大致位置,所以我认为线性加速度的积分就足够了。我知道错误是可怕的,因为错误的传播,但也许它将在我的设置中工作。我只需要近似位置即可将相机对准Android手机。

我编写了双重整合,但我做错了。如果电话在桌子上是静止的,则位置(x,y,z)总是保持增加。有什么问题?

 static final float NS2S = 1.0f / 1000000000.0f;
    float[] last_values = null;
    float[] velocity = null;
    float[] position = null;
    float[] acceleration = null;
    long last_timestamp = 0;
    SensorManager mSensorManager;
    Sensor mAccelerometer;

public void onSensorChanged(SensorEvent event) {
         if (event.sensor.getType() != Sensor.TYPE_LINEAR_ACCELERATION)
             return;

         if(last_values != null){
                float dt = (event.timestamp - last_timestamp) * NS2S;

                acceleration[0]=(float) event.values[0] - (float) 0.0188;
                acceleration[1]=(float) event.values[1] - (float) 0.00217;
                acceleration[2]=(float) event.values[2] + (float) 0.01857;

                for(int index = 0; index < 3;++index){
                    velocity[index] += (acceleration[index] + last_values[index])/2 * dt;
                    position[index] += velocity[index] * dt;
                }
            }
            else{
                last_values = new float[3];
                acceleration = 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(acceleration, 0, last_values, 0, 3);
            last_timestamp = event.timestamp;
    }

这些是手机放在桌面上时的位置(无动作)。 (x,y,z)值正在增加,但手机仍在。 enter image description here

这些是计算每个轴的移动平均值并从每个测量值减去后的位置。手机还在。 enter image description here

如何改进代码或其他方法以获得房间内的大致位置?

3 个答案:

答案 0 :(得分:4)

加速度计中存在不可避免的测量误差。这些是由表中的微小振动,制造中的缺陷等引起的。等等随着时间的推移累积这些误差会导致Random Walk。这就是定位系统只能通过某些过滤器使用加速度计作为定位辅助的原因。它们仍然需要某种形式的航位推算,例如GPS(在门上不能很好地工作)。

目前有很多关于室内定位系统的研究。可以利用现有基础设施的系统的一些研究领域是WiFi和LED照明定位。目前还没有明显的解决方案,但我确信我们需要专门的解决方案来实现准确,可靠的室内定位。

你说这个职位总是在不断增加。你的意思是,即使重置几次后,x,y和z分量也只会变为正值?或者你的意思是这个位置从零开始漂移?

如果在手机静止时输出原始加速度测量值,您应该会看到测量误差。将一堆这些测量值放在Excel电子表格中。计算平均值和标准差。所有轴的平均值应为零。如果没有,您可以使用简单的平均滤波器在代码中删除偏差(计算运行平均值并从每个结果中减去)。标准偏差将显示在N个时间步之后您可以在每个轴上漂移多远作为standard_deviation * sqrt(N)。这可以帮助您在数学上确定作为时间函数(或N个时间步长)的预期精度。

答案 1 :(得分:2)

Brian是对的,已经部署了室内定位系统,可以在几乎任何房间内轻松找到基础设施。 已被证明最可靠的解决方案之一是WiFi指纹识别。我建议你看一下indoo.rs - www.indoo.rs - 他们是行业的先驱,并且已经拥有一个非常发达的系统。

答案 2 :(得分:0)

这可能不是最优雅或最可靠的解决方案,但就我而言,它可以达到目的。

注意在我的情况下,我抓住一个位置,然后用户甚至可以进入需要室内定位的活动..而我只关心他们已经移动了多少的粗略估计。

我有一个传感器管理器,它根据设备方向创建旋转矩阵。 (使用Sensor.TYPE_ROTATION_VECTOR)这显然不会让我前进,后退或左右移动,而只是设备方向。通过该设备方向,我可以很好地了解用户的度数(它们面向哪个方向)并使用KitKat 4.4中提供的Sensor_Step_Detector,我假设步长为1米朝向用户的方向正面临..

同样,我知道这不是完全证明或非常准确,但根据您的目的,这也可能是一个简单的解决方案..

每次检测到一个步骤我基本上都会调用这个函数:

public void computeNewLocationByStep() {
       Location newLocal = new Location("");
       double vAngle = getBearingInDegrees(); // returns my users bearing
       double vDistance = 1 / g.kEarthRadiusInMeters; //kEarthRadiusInMeters =  6353000;
        vAngle = Math.toRadians(vAngle);

        double vLat1 = Math.toRadians(_location.getLatitude());
        double vLng1 = Math.toRadians(_location.getLongitude());

        double vNewLat = Math.asin(Math.sin(vLat1) * Math.cos(vDistance) +
                      Math.cos(vLat1) * Math.sin(vDistance) * Math.cos(vAngle));

        double vNewLng = vLng1 + Math.atan2(Math.sin(vAngle) * Math.sin(vDistance) * Math.cos(vLat1),
                              Math.cos(vDistance) - Math.sin(vLat1) * Math.sin(vNewLat));



        newLocal.setLatitude(Math.toDegrees(vNewLat));
        newLocal.setLongitude(Math.toDegrees(vNewLng));

        stepCount =0;
        _location = newLocal;

    }