Skip to content

Commit

Permalink
Convert MissionCommandTree to Singleton
Browse files Browse the repository at this point in the history
  • Loading branch information
HTRamsey committed Nov 9, 2024
1 parent 74e588b commit ac083a3
Show file tree
Hide file tree
Showing 26 changed files with 221 additions and 254 deletions.
2 changes: 1 addition & 1 deletion src/FirmwarePlugin/APM/APMFirmwarePlugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ void APMFirmwarePlugin::_getParameterMetaDataVersionInfo(const QString& metaData
}


QList<MAV_CMD> APMFirmwarePlugin::supportedMissionCommands(QGCMAVLink::VehicleClass_t vehicleClass)
QList<MAV_CMD> APMFirmwarePlugin::supportedMissionCommands(QGCMAVLink::VehicleClass_t vehicleClass) const
{
QList<MAV_CMD> supportedCommands = {
MAV_CMD_NAV_WAYPOINT,
Expand Down
2 changes: 1 addition & 1 deletion src/FirmwarePlugin/APM/APMFirmwarePlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class APMFirmwarePlugin : public FirmwarePlugin
// Overrides from FirmwarePlugin

QList<VehicleComponent*> componentsForVehicle(AutoPilotPlugin* vehicle) override;
QList<MAV_CMD> supportedMissionCommands(QGCMAVLink::VehicleClass_t vehicleClass) override;
QList<MAV_CMD> supportedMissionCommands(QGCMAVLink::VehicleClass_t vehicleClass) const override;

AutoPilotPlugin* autopilotPlugin (Vehicle* vehicle) override;
bool isCapable (const Vehicle *vehicle, FirmwareCapabilities capabilities) override;
Expand Down
2 changes: 1 addition & 1 deletion src/FirmwarePlugin/FirmwarePlugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ bool FirmwarePlugin::sendHomePositionToVehicle(void)
return false;
}

QList<MAV_CMD> FirmwarePlugin::supportedMissionCommands(QGCMAVLink::VehicleClass_t /* vehicleClass */)
QList<MAV_CMD> FirmwarePlugin::supportedMissionCommands(QGCMAVLink::VehicleClass_t /* vehicleClass */) const
{
// Generic supports all commands
return QList<MAV_CMD>();
Expand Down
2 changes: 1 addition & 1 deletion src/FirmwarePlugin/FirmwarePlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ class FirmwarePlugin : public QObject
virtual FactMetaData* _getMetaDataForFact(QObject* /*parameterMetaData*/, const QString& /*name*/, FactMetaData::ValueType_t /* type */, MAV_TYPE /*vehicleType*/) { return nullptr; }

/// List of supported mission commands. Empty list for all commands supported.
virtual QList<MAV_CMD> supportedMissionCommands(QGCMAVLink::VehicleClass_t vehicleClass);
virtual QList<MAV_CMD> supportedMissionCommands(QGCMAVLink::VehicleClass_t vehicleClass) const;

/// Returns the name of the mission command json override file for the specified vehicle type.
/// @param vehicleClass Vehicle class to return file for, VehicleClassGeneric is a request for overrides for all vehicle types
Expand Down
2 changes: 1 addition & 1 deletion src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ void PX4FirmwarePlugin::_getParameterMetaDataVersionInfo(const QString& metaData
return PX4ParameterMetaData::getParameterMetaDataVersionInfo(metaDataFile, majorVersion, minorVersion);
}

QList<MAV_CMD> PX4FirmwarePlugin::supportedMissionCommands(QGCMAVLink::VehicleClass_t vehicleClass)
QList<MAV_CMD> PX4FirmwarePlugin::supportedMissionCommands(QGCMAVLink::VehicleClass_t vehicleClass) const
{
QList<MAV_CMD> supportedCommands = {
MAV_CMD_NAV_WAYPOINT,
Expand Down
2 changes: 1 addition & 1 deletion src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class PX4FirmwarePlugin : public FirmwarePlugin
// Overrides from FirmwarePlugin

QList<VehicleComponent*> componentsForVehicle(AutoPilotPlugin* vehicle) override;
QList<MAV_CMD> supportedMissionCommands(QGCMAVLink::VehicleClass_t vehicleClass) override;
QList<MAV_CMD> supportedMissionCommands(QGCMAVLink::VehicleClass_t vehicleClass) const override;

AutoPilotPlugin* autopilotPlugin (Vehicle* vehicle) override;
bool isCapable (const Vehicle *vehicle, FirmwareCapabilities capabilities) override;
Expand Down
2 changes: 1 addition & 1 deletion src/MissionManager/KMLPlanDomDocument.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void KMLPlanDomDocument::_addFlightPath(Vehicle* vehicle, QList<MissionItem*> rg
QList<QGeoCoordinate> rgFlightCoords;
QGeoCoordinate homeCoord = rgMissionItems[0]->coordinate();
for (const MissionItem* item : rgMissionItems) {
const MissionCommandUIInfo* uiInfo = qgcApp()->toolbox()->missionCommandTree()->getUIInfo(vehicle, QGCMAVLink::VehicleClassGeneric, item->command());
const MissionCommandUIInfo* uiInfo = MissionCommandTree::instance()->getUIInfo(vehicle, QGCMAVLink::VehicleClassGeneric, item->command());
if (uiInfo) {
double altAdjustment = item->frame() == MAV_FRAME_GLOBAL ? 0 : homeCoord.altitude(); // Used to convert to amsl
if (uiInfo->isTakeoffCommand() && !vehicle->fixedWing()) {
Expand Down
160 changes: 79 additions & 81 deletions src/MissionManager/MissionCommandTree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,70 +8,68 @@
****************************************************************************/

#include "MissionCommandTree.h"
#include "Vehicle.h"
#include "FirmwarePluginManager.h"
#include "QGCApplication.h"
#include "FirmwarePlugin.h"
#include "MissionCommandUIInfo.h"
#include "FirmwarePluginManager.h"
#include "MissionCommandList.h"
#include "MissionCommandUIInfo.h"
#include "QGCLoggingCategory.h"
#include "Vehicle.h"

#include <QtCore/qapplicationstatic.h>
#include <QtQml/QtQml>

MissionCommandTree::MissionCommandTree(QGCApplication* app, QGCToolbox* toolbox, bool unitTest)
: QGCTool (app, toolbox)
, _allCommandsCategory (tr("All commands"))
, _settingsManager (nullptr)
, _unitTest (unitTest)
{
}
QGC_LOGGING_CATEGORY(MissionCommandTreeLog, "qgc.missionmanager.missioncommandtree");

Q_APPLICATION_STATIC(MissionCommandTree, _missionCommandTreeInstance);

void MissionCommandTree::setToolbox(QGCToolbox* toolbox)
MissionCommandTree::MissionCommandTree(bool unitTest, QObject *parent)
: QObject(parent)
{
QGCTool::setToolbox(toolbox);
// qCDebug(MissionCommandTreeLog) << Q_FUNC_INFO << this;

_settingsManager = toolbox->settingsManager();
(void) qmlRegisterUncreatableType<MissionCommandTree>("QGroundControl", 1, 0, "MissionCommandTree", "Reference only");

#ifdef UNITTEST_BUILD
if (_unitTest) {
if (unitTest) {
// Load unit testing tree
_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassGeneric] = new MissionCommandList(":/unittest/UT-MavCmdInfoCommon.json", true, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassFixedWing] = new MissionCommandList(":/unittest/UT-MavCmdInfoFixedWing.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassMultiRotor] = new MissionCommandList(":/unittest/UT-MavCmdInfoMultiRotor.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassVTOL] = new MissionCommandList(":/unittest/UT-MavCmdInfoVTOL.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassSub] = new MissionCommandList(":/unittest/UT-MavCmdInfoSub.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassRoverBoat] = new MissionCommandList(":/unittest/UT-MavCmdInfoRover.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassGeneric] = new MissionCommandList(":/unittest/UT-MavCmdInfoCommon.json", true, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassFixedWing] = new MissionCommandList(":/unittest/UT-MavCmdInfoFixedWing.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassMultiRotor] = new MissionCommandList(":/unittest/UT-MavCmdInfoMultiRotor.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassVTOL] = new MissionCommandList(":/unittest/UT-MavCmdInfoVTOL.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassSub] = new MissionCommandList(":/unittest/UT-MavCmdInfoSub.json", false, this);
_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassRoverBoat] = new MissionCommandList(":/unittest/UT-MavCmdInfoRover.json", false, this);
} else {
#endif
// Load all levels of hierarchy
for (const QGCMAVLink::FirmwareClass_t firmwareClass: FirmwarePluginManager::instance()->supportedFirmwareClasses()) {
FirmwarePlugin* plugin = FirmwarePluginManager::instance()->firmwarePluginForAutopilot(QGCMAVLink::firmwareClassToAutopilot(firmwareClass), MAV_TYPE_QUADROTOR);

const FirmwarePlugin *const plugin = FirmwarePluginManager::instance()->firmwarePluginForAutopilot(QGCMAVLink::firmwareClassToAutopilot(firmwareClass), MAV_TYPE_QUADROTOR);
for (const QGCMAVLink::VehicleClass_t vehicleClass: QGCMAVLink::allVehicleClasses()) {
QString overrideFile = plugin->missionCommandOverrides(vehicleClass);
const QString overrideFile = plugin->missionCommandOverrides(vehicleClass);
if (!overrideFile.isEmpty()) {
_staticCommandTree[firmwareClass][vehicleClass] = new MissionCommandList(overrideFile, firmwareClass == QGCMAVLink::FirmwareClassGeneric && vehicleClass == QGCMAVLink::VehicleClassGeneric /* baseCommandList */, this);
const bool baseCommandList = ((firmwareClass == QGCMAVLink::FirmwareClassGeneric) && (vehicleClass == QGCMAVLink::VehicleClassGeneric));
_staticCommandTree[firmwareClass][vehicleClass] = new MissionCommandList(overrideFile, baseCommandList, this);
}
}
}
#ifdef UNITTEST_BUILD
}
#endif
}

MissionCommandTree::~MissionCommandTree()
{
// qCDebug(MissionCommandTreeLog) << Q_FUNC_INFO << this;
}

qmlRegisterUncreatableType<MissionCommandTree>("QGroundControl", 1, 0, "MissionCommandTree", "Reference only");
MissionCommandTree *MissionCommandTree::instance()
{
return _missionCommandTreeInstance();
}

/// Add the next level of the hierarchy to a collapsed tree.
/// @param cmdList List of mission commands to collapse into ui info
/// @param collapsedTree Tree we are collapsing into
void MissionCommandTree::_collapseHierarchy(const MissionCommandList* cmdList,
QMap<MAV_CMD, MissionCommandUIInfo*>& collapsedTree)
void MissionCommandTree::_collapseHierarchy(const MissionCommandList *cmdList, QMap<MAV_CMD, MissionCommandUIInfo*> &collapsedTree) const
{
if (!cmdList) {
return;
}

for (MAV_CMD command: cmdList->commandIds()) {
MissionCommandUIInfo* uiInfo = cmdList->getUIInfo(command);
for (const MAV_CMD command: cmdList->commandIds()) {
MissionCommandUIInfo *const uiInfo = cmdList->getUIInfo(command);
if (uiInfo) {
if (collapsedTree.contains(command)) {
collapsedTree[command]->_overrideInfo(uiInfo);
Expand All @@ -82,7 +80,7 @@ void MissionCommandTree::_collapseHierarchy(const MissionCommandList*
}
}

void MissionCommandTree::_buildAllCommands(Vehicle* vehicle, QGCMAVLink::VehicleClass_t vtolMode)
void MissionCommandTree::_buildAllCommands(Vehicle *vehicle, QGCMAVLink::VehicleClass_t vtolMode)
{
QGCMAVLink::FirmwareClass_t firmwareClass;
QGCMAVLink::VehicleClass_t vehicleClass;
Expand All @@ -94,7 +92,7 @@ void MissionCommandTree::_buildAllCommands(Vehicle* vehicle, QGCMAVLink::Vehicle
return;
}

QMap<MAV_CMD, MissionCommandUIInfo*>& collapsedTree = _allCommands[firmwareClass][vehicleClass];
QMap<MAV_CMD, MissionCommandUIInfo*> &collapsedTree = _allCommands[firmwareClass][vehicleClass];

// Base of the tree is all commands
_collapseHierarchy(_staticCommandTree[MAV_AUTOPILOT_GENERIC][QGCMAVLink::VehicleClassGeneric], collapsedTree);
Expand All @@ -116,18 +114,19 @@ void MissionCommandTree::_buildAllCommands(Vehicle* vehicle, QGCMAVLink::Vehicle

// Build category list from supported commands
QList<MAV_CMD> supportedCommands = vehicle->firmwarePlugin()->supportedMissionCommands(vehicleClass);
for (MAV_CMD cmd: collapsedTree.keys()) {
for (const MAV_CMD cmd: collapsedTree.keys()) {
if (supportedCommands.contains(cmd)) {
QString newCategory = collapsedTree[cmd]->category();
const QString newCategory = collapsedTree[cmd]->category();
if (!_supportedCategories[firmwareClass][vehicleClass].contains(newCategory)) {
_supportedCategories[firmwareClass][vehicleClass].append(newCategory);
}
}
}

_supportedCategories[firmwareClass][vehicleClass].append(_allCommandsCategory);
}

QStringList MissionCommandTree::_availableCategoriesForVehicle(Vehicle* vehicle)
QStringList MissionCommandTree::_availableCategoriesForVehicle(Vehicle *vehicle)
{
QGCMAVLink::FirmwareClass_t firmwareClass;
QGCMAVLink::VehicleClass_t vehicleClass;
Expand All @@ -138,83 +137,82 @@ QStringList MissionCommandTree::_availableCategoriesForVehicle(Vehicle* vehicle)
return _supportedCategories[firmwareClass][vehicleClass];
}

QString MissionCommandTree::friendlyName(MAV_CMD command)
QString MissionCommandTree::friendlyName(MAV_CMD command) const
{
MissionCommandList * commandList = _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric];
MissionCommandUIInfo* uiInfo = commandList->getUIInfo(command);
const MissionCommandList *const commandList = _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric];
const MissionCommandUIInfo *const uiInfo = commandList->getUIInfo(command);

if (uiInfo) {
return uiInfo->friendlyName();
} else {
return QStringLiteral("MAV_CMD(%1)").arg((int)command);
}
return uiInfo ? uiInfo->friendlyName() : QStringLiteral("MAV_CMD(%1)").arg(static_cast<int>(command));
}

QString MissionCommandTree::rawName(MAV_CMD command)
QString MissionCommandTree::rawName(MAV_CMD command) const
{
MissionCommandList * commandList = _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric];
MissionCommandUIInfo* uiInfo = commandList->getUIInfo(command);
const MissionCommandList *const commandList = _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric];
const MissionCommandUIInfo *const uiInfo = commandList->getUIInfo(command);

if (uiInfo) {
return uiInfo->rawName();
} else {
return QStringLiteral("MAV_CMD(%1)").arg((int)command);
}
return uiInfo ? uiInfo->rawName() : QStringLiteral("MAV_CMD(%1)").arg(static_cast<int>(command));
}

bool MissionCommandTree::isLandCommand(MAV_CMD command)
bool MissionCommandTree::isLandCommand(MAV_CMD command) const
{
MissionCommandList * commandList = _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric];
MissionCommandUIInfo* uiInfo = commandList->getUIInfo(command);
const MissionCommandList *const commandList = _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric];
const MissionCommandUIInfo *const uiInfo = commandList->getUIInfo(command);

return uiInfo ? uiInfo->isLandCommand() : false;
return (uiInfo && uiInfo->isLandCommand());
}

bool MissionCommandTree::isTakeoffCommand(MAV_CMD command)
bool MissionCommandTree::isTakeoffCommand(MAV_CMD command) const
{
MissionCommandList * commandList = _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric];
MissionCommandUIInfo* uiInfo = commandList->getUIInfo(command);
const MissionCommandList *const commandList = _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric];
const MissionCommandUIInfo *const uiInfo = commandList->getUIInfo(command);

return uiInfo ? uiInfo->isTakeoffCommand() : false;
return (uiInfo && uiInfo->isTakeoffCommand());
}

const QList<MAV_CMD>& MissionCommandTree::allCommandIds(void) const
const QList<MAV_CMD> &MissionCommandTree::allCommandIds() const
{
return _staticCommandTree[QGCMAVLink::FirmwareClassGeneric][QGCMAVLink::VehicleClassGeneric]->commandIds();
}

const MissionCommandUIInfo* MissionCommandTree::getUIInfo(Vehicle* vehicle, QGCMAVLink::VehicleClass_t vtolMode, MAV_CMD command)
const MissionCommandUIInfo *MissionCommandTree::getUIInfo(Vehicle* vehicle, QGCMAVLink::VehicleClass_t vtolMode, MAV_CMD command)
{
QGCMAVLink::FirmwareClass_t firmwareClass;
QGCMAVLink::VehicleClass_t vehicleClass;
QGCMAVLink::VehicleClass_t vehicleClass;

_firmwareAndVehicleClassInfo(vehicle, vtolMode, firmwareClass, vehicleClass);
_buildAllCommands(vehicle, vtolMode);

const QMap<MAV_CMD, MissionCommandUIInfo*>& infoMap = _allCommands[firmwareClass][vehicleClass];
MissionCommandUIInfo *result = nullptr;

const QMap<MAV_CMD, MissionCommandUIInfo*> &infoMap = _allCommands[firmwareClass][vehicleClass];
if (infoMap.contains(command)) {
return infoMap[command];
} else {
return nullptr;
result = infoMap[command];
}

return result;
}

QVariantList MissionCommandTree::getCommandsForCategory(Vehicle* vehicle, const QString& category, bool showFlyThroughCommands)
QStringList MissionCommandTree::categoriesForVehicle(Vehicle *vehicle)
{
return _availableCategoriesForVehicle(vehicle);
}

QVariantList MissionCommandTree::getCommandsForCategory(Vehicle *vehicle, const QString &category, bool showFlyThroughCommands)
{
QGCMAVLink::FirmwareClass_t firmwareClass;
QGCMAVLink::VehicleClass_t vehicleClass;
QGCMAVLink::VehicleClass_t vehicleClass;

_firmwareAndVehicleClassInfo(vehicle, QGCMAVLink::VehicleClassGeneric, firmwareClass, vehicleClass);
_buildAllCommands(vehicle, QGCMAVLink::VehicleClassGeneric);

// vehicle can be null in which case _firmwareAndVehicleClassInfo will tell of the firmware/vehicle type for the offline editing vehicle.
// We then use that to get a firmware plugin so we can get the list of supported commands.
FirmwarePlugin* firmwarePlugin = FirmwarePluginManager::instance()->firmwarePluginForAutopilot(QGCMAVLink::firmwareClassToAutopilot(firmwareClass), QGCMAVLink::vehicleClassToMavType(vehicleClass));
QList<MAV_CMD> supportedCommands = firmwarePlugin->supportedMissionCommands(vehicleClass);
const FirmwarePlugin *const firmwarePlugin = FirmwarePluginManager::instance()->firmwarePluginForAutopilot(QGCMAVLink::firmwareClassToAutopilot(firmwareClass), QGCMAVLink::vehicleClassToMavType(vehicleClass));
const QList<MAV_CMD> supportedCommands = firmwarePlugin->supportedMissionCommands(vehicleClass);

const QMap<MAV_CMD, MissionCommandUIInfo*> commandMap = _allCommands[firmwareClass][vehicleClass];
QVariantList list;
QMap<MAV_CMD, MissionCommandUIInfo*> commandMap = _allCommands[firmwareClass][vehicleClass];
for (MAV_CMD command: commandMap.keys()) {
for (const MAV_CMD command: commandMap.keys()) {
if (supportedCommands.isEmpty() || supportedCommands.contains(command)) {
MissionCommandUIInfo* uiInfo = commandMap[command];
if ((uiInfo->category() == category || category == _allCommandsCategory) && (showFlyThroughCommands || !uiInfo->specifiesCoordinate() || uiInfo->isStandaloneCoordinate())) {
Expand All @@ -226,11 +224,11 @@ QVariantList MissionCommandTree::getCommandsForCategory(Vehicle* vehicle, const
return list;
}

void MissionCommandTree::_firmwareAndVehicleClassInfo(Vehicle* vehicle, QGCMAVLink::VehicleClass_t vtolMode, QGCMAVLink::FirmwareClass_t& firmwareClass, QGCMAVLink::VehicleClass_t& vehicleClass) const
void MissionCommandTree::_firmwareAndVehicleClassInfo(Vehicle *vehicle, QGCMAVLink::VehicleClass_t vtolMode, QGCMAVLink::FirmwareClass_t &firmwareClass, QGCMAVLink::VehicleClass_t &vehicleClass) const
{
firmwareClass = QGCMAVLink::firmwareClass(vehicle->firmwareType());
vehicleClass = QGCMAVLink::vehicleClass(vehicle->vehicleType());
if (vehicleClass == QGCMAVLink::VehicleClassVTOL && vtolMode != QGCMAVLink::VehicleClassGeneric) {
if ((vehicleClass == QGCMAVLink::VehicleClassVTOL) && (vtolMode != QGCMAVLink::VehicleClassGeneric)) {
vehicleClass = vtolMode;
}
}
Loading

0 comments on commit ac083a3

Please sign in to comment.