相比于室内定位,GPS定位已经很成熟了,主要是获取到星历报文后,解析GPGSV,GPGGA,GPGSA等后,获得经度和维度,再通过纠偏,去噪,抽稀,绑路等操作后,显示在地图上。
使用的是GPS模块,通过spi与stm32连接。先用AT指令对GPS模块进行配置,以及接收GPS数据。
1.使能GNSS模块
2.配置GNSS
3.查询星历
当定位成功后,就会返回有效的星历数据。
AT+QGNSSRD?
+QGNSSRD: $GNRMC,032225.306,A,3150.7859,N,11711.9215,E,0.06,204.08,140716,,,A*70
$GNVTG,204.08,T,,M,0.06,N,0.11,K,A*2B
$GNGGA,032225.306,3150.7859,N,11711.9215,E,1,9,1.54,35.0,M,0.0,M,,*40
$GPGSA,A,3,08,30,16,07,27,26,,,,,,,1.75,1.54,0.83*00
$BDGSA,A,3,10,04,07,,,,,,,,,,1.75,1.54,0.83*19
$GPGSV,3,1,09,08,70,004,49,07,55,309,44,42,45,141,,27,38,040,49*7D
$GPGSV,3,2,09,16,28,079,45,30,28,317,31,26,06,096,43,193,,,*7C
$GPGSV,3,3,09,23,,,28*7B
$BDGSV,1,1,03,07,74,113,48,10,74,329,47,04,32,119,40*51
$GNGLL,3150.7859,N,11711.9215,E,032225.306,A,A*4A
先通过$GNRMC等特征将数据划分。再对每个数据进行解析后放入对应的结构体中,如第三行的GNGGA:
$GNGGA,032225.306,3150.7859,N,11711.9215,E,1,9,1.54,35.0,M,0.0,M,*40
意义:$信息类型,时间,维度,南/北,经度,东/西,gps状态,正在使用的卫星数量,水平精度因子,海拔高度,高度单位。。。
模块获得的经纬度坐标只是原始坐标系,需要进行纠偏转换。可以调用百度API或者高德API,转换为百度/高德坐标系。需到对应平台申请权限。
这里使用的是百度的API,使用HTTP框架通过URL调用api回调百度坐标系的坐标。
snprintf(szReqUrl, 1024, "http://api.map.baidu.com/geoconv/v1/?coords=%.6f,%.6f&from=1&to=5&ak=xxxxxxxxxxxxx",
req->lng, req->lat);
std::string strRes;
int nRet = HttpGet(szReqUrl, strRes);
将百度坐标系的坐标放入百度地图中,红色为真实行走路线,由于GPS模块质量不好,漂移比较大,但还是可以再进行优化
这里使用卡尔曼滤波来去噪,去噪结果。
抽稀并没有做,如果数据量大,可以添加抽稀算法。
如果活动位置只在道路,还可以调用绑路的百度api。
如果还想优化,可以用星历中的其他数据处理。测试过精度因子,速度,都不太理想。或者添加惯性导航,就如百度地图一样。