APP下载

基于PDA的POI数据采集系统设计与实现

2009-10-26常海军

新媒体研究 2009年13期

夏 江 常海军

[摘要]提出一种在Windce5.0下用EVC和Max mobile结合GPS全球定位系统定位信息加语音的录制和回放的技术,实现电子地图作业过程中,POI采集和更新程序的实现方法。

[关键词]MapX- MobileEVC NEMA0183语音 POI

中图分类号:TP2文献标识码:A文章编号:1671-7597(2009)0710076-03

电子地图应用的飞速发展已逐渐在地图行业中占有越来越大的比重、同时城市范围也在不断的扩大,新修的道路和各种设施比比皆是,电子地图的更新问题已逐渐成了电子地图应用的一种难言之痛,GPS导航成为了一种普遍采用的导航定位技术,并在精度、实时性、全天候等方面取得了长足进步。本文就针对利用前比较普及的GPS系统,实现电子地图中POI更新的一种方法。

一、MapInfo MapX Mobile简介

MapX Mobile是一个可以用在Pocket PC的MapX平台,用MapX Mobile

建立的软件可以单独在设备上运行,并能够和Pocket PC的Windows CE操作系统兼容,不需要无线连接。

二、定位信息的接收

通常GPS定位信息接收系统主要由GPS接收天线、变频器、信号通道、微处理器、存储器以及电源等部分组成。由于GPS定位信息内容较少,因此多用RS-232串口将定位信息(NEMA0183语句)从GPS接收机传送到PDA中进行信息提取处理。从串口读取数据有多种方法,在此直接使用 Win32 API函数对其进行编程处理。在Wince5.0下不允许直接对硬件端口进行控制操作,所有的端口均被视为“文件”,因此在对串口进行侦听之前需要通过打开文件来打开串口,并对其进行相关参数配置:

m_nPortNr=portNo;

wsprintf(szPort, L"COM%d:", portNo); //设置串口名

m_hComm = CreateFile(//打开串口

szPort,

GENERIC_READ | GENERIC_WRITE, //允许读和写

0, //独占方式

NULL,OPEN_EXISTING, //打开而不是创建

0, NULL );

// 设置串口的超时特性为立即返回。

if (!GetCommState(m_hComm,&m_dcb))

{

return FALSE;

}

m_dcb.BaudRate = baud; // 设置波特率

m_dcb.ByteSize = databits; // 数据位,范围:4-8

m_dcb.Parity = NOPARITY; // 校验模式

m_dcb.StopBits = stopbits; // 停止位

//设置串口读写时间

GetCommTimeouts (m_hComm, &m_CommTimeouts);

m_CommTimeouts.ReadIntervalTimeout = 1000;

m_CommTimeouts.ReadTotalTimeoutMultiplier = 0;

m_pPortOwner = pPortOwner;

//指定端口监测的事件集

SetCommMask (m_hComm, EV_RXCHAR | EV_CTS);

//创建读串口线程

m_hReadThread = CreateThread(NULL,0,ReadThreadFunc,this,0,&

m_dwRThreadID);

return TRUE;

}

在成功创建读串口线程后,可采取轮询串口和事件触发两种方式对数据进行接收处理,本文在此采取效率比较高的事件触发方式进行接收处理,通过等待EV_RXCHAR事件的发生来启动ReadFile函数完成对GPS定位信息的接收:

ReadThreadFunc(LPVOID lparam)

{

CCESeries *ceSeries = (CCESeries*)lparam;

DWORD evtMask;

BYTE * readBuf = NULL;//读取的字节

DWORD actualReadLen=0;//实际读取的字节数

DWORD willReadLen;

DWORD dwReadErrors;

COMSTAT cmState;

// 清空缓冲,并检查串口是否打开。

ASSERT(ceSeries->m_hComm !=INVALID_HANDLE_VALUE);

//清空串口

PurgeComm(ceSeries->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR );

SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );

while (TRUE)

{

if (WaitCommEvent(ceSeries->m_hComm,&evtMask,0))

{

SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );

//表示串口收到字符

if (evtMask & EV_RXCHAR)

{

ClearCommError(ceSeries->m_hComm,&dwReadErrors,&cmState);

willReadLen = cmState.cbInQue ;

readBuf = new BYTE[willReadLen];

ReadFile(ceSeries->m_hComm, readBuf, willReadLen, &actualReadLen,0);

//如果读取的数据大于0,

if (actualReadLen>0)

{

::SendMessage((ceSeries->m_pPortOwner)->m_hWnd, WM_COMM_RXCHAR,

(WPARAM) readBuf, (LPARAM) ceSeries->m_nPortNr);

}

}

return 0;

}

