FollowMe模块设计思路与学习总结
组成结构
- FollowMe (跟踪引导)
实现思路
FollowMe
头文件包含以下头文件:
- #include < QTimer>
- #include < QObject>
- #include < QThread>
- #include < QGeoPositionInfo>
- #include < QGeoPositionInfoSource>
- #include < QElapsedTimer>
- #include “QGCToolbox.h”
- #include “MAVLinkProtocol.h”
源文件包含以下头文件:
- #include < QElapsedTimer>
- #include < cmath>
- #include “MultiVehicleManager.h”
- #include “FirmwarePlugin.h”
- #include “MAVLinkProtocol.h”
- #include “FollowMe.h”
- #include “Vehicle.h”
- #include “PositionManager.h”
定义一个结构体motionReport_s,包含时间标记,X轴位置,Y轴位置和高度,XYZ轴速度和加速度。
定义一个新枚举,位置为0,速度为1,加速度为2,高度等级为3。
定义变量:
- estimatation_capabilities (估算能力)
- _**gcsMotionReportTimer** (定时器定时发出运动报告)
定义一个公有槽: void followMeHandleManager(const QString&); (跟踪引导处理管理器) 如果飞行器有PX4固件且飞行模式包含PX4,那么调用enable函数启动并返回,否则不启动。
定义两个私有槽:
- void _**setGPSLocation**(QGeoPositionInfo geoPositionInfo); (设置GPS位置) 如果GPS信息有效,则获取当前的位置坐标,赋值到经度纬度高度,计算XYZ轴的速度。
- void _**sendGCSMotionReport**(void); (发送门控开关运动报告) 初始化一个追踪目标,并设置它的各项参数。如果飞行器的飞行模式与PX4飞行模式相比为0的话,获取飞行器的信息,并通过连接发送信息将该飞行器设为优先连接。
初始化:将estimatation_capabilities初始化为0,将运动报告结构体中的数据成员用memset初始化,启动计时器并设置单次激发为false,然后把计时器和运动报告联系起来。
成员函数:
- _**enable**() 将位置信息更新与GPS位置连接起来,设置运动报告计时器的间隔,并开始计时。
- _**disable**() 断开位置信息更新与GPS位置的连接,停止运动报告计时器。
- _ degreesToRadian(double deg) (角度转弧度) M_PI/180.0为弧度。
总结
FollowMe类实现了对当前位置的获取,以及XYZ轴方向上的速度计算,通过计时器不断发送位置信息,达到了对飞行器位置实时监控的目的。
#pragma once的用法
为了避免同一个文件被include多次
1 #ifndef方式
2 #pragma once方式
在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别。
方式一:
#ifndef __SOMEFILE_H__
#define __SOMEFILE_H__
... ... // 一些声明语句
#endif
方式二:
#pragma once
... ... // 一些声明语句
#ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况
#pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。
方式一由语言支持所以移植性好,方式二 可以避免名字冲突