qgis 源码学习之core的gps模块
来源:互联网 发布:用c语言求以内素数 编辑:程序博客网 时间:2024/05/17 06:30
我已经编译出了qgis2.4的源码,进行了一些简单的二次开发,但是仍然感觉不爽,这么优秀的软件就单单在它上层做开发,太浪费了,我想学习qgis的源码的架构,顺便学习qgis的二次开发,为我将来的自己架构自己的软件吸取些经验。
qgis的文档还是比较少的,并且1.0版本和2.0以上的版本差别很大,而中文的文档绝大部分针对1.0版本,如果照搬的话会导致编译出现问题。我以下的博文是边看编写。
1.qgis的源码文档如何找到?
http://qgis.org/api/2.4/files.html 这里是找到的。
2.qgis的源码的核心部分主要分为:analysis;core;gui;plugin;4个部分。
上面4个模块的依赖关系依次是:
analysis模块:
gui模块:
Plugin模块:
core模块:
上面4个模块的core和plugin模块均是独立存在的,而其余两个模块均依赖于core模块,所以我打算首先读core模块。
从上面的core模块的内部图可以看出core模块中的gps模块是比较独立的,首先读gps模块。
gps模块里面有一个很重要的概念就是“NMEA”,NMEA是美国国家海洋电子协会(National Marine Electronics Association)的简称,它规定了gps数据的协议,如果解析过gps数据就知道“#BESPOSA"之类的东西就是由它规定的,gps模块规定
config.h里面规定了NMEA协议的版本、NMEA_VERSION_PATCH 补充协议版本,产生调试”assert“的一些宏NMEA_ASSERT(x)。
contex.h定义了输出调试信息的函数:nmea_trace、nmea_trace_buff、nmea_error;对应的.c文件就是对应的实现。
info.h定义了各种NMEA用到的各种数据结构。_nmeaPOS 位置信息里面只有两个变量一个经度另一个是纬度,所以qgis只能是二维的不可能是三维的地图软件。nmeaSATELLITE卫星信息。nmeaSATINFO是nmeaSATELLITE的包装:里面描述了有多少卫星是可见的,有多少卫星是可用的。;nmeaINFO是gps解析数据的结构体。
下面的gmath.h使用了这个info.h文件。这个文件在gps模块是个基础的头文件。
gmath.h定义了数学函数例如定义了PI、地球的平均半径等宏;角度弧度转化函数(nmea_degree2radian);NMEA degree(NMEA度)和弧度、角度转化。计算位置精度因子(pdop)、精度衰减因子(PDP)函数:nmea_calc_pdop等。位置转化函数:主要是由原始的gps字符串转化为逻辑量,例如:nmea_info2pos是由NMEA的原始数据解析后倒入POS结构中里里面的实现也很简单:
pos->lat = nmea_ndeg2radian( info->lat );pos->lon = nmea_ndeg2radian( info->lon );
nmeatime.h 定义了一个“nmeaTIME"的结构体,和一个获取当前时间的函数nmea_time_now。
nmea_time_now函数在time.c中定义,调用Windows的GetSystemTime函数,所以这个函数是调用的系统时间。
parse.h解析gps数据包用的各个函数
<span style="font-size:10px;">int nmea_pack_type( const char *buff, int buff_sz );//包的类型int nmea_find_tail( const char *buff, int buff_sz, int *res_crc );//寻找包尾,并进行crc校验int nmea_parse_GPGGA( const char *buff, int buff_sz, nmeaGPGGA *pack );//解析GPGGA包int nmea_parse_GPGSA( const char *buff, int buff_sz, nmeaGPGSA *pack );int nmea_parse_GPGSV( const char *buff, int buff_sz, nmeaGPGSV *pack );int nmea_parse_GPRMC( const char *buff, int buff_sz, nmeaGPRMC *pack );int nmea_parse_GPVTG( const char *buff, int buff_sz, nmeaGPVTG *pack );void nmea_GPGGA2info( nmeaGPGGA *pack, nmeaINFO *info );//从pack填充info结构,下同void nmea_GPGSA2info( nmeaGPGSA *pack, nmeaINFO *info );void nmea_GPGSV2info( nmeaGPGSV *pack, nmeaINFO *info );void nmea_GPRMC2info( nmeaGPRMC *pack, nmeaINFO *info );void nmea_GPVTG2info( nmeaGPVTG *pack, nmeaINFO *info );</span>
parser.h定义了一个解析结构体,但是这里面的函数从来没有在qgis里面用过,主要使用parse.h的函数,所以这个文件可以略过。。。。
unites.h定义了3个单位与米进行换算的公式:分别是
#define NMEA_TUD_YARDS (1.0936) /**< Yeards, meter * NMEA_TUD_YARDS = yard 码*/#define NMEA_TUD_KNOTS (1.852) /**< Knots, kilometer / NMEA_TUD_KNOTS = knot节 */#define NMEA_TUD_MILES (1.609) /**< Miles, kilometer / NMEA_TUD_MILES = mile 英里 */
tok.h定义了几个函数,主要有格式化输入输出,字符串转int,字符串转float。
int nmea_calc_crc( const char *buff, int buff_sz );//计算buffer中的crc,并返回crc值int nmea_atoi( const char *str, size_t str_sz, int radix );//转化成intdouble nmea_atof( const char *str, int str_sz );//字符串转floatint nmea_printf( char *buff, int buff_sz, const char *format, ... );//格式化输出int nmea_scanf( const char *buff, int buff_sz, const char *format, ... );//格式化输出
sentence.h定义了gps的rawData的集中数据类型和各种结构nmeaPACKTYPE等。和info.h一样这也是很基础的文件。
下面的文件是qgs独有的文件,上面的文件是nmea库的,是qgis借用nmea的。
qgsgpsconnection.h里面定义了自己的QgsSatelliteInfo(gps卫星信息)和QgsGPSInformation(gps信息)这两个struct。这两个struct与nmea在info.h定义的两个struct类似。QgsGPSConnection是一个抽象的gps设备类,定义了一个parseData接口,在使用这个类的时候,首先传入一个QIODevice设备,这类调用parseData接口然后就可以解析数据了。很牛逼的写法,值得学习。实现了硬件层和软件层的隔离。connect和close函数用来打开关闭设备。它是如何实现设备与解析结合的呢?
QgsGPSConnection::QgsGPSConnection( QIODevice* dev ): QObject( 0 ), mSource( dev ), mStatus( NotConnected ){ clearLastGPSInformation(); QObject::connect( dev, SIGNAL( readyRead() ), this, SLOT( parseData() ) );}
它是通过调用一个qt的connect来实现的。
这个类里其他主要的函数有
currentGPSInformation//得到当前的gps状态status//得到当前硬件的状态,是否正常工作等。
QgsGPSConnectionRegistry类用来注册QgsGPSConnection类。这个类是一个单例的。里面采用Qset来实现。instance函数采用一个static的变量来实现。这种写法要比定义一个成员变量要简洁,并且不用使用锁。
QgsGPSConnectionRegistry* QgsGPSConnectionRegistry::instance(){ static QgsGPSConnectionRegistry mInstance; return &mInstance;}
QgsNMEAConnection 类是QgsGPSConnection的一个具体的实现,作用是解析来自gps的NMEA数据,主要是实现了QgsGPSConnection的parseData函数。QgsGpsdConnection类继承自QgsNMEAConnection类,主要是实现对gpsd守护进程的监视。gpsd是监视来自usb或者串口的gps数据,然后通过tCP 的2947 端口把数据发送出去,gpsd的网址:http://www.catb.org/gpsd
class CORE_EXPORT QgsGPSDetector : public QObject{ Q_OBJECT public: QgsGPSDetector( QString portName ); ~QgsGPSDetector();/*通过调用qt提供的函数枚举所有的串口*/ static QList< QPair<QString, QString> > availablePorts(); public slots: /* 函数里面定义了一个timmer时间为2000毫秒,每2000秒调用一次advance函数。 尝试打开mPortList里面存储的所有的串口,每个串口尝试使用mBaudList里面存储的波特率。 如果执行完串口的open函数后,把detected函数connect给gps信息改变slot。 */ void advance(); void detected( const QgsGPSInformation& ); void connDestroyed( QObject * ); signals: void detected( QgsGPSConnection * ); void detectionFailed(); private: int mPortIndex; int mBaudIndex; QList< QPair< QString, QString > > mPortList; QList<BaudRateType> mBaudList; QgsGPSConnection *mConn;};
QgsQtLocationConnection类从QgsGPSConnection继承。
class CORE_EXPORT QgsQtLocationConnection: public QgsGPSConnection{ Q_OBJECT public://调用startMonitor函数和strtGPS函数,开启一个0.5秒的timer,timer不停的调用broadcastConnectionAvailable,来广播最后一次的gps状态 QgsQtLocationConnection(); ~QgsQtLocationConnection(); protected slots: /**Needed to make QtLocation detected*/ void broadcastConnectionAvailable( ); /**Parse available data source content*/ void parseData(); /**Called when the position updated. * @note not available in python binding */ void positionUpdated( const QGeoPositionInfo &info ); /**Called when the number of satellites in view is updated. * @note not available in python bindings on android */ void satellitesInViewUpdated( const QList<QGeoSatelliteInfo>& satellites ); /**Called when the number of satellites in use is updated. * @note not available in python bindings on android */ void satellitesInUseUpdated( const QList<QGeoSatelliteInfo>& satellites ); private: void startGPS(); void startSatelliteMonitor(); QString mDevice; QGeoPositionInfo mInfo; QPointer<QGeoPositionInfoSource> locationDataSource; QPointer<QGeoSatelliteInfoSource> satelliteInfoSource;};
gps模块总结:
里面分为两个部分前缀不带qgs和前缀带qgs的。不带qgs的为其他的开源软件中抠出来的代码,代码可能全部来自nmea的库。前缀带qgs的为qgs的代码。
最基础的类为QgsGPSConnection,它是:QgsQtLocationConnection、QgsNMEAConnection 的父类。QgsGPSConnectionRegistry用来注册QgsGPSConnection类。总之QgsGPSConnection是这个gps模块里的核心。
gps模块里还有两个比较基础的数据结构:QgsSatelliteInfo(gps卫星信息)和QgsGPSInformation(gps信息)它是上面QgsGPSConnection向外发送signal的载体。
gps模块完毕2015.1.23
- qgis 源码学习之core的gps模块
- qgis源码学习2之core模块的raster
- qgis源码学习3之core模块的qgis.h文件
- QGis provider模块的编写
- QGIS学习之-环境搭建
- QGIS学习之-显示SVG图片
- Spring之Core模块
- Spring之Core模块
- QGIS开发之矢量图层的使用
- gps各个模块的解析
- 移植quectel的GPS模块
- QGIS源码编译问题
- QGIS源码编译
- core模块的初始化
- OpenFeint源码学习之Challenge模块
- [Python源码学习]之模块路径
- Live555源码学习笔记之UsageEnvironment模块
- libzdb源码学习之二:异常模块
- 两种方法模仿支付宝进入到后台界面模糊
- 静态字符串的连接操作
- Java中的String为什么是不可变的? -- String源码分析
- HTML之Canvas基础
- zkw Splay学习笔记
- qgis 源码学习之core的gps模块
- redis 源码学习(核心数据结构剖析)
- android Studio安装详解
- Maven(一) Maven的安装
- Java多线程一捋
- 5行代码怎么实现Hadoop的WordCount?
- 苹果语音
- java 构造函数(本例意在说明如果一个类里定义了构造函数,则系统不会再给定义默认的无参构造函数)
- 进程控制3 守护进程 华清远见-《嵌入式 Linux 应用程序开发标准教程》