本文介绍了如何将GPS模块输出的WGS-84坐标转换为适合百度地图API的BD-09坐标。首先,文章阐述了GPS模块的型号及原始数据帧,接着说明了由于国内坐标系的特殊性,需要从WGS-84经过GCJ-02到BD-09的转换。最后,提供了在QtCreator中编写的C语言转换代码,该代码可移植到其他C语言环境。
GPS模块型号: 中科微电子GPS模块
GPS输出的原始数据帧:
- $GNGGA,114955.000,2842.4158,N,11549.5439,E,1,05,3.8,54.8,M,0.0,M,,*4F
- $GNGLL,2842.4158,N,11549.5439,E,114955.000,A,A*4D
- $GPGSA,A,3,10,31,18,,,,,,,,,,5.7,3.8,4.2*37
- $BDGSA,A,3,07,10,,,,,,,,,,,5.7,3.8,4.2*2A
- $GPGSV,3,1,10,10,49,184,42,12,16,039,,14,54,341,,18,22,165,23*7B
- $GPGSV,3,2,10,22,11,318,,25,51,055,,26,24,205,,29,13,110,*7C
- $GPGSV,3,3,10,31,50,287,36,32,66,018,*7F
- $BDGSV,1,1,04,03,,,07,05,,,29,07,79,246,33,10,52,232,19*62
- $GNRMC,114955.000,A,2842.4158,N,11549.5439,E,0.00,44.25,061117,,,A*4D
- $GNVTG,44.25,T,,M,0.00,N,0.00,K,A*14
- $GNZDA,114955.000,06,11,2017,00,00*47
- $GPTXT,01,01,01,ANTENNA OK*35
-
得到GPS原始坐标数据之后,想通过百度地图API接口直接显示实际定位。
国际经纬度坐标标准为WGS-84,国内必须至少使用国测局制定的GCJ- 02,对地理位置进行首次加密。
百度坐标在此基础上,进行了BD-09二次加密措施,更加保护了个人隐私。
百度对外接口的坐标系并不是GPS采集的真实经 纬度,需要通过坐标转换接口进行转换。
下面代码在QtCreator里编写,可以将代码移植到任何支持C语言的环境中编译运行。
- #include <QCoreApplication>
- #include <QString>
- #include <QDebug>
- extern C;
- {
- #include <math.h>;
- }
-
- class GPS_Data
- {
- public:
- double lat; //纬度
- double lng; //经度
- QString GPS_Data;
- };
- class GPS_Data gps_data;
-
- void GPS_ReadUasrtData();
- #define M_PI 3.14159265358979324
- double a = 6378245.0;
- double ee = 0.00669342162296594323;
- double x_pi = M_PI * 3000.0 / 180.0;
-
- double wgs2gcj_lat(double x, double y)
- {
- double ret1 = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(abs(x));
- ret1 += (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0;
- ret1 += (20.0 * sin(y * M_PI) + 40.0 * sin(y / 3.0 * M_PI)) * 2.0 / 3.0;
- ret1 += (160.0 * sin(y / 12.0 * M_PI) + 320 * sin(y * M_PI / 30.0)) * 2.0 / 3.0;
- return ret1;
- }
-
- double wgs2gcj_lng(double x, double y)
- {
- double ret2 = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(abs(x));
- ret2 += (20.0 *sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0;
- ret2 += (20.0 * sin(x * M_PI) + 40.0 * sin(x / 3.0 * M_PI)) * 2.0 / 3.0;
- ret2 += (150.0 *sin(x / 12.0 * M_PI) + 300.0 * sin(x / 30.0 * M_PI)) * 2.0 / 3.0;
- return ret2;
- }
-
- void wgs2gcj(double *lat,double *lng)
- {
- double dLat = wgs2gcj_lat(*lng - 105.0, *lat - 35.0);
- double dLon = wgs2gcj_lng(*lng - 105.0, *lat - 35.0);
- double radLat = *lat / 180.0 * M_PI;
- double magic = sin(radLat);
- magic = 1 - ee * magic * magic;
- double sqrtMagic = sqrt(magic);
- dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * M_PI);
- dLon = (dLon * 180.0) / (a / sqrtMagic * cos(radLat) * M_PI);
- *lat = *lat + dLat;
- *lng = *lng + dLon;
- }
-
- void gcj2bd(double *lat,double *lng)
- {
- double x = *lng, y = *lat;
- double z = sqrt(x * x + y * y) + 0.00002 * sin(y * x_pi);
- double theta = atan2(y, x) + 0.000003 * cos(x * x_pi);
- *lng = z * cos(theta) + 0.0065;
- *lat = z * sin(theta) + 0.006;
- }
-
- int main(int argc, char *argv[])
- {
- QCoreApplication a(argc, argv);
- GPS_ReadUasrtData();
-
- //得到GPS原始坐标
- double lat=gps_data.lat;
- double lng=gps_data.lng;
-
- //坐标转换
- wgs2gcj(&lat,&lng);
- gcj2bd(&lat,&lng);
-
- //得到百度地图的坐标,可以直接在百度地图上显示
- qDebug()<<"纬度: "<<QString("%1").arg(lat,0,'g',13);
- qDebug()<<"经度: "<<QString("%1").arg(lng,0,'g',13);
-
- return a.exec();
- }
- void GPS_ReadUasrtData()
- {
- /*GPS的原始数据帧*/
- gps_data.GPS_Data="$GNGGA,114955.000,2842.4158,N,11549.5439,E,1,05,3.8,54.8,M,0.0,M,,*4F"
- "$GNGLL,2842.4158,N,11549.5439,E,114955.000,A,A*4D"
- "$GPGSA,A,3,10,31,18,,,,,,,,,,5.7,3.8,4.2*37"
- "$BDGSA,A,3,07,10,,,,,,,,,,,5.7,3.8,4.2*2A"
- " $GPGSV,3,1,10,10,49,184,42,12,16,039,,14,54,341,,18,22,165,23*7B"
- "$GPGSV,3,2,10,22,11,318,,25,51,055,,26,24,205,,29,13,110,*7C"
- "$GPGSV,3,3,10,31,50,287,36,32,66,018,*7F"
- "$BDGSV,1,1,04,03,,,07,05,,,29,07,79,246,33,10,52,232,19*62"
- "$GNRMC,114955.000,A,2842.4158,N,11549.5439,E,0.00,44.25,061117,,,A*4D"
- "$GNVTG,44.25,T,,M,0.00,N,0.00,K,A*14"
- "$GNZDA,114955.000,06,11,2017,00,00*47"
- "$GPTXT,01,01,01,ANTENNA OK*35";
-
- /*解析GPS模块的数据*/
- //QString lat; //纬度
- //QString lng; //经度
- if(gps_data.GPS_Data.size()>200)
- {
- int index=gps_data.GPS_Data.indexOf("$GNGGA");
- if(index>=0)
- {
- QString text=gps_data.GPS_Data.mid(index);
- if(text.size()>60)
- {
- QString lat=text.section(',',2,2);
- QString lng=text.section(',',4,4);
- if(lat.isEmpty()==false && lng.isEmpty()==false)
- {
- unsigned int int_data;
- double s_Longitude,s_latitude;
-
- //转换纬度
- s_latitude=lat.toDouble();
-
- s_latitude=s_latitude/100;
- int_data=s_latitude;//得到纬度整数部分
- s_latitude=s_latitude-int_data;//得到纬度小数部分
- s_latitude=(s_latitude)*100;
- gps_data.lat=int_data+(s_latitude/60.0); //得到转换后的值
-
- //转换经度
- s_Longitude=lng.toDouble();
-
- s_Longitude=s_Longitude/100;
- int_data=s_Longitude;//得到经度整数部分
- s_Longitude=s_Longitude-int_data; //得到经度小数部分
- s_Longitude=s_Longitude*100;
-
- //gai guo le
- gps_data.lng=int_data+(s_Longitude/60.0);
-
- }
- }
- }
- gps_data.GPS_Data.clear();
- }
- }