2010年1月30日星期六

GPS导航DIY指南

年底要去老婆老家,准备开车去,一路近800公里,又是第一次开,有一个导航当然是最好不过了~作为导航业内人士,有现成的GPS设备可以用,当然不屑用市面上的GPS导航仪(好吧,我承认没有钱也是一个重要的原因~),DIY自然成了我的首选! 导航其实就是能在地图上显示出你当前的位置、方向、速度等信息,所需的硬件就是GPS接收机和显示地图的设备,所需的软件就是接收GPS接收机的数据并解析显示于地图上。下面就来一个个的分析。
 
先说说硬件吧~
 
GPS接收机有现成的,无非是精度好点差点,都属于单点定位,精度在5-15米之间,这个问题不大~
显示地图的设备无非是嵌入式系统或者本本。嵌入式系统的优点是小巧方便,缺点是功能比较弱,需要专门定制软件,作为DIY的话不方便利用已有的成果,且屏 幕一般都比本本小得多,另外一个放弃的重要原因是我手头上虽然有一个嵌入式系统,还带触摸屏,但是这个东西关系着毕业大计,金贵着呢,可不敢随便拿出来折腾!因此这里我选用本本作为显示地图的载体。它功能强,屏幕大,有丰富的软件资源可供利用,唯一的缺点就是有点大,不方便直接放在前车窗,会挡住视线,估计要放在副驾驶位子上了~
至于GPS接收机与本本的连接当然用经典的串口了(其实我也知道蓝牙更好~),本本没有物理串口不要紧,用USB-串口转接线,还省去了不能带电插拔的麻烦!
 
再来说说软件。

