我的算法计算智能手机的位置 - 全球定位系统和传感器 [英] My Algorithm to Calculate Position of Smartphone - GPS and Sensors

查看:326
本文介绍了我的算法计算智能手机的位置 - 全球定位系统和传感器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发一个Android应用程序来计算排名,基于传感器的数据。

I am developing an android application to calculate position based on Sensor's Data

  1. 加速度计 - >计算线性加速度

  1. Accelerometer --> Calculate Linear Acceleration

磁力仪+加速度计 - >移动方向

Magnetometer + Accelerometer --> Direction of movement

初​​始位置将取自GPS(纬度+经度)。

The initial position will be taken from GPS (Latitude + Longitude).

现在基于传感器的读数我需要计算的智能手机的新位置:

Now based on Sensor's Readings i need to calculate the new position of the Smartphone:

我的算法如下 - (但不计算准确的位置):请帮我完善它。

My Algorithm is following - (But is not calculating Accurate Position): Please help me improve it.

注意: 我的算法code是用C#(我派传感器数据到服务器 - 当数据被存储在数据库中,我计算在服务器上的位置)

所有datetime对象已使用时间戳计算 - 从01-01-1970

    var prevLocation = ServerHandler.getLatestPosition(IMEI);
    var newLocation = new ReceivedDataDTO()
                          {
                              LocationDataDto = new LocationDataDTO(),
                              UsersDto = new UsersDTO(),
                              DeviceDto = new DeviceDTO(),
                              SensorDataDto = new SensorDataDTO()
                          };

    //First Reading
    if (prevLocation.Latitude == null)
    {
        //Save GPS Readings
        newLocation.LocationDataDto.DeviceId = ServerHandler.GetDeviceIdByIMEI(IMEI);
        newLocation.LocationDataDto.Latitude = Latitude;
        newLocation.LocationDataDto.Longitude = Longitude;
        newLocation.LocationDataDto.Acceleration = float.Parse(currentAcceleration);
        newLocation.LocationDataDto.Direction = float.Parse(currentDirection);
        newLocation.LocationDataDto.Speed = (float) 0.0;
        newLocation.LocationDataDto.ReadingDateTime = date;
        newLocation.DeviceDto.IMEI = IMEI;
        // saving to database
        ServerHandler.SaveReceivedData(newLocation);
        return;
    }


    //If Previous Position not NULL --> Calculate New Position
   **//Algorithm Starts HERE**

    var oldLatitude = Double.Parse(prevLocation.Latitude);
    var oldLongitude = Double.Parse(prevLocation.Longitude);
    var direction = Double.Parse(currentDirection);
    Double initialVelocity = prevLocation.Speed;

    //Get Current Time to calculate time Travelling - In seconds
    var secondsTravelling = date - tripStartTime;
    var t = secondsTravelling.TotalSeconds;

    //Calculate Distance using physice formula, s= Vi * t + 0.5 *  a * t^2
    // distanceTravelled = initialVelocity * timeTravelling + 0.5 * currentAcceleration * timeTravelling * timeTravelling;
    var distanceTravelled = initialVelocity * t + 0.5 * Double.Parse(currentAcceleration) * t * t;

    //Calculate the Final Velocity/ Speed of the device.
    // this Final Velocity is the Initil Velocity of the next reading
    //Physics Formula: Vf = Vi + a * t
    var finalvelocity = initialVelocity + Double.Parse(currentAcceleration) * t;


    //Convert from Degree to Radians (For Formula)
    oldLatitude = Math.PI * oldLatitude / 180;
    oldLongitude = Math.PI * oldLongitude / 180;
    direction = Math.PI * direction / 180.0;

    //Calculate the New Longitude and Latitude
    var newLatitude = Math.Asin(Math.Sin(oldLatitude) * Math.Cos(distanceTravelled / earthRadius) + Math.Cos(oldLatitude) * Math.Sin(distanceTravelled / earthRadius) * Math.Cos(direction));
    var newLongitude = oldLongitude + Math.Atan2(Math.Sin(direction) * Math.Sin(distanceTravelled / earthRadius) * Math.Cos(oldLatitude), Math.Cos(distanceTravelled / earthRadius) - Math.Sin(oldLatitude) * Math.Sin(newLatitude));

    //Convert From Radian to degree/Decimal
    newLatitude = 180 * newLatitude / Math.PI;
    newLongitude = 180 * newLongitude / Math.PI;

