GPS deviation correction

Analysis of the principle, refer to an answer on the Internet http://q.cnblogs.com/q/41339/

It is well known that the earth is an irregular ellipsoid. The definition of the coordinate system in GIS is determined by two sets of parameters: datum plane and map projection, while the definition of datum plane is determined by a specific ellipsoid and its corresponding transformation parameters. The datum is an approximation of the earth's surface in a specific area using a specific ellipsoid, so each country or region has its own datum. The datum plane is established on the basis of the ellipsoid. The ellipsoid can correspond to multiple datum planes, while the datum plane can only correspond to one ellipsoid.

It means that whether it is Google Maps, Soso Maps, AutoNavi Maps, or Baidu Maps, the difference is only the latitude and longitude made according to different geodetic coordinate system standards. Standards are different.

Google Maps uses the WGS84 geographic coordinate system (except China), Google China Maps and Soso China Maps use the GCJ02 geographic coordinate system, Baidu uses the BD09 coordinate system, and devices generally include GPS chips or Beidou chips. The latitude and longitude is the WGS84 geographic coordinate system, why not use the WGS84 geographic coordinate system uniformly? Therefore, everyone feels that the positioning is inaccurate, and it is called the published map as a map of Mars, but the coordinate system is different.

This is why the latitude and longitude collected by the device often has a large deviation when displayed on the map, which is far beyond the technical specification of the 10-meter offset of civilian GPS, so we have Google map deviation correction Tencent Soso deviation correction hybrid map deviation correction Baidu The value of the existence of Google Interchange.

So how to correct the deviation of Google map, Soso map or Baidu map? If there is no good algorithm for direct conversion, so everyone uses the method of comparison. Divide the earth into several small pieces to find it. The deviation of the map is recorded, and then according to any latitude and longitude to find the closest deviation plus the deviation, the longitude and latitude conversion between different maps can be realized. Now there is 0.01 degree correction longitude and latitude information, which can be provided in any format, and the longitude and latitude offset can be directly adjusted back.

Baidu map correction information contains a total of 29,699,997 correction data in China's waters, while Google Maps only contains a total of 12,597,551 correction data in China.

The following are two correction algorithms that I found on the Internet.

First:

package correctPosition;
public class MapPoint
{
    private double latitude;

    private double longitude;

    private double x;

    private double y;

    public double getLatitude()
    {
        return latitude;
    }

    public void setLatitude(double latitude)
    {
        this.latitude = latitude;
    }

    public double getLongitude()
    {
        return longitude;
    }

    public void setLongitude(double longitude)
    {
        this.longitude = longitude;
    }

    public double getX()
    {
        return x;
    }

    public void setX(double x)
    {
        this.x = x;
    }

    public double getY()
    {
        return y;
    }

    public void setY(double y)
    {
        this.y = y;
    }
}

 

package correctPosition;
/**
 * Longitude and latitude correction tools
 * [A brief description of the function in one sentence]<p>
 * [Function detailed description]<p>
 * uthorauthor PeiYu
 * @version 1.0, 2012-8-24
 * @see
 * @since gframe-v100
 */
public class MapFix
{
    private double casm_f = 0.0;

    private double casm_rr = 0.0;

    private double casm_t1 = 0.0;

    private double casm_t2 = 0.0;

    private double casm_x1 = 0.0;

    private double casm_x2 = 0.0;

    private double casm_y1 = 0.0;

    private double casm_y2 = 0.0;

    private MapFix()
    {
        casm_rr = 0.0;
        casm_t1 = 0.0;
        casm_t2 = 0.0;
        casm_x1 = 0.0;
        casm_y1 = 0.0;
        casm_x2 = 0.0;
        casm_y2 = 0.0;
        casm_f = 0.0;
    }

    private static MapFix instance;

    public static MapFix getInstance()
    {
        if (instance == null)
        {
            instance = new MapFix();
        }
        return instance;
    }

    /**
     * Correction
     * @param x longitude
     * @param y latitude
     * @return [0] Longitude after correction [1] Latitude after correction
     */
    public double[] fix(double x , double y)
    {
        double[] res = new double[2];
        try
        {
            double num = x * 3686400.0;
            double num2 = y * 3686400.0;
            double num3 = 0.0;
            double num4 = 0.0;
            double num5 = 0.0;
            MapPoint point = wgtochina_lb(1, (int) num, (int) num2, (int) num5, (int) num3, (int) num4);
            double num6 = point.getX();
            double num7 = point.getY();
            num6 /= 3686400.0;
            num7 /= 3686400.0;
            res[0] = num6;
            res [1] = num7;
        }
        catch (Exception ex)
        {
            System.out.println(ex);
        }
        return res;
    }

    private void IniCasm(double w_time , double w_lng , double w_lat)
    {
        casm_t1 = w_time;
        casm_t2 = w_time;
        double num = (int) (w_time / 0.357);
        casm_rr = w_time - (num * 0.357);
        if (w_time == 0.0)
        {
            casm_rr = 0.3;
        }
        casm_x1 = w_lng;
        casm_y1 = w_years;
        casm_x2 = w_lng;
        casm_y2 = w_years;
        casm_f = 3.0;
    }