以前也查过,windows下的免费的导航软件很少,OZI的demo版据说功能限制很多,GooPs试用过,反正是不咋的,需要GE开着,没法联网的时候要事先在缓存里有地图才行,比较麻烦,不实用!再来看Linux下的GPS导航软件,其他的我不知道,反正是一眼就看中gpsDrive[1]了!瞧人家主页上说的,支持Linux、Mac OSX和FreeBSD,就是不支持Windows!我喜欢^_^装了一看,界面还蛮好看的,估计接上GPS就能工作了!就选它了~
选好了gpsDrive,下面就是找地图下载了~在gpsDrive的主页里它主要是从OpenStreetMap项目里下载地图,顺链接过去看了一下, 这玩意靠的是大家都来贡献,在中国地图基本上没法用!还是要另想办法啊~在谷歌里搜索gpsdrive,还真找到一个台湾的哥们在eeePC上用过[2],给出了使用指南,最关键的是给出了一个地图下载的网址[3]!赶紧顺着网址看过去,嘿,还真是专门为qpeGPS和 gpsDrive设计的!里面可以设定要下载的范围、缩放等级、重叠率等,然后记着要点击“Generate wGet”,不然非等死你不可!即使这样,生成一个包含690个小图的下载链接及配套经纬度信息的页面也要让我的Firefox假死几分钟~
有了下载链接和经纬度信息下面怎么办呢?很简单,把下载链接都拷到一个文件里,保存为sh文件,然后执行即可。需要注意的是,网络不好的时候,经常会停在某个wget半天也不动弹,是可忍,孰不可忍!我的经验是肉眼看看不行了就Ctrl+C中断sh的执行,将已经保存下来的图片对应的wget命令注释掉(我用kate里的Ctrl+D来干这事,忒方便),然后再次执行。这样的过程根据网络的好坏不同,可能需要执行N次(在我这里N>10),这也是 整个地图下载过程中最ugly的部分(应该也可以编程来自动处理这种情况的,但宽恕我偷懒了~)……下载完的小地图放在~/.gpsdrive/maps/里,还需要将配套的经纬度信息也存到一个文本文件里,以备后用~
这时下载好的小地图尺寸是固定的(1280*1024),满足gpsDrive的要求,相对精度也是没有问题的,但由于万恶的GOV人为增加偏移量,直接使用配套的经纬度信息来显示地图那误差是相当的大,目测大约有600-1000米,当然是没法用了!也许你要问市面上那些GPS导航仪怎么就能定位到路上呢?除了他们一定使用了道路匹配算法外,最主要原因应该还是他们手头上有相应的加密解密算法,这玩意我们自然搞不到,所以只有另想办法~
要不怎么说我人品好呢,就在2009年的下半年,有人刚刚发现了谷歌地图的偏移值可以通过网络查询的方式获得,更为可贵的是,发现者无私的奉献出了全部知识[4-5],让我由衷的敬佩!按照发现者的指引,我成功的解决了谷歌地图偏移的问题[6],根据前面下载的与小地图匹配的经纬度信息来查询偏移值,然后进行修正,最后统一放在了~/.gpsdrive/maps/map_koord.txt文件中~
说到这里技术上的难题基本上都解决了,设定GPS接收机送出NMEA中的RMC语句就可以得到时间、经纬度、方向、速度等信息,配合gpsd,就可以正常使用gpsDrive了!不过根据人品守恒定律,我也该碰到点麻烦了~果然,本来准备用的Garmin 25-LVS的天线好像有问题,导致接收机始终无法输出任何东西,没办法,只好用JNS100来代替。设置输出RMC语句后,用串口调试助手可以看到正确 的输出了GNRMC语句,但是用gpsd+xgps来观察,状态却始终是Unkown,这是怎么回事呢?将输出语句改为GGA,输出的是GPGGA语句,这就可以定位了!但是由于GGA语句的信息不全,还要另外加VTG语句才完整。再设定添加VTG,输出GNVTG,在xgps中依然看不到速度、方向信息!仔细观察了一下,发现问题可能就出在开头的标识符上,凡是GP***开头的好像gpsd就认,以GN***开头的就不认!那就自己加个小程序[7],从/dev/ttyUSB0接收GN***的语句,然后改为GP***后再输出到一个伪终端(/dev/pts/*),让gpsd从那个伪终端接收即可~嘿嘿,幸亏前一阵要离线调试监控系统,逼着自己搞通了虚拟串口和伪终端,现在这样的工作就是小case了~中间也出了一点小波折,改完后的GP***语句gpsd还是不认,观察 gpsd的调试信息发现是校验码错误,这才想起来光改了内容,没有生成新的校验码,不错才有鬼了!NMEA的校验码很简单,就是字节的XOR操作,很快就搞定了,这时xgps里已经能够正确的显示所有需要的信息了~
最后连上lab的GPS天线测试了一下,肉眼观察误差在5米之内,perfect!至此,所有的技术问题都解决了,剩下的就是找个盒子把这些零碎装起来, 只留三个接口出来,加上我的本本就可以GPS车载导航了~
具体的程序我依然都放在了代码发芽网上,这里就给个链接,因为内容仍会时不时的更新一下,不方便直接放在这里。
[1] GpsDrive - a free car (bike, ship, plane) navigation system:http://www.gpsdrive.de/
[2] EeePC上用GPSDrive玩GPS和Google Map:http://www.terewong.com/mytoys0ab27.htm
[3] Google maps to qpeGPS and gpsDrive:http://gtm.tel.uva.es/ztep/maps/dmap.htm
[4] 中国地图经纬度偏移修正算法完美解决方案:http://blog.csdn.net/dongmeng110/archive/2009/10/31/4750380.aspx
[5] Google地图经纬度到像素索引值的转换公式:http://blog.csdn.net/dongmeng110/archive/2009/12/13/4997634.aspx
[6] 谷歌地图校准程序:http://fayaa.com/code/view/8649/
[7] 串口接收GNRMC转发GPRMC到伪终端:http://fayaa.com/code/view/8643/

ps,后来发现25LVS不是天线的问题,而是串口的线断了!重新焊了一下,又用上了!这下子原来写的“串口接收GNRMC转发GPRMC到伪终端”程序就用不上了,开了GPSD直接就可以收到GPRMC语句,更加的方便了~~定位精度还是很高的,显示在地图上能有5米左右。但是开始纸盒子的安装设计不太好,受力点集中在串口连接头上,因为没有螺丝固定,很容易就掉下来了,另外电源的连接头也不牢靠。干脆换了一个扁扁的硬纸盒子,把各种连接头都放在了盒子里面,只将又粗又结实的USB线和电源线引出来,这下就牢靠多了!当然天线也是要引出来~

多讲一句,有了淘宝就是好啊,本来以为一个磁性天线要200多,在淘宝上一查,20块就可以搞定!买了两根,试了一下,一点问题也没有!现在是已经停产的25LVS+20块钱的磁性天线+自己的本本,嘿嘿,非常便宜,心里没有负担啦!^_^
在校园里跑车试了一下,在一条仅能通过一辆车的路上,GPS也能精确的定位,感觉精度已经差不多1-2米了!真是意外啊!现在一切准备就绪,就等出发啦~~