这是我得到的结果 - >电话是不动的。正如你所看到的速度27.3263111114502 所以有一些错误的计算速度,但我不知道是什么

This is the Result I get --> Phone was not moving. As you can see speed is 27.3263111114502 So there is something wrong in calculating Speed but I don't know what

答:

我找到了一个解决方案,来计算基于传感器的位置。我已经发布了如下回答。

I found a solution to calculate position based on Sensor: I have posted an Answer below.

如果您需要任何帮助,请发表评论

If you need any help, please leave a comment

这是相对于GPS的结果(注意: GPS是在红)

this is The results compared to GPS (Note: GPS is in Red)

推荐答案

解决我用传感器我想发表我的code在这里情况下,任何人都需要在今后的计算出的位置后:

After solving the position I calculated using Sensors I would like to post my code here in case anyone needs in future:

注意:这是只检查了三星Galaxy S2手机,只有当人走的手机,它并没有被汽车或骑自行车上移动时进行测试

这就是当与GPS相比,相比我得到的结果,(红线GPS,蓝与传感器计算出的位置)

在code是不是很有效,但我希望我的分享这个code会帮助别人的同时他们指出正确的方向。

The code is not very efficient, but I hope my sharing this code will help someone and point them in the right direction.

我有两个单独的类:

  1. CalculatePosition
  2. CustomSensorService