    private double random_yj()
    {
        double num = 314159269.0;
        double num2 = 453806245.0;
        casm_rr = (num * casm_rr) + num2;
        double num3 = (int) (casm_rr / 2.0);
        casm_rr - = num3 * 2.0;
        casm_rr /= 2.0;
        return casm_rr;
    }

    private double Transform_jy5(double x , double xx)
    {
        double num = 6378245.0;
        double num2 = 0.00669342;
        double num3 = Math.sqrt(1.0 - ((num2 * yj_sin2(x * 0.0174532925199433)) * yj_sin2(x * 0.0174532925199433)));
        return ((xx * 180.0) / (((num / num3) * Math.cos(x * 0.0174532925199433)) * 3.1415926));
    }

    private double Transform_jyj5(double x , double yy)
    {
        double num = 6378245.0;
        double num2 = 0.00669342;
        double d = 1.0 - ((num2 * yj_sin2(x * 0.0174532925199433)) * yj_sin2(x * 0.0174532925199433));
        double num4 = (num * (1.0 - num2)) / (d * Math.sqrt(d));
        return ((yy * 180.0) / (num4 * 3.1415926));
    }

    private double Transform_yj5(double x , double y)
    {
        double num = ((((300.0 + (1.0 * x)) + (2.0 * y)) + ((0.1 * x) * x)) + ((0.1 * x) * y))
                + (0.1 * Math.sqrt(Math.sqrt(x * x)));
        num += ((20.0 * yj_sin2(18.849555921538762 * x)) + (20.0 * yj_sin2(6.283185307179588 * x))) * 0.6667;
        num += ((20.0 * yj_sin2(3.141592653589794 * x)) + (40.0 * yj_sin2(1.0471975511965981 * x))) * 0.6667;
        return (num + (((150.0 * yj_sin2(0.26179938779914952 * x)) + (300.0 * yj_sin2(0.10471975511965979 * x))) * 0.6667));
    }

    private double Transform_yjy5(double x , double y)
    {
        double num = ((((-100.0 + (2.0 * x)) + (3.0 * y)) + ((0.2 * y) * y)) + ((0.1 * x) * y))
                + (0.2 * Math.sqrt(Math.sqrt(x * x)));
        num += ((20.0 * yj_sin2(18.849555921538762 * x)) + (20.0 * yj_sin2(6.283185307179588 * x))) * 0.6667;
        num += ((20.0 * yj_sin2(3.141592653589794 * y)) + (40.0 * yj_sin2(1.0471975511965981 * y))) * 0.6667;
        return (num + (((160.0 * yj_sin2(0.26179938779914952 * y)) + (320.0 * yj_sin2(0.10471975511965979 * y))) * 0.6667));
    }

    private MapPoint wgtochina_lb (int wg_flag, int wg_lng, int wg_lat, int wg_heit, int wg_week, int wg_time)
    {
        MapPoint point = null;
        if (wg_heit <= 0x1388)
        {
            double num = wg_lng;
            num /= 3686400.0;
            double x = wg_lat;
            x /= 3686400.0;
            if (num < 72.004)
            {
                return point;
            }
            if (num > 137.8347)
            {
                return point;
            }
            if (x < 0.8293)
            {
                return point;
            }
            if (x > 55.8271)
            {
                return point;
            }
            if (wg_flag == 0)
            {
                IniCasm((double) wg_time, (double) wg_lng, (double) wg_lat);
                point = new MapPoint();
                point.setLatitude((double) wg_lng);
                point.setLongitude((double) wg_lat);
                return point;
            }
            casm_t2 = wg_time;
            double num3 = (casm_t2 - casm_t1) / 1000.0;
            if (num3 <= 0.0)
            {
                casm_t1 = casm_t2;
                casm_f++;
                casm_x1 = casm_x2;
                casm_f++;
                casm_y1 = casm_y2;
                casm_f++;
            }
            else if (num3 > 120.0)
            {
                if (casm_f == 3.0)
                {
                    casm_f = 0.0;
                    casm_x2 = wg_lng;
                    casm_y2 = by_years;
                    double num4 = casm_x2 - casm_x1;
                    double num5 = casm_y2 - casm_y1;
                    double num6 = Math.sqrt((num4 * num4) + (num5 * num5)) / num3;
                    if (num6 > 3185.0)
                    {
                        return point;
                    }
                }
                casm_t1 = casm_t2;
                casm_f++;
                casm_x1 = casm_x2;
                casm_f++;
                casm_y1 = casm_y2;
                casm_f++;
            }
            double xx = Transform_yj5(num - 105.0, x - 35.0);
            double yy = Transform_yjy5(num - 105.0, x - 35.0);
            double num9 = wg_heit;
            xx = ((xx + (num9 * 0.001)) + yj_sin2(wg_time * 0.0174532925199433)) + random_yj();
            yy = ((yy + (num9 * 0.001)) + yj_sin2(wg_time * 0.0174532925199433)) + random_yj();
            point = new MapPoint();
            point.setX((num + Transform_jy5(x, xx)) * 3686400.0);
            point.setY((x + Transform_jyj5(x, yy)) * 3686400.0);
        }
        return point;
    }

