diff --git a/qgroundcontrol.pri b/qgroundcontrol.pri index 9a7571da56511fc14262998ce130a68af0116a6b..1189c7aef19abcfc6abf3f3b548b93f7a4a93d55 100644 --- a/qgroundcontrol.pri +++ b/qgroundcontrol.pri @@ -25,21 +25,6 @@ # #------------------------------------------------- -QT += network opengl svg xml phonon - -TEMPLATE = app -TARGET = qgroundcontrol - -BASEDIR = . -BUILDDIR = build -LANGUAGE = C++ - -CONFIG += debug_and_release console - -OBJECTS_DIR = $$BUILDDIR/obj -MOC_DIR = $$BUILDDIR/moc -UI_HEADERS_DIR = src/ui/generated - #$$BASEDIR/lib/qextserialport/include # $$BASEDIR/lib/openjaus/libjaus/include \ # $$BASEDIR/lib/openjaus/libopenJaus/include diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index ca7105b6ab8f44750428a1828fd5ff0905ca209d..a4dfc8e54ecea42c3cc225f26466d7fca32eaffe 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -8,6 +8,22 @@ include(lib/QMapControl/QMapControl.pri) message("Including bundled QMapControl version as FALLBACK. This is fine on Linux and MacOS, but not the best choice in Windows") + +QT += network opengl svg xml phonon + +TEMPLATE = app +TARGET = qgroundcontrol + +BASEDIR = . +BUILDDIR = build +LANGUAGE = C++ + +CONFIG += debug_and_release console + +OBJECTS_DIR = $$BUILDDIR/obj +MOC_DIR = $$BUILDDIR/moc +UI_HEADERS_DIR = src/ui/generated + # } # Include general settings for MAVGround # necessary as last include to override any non-acceptable settings @@ -22,7 +38,8 @@ include(src/lib/qextserialport/qextserialport.pri) include(src/lib/qwt/qwt.pri) DEPENDPATH += . \ lib/QMapControl \ - lib/QMapControl/src + lib/QMapControl/src \ + plugins INCLUDEPATH += . \ lib/QMapControl \ ../mavlink/include \ diff --git a/src/Core.cc b/src/Core.cc index 9ae80bb01fc085f4dd1fc8bbec8b21ecc4deda28..5cccf453a959a6f2a999ccfd8cd772de81c843e7 100644 --- a/src/Core.cc +++ b/src/Core.cc @@ -131,7 +131,7 @@ Core::Core(int &argc, char* argv[]) : QApplication(argc, argv) } } - // MAVLinkSimulationLink* simulationLink = new MAVLinkSimulationLink(MG::DIR::getSupportFilesDirectory() + "/demo-log.txt"); + // MAVLinkSimulationLink* simulationLink = new MAVLinkSimulationLink(MG::DIR::getSupportFilesDirectory() + "/demo-log.txt"); MAVLinkSimulationLink* simulationLink = new MAVLinkSimulationLink(":/demo-log.txt"); mainWindow->addLink(simulationLink); } @@ -164,7 +164,42 @@ void Core::startLinkManager() **/ void Core::startUASManager() { - UASManager::instance(); + // Load UAS plugins + QDir pluginsDir = QDir(qApp->applicationDirPath()); + +#if defined(Q_OS_WIN) + if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release") + pluginsDir.cdUp(); +#elif defined(Q_OS_LINUX) + if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release") + pluginsDir.cdUp(); +#elif defined(Q_OS_MAC) + if (pluginsDir.dirName() == "MacOS") + { + pluginsDir.cdUp(); + pluginsDir.cdUp(); + pluginsDir.cdUp(); + } +#endif + pluginsDir.cd("plugins"); + + UASManager* m = UASManager::instance(); + + // Load plugins + + QStringList pluginFileNames; + + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) + { + QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + if (plugin) + { + //populateMenus(plugin); + pluginFileNames += fileName; + printf(QString("Loaded plugin from " + fileName + "\n").toStdString().c_str()); + } + } } diff --git a/src/plugins/.gitignore b/src/plugins/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d32bef15ffee7c4a8bbdd9511fdd3b7bed7d0ad1 --- /dev/null +++ b/src/plugins/.gitignore @@ -0,0 +1,5 @@ +moc_* +*.o +Makefile +Makefile.Debug +Makefile.Release diff --git a/src/plugins/PxMAV.cc b/src/plugins/PxMAV.cc new file mode 100644 index 0000000000000000000000000000000000000000..a761a4e004cd7ee02f0f49ccb3745d7c769e9183 --- /dev/null +++ b/src/plugins/PxMAV.cc @@ -0,0 +1,114 @@ +#include "PxMAV.h" + +#include + +PxMAV::PxMAV() : + UAS(NULL, 0) +{ +} + +PxMAV::PxMAV(MAVLinkProtocol* mavlink, int id) : + UAS(mavlink, id) +{ +} + +/** + * This function is called by MAVLink once a complete, uncorrupted (CRC check valid) + * mavlink packet is received. + * + * @param link Hardware link the message came from (e.g. /dev/ttyUSB0 or UDP port). + * messages can be sent back to the system via this link + * @param message MAVLink message, as received from the MAVLink protocol stack + */ +void PxMAV::receiveMessage(LinkInterface* link, mavlink_message_t message) +{ + // Let UAS handle the default message set + UAS::receiveMessage(link, message); + mavlink_message_t* msg = &message; + + //qDebug() << "PX RECEIVED" << msg->sysid << msg->compid << msg->msgid; + + + // Handle your special messages + switch (msg->msgid) + { + case MAVLINK_MSG_ID_WATCHDOG_HEARTBEAT: + { + mavlink_watchdog_heartbeat_t payload; + mavlink_msg_watchdog_heartbeat_decode(msg, &payload); + + emit watchdogReceived(this->uasId, payload.watchdog_id, payload.process_count); + } + break; + + case MAVLINK_MSG_ID_WATCHDOG_PROCESS_INFO: + { + mavlink_watchdog_process_info_t payload; + mavlink_msg_watchdog_process_info_decode(msg, &payload); + + emit processReceived(this->uasId, payload.watchdog_id, payload.process_id, QString((const char*)payload.name), QString((const char*)payload.arguments), payload.timeout); + } + break; + + case MAVLINK_MSG_ID_WATCHDOG_PROCESS_STATUS: + { + mavlink_watchdog_process_status_t payload; + mavlink_msg_watchdog_process_status_decode(msg, &payload); + emit processChanged(this->uasId, payload.watchdog_id, payload.process_id, payload.state, (payload.muted == 1) ? true : false, payload.crashes, payload.pid); + } + break; + case MAVLINK_MSG_ID_DEBUG_VECT: + { + mavlink_debug_vect_t vect; + mavlink_msg_debug_vect_decode(msg, &vect); + QString str((const char*)vect.name); + emit valueChanged(uasId, str+".x", vect.x, MG::TIME::getGroundTimeNow()); + emit valueChanged(uasId, str+".y", vect.y, MG::TIME::getGroundTimeNow()); + emit valueChanged(uasId, str+".z", vect.z, MG::TIME::getGroundTimeNow()); + } + break; + case MAVLINK_MSG_ID_VISION_POSITION_ESTIMATE: + { + mavlink_vision_position_estimate_t pos; + mavlink_msg_vision_position_estimate_decode(&message, &pos); + quint64 time = getUnixTime(pos.usec); + emit valueChanged(uasId, "vis. time", pos.usec, time); + emit valueChanged(uasId, "vis. roll", pos.roll, time); + emit valueChanged(uasId, "vis. pitch", pos.pitch, time); + emit valueChanged(uasId, "vis. yaw", pos.yaw, time); + emit valueChanged(uasId, "vis. x", pos.x, time); + emit valueChanged(uasId, "vis. y", pos.y, time); + emit valueChanged(uasId, "vis. z", pos.z, time); + emit valueChanged(uasId, "vis. vx", pos.vx, time); + emit valueChanged(uasId, "vis. vy", pos.vy, time); + emit valueChanged(uasId, "vis. vz", pos.vz, time); + emit valueChanged(uasId, "vis. vyaw", pos.vyaw, time); + // Set internal state + if (!positionLock) + { + // If position was not locked before, notify positive + // GAudioOutput::instance()->notifyPositive(); + } + positionLock = true; + } + break; + default: + // Do nothing + break; + } +} + +void PxMAV::sendProcessCommand(int watchdogId, int processId, unsigned int command) +{ + mavlink_watchdog_command_t payload; + payload.target_system_id = uasId; + payload.watchdog_id = watchdogId; + payload.process_id = processId; + payload.command_id = (uint8_t)command; + + mavlink_message_t msg; + mavlink_msg_watchdog_command_encode(mavlink->getSystemId(), mavlink->getComponentId(), &msg, &payload); + sendMessage(msg); +} + + Q_EXPORT_PLUGIN2(pixhawk_plugins, PxMAV) diff --git a/src/plugins/PxMAV.h b/src/plugins/PxMAV.h new file mode 100644 index 0000000000000000000000000000000000000000..a3639ea9c25cb3b863a8ef8f677e6f6837703a36 --- /dev/null +++ b/src/plugins/PxMAV.h @@ -0,0 +1,24 @@ +#ifndef PXMAV_H +#define PXMAV_H + +#include "UAS.h" + +class PxMAV : public UAS +{ + Q_OBJECT + Q_INTERFACES(UASInterface) +public: + PxMAV(MAVLinkProtocol* mavlink, int id); + PxMAV(); +public slots: + /** @brief Receive a MAVLink message from this MAV */ + void receiveMessage(LinkInterface* link, mavlink_message_t message); + /** @brief Send a command to an onboard process */ + void sendProcessCommand(int watchdogId, int processId, unsigned int command); +signals: + void watchdogReceived(int systemId, int watchdogId, unsigned int processCount); + void processReceived(int systemId, int watchdogId, int processId, QString name, QString arguments, int timeout); + void processChanged(int systemId, int watchdogId, int processId, int state, bool muted, int crashed, int pid); +}; + +#endif // PXMAV_H diff --git a/src/plugins/pixhawk_plugins.pro b/src/plugins/pixhawk_plugins.pro new file mode 100644 index 0000000000000000000000000000000000000000..3698d92ba66f70433a945aa3bbe7733e17541560 --- /dev/null +++ b/src/plugins/pixhawk_plugins.pro @@ -0,0 +1,22 @@ +# This plugin is also identified by this line in PxMAV.cc +# Q_EXPORT_PLUGIN2(pixhawk_plugins, PxMAV) + +include(../../qgroundcontrol.pri) + +TEMPLATE = lib +CONFIG += plugin +QT += phonon +INCLUDEPATH += ../. \ + ../../../mavlink/include \ + ../../MAVLink/include \ + ../../mavlink/include \ + ../uas \ + ../comm +HEADERS = PxMAV.h +SOURCES = PxMAV.cc \ + ../uas/UAS.cc \ + ../GAudioOutput.cc \ + ../comm/MAVLinkProtocol.cc \ + ../uas/UASManager.cc +TARGET = $$qtLibraryTarget(pixhawk_plugins) +DESTDIR = ../../plugins diff --git a/src/uas/PxQuadMAV.h b/src/uas/PxQuadMAV.h index 65552eeb237cceef22908dc46c8fab8f5b37f6c2..6170bc86397e63d9165b542a2748ae40a1a6031b 100644 --- a/src/uas/PxQuadMAV.h +++ b/src/uas/PxQuadMAV.h @@ -6,6 +6,7 @@ class PxQuadMAV : public UAS { Q_OBJECT + Q_INTERFACES(UASInterface) public: PxQuadMAV(MAVLinkProtocol* mavlink, int id); public slots: diff --git a/src/uas/UAS.cc b/src/uas/UAS.cc index f48ce8faf9b1ed325dfdb057ef02b55f09a1fe5e..bb4ef71551383de5ec13de099fa6df58702df277 100644 --- a/src/uas/UAS.cc +++ b/src/uas/UAS.cc @@ -43,7 +43,7 @@ This file is part of the PIXHAWK project #include "MAVLinkProtocol.h" #include -UAS::UAS(MAVLinkProtocol* protocol, int id) : +UAS::UAS(MAVLinkProtocol* protocol, int id) : UASInterface(), uasId(id), startTime(MG::TIME::getGroundTimeNow()), commStatus(COMM_DISCONNECTED), @@ -73,6 +73,7 @@ UAS::UAS(MAVLinkProtocol* protocol, int id) : positionLock(false), statusTimeout(new QTimer(this)) { + color = UASInterface::getNextColor(); setBattery(LIPOLY, 3); statusTimeout->setInterval(500); connect(statusTimeout, SIGNAL(timeout()), this, SLOT(updateState())); diff --git a/src/uas/UASInterface.h b/src/uas/UASInterface.h index 8422c446e9df63f17467a2e54c018a11a59290b7..bbf0106dadf0c208b4c7f924660be8a97b4ad06a 100644 --- a/src/uas/UASInterface.h +++ b/src/uas/UASInterface.h @@ -51,10 +51,6 @@ class UASInterface : public QObject { Q_OBJECT public: - UASInterface() : - color(UASInterface::getNextColor()) - { - } virtual ~UASInterface() {} /* MANAGEMENT */ @@ -312,4 +308,6 @@ signals: void systemTypeSet(UASInterface* uas, unsigned int type); }; +Q_DECLARE_INTERFACE(UASInterface, "org.qgroundcontrol/1.0"); + #endif // _UASINTERFACE_H_