赞
踩
所有的热爱都要不遗余力,真正喜欢它便给它更高的优先级,和更多的时间吧!
关于QGC地面站其它文章请点击这里: QGC地面站
QGroundControl(QGC)是一款开源的跨平台地面站软件,用于控制和监控各种类型的无人机、无人船、无人车等载具。它提供了丰富的功能,包括飞行计划、实时地图、传感器数据显示、飞行状态监测、遥控器控制、实时视频显示等,可以支持多种硬件设备和自定义设置。
当无人机在地图上飞行时,实现飞机图标实时跟随一个参数小面板,让用户对关键信息一目了然。 此参数小面板设置为半透明,可实时跟随飞机图标移动,显示内容包括电池剩余百分比、电池电压、飞行模式、地速、空速、爬升速度、相对高度、飞行距离等关键参数。如下gif:
代码如下:(FlightDisplayViewMap.qml):
// Add the vehicles to the map 244行
MapItemView { //标记1
model: QGroundControl.multiVehicleManager.vehicles //标记2
delegate: VehicleMapItem { //标记3
vehicle: object
coordinate: object.coordinate //标记4
map: flightMap
size: mainIsMap ? ScreenTools.defaultFontPixelHeight * 3 : ScreenTools.defaultFontPixelHeight
//z: QGroundControl.zOrderVehicles //总修改1-1
}
z: QGroundControl.zOrderTopMost //总修改1-2
}
参考:QT Creator 帮助中搜 “MapItemView”,MapQuickItem
● 标记1:MapItemView是用来构成Map的一部分的。它数据主要是源自model(ListModel、RouteModel等)。和ListView 相似 ,也是mode-delegate模型。 仅仅不同于MapItemView的代理Delegate需要为地图控件,即位置设置为经纬度坐标。ListView的Delegate控件为桌面控件,位置设置为屏幕位置。 MapItemView类型只有在包含在Map中时才有意义,它不能独立存在。
● 标记2:model:提供数据给委托定义的mapItem(VehicleMapItem),由它提供的信息(飞行模式、地速、空速、爬升速度、相对高度、飞行距离)作为Map ItemView的输入,下面再具体讲解。记住model 仅支持 “QAbstractItemModel” 的基础模型。
显然 “QGroundControl.multiVehicleManager.vehicles” 是 QAbstractItemModel 类型的,如下:
// src\Vehicle\MultiVehicleManager.h:100
QmlObjectListModel* vehicles(void) { return &_vehicles; }
● 标记3:delegate:定义了模型中的每个项改如何显示。 要求 delegate 必须为组件,且包含一个map Item, “MapQuickItem”类型的居多。
● 标记4:coordinate:定位坐标。为什么能动态跟随,此为最关键的属性,它在C++ vehiclel 类中会实时更新。(NOTIFY修饰的属性,下文会讲到)
coordinate是“MapQuickItem”的一个属性。 此属性保存MapQuickItem的锚点坐标。在地图显示时,由anchorPoint指定的sourceItem上的点与此坐标保持会一致。
在此MapItemView中。object 对应的就是 vehicles ,委托了VehicleMapItem来实现,VehicleMapItem为MapQuickItem类型的。MapQuickItem的sourceItem指定了一个Item来如何显示。该Item就是9行3列的关键参数的显示信息。
● 修改1: 此文件中仅修改一处“z” 属性,是为了让面板在顶层显示。记得放在“MapItemView”的属性下,不然不会生效,这很关键
接下来让我再看看代理中的文件吧!
上文提到 model,由它提供的飞行模式、地速、空速、爬升速度、相对高度、飞行距离的。
flightMode、roll、groundSpeed都是在“VehicleMapItem”中定义的变量。 object.flightMode、object.roll.rawValue、 object.groundSpeed.rawValue来自于“vehicles”。那么再看下 C++中的Vehicle吧
● 修改2: 在文件头增加如下属性:
//总修改2: (object = vehicle = QGroundControl.multiVehicleManager.vehicles)
property string flightMode: vehicle.flightMode;
property real roll: vehicle.roll.rawValue;
property real groundSpeed: vehicle.groundSpeed.rawValue;
property real airSpeed: vehicle.airSpeed.rawValue;
property real climbRate: vehicle.climbRate.rawValue;
property real altitudeRelative: vehicle.altitudeRelative.rawValue;
property real flightDistance: vehicle.flightDistance.rawValue;
property real distanceToHome: object.distanceToHome.rawValue;
property real batteryPercentRemain: object.battery.percentRemaining.value
property real batteryVoltage: object.battery.voltage.value;
object = vehicle = QGroundControl.multiVehicleManager.vehicles ,让我们在看看vehicle类…
● C++中的Vehicle类的分析。
要在QML实时显示,那么必须是“NOTIFY”修饰的信号,它给属性关联一个信号,当属性的值发生变化时就会触发该信号。比下flightMode属性,
Q_PROPERTY(QString flightMode READ flightMode WRITE setFlightMode NOTIFY flightModeChanged)
C++和QML之间不懂如何交互的可以点击这里:Qt Quick Qml 之QML与C++ 混合编程学习
当我们在 C++中改变该参数值时,发射 flightModeChanged 信号, 来通知 qml 相关的属性有更改,进而实现相关的状态更改。没有“NOTIFY”修饰的,不会实时触发,也不会动态更新了。
但是是不是发现在Vehicle类中,一些关键的属性并没有使用NOTIFY ?
如下:
Fact* roll () { return &_rollFact; }
Fact* rollRate () { return &_rollRateFact; }
Fact* pitchRate () { return &_pitchRateFact; }
Fact* yawRate () { return &_yawRateFact; }
Fact* airSpeed () { return &_airSpeedFact; }
Fact* groundSpeed () { return &_groundSpeedFact; }
Fact* climbRate () { return &_climbRateFact; }
仔细分析Fact类:
class Fact : public QObject
{
Q_OBJECT
...
Q_PROPERTY(QString shortDescription READ shortDescription CONSTANT)
Q_PROPERTY(QString units READ cookedUnits CONSTANT)
Q_PROPERTY(QVariant value READ cookedValue WRITE setCookedValue NOTIFY valueChanged)
Q_PROPERTY(QVariant rawValue READ rawValue WRITE setRawValue NOTIFY rawValueChanged)
}
发现“rawValue ”也用“NOTIFY”修饰了。所以问题就很简单了,直接去到 “rawValue” 就好
...
property string flightMode: vehicle.flightMode;
property real roll: vehicle.roll.rawValue;
property real groundSpeed: vehicle.groundSpeed.rawValue;
property real airSpeed: vehicle.airSpeed.rawValue;
property real climbRate: vehicle.climbRate.rawValue;
...
● 修改3: 在MapQuickItem中的“ sourceItem: Item "中最后增加矩形框:
Rectangle { id: cchVehicleStatusView; anchors.bottom: vehicleIcon.top; anchors.bottomMargin: 4 anchors.horizontalCenter: vehicleIcon.horizontalCenter; color: "#DDDDFF" radius: 10 width: buttonColumn.implicitWidth * 1.1 height: buttonColumn.implicitHeight * 1.1 opacity : 0.8; border.color: "black" border.width: 2 Column { id: buttonColumn width: statusNameRepeater.implicitWidth height: statusNameRepeater.implicitHeight anchors.top: parent.top anchors.topMargin: 6 anchors.left: parent.left anchors.leftMargin: 6 spacing: ScreenTools.defaultFontPixelHeight / 2 Repeater { id: statusNameRepeater model: 9 property var statusNames: [ "电池剩余百分比: ", "电池电压: ", qsTr("飞行模式:"), qsTr("地速: "), qsTr("空速: "), qsTr("爬升速度: "), qsTr("相对高度: "), qsTr("飞行距离: "),"到home点距离: "] property var statusValues: [batteryPercentRemain, batteryVoltage, flightMode, groundSpeed.toFixed(2), airSpeed.toFixed(2), climbRate.toFixed(2), altitudeRelative.toFixed(2), flightDistance.toFixed(2), distanceToHome.toFixed(2)] property var statusUnits: ["%", "v", "", "(m/s)", "(m/s)", "(m/s)", "(m)", "(m)", "(m)"] Row{ id: _row QGCLabel { color: "#424200" horizontalAlignment: Text.AlignHCenter font.pointSize: ScreenTools.mediumFontPointSize * 1.0 text: statusNameRepeater.statusNames[index] font.bold: true } QGCLabel { color: "#336666" horizontalAlignment: Text.AlignHCenter font.pointSize: ScreenTools.mediumFontPointSize *1.0 text: statusNameRepeater.statusValues[index] + statusNameRepeater.statusUnits[index] font.bold: true } } } } }
这个Column和Row的嵌套布局的详细解释,可以看我的 QT Quick QML 布局——定位置布局(Row、Column、Grid、Flow和Repeater) 总结。 这里不再介绍。
如下绿色框中:
有其他想法的,可以在飞行视图中,增加一个控件,来配置矩形框是否显示;还可以增加一个定时器让变化的数据高亮显示;有UI美工支持的还可以弄个炫酷的皮肤。
关于QGC地面站其它文章请点击这里: QGC地面站
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。