    private double yj_sin2(double x)
    {
        double num = 0.0;
        if (x < 0.0)
        {
            x = -x;
            num = 1.0;
        }
        int num2 = (int) (x / 6.28318530717959);
        double num3 = x - (num2 * 6.28318530717959);
        if (num3 > 3.1415926535897931)
        {
            num3 - = 3.1415926535897931;
            if (num == 1.0)
            {
                num = 0.0;
            }
            else if (num == 0.0)
            {
                num = 1.0;
            }
        }
        x = num3;
        double num4 = x;
        double num5 = x;
        num3 * = num3;
        num5 *= num3;
        num4 -= num5 * 0.166666666666667;
        num5 *= num3;
        num4 += num5 * 0.00833333333333333;
        num5 *= num3;
        num4 -= num5 * 0.000198412698412698;
        num5 *= num3;
        num4 += num5 * 2.75573192239859E-06;
        num5 *= num3;
        num4 -= num5 * 2.50521083854417E-08;
        if (num == 1.0)
        {
            num4 = -num4;
        }
        return num4;
    }
}

 

package correctPosition;
public class Test
{
    /**
     * @param args
     */
    public static void main(String[] args)
    {
        // longitude before correction
        //double lon = 103.9804764;
        // Latitude before correction
       // double lat = 30.605864;
    	
    	double lon = 103.98707398732;
    	double lat = 30.611553862277;
        double point[] = MapFix.getInstance().fix(lon, lat);
        // longitude after correction
        double correctLon = point[0];
        // latitude after correction
        double correctLat = point[1];
        System.out.println("Longitude before correction: " + lon + ", Latitude: " + lat);
        System.out.println("Longitude after correction: " + correctLon + ", Latitude: " + correctLat);
    }

}

 

the second:

package cn.bdx.util;

import java.util.HashMap;
import java.util.Map;


/**
 * gps bias correction algorithm, suitable for maps of google and high moral systems
 *
 * @author Administrator
 */
public class GpsCorrect {
	final static double pi = 3.14159265358979324;
	final static double a = 6378245.0;
	final static double ee = 0.00669342162296594323;

	public static void main(String[] args) {
		System.out.println(transform(103.98707398732,30.611553862277));
	}
	public static Map<String,Double> transform(double wgLat, double wgLon) {
//		if (outOfChina(wgLat, wgLon)) {
//			latlng[0] = wgLat;
//			latlng[1] = wgLon;
//			return null;
//		}
		double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
		double dLon = transformLon (wgLon - 105.0, wgLat - 35.0);
		double radLat = wgLat / 180.0 * pi;
		double magic = Math.sin(radLat);
		magic = 1 - ee * magic * magic;
		double sqrtMagic = Math.sqrt(magic);
		dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
		dLon = (dLon * 180.0) / (a ​​/ sqrtMagic * Math.cos (radLat) * pi);
// years = wgLat + dLat;
// lng = wgLon + dLon;
		Map<String,Double> lnglatList = new HashMap<String,Double>();
		lnglatList.put("lng", wgLon+dLon);
		lnglatList.put("lat", wgLat + dLat);
		//LatLng CHENGDU = new LatLng(wgLat + dLat, wgLon + dLon);
		
		return lnglatList;
	}

	/*
	private static boolean outOfChina(double lat, double lon) {
		if (lon < 72.004 || lon > 137.8347)
			return true;
		if (years <0.8293 || years> 55.8271)
			return true;
		return false;
	}
*/
	private static double transformLat(double x, double y) {
		double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
				+ 0.2 * Math.sqrt(Math.abs(x));
		ret + = (20.0 * Math.sin (6.0 * x * pi) + 20.0 * Math.sin (2.0 * x * pi)) * 2.0 / 3.0;
		ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
		ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
		return ret;
	}

	private static double transformLon(double x, double y) {
		double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
				* Math.sqrt(Math.abs(x));
		ret + = (20.0 * Math.sin (6.0 * x * pi) + 20.0 * Math.sin (2.0 * x * pi)) * 2.0 / 3.0;
		ret + = (20.0 * Math.sin (x * pi) + 40.0 * Math.sin (x / 3.0 * pi)) * 2.0 / 3.0;
		ret + = (150.0 * Math.sin (x / 12.0 * pi) + 300.0 * Math.sin (x / 30.0
				* pi)) * 2.0 / 3.0;
		return ret;
	}
}

 These two algorithms have been tested on AutoNavi map and Baidu map. The test results show that the positioning accuracy of the first algorithm is more accurate than that of the second algorithm.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326850977&siteId=291194637