三、提取定位数据

GPS接收机处于正常工作状态时,GPS导航定位信息通过串口按设定的时间间隔传送到PDA中。前面的程序代码只是从串口接收数据以字节流的方式放置于指定缓存中,必须通过程序将字节流中的相关信息提取出来,将其格式化为符合程序需要的定位信息数据。同其他通讯协议类似,NMEA 0183信息自有其完善帧结构描述体系。对于本文中其发送到PDA的帧信息主要由帧头、帧尾和帧内数据组成,根据数据帧的不同,帧头也不相同,主要有:

“$GPRMC” 、“$GPGGA”、“$GPGSA” 以及“$GPGSV”等。这些帧头标识了后续帧内数据的组成结构,各帧均以回车符和换行符标识一帧的结束。

对于通常的情况,定位数据如经纬度、速度、时间、等均可以从“$GPRMC”帧中获取得到,而关于定位时间、纬度、经度、高度、定位所用的卫星数、DOP值、差分状态和校正时段等相关信息可从“$GPGGA”帧中获取得,下面这两种帧结构的相关描述:

$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh

<1>UTC时间,hhmmss(时分秒)格式

<2>定位状态,A=有效定位,V=无效定位

<3>纬度ddmm.mmmm(度分)格式(前面的0也将被传输)

<4>纬度半球N(北半球)或S(南半球)

<5>经度dddmm.mmmm(度分)格式(前面的0也将被传输)

<6>经度半球E(东经)或W(西经)

<7>地面速率(000.0~999.9节,前面的0也将被传输)

<8>地面航向(000.0~359.9度,以真北为参考基准,前面的0也将被传输)

<9>UTC日期,ddmmyy(日月年)格式

<10> 磁偏角(000.0~180.0度,前面的0也将被传输)

<11> 磁偏角方向,E(东)或W(西)

<12> 模式指示

$GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,M,<10>,M,<11>,<12>*xx

<1>UTC时间,格式为hhmmss.sss

<2>纬度,格式为ddmm.mmmm(第一位是零也将传送)

<3>纬度半球,N或S(北纬或南纬)

<4>经度,格式为dddmm.mmmm(第一位零也将传送)

<5>经度半球,E或W(东经或西经)

<6>定位质量指示,0=定位无效,1=定位有效

<7>使用卫星数量,从00到12(第一个零也将传送)

<8>水平精确度,0.5到99.9

<9>天线离海平面的高度,-9999.9到9999.9米

<10> 大地水准面高度,-9999.9到9999.9米

<11> 差分GPS数据期限(RTCM SC-104),最后设立RTCM传送的秒数量

<12> 差分参考基站标号,从0000到1023(首位0也将传送)

M 指单位米

至于其他几种帧格式,除了特殊用途外,平时并不常用,虽然接收机也在源源不断地向主机发送各种数据帧,但在处理时一般先通过对帧头的判断而只对"$GPRMC"和$GPGGA帧进行数据处理。如果情况特殊,需要从其他帧获取数据,处理方法与之也是完全类似的。由于帧内各数据段由逗号分割,因此在处理缓存数据时一般是通过搜寻ASCII码"$"来判断是否是帧头,在对帧头的类别进行识别后再通过对所经历逗号个数的计数来判断出当前正在处理的是哪一种定位导航参数,并做出相应的处理。下面就是对缓存数据中的"$GPRMC"和$GPGGA进行解帧处理的主要代码:

$GPRMC:

class CRMCResponse

{

NMEA_TIMEm_Time; // UTC时间

NMEA_DATEm_Date; // UTC日期

BOOL m_IsDataValid;// 定位状态

NMEA_LATITUDEm_Latitude; // 纬度

NMEA_LONGITUDE m_Longitude;// 经度

double m_Bearing;// 地面航向

//提取出相应的数据项

BOOL Parse(const CNmeaSentence& sentence);

};

BOOL CRMCResponse:: Parse(const CNmeaSentence& sentence)

