一、概述
当前主流的卫星导航系统主要有中国的北斗,美国的GPS,俄罗斯的GLONASS和欧洲的伽利略。同一时刻,我们的头顶上飞过各家数量各异的导航卫星。在一些全球定位模块中,有的可以同时接收各家导航卫星的信号,如和芯星通的UB482模块。 我们通过UB482模块的串口,可以同时接收到所有导航卫星的数据,根据NMEA0183协议解析出可用的经纬高等信息。
下面以NMEA0183协议为例,解析APM中卫星导航数据。
二、APM中NMEA协议卫星数据流
1.初始化
一般卫星的数据都是通过串口传递的。在APM中,在serial_manager类根据协议类型初始化串口,其调用关系见下图。具体调用代码见void AP_SerialManager::init()函数。
(1)
GPS初始化在AP_GPS::init()函数中,通过serial_manager.find_serial(AP_SerialManager::SerialProtocol_GPS, uart_idx)函数找到对应的串口。
2.数据更新
如图(2)所示,了解数据流之前先看类图。GPS相关的处理也是遵循APM一贯的逻辑,前后端相互包含,后端是具体实现类的抽象父类。AP_GPS_Backend与AP_GPS相互包含,每个具体的协议继承AP_GPS_Backend。通过前端AP_GPS类的成员类*drivers[instance]访问具体实例化后的AP_GPS_NMEA类中的成员变量与成员方法。
(2)
如图(3)所示,在new AP_GPS_NMEA对象时,传入前端AP_GPS的this指针,AP_GPS类中的私有成员结构体AP_GPS_State的引用,私有成员类AP_HAL::UARTDriver。故在AP_GPS_NMEA中操作的state,数值即为AP_GPS中的state数值。该过程在detect_instance(instance)函数中完成。
(3)
如图(4)所示,以解析NMEA协议为例。drives是AP_GPS_Backend类型的,是AP_GPS_NMEA的父类。APM通过父类AP_GPS_Backend调用子类AP_GPS_NMEA的read函数。从而一步一步调用到AP_GPS_NMEA::_term_complete()函数。在_term_complete()函数中将state赋值,完成卫星数据解析与传递。 具体解析过程见这里。
(4)
AP_GPS::update()函数在调度器中以50Hz的频率调用。
3.上层应用
APM代码中添加了一个数据抽象层AP_DAL。在AP_DAL_GPS::start_frame()函数中,通过静态成员函数AP::gps()获取底层GPS的数据。凡是上层需要应用到GPS数据的,都可以通过AP::gps()函数获取。
(5)
GPS数据在EKF中应用过程如图(6)所示。其中AP_DAL_GPS::start_frame()在AP_DAL::start_frame()中更新;AP_DAL::start_frame()在NavEKF3::UpdateFilter(void)中以400Hz频率更新。