0

IMU를 사용하여 Android 실내 추적 응용 프로그램을 만들려고합니다.IMU를 사용하는 실내 추적 응용 프로그램

지금 내 앱은 ACCELEROMETER, GEOMAGNETIC_FIELD 및 GYROSCOPE의 데이터를 융합하여 작성한 가속도계 및 소프트웨어 센서 ROTATION_VECTOR를 기반으로합니다. 나는 단계를 감지하기 위해 가속도계를 사용하고 방향을 위해 ROTATION_VECTOR 센서를 사용하고 있습니다. 단계가 감지되면 ROTATION VECTOR에서 데이터를 가져 와서 시작 각도와 현재 각도 사이의 각도 차이를 계산하고 새 좌표를 계산하고 새 위치를 표시합니다. (고정 길이의 스텝을 사용합니다)

문제가되는 부분은 다음과 같습니다. 오리엔테이션의 정확성. 필자는 칼만 필터를 사용할 것을 제안하는 몇 가지 논문을 읽었지 만, 구현 방법은 여전히 ​​수수께끼입니다.

누군가가이 문제를 도와 주면 매우 감사 할 것입니다. 칼만 필터를 이해하는 방법을 몇 가지 자습서를 제안하거나, 내 애플 리케이션의 정확성을 향상시키는 방법을 보여줘.

고마워요.

내 코드 :

package com.example.jozef.gyrouhol; 

import android.hardware.Sensor; 
import android.hardware.SensorEvent; 
import android.hardware.SensorEventListener; 
import android.hardware.SensorManager; 
import android.os.Bundle; 
import android.support.v7.app.AppCompatActivity; 
import android.widget.TextView; 
import android.widget.Toast; 
import android.app.Activity; 
import java.lang.Math; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Locale; 
import java.util.concurrent.TimeUnit; 

public class Gyro extends AppCompatActivity implements SensorEventListener { 

    private SensorManager mSensorManager; 
    private Sensor mRotationSensor, mStepSensor; 

    private static final int SENSOR_DELAY = 1000; 
    private static final int FROM_RADS_TO_DEGS = -57; 
    private double norming; 

    private ObjectHandler mData; 

    private int count = 0; 
    private int pmin = 0, pmax=0; 
    private long actualTime = 0; 

    private float mStartingAngle; 
    private HouseBackground myView; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 

     super.onCreate(savedInstanceState); 
     myView = new HouseBackground(this); 
     setContentView(myView); 

     try { 

      mSensorManager = (SensorManager) getSystemService(Activity.SENSOR_SERVICE); 
      mRotationSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR); 
      mStepSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
      mSensorManager.registerListener(this, mRotationSensor, SENSOR_DELAY); 
      mSensorManager.registerListener(this,mStepSensor,SENSOR_DELAY); 
     } 
     catch (Exception e) { 
      Toast.makeText(this, "Hardware compatibility issue", Toast.LENGTH_LONG).show(); 
     } 

     mData = new ObjectHandler(); 
    } 

    @Override 
    public void onAccuracyChanged(Sensor sensor, int accuracy) { 
     // TODO Auto-generated method stub 
    } 

    @Override 
    public void onSensorChanged(SensorEvent event) { 


     if (event.sensor == mRotationSensor) { 

      update(event.values); 
     } 

     if(event.sensor == mStepSensor) { 

      norming = Math.sqrt((event.values[0]*event.values[0])+(event.values[1]*event.values[1])+(event.values[2]*event.values[2])); 
      stepCount(norming); 
     } 
    } 

    private void update(float[] vectors) { 

     float[] rotationMatrix = new float[9]; 
     SensorManager.getRotationMatrixFromVector(rotationMatrix, vectors); 

     float[] orientation = new float[3]; 
     SensorManager.getOrientation(rotationMatrix, orientation); 

     float xdeg = orientation[0]* FROM_RADS_TO_DEGS; 
     mData.ObjectHandlersetAngle(xdeg); 
    } 

    protected void onPause() { 

     mSensorManager.unregisterListener((SensorEventListener) this); 
     super.onPause(); 
    } 

    public void stepCount (double mNorming){ 
     if (norming > 10.403) 

      pmax = 1; 

     if (norming < 8.45) 

      pmin = 1; 

     if (pmax == 1 && pmin == 1) { 

      if (count == 0){ 
       count++; 
       actualTime = System.currentTimeMillis(); 
       if(mStartingAngle == 0) 
       { 
        mStartingAngle = mData.ObjectHandlergetAngle(); 
       } 
       myView.newPointAdd((int) (myView.getLastX()-Math.round(93*Math.cos(Math.toRadians(mData.ObjectHandlergetAngle()-mStartingAngle)))), (int) (myView.getLastY()-Math.round(93*Math.sin(Math.toRadians(mData.ObjectHandlergetAngle()-mStartingAngle))))); 

      } 

      else { 
       if (System.currentTimeMillis() - actualTime > 400) { 
        count++; 
        actualTime = System.currentTimeMillis(); 
        int xnew = (int) (myView.getLastX()-Math.round(93*Math.cos(Math.toRadians(mData.ObjectHandlergetAngle()-mStartingAngle)))); 
        int ynew = (int) (myView.getLastY()-Math.round(93*Math.sin(Math.toRadians(mData.ObjectHandlergetAngle()-mStartingAngle)))); 
        myView.newPointAdd(xnew,ynew); 
       } 
      } 

      pmin = 0; 
      pmax = 0; 
     } 
    } 
} 

답변

0
@Override 
public void onSensorChanged(SensorEvent event) { 


    final float alpha = 0.97f; 

    synchronized (this) { 
     if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { 

      mGravity[0] = alpha * mGravity[0] + (1 - alpha) 
        * event.values[0]; 
      mGravity[1] = alpha * mGravity[1] + (1 - alpha) 
        * event.values[1]; 
      mGravity[2] = alpha * mGravity[2] + (1 - alpha) 
        * event.values[2]; 
     } 

     if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { 

      mGeomagnetic[0] = alpha * mGeomagnetic[0] + (1 - alpha) 
        * event.values[0]; 
      mGeomagnetic[1] = alpha * mGeomagnetic[1] + (1 - alpha) 
        * event.values[1]; 
      mGeomagnetic[2] = alpha * mGeomagnetic[2] + (1 - alpha) 
        * event.values[2]; 

     } 

     float R[] = new float[9]; 
     float I[] = new float[9]; 
     boolean success = SensorManager.getRotationMatrix(R, I, mGravity, 
       mGeomagnetic); 
     if (success) { 
      float orientation[] = new float[3]; 
      SensorManager.getOrientation(R, orientation); 
      float azimuth = orientation[0]; //in radians 
      azimuth = azimuth * 360/(2 * (float) Math.PI); // -180 to 180 


     } 
    } 
}