公共类CalculatePosition {

public class CalculatePosition {

        static Double earthRadius = 6378D;
        static Double oldLatitude,oldLongitude;
        static Boolean IsFirst = true;

        static Double sensorLatitude, sensorLongitude;

        static Date CollaborationWithGPSTime;
        public static float[] results;



        public static void calculateNewPosition(Context applicationContext,
                Float currentAcceleration, Float currentSpeed,
                Float currentDistanceTravelled, Float currentDirection, Float TotalDistance) {


            results = new float[3];
            if(IsFirst){
                CollaborationWithGPSTime = new Date();
                Toast.makeText(applicationContext, "First", Toast.LENGTH_LONG).show();
                oldLatitude = CustomLocationListener.mLatitude;
                oldLongitude = CustomLocationListener.mLongitude;
                sensorLatitude = oldLatitude;
                sensorLongitude = oldLongitude;
                LivePositionActivity.PlotNewPosition(oldLongitude,oldLatitude,currentDistanceTravelled * 1000, currentAcceleration, currentSpeed, currentDirection, "GPSSensor",0.0F,TotalDistance);
                IsFirst  = false;
                return;
            } 

            Date CurrentDateTime = new Date();

            if(CurrentDateTime.getTime() - CollaborationWithGPSTime.getTime() > 900000){
                //This IF Statement is to Collaborate with GPS position --> For accuracy --> 900,000 == 15 minutes
                oldLatitude = CustomLocationListener.mLatitude;
                oldLongitude = CustomLocationListener.mLongitude;
                LivePositionActivity.PlotNewPosition(oldLongitude,oldLatitude,currentDistanceTravelled * 1000, currentAcceleration, currentSpeed, currentDirection, "GPSSensor", 0.0F, 0.0F);
                return;
            }

            //Convert Variables to Radian for the Formula
            oldLatitude = Math.PI * oldLatitude / 180;
            oldLongitude = Math.PI * oldLongitude / 180;
            currentDirection = (float) (Math.PI * currentDirection / 180.0);

            //Formulae to Calculate the NewLAtitude and NewLongtiude
            Double newLatitude = Math.asin(Math.sin(oldLatitude) * Math.cos(currentDistanceTravelled / earthRadius) + 
                    Math.cos(oldLatitude) * Math.sin(currentDistanceTravelled / earthRadius) * Math.cos(currentDirection));
            Double newLongitude = oldLongitude + Math.atan2(Math.sin(currentDirection) * Math.sin(currentDistanceTravelled / earthRadius)
                    * Math.cos(oldLatitude), Math.cos(currentDistanceTravelled / earthRadius)
                    - Math.sin(oldLatitude) * Math.sin(newLatitude));

            //Convert Back from radians
            newLatitude = 180 * newLatitude / Math.PI;
            newLongitude = 180 * newLongitude / Math.PI;
            currentDirection = (float) (180 * currentDirection / Math.PI);

            //Update old Latitude and Longitude
            oldLatitude = newLatitude;
            oldLongitude = newLongitude;

            sensorLatitude = oldLatitude;
            sensorLongitude = oldLongitude;

            IsFirst = false;
            //Plot Position on Map
            LivePositionActivity.PlotNewPosition(newLongitude,newLatitude,currentDistanceTravelled * 1000, currentAcceleration, currentSpeed, currentDirection, "Sensor", results[0],TotalDistance);





    }
}

公共类CustomSensorService扩展服务实现SensorEventListener {

public class CustomSensorService extends Service implements SensorEventListener{

static SensorManager sensorManager;
static Sensor mAccelerometer;
private Sensor mMagnetometer;
private Sensor mLinearAccelertion;

static Context mContext;

private static float[] AccelerometerValue;
private static float[] MagnetometerValue;

public static  Float currentAcceleration = 0.0F;
public static  Float  currentDirection = 0.0F;
public static Float CurrentSpeed = 0.0F;
public static Float CurrentDistanceTravelled = 0.0F;
/*---------------------------------------------*/
float[] prevValues,speed;
float[] currentValues;
float prevTime, currentTime, changeTime,distanceY,distanceX,distanceZ;
float[] currentVelocity;
public static CalculatePosition CalcPosition;
/*-----FILTER VARIABLES-------------------------*-/
 * 
 * 
 */

public static Float prevAcceleration = 0.0F;
public static Float prevSpeed = 0.0F;
public static Float prevDistance = 0.0F;

public static Float totalDistance;

TextView tv;
Boolean First,FirstSensor = true;

@Override
public void onCreate(){

    super.onCreate();
    mContext = getApplicationContext();
    CalcPosition =  new CalculatePosition();
    First = FirstSensor = true;
    currentValues = new float[3];
    prevValues = new float[3];
    currentVelocity = new float[3];
    speed = new float[3];
    totalDistance = 0.0F;
    Toast.makeText(getApplicationContext(),"Service Created",Toast.LENGTH_SHORT).show();

    sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

    mAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    mMagnetometer = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    //mGyro = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
    mLinearAccelertion = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);

    sensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
    sensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_NORMAL);
    //sensorManager.registerListener(this, mGyro, SensorManager.SENSOR_DELAY_NORMAL);
    sensorManager.registerListener(this, mLinearAccelertion, SensorManager.SENSOR_DELAY_NORMAL);

}

@Override
public void onDestroy(){
    Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show();
    sensorManager.unregisterListener(this);
    //sensorManager = null;
    super.onDestroy();
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
    // TODO Auto-generated method stub

}

@Override
public void onSensorChanged(SensorEvent event) {

    float[] values = event.values;
    Sensor mSensor = event.sensor;

    if(mSensor.getType() == Sensor.TYPE_ACCELEROMETER){
        AccelerometerValue = values;
    }

    if(mSensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION){           
        if(First){
            prevValues = values;
            prevTime = event.timestamp / 1000000000;
            First = false;
            currentVelocity[0] = currentVelocity[1] = currentVelocity[2] = 0;
            distanceX = distanceY= distanceZ = 0;
        }
        else{
            currentTime = event.timestamp / 1000000000.0f;

            changeTime = currentTime - prevTime;

            prevTime = currentTime;



            calculateDistance(event.values, changeTime);

            currentAcceleration =  (float) Math.sqrt(event.values[0] * event.values[0] + event.values[1] * event.values[1] + event.values[2] * event.values[2]);

            CurrentSpeed = (float) Math.sqrt(speed[0] * speed[0] + speed[1] * speed[1] + speed[2] * speed[2]);
            CurrentDistanceTravelled = (float) Math.sqrt(distanceX *  distanceX + distanceY * distanceY +  distanceZ * distanceZ);
            CurrentDistanceTravelled = CurrentDistanceTravelled / 1000;

            if(FirstSensor){
                prevAcceleration = currentAcceleration;
                prevDistance = CurrentDistanceTravelled;
                prevSpeed = CurrentSpeed;
                FirstSensor = false;
            }
            prevValues = values;

        }
    }

    if(mSensor.getType() == Sensor.TYPE_MAGNETIC_FIELD){
        MagnetometerValue = values;
    }

    if(currentAcceleration != prevAcceleration || CurrentSpeed != prevSpeed || prevDistance != CurrentDistanceTravelled){

        if(!FirstSensor)
            totalDistance = totalDistance + CurrentDistanceTravelled * 1000;
        if (AccelerometerValue != null && MagnetometerValue != null && currentAcceleration != null) {
            //Direction
            float RT[] = new float[9];
            float I[] = new float[9];
            boolean success = SensorManager.getRotationMatrix(RT, I, AccelerometerValue,
                    MagnetometerValue);
            if (success) {
                float orientation[] = new float[3];
                SensorManager.getOrientation(RT, orientation);
                float azimut = (float) Math.round(Math.toDegrees(orientation[0]));
                currentDirection =(azimut+ 360) % 360;
                if( CurrentSpeed > 0.2){
                    CalculatePosition.calculateNewPosition(getApplicationContext(),currentAcceleration,CurrentSpeed,CurrentDistanceTravelled,currentDirection,totalDistance);
                }
            }
            prevAcceleration = currentAcceleration;
            prevSpeed = CurrentSpeed;
            prevDistance = CurrentDistanceTravelled;
        }
    }

}


@Override
public IBinder onBind(Intent arg0) {
    // TODO Auto-generated method stub
    return null;
}
public void calculateDistance (float[] acceleration, float deltaTime) {
    float[] distance = new float[acceleration.length];

    for (int i = 0; i < acceleration.length; i++) {
        speed[i] = acceleration[i] * deltaTime;
        distance[i] = speed[i] * deltaTime + acceleration[i] * deltaTime * deltaTime / 2;
    }
    distanceX = distance[0];
    distanceY = distance[1];
    distanceZ = distance[2];
}

}

