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;
}
}
}