diff --git a/.gitignore b/.gitignore index 3328a8981f319e0f4cfd432684dceb483f77a4db..06aaffca0aa6023303de3db53a1dcf55de5bf66a 100644 --- a/.gitignore +++ b/.gitignore @@ -52,5 +52,5 @@ user_config.pri thirdParty/qserialport-build-desktop/ thirdParty/qserialport/bin/ thirdParty/qserialport/lib/ -apmplanner2.xcodeproj/ GeneratedFiles/ +/qupgrade/ diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 206cb397d68f04424412e5602663d632f84006c4..371688a7f8120e9e64f259c228520a57e7d832d8 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -142,6 +142,27 @@ INCLUDEPATH += \ include(src/apps/mavlinkgen/mavlinkgen.pri) +# Include QUpgrade tool +exists(qupgrade) { + SOURCES += qupgrade/src/apps/qupgrade/qgcfirmwareupgradeworker.cpp \ + qupgrade/src/apps/qupgrade/uploader.cpp \ + qupgrade/src/apps/qupgrade/dialog_bare.cpp + + HEADERS += qupgrade/src/apps/qupgrade/qgcfirmwareupgradeworker.h \ + qupgrade/src/apps/qupgrade/uploader.h \ + qupgrade/src/apps/qupgrade/dialog_bare.h + + FORMS += qupgrade/src/apps/qupgrade/dialog_bare.ui + + linux*:CONFIG += qesp_linux_udev + + include(qupgrade/libs/qextserialport/src/qextserialport.pri) + + INCLUDEPATH += qupgrade/src/apps/qupgrade + + DEFINES += "QUPGRADE_SUPPORT" +} + # Include QWT plotting library include(libs/qwt/qwt.pri) @@ -153,12 +174,6 @@ INCLUDEPATH += . # Include serial port library (QSerialPort) include(libs/serialport/qserialport.pri) -## Serial port detection (ripped-off from qextserialport library) -#macx|macx-g++|macx-g++42::SOURCES += libs/qextserialport/qextserialenumerator_osx.cpp -#linux-g++::SOURCES += libs/qextserialport/qextserialenumerator_unix.cpp -#linux-g++-64::SOURCES += libs/qextserialport/qextserialenumerator_unix.cpp -#win32-msvc2008|win32-msvc2010|win32-msvc2012::SOURCES += libs/qextserialport/qextserialenumerator_win.cpp - # Input FORMS += src/ui/MainWindow.ui \ src/ui/CommSettings.ui \ diff --git a/src/comm/SerialLink.cc b/src/comm/SerialLink.cc index d3fe69f869ef7a18d101874c0ec213f6573eafc3..9935bf33d22b74ff6c0c02a48a46687a28dc8357 100644 --- a/src/comm/SerialLink.cc +++ b/src/comm/SerialLink.cc @@ -157,18 +157,20 @@ void SerialLink::run() int linkErrorCount = 0; forever { + { QMutexLocker locker(&this->m_stoppMutex); - if(m_stopp) { - m_stopp = false; - break; // exit the thread - } + if(m_stopp) { + m_stopp = false; + break; // exit the thread + } - if (m_reqReset) { - m_reqReset = false; - emit communicationUpdate(getName(),"Reset requested via DTR signal"); - m_port->setDataTerminalReady(true); - msleep(250); - m_port->setDataTerminalReady(false); + if (m_reqReset) { + m_reqReset = false; + emit communicationUpdate(getName(),"Reset requested via DTR signal"); + m_port->setDataTerminalReady(true); + msleep(250); + m_port->setDataTerminalReady(false); + } } if (isConnected() && (linkErrorCount > 100)) { diff --git a/src/uas/QGCUASParamManager.cc b/src/uas/QGCUASParamManager.cc index d62244e55279c77fc8d262dc373bbb6eda0d2cb1..68f1ed0dfc53c91e9b9ef5fc3ed9d38811f1ca39 100644 --- a/src/uas/QGCUASParamManager.cc +++ b/src/uas/QGCUASParamManager.cc @@ -48,7 +48,10 @@ void QGCUASParamManager::clearAllPendingParams() paramDataModel.clearAllPendingParams(); } - +QList QGCUASParamManager::getComponentForParam(const QString& parameter) const +{ + return paramDataModel.getComponentForOnboardParam(parameter); +} bool QGCUASParamManager::getParameterValue(int component, const QString& parameter, QVariant& value) const diff --git a/src/uas/QGCUASParamManager.h b/src/uas/QGCUASParamManager.h index f4598db0afa85086e7d65b826eddb479e8cebd46..81a12575a506e291ca0768407f326b51013b6a66 100644 --- a/src/uas/QGCUASParamManager.h +++ b/src/uas/QGCUASParamManager.h @@ -23,9 +23,32 @@ public: /** @brief Get the known, confirmed value of a parameter */ virtual bool getParameterValue(int component, const QString& parameter, QVariant& value) const; + /** + * @brief Get a list of all component IDs using this parameter name + * @param parameter The string encoding the parameter name + * @return A list with all components using this parameter name. Can be empty. + */ + virtual QList getComponentForParam(const QString& parameter) const; + /** @brief Provide tooltips / user-visible descriptions for parameters */ virtual void setParamDescriptions(const QMap& paramDescs); + /** + * @brief Count the pending parameters in the current transmission + * @return The number of pending parameters + */ + virtual int countPendingParams() { + return paramDataModel.countPendingParams(); + } + + /** + * @brief Count the number of onboard parameters + * @return The number of onboard parameters + */ + virtual int countOnboardParams() { + return paramDataModel.countOnboardParams(); + } + /** @brief Get the UAS of this widget * @return The MAV of this mgr. Unless the MAV object has been destroyed, this is never null. */ diff --git a/src/uas/UASParameterDataModel.cc b/src/uas/UASParameterDataModel.cc index 5ecb37db8981fca11b55f26e110e68796a224e7b..b3aaed28ef050c556a11db04418fd7baefa5bba4 100644 --- a/src/uas/UASParameterDataModel.cc +++ b/src/uas/UASParameterDataModel.cc @@ -192,6 +192,19 @@ bool UASParameterDataModel::getOnboardParamValue(int componentId, const QString& return false; } +QList UASParameterDataModel::getComponentForOnboardParam(const QString& parameter) const +{ + QList components; + // Iterate through all components + foreach (int comp, onboardParameters.keys()) + { + if (onboardParameters.value(comp)->contains(parameter)) + components.append(comp); + } + + return components; +} + void UASParameterDataModel::forgetAllOnboardParams() { onboardParameters.clear(); diff --git a/src/uas/UASParameterDataModel.h b/src/uas/UASParameterDataModel.h index 738e9c36e56466c0af9d90c5b2656aa74b2ac05c..bcff40ab8ca1ef0c1cb2435f48945ee029da16c4 100644 --- a/src/uas/UASParameterDataModel.h +++ b/src/uas/UASParameterDataModel.h @@ -34,7 +34,12 @@ public: */ virtual void addComponent(int compId); - + /** + * @brief Return a list of all components for this parameter name + * @param parameter The parameter string to search for + * @return A list with all components, can be potentially empty + */ + virtual QList getComponentForOnboardParam(const QString& parameter) const; /** @brief Save the onboard parameter with a the type specified in the QVariant as fixed */ virtual void setOnboardParamWithType(int componentId, QString& key, QVariant& value); diff --git a/src/ui/QGCPX4VehicleConfig.cc b/src/ui/QGCPX4VehicleConfig.cc index c37c1342287983fd47aa95d639b8507316d7ddb9..dcd406e582212f03dcb7e523dee481005d420dcf 100644 --- a/src/ui/QGCPX4VehicleConfig.cc +++ b/src/ui/QGCPX4VehicleConfig.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include "QGCPX4VehicleConfig.h" @@ -21,12 +22,14 @@ #include "UASParameterCommsMgr.h" #include "ui_QGCPX4VehicleConfig.h" #include "px4_configuration/QGCPX4AirframeConfig.h" +#include -#define WIDGET_INDEX_RC 0 -#define WIDGET_INDEX_SENSOR_CAL 1 -#define WIDGET_INDEX_AIRFRAME_CONFIG 2 -#define WIDGET_INDEX_GENERAL_CONFIG 3 -#define WIDGET_INDEX_ADV_CONFIG 4 +#define WIDGET_INDEX_FIRMWARE 0 +#define WIDGET_INDEX_RC 1 +#define WIDGET_INDEX_SENSOR_CAL 2 +#define WIDGET_INDEX_AIRFRAME_CONFIG 3 +#define WIDGET_INDEX_GENERAL_CONFIG 4 +#define WIDGET_INDEX_ADV_CONFIG 5 #define MIN_PWM_VAL 800 #define MAX_PWM_VAL 2200 @@ -48,6 +51,9 @@ QGCPX4VehicleConfig::QGCPX4VehicleConfig(QWidget *parent) : rc_mode(RC_MODE_NONE), calibrationEnabled(false), px4AirframeConfig(NULL), + #ifdef QUPGRADE_SUPPORT + firmwareDialog(NULL), + #endif ui(new Ui::QGCPX4VehicleConfig) { doneLoadingConfig = false; @@ -71,6 +77,17 @@ QGCPX4VehicleConfig::QGCPX4VehicleConfig(QWidget *parent) : px4AirframeConfig = new QGCPX4AirframeConfig(this); ui->airframeLayout->addWidget(px4AirframeConfig); +#ifdef QUPGRADE_SUPPORT + firmwareDialog = new DialogBare(this); + ui->firmwareLayout->addWidget(firmwareDialog); +#else +#error Please check out QUpgrade from http://github.com/LorenzMeier/qupgrade/ into the QGroundControl folder. + + QLabel* label = new QLabel(this); + label->setText("THIS VERSION OF QGROUNDCONTROL WAS BUILT WITHOUT QUPGRADE. To enable firmware upload support, checkout QUpgrade WITHIN the QGroundControl folder"); + ui->firmwareLayout->addWidget(label); +#endif + ui->rollWidget->setOrientation(Qt::Horizontal); ui->rollWidget->setName("Roll"); ui->yawWidget->setOrientation(Qt::Horizontal); @@ -91,6 +108,7 @@ QGCPX4VehicleConfig::QGCPX4VehicleConfig(QWidget *parent) : connect(ui->generalMenuButton,SIGNAL(clicked()),this,SLOT(generalMenuButtonClicked())); connect(ui->advancedMenuButton,SIGNAL(clicked()),this,SLOT(advancedMenuButtonClicked())); connect(ui->airframeMenuButton, SIGNAL(clicked()), this, SLOT(airframeMenuButtonClicked())); + connect(ui->firmwareMenuButton, SIGNAL(clicked()), this, SLOT(firmwareButtonClicked())); ui->rcCalibrationButton->setCheckable(true); connect(ui->rcCalibrationButton, SIGNAL(clicked(bool)), this, SLOT(toggleCalibrationRC(bool))); @@ -176,6 +194,11 @@ void QGCPX4VehicleConfig::airframeMenuButtonClicked() ui->stackedWidget->setCurrentIndex(WIDGET_INDEX_AIRFRAME_CONFIG); } +void QGCPX4VehicleConfig::firmwareMenuButtonClicked() +{ + ui->stackedWidget->setCurrentIndex(WIDGET_INDEX_FIRMWARE); +} + void QGCPX4VehicleConfig::identifyChannelMapping(int aert_index) { if (chanCount == 0) @@ -1089,7 +1112,7 @@ void QGCPX4VehicleConfig::remoteControlChannelRawChanged(int chan, float val) channelWanted = -1; - // Reject + // Confirm found channel QMessageBox msgBox; msgBox.setText(tr("%1 Channel found.").arg(channelNames[chanFound])); msgBox.setInformativeText(tr("Found %1 to be on the raw RC channel %2").arg(channelNames[chanFound]).arg(chan + 1)); diff --git a/src/ui/QGCPX4VehicleConfig.h b/src/ui/QGCPX4VehicleConfig.h index 8d735a175de8f6b0cededced0b3cfe6f74d5351f..83b85c927e4760c66e71f54ddfa49b14dba0f362 100644 --- a/src/ui/QGCPX4VehicleConfig.h +++ b/src/ui/QGCPX4VehicleConfig.h @@ -13,6 +13,7 @@ #include "px4_configuration/QGCPX4AirframeConfig.h" class UASParameterCommsMgr; +class DialogBare; namespace Ui { class QGCPX4VehicleConfig; @@ -40,6 +41,8 @@ public slots: void generalMenuButtonClicked(); void advancedMenuButtonClicked(); void airframeMenuButtonClicked(); + void firmwareMenuButtonClicked(); + void identifyChannelMapping(int aert_index); /** Set the MAV currently being calibrated */ @@ -248,6 +251,7 @@ protected: QMap paramTooltips; ///< Tooltips for the ? button next to a parameter. QGCPX4AirframeConfig* px4AirframeConfig; + DialogBare* firmwareDialog; private: Ui::QGCPX4VehicleConfig *ui; diff --git a/src/ui/QGCPX4VehicleConfig.ui b/src/ui/QGCPX4VehicleConfig.ui index 9f2942dfc78bde637654f518f2e105afd706d9ac..4322884b0942526bab47c25c981f553cce38314f 100644 --- a/src/ui/QGCPX4VehicleConfig.ui +++ b/src/ui/QGCPX4VehicleConfig.ui @@ -52,6 +52,14 @@ QLayout::SetMinAndMaxSize + + + + Firmware +Upgrade + + + @@ -146,8 +154,19 @@ Config - 1 + 0 + + + + + + Firmware Upgrade + + + + + diff --git a/src/ui/px4_configuration/QGCPX4AirframeConfig.cc b/src/ui/px4_configuration/QGCPX4AirframeConfig.cc index f049fee870ea280eef6ffacf1efc1d15a49c8b3c..d660035505d8d99ed9ef37004de85ffdc46cde7a 100644 --- a/src/ui/px4_configuration/QGCPX4AirframeConfig.cc +++ b/src/ui/px4_configuration/QGCPX4AirframeConfig.cc @@ -1,3 +1,5 @@ +#include + #include "QGCPX4AirframeConfig.h" #include "ui_QGCPX4AirframeConfig.h" @@ -7,6 +9,7 @@ QGCPX4AirframeConfig::QGCPX4AirframeConfig(QWidget *parent) : QWidget(parent), mav(NULL), + selectedId(-1), ui(new Ui::QGCPX4AirframeConfig) { ui->setupUi(this); @@ -62,23 +65,73 @@ void QGCPX4AirframeConfig::setActiveUAS(UASInterface* uas) void QGCPX4AirframeConfig::setAirframeID(int id) { - // If UAS is present, get param manager and set SYS_AUTOSTART ID - if (!mav) - return; - - mav->getParamManager()->setParameter(0, "SYS_AUTOSTART", (qint32)id); + selectedId = id; } void QGCPX4AirframeConfig::applyAndReboot() { - UAS* uas = qobject_cast(mav); + // Guard against the case of an edit where we didn't receive all params yet + if (selectedId < 0) + { + QMessageBox msgBox; + msgBox.setText(tr("No airframe selected")); + msgBox.setInformativeText(tr("Please select an airframe first.")); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + (void)msgBox.exec(); + + return; + } + + if (!mav) + return; + + if (mav->getParamManager()->countOnboardParams() == 0 && + mav->getParamManager()->countPendingParams() == 0) + { + mav->getParamManager()->requestParameterListIfEmpty(); + QGC::SLEEP::msleep(100); + } + + // Guard against the case of an edit where we didn't receive all params yet + if (mav->getParamManager()->countPendingParams() > 0) + { + QMessageBox msgBox; + msgBox.setText(tr("Parameter sync with UAS not yet complete")); + msgBox.setInformativeText(tr("Please wait a few moments and retry")); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + (void)msgBox.exec(); - if (!uas) return; + } + + QList components = mav->getParamManager()->getComponentForParam("SYS_AUTOSTART"); + + // Guard against multiple components responding - this will never show in practice + if (components.count() != 1) { + QMessageBox msgBox; + msgBox.setText(tr("Invalid system setup detected")); + msgBox.setInformativeText(tr("None or more than one component advertised to provide the main system configuration option. This is an invalid system setup - please check your autopilot.")); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + (void)msgBox.exec(); + + return; + } + + qDebug() << "Setting comp" << components.first() << "SYS_AUTOSTART" << (qint32)selectedId; + + mav->getParamManager()->setParameter(components.first(), "SYS_AUTOSTART", (qint32)selectedId); + + // Send pending params + mav->getParamManager()->sendPendingParameters(); + QGC::SLEEP::msleep(300); // Store parameters - uas->executeCommand(MAV_CMD_PREFLIGHT_STORAGE, 1, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0); + mav->getParamManager()->copyVolatileParamsToPersistent(); + QGC::SLEEP::msleep(500); // Reboot - uas->executeCommand(MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, 1, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0); + mav->executeCommand(MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, 1, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0); } void QGCPX4AirframeConfig::setAutoConfig(bool enabled) diff --git a/src/ui/px4_configuration/QGCPX4AirframeConfig.h b/src/ui/px4_configuration/QGCPX4AirframeConfig.h index 86ebce89643ef7b95994d3a42bdf9705e49135dd..4c3c9a0d1bcd42fad65152bcc3b7090f00ceea95 100644 --- a/src/ui/px4_configuration/QGCPX4AirframeConfig.h +++ b/src/ui/px4_configuration/QGCPX4AirframeConfig.h @@ -75,6 +75,7 @@ protected: private: UASInterface* mav; + int selectedId; Ui::QGCPX4AirframeConfig *ui; };