QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
MissionCommandTree.cc
Go to the documentation of this file.
2#include "FirmwarePlugin.h"
7#include "Vehicle.h"
8
9#include <QtCore/QApplicationStatic>
10
11QGC_LOGGING_CATEGORY(MissionCommandTreeLog, "Plan.MissionCommandTree");
12
13Q_APPLICATION_STATIC(MissionCommandTree, _missionCommandTreeInstance);
14
15MissionCommandTree::MissionCommandTree(bool unitTest, QObject *parent)
16 : QObject(parent)
17{
18 qCDebug(MissionCommandTreeLog) << this;
19
20 if (unitTest) {
21 // Load unit testing tree
22 _staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassGeneric] = new MissionCommandList(":/unittest/UT-MavCmdInfoCommon.json", true, this);
23 _staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassFixedWing] = new MissionCommandList(":/unittest/UT-MavCmdInfoFixedWing.json", false, this);
24 _staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassMultiRotor] = new MissionCommandList(":/unittest/UT-MavCmdInfoMultiRotor.json", false, this);
25 _staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassVTOL] = new MissionCommandList(":/unittest/UT-MavCmdInfoVTOL.json", false, this);
26 _staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassSub] = new MissionCommandList(":/unittest/UT-MavCmdInfoSub.json", false, this);
27 _staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassRoverBoat] = new MissionCommandList(":/unittest/UT-MavCmdInfoRover.json", false, this);
28 } else {
29 // Load all levels of hierarchy
33 const QString overrideFile = plugin->missionCommandOverrides(vehicleClass);
34 if (!overrideFile.isEmpty()) {
35 const bool baseCommandList = ((firmwareClass == QGCMAVLink::FirmwareClassGeneric) && (vehicleClass == QGCMAVLink::VehicleClassGeneric));
36 _staticCommandTree[firmwareClass][vehicleClass] = new MissionCommandList(overrideFile, baseCommandList, this);
37 }
38 }
39 }
40 }
41}
42
44{
45 for (const auto &vehicleMap : std::as_const(_allCommands)) {
46 for (const auto &commandMap : vehicleMap) {
47 for (MissionCommandUIInfo *const uiInfo : commandMap) {
48 delete uiInfo;
49 }
50 }
51 }
52 _allCommands.clear();
53
54 qCDebug(MissionCommandTreeLog) << this;
55}
56
58{
59 return _missionCommandTreeInstance();
60}
61
62void MissionCommandTree::_collapseHierarchy(const MissionCommandList *cmdList, QMap<MAV_CMD, MissionCommandUIInfo*> &collapsedTree) const
63{
64 if (!cmdList) {
65 return;
66 }
67
68 for (const MAV_CMD command: cmdList->commandIds()) {
69 MissionCommandUIInfo *const uiInfo = cmdList->getUIInfo(command);
70 if (uiInfo) {
71 if (collapsedTree.contains(command)) {
72 collapsedTree[command]->_overrideInfo(uiInfo);
73 } else {
74 collapsedTree[command] = new MissionCommandUIInfo(*uiInfo);
75 }
76 }
77 }
78}
79
80void MissionCommandTree::_buildAllCommands(Vehicle *vehicle, QGCMAVLink::VehicleClass_t vtolMode)
81{
82 QGCMAVLink::FirmwareClass_t firmwareClass;
83 QGCMAVLink::VehicleClass_t vehicleClass;
84
85 _firmwareAndVehicleClassInfo(vehicle, vtolMode, firmwareClass, vehicleClass);
86
87 if (_allCommands.contains(firmwareClass) && _allCommands[firmwareClass].contains(vehicleClass)) {
88 // Already built
89 return;
90 }
91
92 QMap<MAV_CMD, MissionCommandUIInfo*> &collapsedTree = _allCommands[firmwareClass][vehicleClass];
93
94 // Base of the tree is all commands
95 _collapseHierarchy(_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassGeneric], collapsedTree);
96
97 // Add the overrides for specific vehicle types
98 if (vehicleClass != QGCMAVLink::VehicleClassGeneric) {
99 _collapseHierarchy(_staticCommandTree[QGCMAVLink::FirmwareClassGeneric][vehicleClass], collapsedTree);
100 }
101
102 // Add the overrides for specific firmware class, all vehicles
103 if (firmwareClass != QGCMAVLink::FirmwareClassGeneric) {
104 _collapseHierarchy(_staticCommandTree[firmwareClass][QGCMAVLink::VehicleClassGeneric], collapsedTree);
105
106 // Add overrides for specific vehicle class
107 if (vehicleClass != QGCMAVLink::VehicleClassGeneric) {
108 _collapseHierarchy(_staticCommandTree[firmwareClass][vehicleClass], collapsedTree);
109 }
110 }
111
112 // Build category list from supported commands
113 QList<MAV_CMD> supportedCommands = vehicle->firmwarePlugin()->supportedMissionCommands(vehicleClass);
114 for (const MAV_CMD cmd: collapsedTree.keys()) {
115 if (supportedCommands.contains(cmd)) {
116 const QString newCategory = collapsedTree[cmd]->category();
117 if (!_supportedCategories[firmwareClass][vehicleClass].contains(newCategory)) {
118 _supportedCategories[firmwareClass][vehicleClass].append(newCategory);
119 }
120 }
121 }
122
123 _supportedCategories[firmwareClass][vehicleClass].append(_allCommandsCategory);
124}
125
126QStringList MissionCommandTree::_availableCategoriesForVehicle(Vehicle *vehicle)
127{
128 QGCMAVLink::FirmwareClass_t firmwareClass;
129 QGCMAVLink::VehicleClass_t vehicleClass;
130
131 _firmwareAndVehicleClassInfo(vehicle, QGCMAVLink::VehicleClassGeneric, firmwareClass, vehicleClass);
132 _buildAllCommands(vehicle, QGCMAVLink::VehicleClassGeneric);
133
134 return _supportedCategories[firmwareClass][vehicleClass];
135}
136
137QString MissionCommandTree::friendlyName(MAV_CMD command) const
138{
139 const MissionCommandList *const commandList = _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric];
140 const MissionCommandUIInfo *const uiInfo = commandList->getUIInfo(command);
141
142 return uiInfo ? uiInfo->friendlyName() : QStringLiteral("MAV_CMD(%1)").arg(static_cast<int>(command));
143}
144
145QString MissionCommandTree::rawName(MAV_CMD command) const
146{
147 const MissionCommandList *const commandList = _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric];
148 const MissionCommandUIInfo *const uiInfo = commandList->getUIInfo(command);
149
150 return uiInfo ? uiInfo->rawName() : QStringLiteral("MAV_CMD(%1)").arg(static_cast<int>(command));
151}
152
153bool MissionCommandTree::isLandCommand(MAV_CMD command) const
154{
155 const MissionCommandList *const commandList = _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric];
156 const MissionCommandUIInfo *const uiInfo = commandList->getUIInfo(command);
157
158 return (uiInfo && uiInfo->isLandCommand());
159}
160
161bool MissionCommandTree::isTakeoffCommand(MAV_CMD command) const
162{
163 const MissionCommandList *const commandList = _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric];
164 const MissionCommandUIInfo *const uiInfo = commandList->getUIInfo(command);
165
166 return (uiInfo && uiInfo->isTakeoffCommand());
167}
168
169const QList<MAV_CMD> &MissionCommandTree::allCommandIds() const
170{
171 return _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric]->commandIds();
172}
173
175{
176 QGCMAVLink::FirmwareClass_t firmwareClass;
177 QGCMAVLink::VehicleClass_t vehicleClass;
178
179 _firmwareAndVehicleClassInfo(vehicle, vtolMode, firmwareClass, vehicleClass);
180 _buildAllCommands(vehicle, vtolMode);
181
182 MissionCommandUIInfo *result = nullptr;
183
184 const QMap<MAV_CMD, MissionCommandUIInfo*> &infoMap = _allCommands[firmwareClass][vehicleClass];
185 if (infoMap.contains(command)) {
186 result = infoMap[command];
187 }
188
189 return result;
190}
191
193{
194 return _availableCategoriesForVehicle(vehicle);
195}
196
197QVariantList MissionCommandTree::getCommandsForCategory(Vehicle *vehicle, const QString &category, bool showFlyThroughCommands)
198{
199 QGCMAVLink::FirmwareClass_t firmwareClass;
200 QGCMAVLink::VehicleClass_t vehicleClass;
201
202 _firmwareAndVehicleClassInfo(vehicle, QGCMAVLink::VehicleClassGeneric, firmwareClass, vehicleClass);
203 _buildAllCommands(vehicle, QGCMAVLink::VehicleClassGeneric);
204
205 // vehicle can be null in which case _firmwareAndVehicleClassInfo will tell of the firmware/vehicle type for the offline editing vehicle.
206 // We then use that to get a firmware plugin so we can get the list of supported commands.
208 const QList<MAV_CMD> supportedCommands = firmwarePlugin->supportedMissionCommands(vehicleClass);
209
210 const QMap<MAV_CMD, MissionCommandUIInfo*> commandMap = _allCommands[firmwareClass][vehicleClass];
211 QVariantList list;
212 for (const MAV_CMD command: commandMap.keys()) {
213 if (supportedCommands.isEmpty() || supportedCommands.contains(command)) {
214 MissionCommandUIInfo* uiInfo = commandMap[command];
215 if ((uiInfo->category() == category || category == _allCommandsCategory) && (showFlyThroughCommands || !uiInfo->specifiesCoordinate() || uiInfo->isStandaloneCoordinate())) {
216 list.append(QVariant::fromValue(uiInfo));
217 }
218 }
219 }
220
221 return list;
222}
223
224void MissionCommandTree::_firmwareAndVehicleClassInfo(Vehicle *vehicle, QGCMAVLink::VehicleClass_t vtolMode, QGCMAVLink::FirmwareClass_t &firmwareClass, QGCMAVLink::VehicleClass_t &vehicleClass) const
225{
226 firmwareClass = QGCMAVLink::firmwareClass(vehicle->firmwareType());
227 vehicleClass = QGCMAVLink::vehicleClass(vehicle->vehicleType());
228 if ((vehicleClass == QGCMAVLink::VehicleClassVTOL) && (vtolMode != QGCMAVLink::VehicleClassGeneric)) {
229 vehicleClass = vtolMode;
230 }
231}
Q_APPLICATION_STATIC(MissionCommandTree, _missionCommandTreeInstance)
#define QGC_LOGGING_CATEGORY(name, categoryStr)
FirmwarePlugin * firmwarePluginForAutopilot(MAV_AUTOPILOT firmwareType, MAV_TYPE vehicleType)
QList< QGCMAVLink::FirmwareClass_t > supportedFirmwareClasses()
Returns list of firmwares which are supported by the system.
static FirmwarePluginManager * instance()
virtual QList< MAV_CMD > supportedMissionCommands(QGCMAVLink::VehicleClass_t) const
List of supported mission commands. Empty list for all commands supported.
virtual QString missionCommandOverrides(QGCMAVLink::VehicleClass_t vehicleClass) const
Maintains a list of MissionCommandUIInfo objects loaded from a json file.
MissionCommandUIInfo * getUIInfo(MAV_CMD command) const
Returns the ui info for specified command, NULL if command not found.
bool isTakeoffCommand(MAV_CMD command) const
MissionCommandTree(bool unitTest=false, QObject *parent=nullptr)
bool isLandCommand(MAV_CMD command) const
~MissionCommandTree()
Destructor for the MissionCommandTree class.
const QList< MAV_CMD > & allCommandIds() const
static MissionCommandTree * instance()
QString rawName(MAV_CMD command) const
Returns the raw name for the specified command.
QVariantList getCommandsForCategory(Vehicle *vehicle, const QString &category, bool showFlyThroughCommands)
QString friendlyName(MAV_CMD command) const
Returns the friendly name for the specified command.
QStringList categoriesForVehicle(Vehicle *vehicle)
const MissionCommandUIInfo * getUIInfo(Vehicle *vehicle, QGCMAVLink::VehicleClass_t vtolMode, MAV_CMD command)
QString category(void) const
bool isTakeoffCommand(void) const
QString friendlyName(void) const
bool specifiesCoordinate(void) const
bool isStandaloneCoordinate(void) const
QString rawName(void) const
MAV_TYPE vehicleType() const
Definition Vehicle.h:428
FirmwarePlugin * firmwarePlugin()
Provides access to the Firmware Plugin for this Vehicle.
Definition Vehicle.h:444
MAV_AUTOPILOT firmwareType() const
Definition Vehicle.h:427