编辑:

public static void PlotNewPosition(Double newLatitude, Double newLongitude, Float currentDistance, 
        Float currentAcceleration, Float currentSpeed, Float currentDirection, String dataType) {

    LatLng newPosition = new LatLng(newLongitude,newLatitude);

    if(dataType == "Sensor"){
        tvAcceleration.setText("Speed: " + currentSpeed + " Acceleration: " + currentAcceleration + " Distance: " + currentDistance +" Direction: " + currentDirection + " \n"); 
        map.addMarker(new MarkerOptions()
        .position(newPosition)
        .title("Position")
        .snippet("Sensor Position")
        .icon(BitmapDescriptorFactory
                .fromResource(R.drawable.line)));
    }else if(dataType == "GPSSensor"){
        map.addMarker(new MarkerOptions()
        .position(newPosition)
        .title("PositionCollaborated")
        .snippet("GPS Position"));
    }
    else{
        map.addMarker(new MarkerOptions()
        .position(newPosition)
        .title("Position")
        .snippet("New Position")
        .icon(BitmapDescriptorFactory
                .fromResource(R.drawable.linered)));
    }
    map.moveCamera(CameraUpdateFactory.newLatLngZoom(newPosition, 18));
}

这篇关于我的算法计算智能手机的位置 - 全球定位系统和传感器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