{

// 校验接收到GPS数据是否有效,无效则返回

NMEA_BOOLEAN check = sentence.IsChecksumBad(12);

m_Time = sentence.Time(1);

m_Date = sentence.Date(9);

m_Latitude = sentence.Latitude(3, 4);

m_Longitude= sentence.Longitude(5, 6);

return TRUE;

}

$GPGGA:

class CGGAResponse

{

int m_GPSQuality; //GPS信号质量

int m_nSatellites;//使用卫星数量

//提取出相应的数据项

BOOL Parse(const CNmeaSentence& sentence);

};

BOOL CGGAResponse::Parse(const CNmeaSentence& sentence)

{

// 校验接收到GPS数据是否有效,无效则返回

if (sentence.IsChecksumBad(15) == True)

{

return FALSE;

}

m_GPSQuality= sentence.Integer(6);

m_nSatellites = sentence.Integer(7);

return TRUE;

}

现在已将所需信息提取了出来,主要有经纬度、地面速率、地面航向、天线离海平面的高度、使用卫星数量、是否差分、时间、日期等分别提取到了相应变量中,本程序把经纬度作为坐标信息以点的形式保存在实际的程序数据中,而其它相关变量则作为相应点的属性进行保存。应用中往往要根据需要对其做进一步的运算处理,而且GPS使用的WGS-84坐标系也与我国采用的坐标系不同,有时也要对此加以变换。

四、语音的录制和回放部分的实现

POI采集和更新涉及到的内容较多,这就对采集到的信息描述提出较高的要求,在保证地理空间位置相对准确的情况下,也要保证采集到的相关信息的准确性,比较通用的一些做法是同时采取多种手段来满足要求,主要有下几种方式:

现场记录纸的方式:详细记录每一个信息点相关信息,回到内业把相关信息整理出来,这种做法效率较低,本程序不采取这种方法作为辅助手段。

直接录入程序方式:本文采取的方式是在现场直接把相关信息的描述写入程序中,这种做法效率较高,但同时也增加错误的几率,这就需要采取一种辅助手段来帮助修正错误,常用的有现场录音和拍照的方式,本文主要介绍录音程序的程序实现,下面是语音文件读写主要程序代码。

class CWaveFile

{

public:

/* 文件内部定位 */

unsigned int wave_getpos(wave_file *wf);

char wave_setpos(wave_file *wf, unsigned int pos);

//保存和释放语音文件占用的内存

void wave_free(wave_file *wf);

char wave_save(wave_file *wf);

//保存语音文件

DWORD m_dwFlags;

long Write(char* pData, long nLength);

//打开语音文件

BOOL Open(LPCTSTR szFileName,DWORD dwFlags);

void Close();

//读取语音数据

long Read(char* pData, long nLength);

long GetLength() {return m_nLength;}

protected:

FILE* m_pFile; //文件指针

long m_nLength;//读取或写入文件的数据段长度

};

通过以上程序代码,可以作为辅助手段的语音文件可以非常方便地进行读写,在进行内业数据整理的时候,利用采集现场记录数据和相应录音可以进一步提高信息描述的准确性。

上面是本文中提到的程序的主要实现模块,具体的环境有不同的应用要求,实现细节也可能不同,但此种做业方式对电子地图数据的采集和更新来说,经过实际工作的检验,还是比较实用的。

五、小结

本文结合主要的相关程序代码对电子地图数据的采集和更新进行了模块说明,包括NMEA 0183格式说明、串口的程序设计、语音模块作了简要的讲述。通过本文的设计方法可提高电子地图数据的采集和更新效率和数据质量。本文程序在Windows xp下,由EVC++ 4.0编译通过。

参考文献:

[1]李胜乐,MapInfo地理信息系统二次开发实例,电子工业出版社.

[2]汪兵、李存斌、陈鹏等,EVC高级编程及其应用开发(EMBEDDED VISUAL C++嵌入式编程),中国水利水电出版社.

[3]谭思亮、邹超群,Visual C++串口通信工程开发实例导航,人民邮电出版社.

[4]MapX 开发人员指南,MapInfo Corporation Troy,NY.

[5]Programming Microsoft Windows CE.NET,Third Edition,Douglas Boling Microsoft Press.

[6]NMEA-0183 Protocol Description, Mihai, www.remember.ro.

作者简介:

夏江,女,53岁,工程师,河北省地矿局测绘院制图分院副院长、技术负责,从事测绘工作34年;常海军,河北省地矿局测绘院制图分院,工程师。