From e380911b9f0541e08bdfbf95f328c5d1cb090428 Mon Sep 17 00:00:00 2001 From: Bryant Date: Thu, 16 May 2013 21:53:21 -0700 Subject: [PATCH 01/10] Added missing separater to Tool Widgets menu. --- src/ui/MainWindow.ui | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/MainWindow.ui b/src/ui/MainWindow.ui index 4d16d9f..24eef80 100644 --- a/src/ui/MainWindow.ui +++ b/src/ui/MainWindow.ui @@ -89,6 +89,7 @@ + From e6e76007618d604c8b2bbaab1c50209c7f9d52b7 Mon Sep 17 00:00:00 2001 From: Lorenz Meier Date: Tue, 21 May 2013 09:22:18 +0200 Subject: [PATCH 02/10] Hotfix: Fixed widget / UAS initialization order which led to text messages (and other updates) being ignored if the widget was not open when the UAS was created --- src/uas/UAS.cc | 7 +++--- src/ui/DebugConsole.cc | 23 ++++++++++++++--- src/ui/DebugConsole.h | 4 +++ src/ui/MainWindow.cc | 61 ++++++++------------------------------------- src/ui/uas/UASInfoWidget.cc | 19 +++++--------- src/ui/uas/UASListWidget.cc | 5 ++++ 6 files changed, 48 insertions(+), 71 deletions(-) diff --git a/src/uas/UAS.cc b/src/uas/UAS.cc index cc7172c..739334d 100644 --- a/src/uas/UAS.cc +++ b/src/uas/UAS.cc @@ -1148,13 +1148,12 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) case MAVLINK_MSG_ID_STATUSTEXT: { QByteArray b; - b.resize(MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN); + b.resize(MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN+1); mavlink_msg_statustext_get_text(&message, b.data()); - //b.append('\0'); + // Ensure NUL-termination + b[b.length()-1] = '\0'; QString text = QString(b); int severity = mavlink_msg_statustext_get_severity(&message); - //qDebug() << "RECEIVED STATUS:" << text;false - //emit statusTextReceived(severity, text); if (text.startsWith("#audio:")) { diff --git a/src/ui/DebugConsole.cc b/src/ui/DebugConsole.cc index 5468d2c..8e856aa 100644 --- a/src/ui/DebugConsole.cc +++ b/src/ui/DebugConsole.cc @@ -93,14 +93,23 @@ DebugConsole::DebugConsole(QWidget *parent) : // Update measurements the first time updateTrafficMeasurements(); + // First connect management slots, then make sure to add all existing objects + // Connect to link manager to get notified about new links + connect(LinkManager::instance(), SIGNAL(newLink(LinkInterface*)), this, SLOT(addLink(LinkInterface*))); + // Connect to UAS manager to get notified about new UAS + connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), this, SLOT(uasCreated(UASInterface*))); + // Get a list of all existing links links = QList(); foreach (LinkInterface* link, LinkManager::instance()->getLinks()) { addLink(link); } - // Connect to link manager to get notified about new links - connect(LinkManager::instance(), SIGNAL(newLink(LinkInterface*)), this, SLOT(addLink(LinkInterface*))); + // Get a list of all existing UAS + foreach (UASInterface* uas, UASManager::instance()->getUASList()) { + uasCreated(uas); + } + // Connect link combo box connect(m_ui->linkComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(linkSelected(int))); // Connect send button @@ -169,6 +178,12 @@ void DebugConsole::storeSettings() //qDebug() << "Storing settings!"; } +void DebugConsole::uasCreated(UASInterface* uas) +{ + connect(uas, SIGNAL(textMessageReceived(int,int,int,QString)), + this, SLOT(receiveTextMessage(int,int,int,QString)), Qt::UniqueConnection); +} + /** * Add a link to the debug console output */ @@ -183,8 +198,8 @@ void DebugConsole::addLink(LinkInterface* link) linkSelected(m_ui->linkComboBox->currentIndex()); // Register for name changes - connect(link, SIGNAL(nameChanged(QString)), this, SLOT(updateLinkName(QString))); - connect(link, SIGNAL(deleteLink(LinkInterface* const)), this, SLOT(removeLink(LinkInterface* const))); + connect(link, SIGNAL(nameChanged(QString)), this, SLOT(updateLinkName(QString)), Qt::UniqueConnection); + connect(link, SIGNAL(deleteLink(LinkInterface* const)), this, SLOT(removeLink(LinkInterface* const)), Qt::UniqueConnection); } void DebugConsole::removeLink(LinkInterface* const linkInterface) diff --git a/src/ui/DebugConsole.h b/src/ui/DebugConsole.h index fb63184..4a7cf6b 100644 --- a/src/ui/DebugConsole.h +++ b/src/ui/DebugConsole.h @@ -45,6 +45,8 @@ namespace Ui class DebugConsole; } +class UASInterface; + /** * @brief Shows a debug console * @@ -61,6 +63,8 @@ public: public slots: /** @brief Add a link to the list of monitored links */ void addLink(LinkInterface* link); + /** @brief Add a UAS to the list of monitored UAS */ + void uasCreated(UASInterface* uas); /** @brief Remove a link from the list */ void removeLink(LinkInterface* const link); /** @brief Update a link name */ diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index 0c17819..1f70763 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -1725,43 +1725,17 @@ void MainWindow::UASCreated(UASInterface* uas) break; } + // XXX The multi-UAS selection menu has been disabled for now, + // its redundant with right-clicking the UAS in the list. + // this code piece might be removed later if this is the final + // conclusion (May 2013) // QAction* uasAction = new QAction(icon, tr("Select %1 for control").arg(uas->getUASName()), ui.menuConnected_Systems); // connect(uas, SIGNAL(systemRemoved()), uasAction, SLOT(deleteLater())); // connect(uasAction, SIGNAL(triggered()), uas, SLOT(setSelected())); - connect(uas, SIGNAL(systemSpecsChanged(int)), this, SLOT(UASSpecsChanged(int))); - // ui.menuConnected_Systems->addAction(uasAction); - // FIXME Should be not inside the mainwindow - if (debugConsoleDockWidget) - { - DebugConsole *debugConsole = dynamic_cast(debugConsoleDockWidget->widget()); - if (debugConsole) - { - connect(uas, SIGNAL(textMessageReceived(int,int,int,QString)), - debugConsole, SLOT(receiveTextMessage(int,int,int,QString))); - } - } - - // Health / System status indicator - if (infoDockWidget) - { - UASInfoWidget *infoWidget = dynamic_cast(infoDockWidget->widget()); - if (infoWidget) - { - infoWidget->addUAS(uas); - } - } - // UAS List - if (listDockWidget) - { - UASListWidget *listWidget = dynamic_cast(listDockWidget->widget()); - if (listWidget) - { - listWidget->addUAS(uas); - } - } + connect(uas, SIGNAL(systemSpecsChanged(int)), this, SLOT(UASSpecsChanged(int))); // HIL showHILConfigurationWidget(uas); @@ -1773,25 +1747,12 @@ void MainWindow::UASCreated(UASInterface* uas) } - - // Line chart - //if (!linechartWidget) - //{ - - // Center widgets - - //linechartWidget->addSystem(uas); - - linechartWidget->addSource(mavlinkDecoder); - //addCentralWidget(linechartWidget, tr("Realtime Plot")); - if (dataView->centralWidget() != linechartWidget) - { - dataView->setCentralWidget(linechartWidget); - linechartWidget->show(); - } - //dataView->setCentralWidget(linechartWidget); - //linechartWidget->show(); - //} + linechartWidget->addSource(mavlinkDecoder); + if (dataView->centralWidget() != linechartWidget) + { + dataView->setCentralWidget(linechartWidget); + linechartWidget->show(); + } // Load default custom widgets for this autopilot type loadCustomWidgetsFromDefaults(uas->getSystemTypeName(), uas->getAutopilotTypeName()); diff --git a/src/ui/uas/UASInfoWidget.cc b/src/ui/uas/UASInfoWidget.cc index b09bb9d..8042d88 100644 --- a/src/ui/uas/UASInfoWidget.cc +++ b/src/ui/uas/UASInfoWidget.cc @@ -34,7 +34,7 @@ This file is part of the PIXHAWK project #include #include #include -#include +#include #include #include #include @@ -46,20 +46,12 @@ UASInfoWidget::UASInfoWidget(QWidget *parent, QString name) : QWidget(parent) { ui.setupUi(this); this->name = name; - - connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*))); - activeUAS = NULL; - //instruments = new QMap(); - - // Set default battery type - // setBattery(0, LIPOLY, 3); - startTime = MG::TIME::getGroundTimeNow(); - // startVoltage = 0.0f; + connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*))); + setActiveUAS(UASManager::instance()->getActiveUAS()); - // lastChargeLevel = 0.5f; - // lastRemainingTime = 1; + startTime = QGC::groundTimeMilliseconds(); // Set default values /** Set two voltage decimals and zero charge level decimals **/ @@ -117,7 +109,8 @@ void UASInfoWidget::addUAS(UASInterface* uas) void UASInfoWidget::setActiveUAS(UASInterface* uas) { - activeUAS = uas; + if (uas) + activeUAS = uas; } void UASInfoWidget::updateBattery(UASInterface* uas, double voltage, double percent, int seconds) diff --git a/src/ui/uas/UASListWidget.cc b/src/ui/uas/UASListWidget.cc index e0b52e4..26f64a9 100644 --- a/src/ui/uas/UASListWidget.cc +++ b/src/ui/uas/UASListWidget.cc @@ -67,6 +67,11 @@ UASListWidget::UASListWidget(QWidget *parent) : QWidget(parent), m_ui(new Ui::UA this->setVisible(false); connect(UASManager::instance(),SIGNAL(UASCreated(UASInterface*)),this,SLOT(addUAS(UASInterface*))); + + // Get a list of all existing UAS + foreach (UASInterface* uas, UASManager::instance()->getUASList()) { + addUAS(uas); + } } UASListWidget::~UASListWidget() From 10d1c8280b58b10288eb621dc1f592eac718e775 Mon Sep 17 00:00:00 2001 From: Lorenz Meier Date: Tue, 21 May 2013 22:14:04 +0200 Subject: [PATCH 03/10] Fixed another init bug --- src/ui/HDDisplay.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ui/HDDisplay.cc b/src/ui/HDDisplay.cc index cfeaae7..f83027e 100644 --- a/src/ui/HDDisplay.cc +++ b/src/ui/HDDisplay.cc @@ -128,8 +128,8 @@ HDDisplay::HDDisplay(QStringList* plotList, QString title, QWidget *parent) : if (font.family() != fontFamilyName) qDebug() << "ERROR! Font not loaded: " << fontFamilyName; // Connect with UAS - connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*))); - //start(); + connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)), Qt::UniqueConnection); + setActiveUAS(UASManager::instance()->getActiveUAS()); } HDDisplay::~HDDisplay() @@ -476,6 +476,8 @@ void HDDisplay::renderOverlay() */ void HDDisplay::setActiveUAS(UASInterface* uas) { + if (!uas) + return; // Disconnect any previously connected active UAS if (this->uas != NULL) { removeSource(this->uas); From 8432278f72948b8e6d441d973a2b574465b5eca4 Mon Sep 17 00:00:00 2001 From: Lorenz Meier Date: Tue, 21 May 2013 22:27:57 +0200 Subject: [PATCH 04/10] Fixed a bunch of instantiation-order issues --- src/ui/HSIDisplay.cc | 2 ++ src/ui/QGCWaypointListMulti.cc | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/ui/HSIDisplay.cc b/src/ui/HSIDisplay.cc index 736b5f2..624353d 100644 --- a/src/ui/HSIDisplay.cc +++ b/src/ui/HSIDisplay.cc @@ -178,6 +178,8 @@ HSIDisplay::HSIDisplay(QWidget *parent) : connect(&statusClearTimer, SIGNAL(timeout()), this, SLOT(clearStatusMessage())); statusClearTimer.start(3000); + setActiveUAS(UASManager::instance()->getActiveUAS()); + setFocusPolicy(Qt::StrongFocus); } diff --git a/src/ui/QGCWaypointListMulti.cc b/src/ui/QGCWaypointListMulti.cc index 53a0065..9cbe050 100644 --- a/src/ui/QGCWaypointListMulti.cc +++ b/src/ui/QGCWaypointListMulti.cc @@ -15,6 +15,12 @@ QGCWaypointListMulti::QGCWaypointListMulti(QWidget *parent) : WaypointList* list = new WaypointList(ui->stackedWidget, NULL); lists.insert(offline_uas_id, list); ui->stackedWidget->addWidget(list); + + if (UASManager::instance()->getActiveUAS()) { + systemCreated(UASManager::instance()->getActiveUAS()); + systemSetActive(UASManager::instance()->getActiveUAS()->getUASID()); + } + } void QGCWaypointListMulti::systemDeleted(QObject* uas) From d8b646be32dae519229d6315158d26291c37fb3b Mon Sep 17 00:00:00 2001 From: dongfang Date: Thu, 16 May 2013 13:11:29 +0200 Subject: [PATCH 05/10] experiment --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index aad1ba6..eb9b5c4 100644 --- a/README +++ b/README @@ -1,3 +1,4 @@ +maah QGroundControl Open Source Micro Air Vehicle Ground Control Station Project: From c6ab1f059420e34c44ce4a1b2fe2c01bab651456 Mon Sep 17 00:00:00 2001 From: dongfang Date: Thu, 16 May 2013 21:43:49 +0200 Subject: [PATCH 06/10] First PrimaryFlightDisplay integration that will even compile. Non functionalgit status --- qgroundcontrol.pro | 6 +- src/ui/HUD.cc | 156 +++--- src/ui/HUD.h | 48 +- src/ui/MainWindow.cc | 15 +- src/ui/PrimaryFlightDisplay.cpp | 1124 +++++++++++++++++++++++++++++++++++++++ src/ui/PrimaryFlightDisplay.h | 217 ++++++++ src/ui/QGCRGBDView.cc | 6 +- src/ui/QGCRGBDView.h | 2 +- 8 files changed, 1461 insertions(+), 113 deletions(-) create mode 100644 src/ui/PrimaryFlightDisplay.cpp create mode 100644 src/ui/PrimaryFlightDisplay.h diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 04f6916..ad41181 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -376,7 +376,8 @@ HEADERS += src/MG.h \ src/ui/submainwindow.h \ src/ui/dockwidgettitlebareventfilter.h \ src/ui/uas/UASQuickView.h \ - src/ui/uas/UASQuickViewItem.h + src/ui/uas/UASQuickViewItem.h \ + src/ui/PrimaryFlightDisplay.h # Google Earth is only supported on Mac OS and Windows with Visual Studio Compiler macx|macx-g++|macx-g++42|win32-msvc2008|win32-msvc2010|win32-msvc2012::HEADERS += src/ui/map3D/QGCGoogleEarthView.h @@ -544,7 +545,8 @@ SOURCES += src/main.cc \ src/ui/submainwindow.cpp \ src/ui/dockwidgettitlebareventfilter.cpp \ src/ui/uas/UASQuickViewItem.cc \ - src/ui/uas/UASQuickView.cc + src/ui/uas/UASQuickView.cc \ + src/ui/PrimaryFlightDisplay.cpp # Enable Google Earth only on Mac OS and Windows with Visual Studio compiler macx|macx-g++|macx-g++42|win32-msvc2008|win32-msvc2010|win32-msvc2012::SOURCES += src/ui/map3D/QGCGoogleEarthView.cc diff --git a/src/ui/HUD.cc b/src/ui/HUD.cc index 9ddd900..fdb28cc 100644 --- a/src/ui/HUD.cc +++ b/src/ui/HUD.cc @@ -23,7 +23,7 @@ This file is part of the QGROUNDCONTROL project /** * @file - * @brief Head Up Display (HUD) + * @brief Head Up Display (HUD_old) * * @author Lorenz Meier * @@ -52,14 +52,14 @@ This file is part of the QGROUNDCONTROL project #endif /** - * @warning The HUD widget will not start painting its content automatically - * to update the view, start the auto-update by calling HUD::start(). + * @warning The HUD_old widget will not start painting its content automatically + * to update the view, start the auto-update by calling HUD_old::start(). * * @param width * @param height * @param parent */ -HUD::HUD(int width, int height, QWidget* parent) +HUD_old::HUD_old(int width, int height, QWidget* parent) : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), uas(NULL), yawInt(0.0f), @@ -119,7 +119,7 @@ HUD::HUD(int width, int height, QWidget* parent) load(0.0f), offlineDirectory(""), nextOfflineImage(""), - hudInstrumentsEnabled(true), + HUDInstrumentsEnabled(true), videoEnabled(false), xImageFactor(1.0), yImageFactor(1.0), @@ -151,7 +151,7 @@ HUD::HUD(int width, int height, QWidget* parent) // Refresh timer refreshTimer->setInterval(updateInterval); - connect(refreshTimer, SIGNAL(timeout()), this, SLOT(paintHUD())); + connect(refreshTimer, SIGNAL(timeout()), this, SLOT(paintHUD_old())); // Resize to correct size and fill with image resize(this->width(), this->height()); @@ -186,17 +186,17 @@ HUD::HUD(int width, int height, QWidget* parent) if (UASManager::instance()->getActiveUAS() != NULL) setActiveUAS(UASManager::instance()->getActiveUAS()); } -HUD::~HUD() +HUD_old::~HUD_old() { refreshTimer->stop(); } -QSize HUD::sizeHint() const +QSize HUD_old::sizeHint() const { return QSize(width(), (width()*3.0f)/4); } -void HUD::showEvent(QShowEvent* event) +void HUD_old::showEvent(QShowEvent* event) { // React only to internal (pre-display) // events @@ -205,7 +205,7 @@ void HUD::showEvent(QShowEvent* event) emit visibilityChanged(true); } -void HUD::hideEvent(QHideEvent* event) +void HUD_old::hideEvent(QHideEvent* event) { // React only to internal (pre-display) // events @@ -214,27 +214,27 @@ void HUD::hideEvent(QHideEvent* event) emit visibilityChanged(false); } -void HUD::contextMenuEvent (QContextMenuEvent* event) +void HUD_old::contextMenuEvent (QContextMenuEvent* event) { QMenu menu(this); // Update actions - enableHUDAction->setChecked(hudInstrumentsEnabled); + enableHUDAction->setChecked(HUDInstrumentsEnabled); enableVideoAction->setChecked(videoEnabled); menu.addAction(enableHUDAction); - //menu.addAction(selectHUDColorAction); + //menu.addAction(selectHUD_oldColorAction); menu.addAction(enableVideoAction); menu.addAction(selectOfflineDirectoryAction); menu.addAction(selectSaveDirectoryAction); menu.exec(event->globalPos()); } -void HUD::createActions() +void HUD_old::createActions() { - enableHUDAction = new QAction(tr("Enable HUD"), this); - enableHUDAction->setStatusTip(tr("Show the HUD instruments in this window")); + enableHUDAction = new QAction(tr("Enable HUD_old"), this); + enableHUDAction->setStatusTip(tr("Show the HUD_old instruments in this window")); enableHUDAction->setCheckable(true); - enableHUDAction->setChecked(hudInstrumentsEnabled); + enableHUDAction->setChecked(HUDInstrumentsEnabled); connect(enableHUDAction, SIGNAL(triggered(bool)), this, SLOT(enableHUDInstruments(bool))); enableVideoAction = new QAction(tr("Enable Video Live feed"), this); @@ -255,9 +255,9 @@ void HUD::createActions() /** * - * @param uas the UAS/MAV to monitor/display with the HUD + * @param uas the UAS/MAV to monitor/display with the HUD_old */ -void HUD::setActiveUAS(UASInterface* uas) +void HUD_old::setActiveUAS(UASInterface* uas) { if (this->uas != NULL) { // Disconnect any previously connected active MAV @@ -308,7 +308,7 @@ void HUD::setActiveUAS(UASInterface* uas) } } -//void HUD::updateAttitudeThrustSetPoint(UASInterface* uas, double rollDesired, double pitchDesired, double yawDesired, double thrustDesired, quint64 msec) +//void HUD_old::updateAttitudeThrustSetPoint(UASInterface* uas, double rollDesired, double pitchDesired, double yawDesired, double thrustDesired, quint64 msec) //{ //// updateValue(uas, "roll desired", rollDesired, msec); //// updateValue(uas, "pitch desired", pitchDesired, msec); @@ -316,7 +316,7 @@ void HUD::setActiveUAS(UASInterface* uas) //// updateValue(uas, "thrust desired", thrustDesired, msec); //} -void HUD::updateAttitude(UASInterface* uas, double roll, double pitch, double yaw, quint64 timestamp) +void HUD_old::updateAttitude(UASInterface* uas, double roll, double pitch, double yaw, quint64 timestamp) { Q_UNUSED(uas); Q_UNUSED(timestamp); @@ -328,7 +328,7 @@ void HUD::updateAttitude(UASInterface* uas, double roll, double pitch, double ya } } -void HUD::updateAttitude(UASInterface* uas, int component, double roll, double pitch, double yaw, quint64 timestamp) +void HUD_old::updateAttitude(UASInterface* uas, int component, double roll, double pitch, double yaw, quint64 timestamp) { Q_UNUSED(uas); Q_UNUSED(timestamp); @@ -338,7 +338,7 @@ void HUD::updateAttitude(UASInterface* uas, int component, double roll, double p } } -void HUD::updateBattery(UASInterface* uas, double voltage, double percent, int seconds) +void HUD_old::updateBattery(UASInterface* uas, double voltage, double percent, int seconds) { Q_UNUSED(uas); Q_UNUSED(seconds); @@ -352,18 +352,18 @@ void HUD::updateBattery(UASInterface* uas, double voltage, double percent, int s } } -void HUD::receiveHeartbeat(UASInterface*) +void HUD_old::receiveHeartbeat(UASInterface*) { } -void HUD::updateThrust(UASInterface* uas, double thrust) +void HUD_old::updateThrust(UASInterface* uas, double thrust) { Q_UNUSED(uas); Q_UNUSED(thrust); // updateValue(uas, "thrust", thrust, MG::TIME::getGroundTimeNow()); } -void HUD::updateLocalPosition(UASInterface* uas,double x,double y,double z,quint64 timestamp) +void HUD_old::updateLocalPosition(UASInterface* uas,double x,double y,double z,quint64 timestamp) { Q_UNUSED(uas); Q_UNUSED(timestamp); @@ -372,7 +372,7 @@ void HUD::updateLocalPosition(UASInterface* uas,double x,double y,double z,quint this->zPos = z; } -void HUD::updateGlobalPosition(UASInterface* uas,double lat, double lon, double altitude, quint64 timestamp) +void HUD_old::updateGlobalPosition(UASInterface* uas,double lat, double lon, double altitude, quint64 timestamp) { Q_UNUSED(uas); Q_UNUSED(timestamp); @@ -381,7 +381,7 @@ void HUD::updateGlobalPosition(UASInterface* uas,double lat, double lon, double this->alt = altitude; } -void HUD::updateSpeed(UASInterface* uas,double x,double y,double z,quint64 timestamp) +void HUD_old::updateSpeed(UASInterface* uas,double x,double y,double z,quint64 timestamp) { Q_UNUSED(uas); Q_UNUSED(timestamp); @@ -397,9 +397,9 @@ void HUD::updateSpeed(UASInterface* uas,double x,double y,double z,quint64 times * Updates the current system state, but only if the uas matches the currently monitored uas. * * @param uas the system the state message originates from - * @param state short state text, displayed in HUD + * @param state short state text, displayed in HUD_old */ -void HUD::updateState(UASInterface* uas,QString state) +void HUD_old::updateState(UASInterface* uas,QString state) { // Only one UAS is connected at a time Q_UNUSED(uas); @@ -410,9 +410,9 @@ void HUD::updateState(UASInterface* uas,QString state) * Updates the current system mode, but only if the uas matches the currently monitored uas. * * @param uas the system the state message originates from - * @param mode short mode text, displayed in HUD + * @param mode short mode text, displayed in HUD_old */ -void HUD::updateMode(int id,QString mode, QString description) +void HUD_old::updateMode(int id,QString mode, QString description) { // Only one UAS is connected at a time Q_UNUSED(id); @@ -420,7 +420,7 @@ void HUD::updateMode(int id,QString mode, QString description) this->mode = mode; } -void HUD::updateLoad(UASInterface* uas, double load) +void HUD_old::updateLoad(UASInterface* uas, double load) { Q_UNUSED(uas); this->load = load; @@ -431,7 +431,7 @@ void HUD::updateLoad(UASInterface* uas, double load) * @param y coordinate in pixels to be converted to reference mm units * @return the screen coordinate relative to the QGLWindow origin */ -float HUD::refToScreenX(float x) +float HUD_old::refToScreenX(float x) { //qDebug() << "sX: " << (scalingFactor * x) << "Orig:" << x; return (scalingFactor * x); @@ -440,7 +440,7 @@ float HUD::refToScreenX(float x) * @param x coordinate in pixels to be converted to reference mm units * @return the screen coordinate relative to the QGLWindow origin */ -float HUD::refToScreenY(float y) +float HUD_old::refToScreenY(float y) { //qDebug() << "sY: " << (scalingFactor * y); return (scalingFactor * y); @@ -451,7 +451,7 @@ float HUD::refToScreenY(float y) * the x and y center offsets. * */ -void HUD::paintCenterBackground(float roll, float pitch, float yaw) +void HUD_old::paintCenterBackground(float roll, float pitch, float yaw) { Q_UNUSED(yaw); @@ -459,7 +459,7 @@ void HUD::paintCenterBackground(float roll, float pitch, float yaw) float referenceWidth = 70.0; float referenceHeight = 70.0; - // HUD is assumed to be 200 x 150 mm + // HUD_old is assumed to be 200 x 150 mm // so that positions can be hardcoded // but can of course be scaled. @@ -522,7 +522,7 @@ void HUD::paintCenterBackground(float roll, float pitch, float yaw) * @param refX position in reference units (mm of the real instrument). This is relative to the measurement unit position, NOT in pixels. * @param refY position in reference units (mm of the real instrument). This is relative to the measurement unit position, NOT in pixels. */ -void HUD::paintText(QString text, QColor color, float fontSize, float refX, float refY, QPainter* painter) +void HUD_old::paintText(QString text, QColor color, float fontSize, float refX, float refY, QPainter* painter) { QPen prevPen = painter->pen(); float pPositionX = refToScreenX(refX) - (fontSize*scalingFactor*0.072f); @@ -546,7 +546,7 @@ void HUD::paintText(QString text, QColor color, float fontSize, float refX, floa painter->setPen(prevPen); } -void HUD::initializeGL() +void HUD_old::initializeGL() { bool antialiasing = true; @@ -575,7 +575,7 @@ void HUD::initializeGL() * @param referenceWidth width in the reference mm-unit space * @param referenceHeight width in the reference mm-unit space */ -void HUD::setupGLView(float referencePositionX, float referencePositionY, float referenceWidth, float referenceHeight) +void HUD_old::setupGLView(float referencePositionX, float referencePositionY, float referenceWidth, float referenceHeight) { int pixelWidth = (int)(referenceWidth * scalingFactor); int pixelHeight = (int)(referenceHeight * scalingFactor); @@ -601,12 +601,12 @@ void HUD::setupGLView(float referencePositionX, float referencePositionY, float //glScalef(scaleX, scaleY, 1.0f); } -void HUD::paintRollPitchStrips() +void HUD_old::paintRollPitchStrips() { } -void HUD::paintEvent(QPaintEvent *event) +void HUD_old::paintEvent(QPaintEvent *event) { // Event is not needed // the event is ignored as this widget @@ -614,7 +614,7 @@ void HUD::paintEvent(QPaintEvent *event) Q_UNUSED(event); } -void HUD::paintHUD() +void HUD_old::paintHUD_old() { if (isVisible()) { // static quint64 interval = 0; @@ -711,7 +711,7 @@ void HUD::paintHUD() // END OF OPENGL PAINTING - if (hudInstrumentsEnabled) { + if (HUDInstrumentsEnabled) { //glEnable(GL_MULTISAMPLE); @@ -900,7 +900,7 @@ void HUD::paintHUD() /** * @param pitch pitch angle in degrees (-180 to 180) */ -void HUD::paintPitchLines(float pitch, QPainter* painter) +void HUD_old::paintPitchLines(float pitch, QPainter* painter) { QString label; @@ -967,7 +967,7 @@ void HUD::paintPitchLines(float pitch, QPainter* painter) } } -void HUD::paintPitchLinePos(QString text, float refPosX, float refPosY, QPainter* painter) +void HUD_old::paintPitchLinePos(QString text, float refPosX, float refPosY, QPainter* painter) { //painter->setPen(QPen(QBrush, normalStrokeWidth)); @@ -996,7 +996,7 @@ void HUD::paintPitchLinePos(QString text, float refPosX, float refPosY, QPainter drawLine(refPosX+pitchWidth/2.0f, refPosY, refPosX+pitchGap/2.0f, refPosY, lineWidth, defaultColor, painter); } -void HUD::paintPitchLineNeg(QString text, float refPosX, float refPosY, QPainter* painter) +void HUD_old::paintPitchLineNeg(QString text, float refPosX, float refPosY, QPainter* painter) { const float pitchWidth = 30.0f; const float pitchGap = pitchWidth / 2.5f; @@ -1046,7 +1046,7 @@ void rotatePointClockWise(QPointF& p, float angle) p.setY((-1.0f * sin(angle) * p.x()) + cos(angle) * p.y()); } -float HUD::refLineWidthToPen(float line) +float HUD_old::refLineWidthToPen(float line) { return line * 2.50f; } @@ -1059,7 +1059,7 @@ float HUD::refLineWidthToPen(float line) * @param angle rotation angle, in radians * @return p Polygon p rotated by angle around the origin point */ -void HUD::rotatePolygonClockWiseRad(QPolygonF& p, float angle, QPointF origin) +void HUD_old::rotatePolygonClockWiseRad(QPolygonF& p, float angle, QPointF origin) { // Standard 2x2 rotation matrix, counter-clockwise // @@ -1078,7 +1078,7 @@ void HUD::rotatePolygonClockWiseRad(QPolygonF& p, float angle, QPointF origin) } } -void HUD::drawPolygon(QPolygonF refPolygon, QPainter* painter) +void HUD_old::drawPolygon(QPolygonF refPolygon, QPainter* painter) { // Scale coordinates QPolygonF draw(refPolygon.size()); @@ -1091,7 +1091,7 @@ void HUD::drawPolygon(QPolygonF refPolygon, QPainter* painter) painter->drawPolygon(draw); } -void HUD::drawChangeRateStrip(float xRef, float yRef, float height, float minRate, float maxRate, float value, QPainter* painter,bool reverse) +void HUD_old::drawChangeRateStrip(float xRef, float yRef, float height, float minRate, float maxRate, float value, QPainter* painter,bool reverse) { float scaledValue = value; @@ -1154,7 +1154,7 @@ void HUD::drawChangeRateStrip(float xRef, float yRef, float height, float minRat } } -//void HUD::drawSystemIndicator(float xRef, float yRef, int maxNum, float maxWidth, float maxHeight, QPainter* painter) +//void HUD_old::drawSystemIndicator(float xRef, float yRef, int maxNum, float maxWidth, float maxHeight, QPainter* painter) //{ // Q_UNUSED(maxWidth); // Q_UNUSED(maxHeight); @@ -1231,7 +1231,7 @@ void HUD::drawChangeRateStrip(float xRef, float yRef, float height, float minRat // } //} -void HUD::drawChangeIndicatorGauge(float xRef, float yRef, float radius, float expectedMaxChange, float value, const QColor& color, QPainter* painter, bool solid) +void HUD_old::drawChangeIndicatorGauge(float xRef, float yRef, float radius, float expectedMaxChange, float value, const QColor& color, QPainter* painter, bool solid) { // Draw the circle QPen circlePen(Qt::SolidLine); @@ -1277,7 +1277,7 @@ void HUD::drawChangeIndicatorGauge(float xRef, float yRef, float radius, float e drawPolygon(p, painter); } -void HUD::drawLine(float refX1, float refY1, float refX2, float refY2, float width, const QColor& color, QPainter* painter) +void HUD_old::drawLine(float refX1, float refY1, float refX2, float refY2, float width, const QColor& color, QPainter* painter) { QPen pen(Qt::SolidLine); pen.setWidth(refLineWidthToPen(width)); @@ -1286,7 +1286,7 @@ void HUD::drawLine(float refX1, float refY1, float refX2, float refY2, float wid painter->drawLine(QPoint(refToScreenX(refX1), refToScreenY(refY1)), QPoint(refToScreenX(refX2), refToScreenY(refY2))); } -void HUD::drawEllipse(float refX, float refY, float radiusX, float radiusY, float startDeg, float endDeg, float lineWidth, const QColor& color, QPainter* painter) +void HUD_old::drawEllipse(float refX, float refY, float radiusX, float radiusY, float startDeg, float endDeg, float lineWidth, const QColor& color, QPainter* painter) { Q_UNUSED(startDeg); Q_UNUSED(endDeg); @@ -1297,12 +1297,12 @@ void HUD::drawEllipse(float refX, float refY, float radiusX, float radiusY, floa painter->drawEllipse(QPointF(refToScreenX(refX), refToScreenY(refY)), refToScreenX(radiusX), refToScreenY(radiusY)); } -void HUD::drawCircle(float refX, float refY, float radius, float startDeg, float endDeg, float lineWidth, const QColor& color, QPainter* painter) +void HUD_old::drawCircle(float refX, float refY, float radius, float startDeg, float endDeg, float lineWidth, const QColor& color, QPainter* painter) { drawEllipse(refX, refY, radius, radius, startDeg, endDeg, lineWidth, color, painter); } -void HUD::resizeGL(int w, int h) +void HUD_old::resizeGL(int w, int h) { if (isVisible()) { glViewport(0, 0, w, h); @@ -1312,17 +1312,17 @@ void HUD::resizeGL(int w, int h) glMatrixMode(GL_MODELVIEW); glPolygonMode(GL_FRONT, GL_FILL); //FIXME - paintHUD(); + paintHUD_old(); } } -void HUD::selectWaypoint(int uasId, int id) +void HUD_old::selectWaypoint(int uasId, int id) { Q_UNUSED(uasId); waypointName = tr("WP") + QString::number(id); } -void HUD::setImageSize(int width, int height, int depth, int channels) +void HUD_old::setImageSize(int width, int height, int depth, int channels) { // Allocate raw image in correct size if (width != receivedWidth || height != receivedHeight || depth != receivedDepth || channels != receivedChannels || image == NULL) { @@ -1378,10 +1378,10 @@ void HUD::setImageSize(int width, int height, int depth, int channels) } -void HUD::startImage(int imgid, int width, int height, int depth, int channels) +void HUD_old::startImage(int imgid, int width, int height, int depth, int channels) { Q_UNUSED(imgid); - //qDebug() << "HUD: starting image (" << width << "x" << height << ", " << depth << "bits) with " << channels << "channels"; + //qDebug() << "HUD_old: starting image (" << width << "x" << height << ", " << depth << "bits) with " << channels << "channels"; // Copy previous image to screen if it hasn't been finished properly finishImage(); @@ -1391,7 +1391,7 @@ void HUD::startImage(int imgid, int width, int height, int depth, int channels) imageStarted = true; } -void HUD::finishImage() +void HUD_old::finishImage() { if (imageStarted) { commitRawDataToGL(); @@ -1399,7 +1399,7 @@ void HUD::finishImage() } } -void HUD::commitRawDataToGL() +void HUD_old::commitRawDataToGL() { qDebug() << __FILE__ << __LINE__ << "Copying raw data to GL buffer:" << rawImage << receivedWidth << receivedHeight << image->format(); if (image != NULL) { @@ -1429,19 +1429,19 @@ void HUD::commitRawDataToGL() update(); } -void HUD::saveImage(QString fileName) +void HUD_old::saveImage(QString fileName) { image->save(fileName); } -void HUD::saveImage() +void HUD_old::saveImage() { //Bring up popup QString fileName = "output.png"; saveImage(fileName); } -void HUD::startImage(quint64 timestamp) +void HUD_old::startImage(quint64 timestamp) { if (videoEnabled && offlineDirectory != "") { // Load and diplay image file @@ -1449,7 +1449,7 @@ void HUD::startImage(quint64 timestamp) } } -void HUD::selectOfflineDirectory() +void HUD_old::selectOfflineDirectory() { QString fileName = QFileDialog::getExistingDirectory(this, tr("Select image directory"), QDesktopServices::storageLocation(QDesktopServices::DesktopLocation)); if (fileName != "") { @@ -1457,17 +1457,17 @@ void HUD::selectOfflineDirectory() } } -void HUD::enableHUDInstruments(bool enabled) +void HUD_old::enableHUD_oldInstruments(bool enabled) { - hudInstrumentsEnabled = enabled; + HUDInstrumentsEnabled = enabled; } -void HUD::enableVideo(bool enabled) +void HUD_old::enableVideo(bool enabled) { videoEnabled = enabled; } -void HUD::setPixels(int imgid, const unsigned char* imageData, int length, int startIndex) +void HUD_old::setPixels(int imgid, const unsigned char* imageData, int length, int startIndex) { Q_UNUSED(imgid); // qDebug() << "at" << __FILE__ << __LINE__ << ": Received startindex" << startIndex << "and length" << length << "(" << startIndex+length << "of" << rawExpectedBytes << "bytes)"; @@ -1478,7 +1478,7 @@ void HUD::setPixels(int imgid, const unsigned char* imageData, int length, int s if (startIndex+length > rawExpectedBytes) { - qDebug() << "HUD: OVERFLOW! startIndex:" << startIndex << "length:" << length << "image raw size" << ((receivedWidth * receivedHeight * receivedChannels * receivedDepth) / 8) - 1; + qDebug() << "HUD_old: OVERFLOW! startIndex:" << startIndex << "length:" << length << "image raw size" << ((receivedWidth * receivedHeight * receivedChannels * receivedDepth) / 8) - 1; } else { @@ -1489,7 +1489,7 @@ void HUD::setPixels(int imgid, const unsigned char* imageData, int length, int s // Check if we just reached the end of the image if (startIndex+length == rawExpectedBytes) { - //qDebug() << "HUD: END OF IMAGE REACHED!"; + //qDebug() << "HUD_old: END OF IMAGE REACHED!"; finishImage(); rawLastIndex = 0; } @@ -1507,11 +1507,11 @@ void HUD::setPixels(int imgid, const unsigned char* imageData, int length, int s } } -void HUD::copyImage() +void HUD_old::copyImage() { - if (isVisible() && hudInstrumentsEnabled) + if (isVisible() && HUDInstrumentsEnabled) { - //qDebug() << "HUD::copyImage()"; + //qDebug() << "HUD_old::copyImage()"; UAS* u = dynamic_cast(this->uas); if (u) { @@ -1527,7 +1527,7 @@ void HUD::copyImage() } } -void HUD::saveImages(bool save) +void HUD_old::saveImages(bool save) { if (save) { diff --git a/src/ui/HUD.h b/src/ui/HUD.h index 92c3d30..d1c2130 100644 --- a/src/ui/HUD.h +++ b/src/ui/HUD.h @@ -29,8 +29,8 @@ This file is part of the QGROUNDCONTROL project * */ -#ifndef HUD_H -#define HUD_H +#ifndef HUD_old_H +#define HUD_old_H #include #include @@ -41,18 +41,18 @@ This file is part of the QGROUNDCONTROL project #include "UASInterface.h" /** - * @brief Displays a Head Up Display (HUD) + * @brief Displays a Head Up Display (HUD_old) * - * This class represents a head up display (HUD) and draws this HUD in an OpenGL widget (QGLWidget). - * It can superimpose the HUD over the current live image stream (any arriving image stream will be auto- + * This class represents a head up display (HUD_old) and draws this HUD_old in an OpenGL widget (QGLWidget). + * It can superimpose the HUD_old over the current live image stream (any arriving image stream will be auto- * matically used as background), or it draws the classic blue-brown background known from instruments. */ -class HUD : public QGLWidget +class HUD_old : public QGLWidget { Q_OBJECT public: - HUD(int width = 640, int height = 480, QWidget* parent = NULL); - ~HUD(); + HUD_old(int width = 640, int height = 480, QWidget* parent = NULL); + ~HUD_old(); void setImageSize(int width, int height, int depth, int channels); void resizeGL(int w, int h); @@ -90,7 +90,7 @@ public slots: /** @brief Select directory where to load the offline files from */ void selectOfflineDirectory(); /** @brief Enable the HUD instruments */ - void enableHUDInstruments(bool enabled); + void enableHUD_oldInstruments(bool enabled); /** @brief Enable Video */ void enableVideo(bool enabled); /** @brief Copy an image from the current active UAS */ @@ -103,9 +103,9 @@ protected slots: void paintPitchLines(float pitch, QPainter* painter); /** @brief Paint text on top of the image and OpenGL drawings */ void paintText(QString text, QColor color, float fontSize, float refX, float refY, QPainter* painter); - /** @brief Setup the OpenGL view for drawing a sub-component of the HUD */ + /** @brief Setup the OpenGL view for drawing a sub-component of the HUD_old */ void setupGLView(float referencePositionX, float referencePositionY, float referenceWidth, float referenceHeight); - void paintHUD(); + void paintHUD_old(); void paintPitchLinePos(QString text, float refPosX, float refPosY, QPainter* painter); void paintPitchLineNeg(QString text, float refPosX, float refPosY, QPainter* painter); @@ -156,8 +156,8 @@ protected: float vGaugeSpacing; ///< Virtual spacing of the gauges from the center, 50 mm per default float vPitchPerDeg; ///< Virtual pitch to mm conversion. Currently one degree is 3 mm up/down in the pitch markings - int xCenter; ///< Center of the HUD instrument in pixel coordinates. Allows to off-center the whole instrument in its OpenGL window, e.g. to fit another instrument - int yCenter; ///< Center of the HUD instrument in pixel coordinates. Allows to off-center the whole instrument in its OpenGL window, e.g. to fit another instrument + int xCenter; ///< Center of the HUD_old instrument in pixel coordinates. Allows to off-center the whole instrument in its OpenGL window, e.g. to fit another instrument + int yCenter; ///< Center of the HUD_old instrument in pixel coordinates. Allows to off-center the whole instrument in its OpenGL window, e.g. to fit another instrument // Image buffers unsigned char* rawBuffer1; ///< Double buffer 1 for the image @@ -172,8 +172,8 @@ protected: int receivedWidth; ///< Width in pixels of the current image int receivedHeight; ///< Height in pixels of the current image - // HUD colors - QColor defaultColor; ///< Color for most HUD elements, e.g. pitch lines, center cross, change rate gauges + // HUD_old colors + QColor defaultColor; ///< Color for most HUD_old elements, e.g. pitch lines, center cross, change rate gauges QColor setPointColor; ///< Color for the current control set point, e.g. yaw desired QColor warningColor; ///< Color for warning messages QColor criticalColor; ///< Color for caution messages @@ -184,17 +184,17 @@ protected: int warningBlinkRate; ///< Blink rate of warning messages, will be rounded to the refresh rate QTimer* refreshTimer; ///< The main timer, controls the update rate - QPainter* hudPainter; - QFont font; ///< The HUD font, per default the free Bitstream Vera SANS, which is very close to actual HUD fonts - QFontDatabase fontDatabase;///< Font database, only used to load the TrueType font file (the HUD font is directly loaded from file rather than from the system) + QPainter* HUD_oldPainter; + QFont font; ///< The HUD_old font, per default the free Bitstream Vera SANS, which is very close to actual HUD_old fonts + QFontDatabase fontDatabase;///< Font database, only used to load the TrueType font file (the HUD_old font is directly loaded from file rather than from the system) bool noCamera; ///< No camera images available, draw the ground/sky box to indicate the horizon bool hardwareAcceleration; ///< Enable hardware acceleration - float strongStrokeWidth; ///< Strong line stroke width, used throughout the HUD - float normalStrokeWidth; ///< Normal line stroke width, used throughout the HUD - float fineStrokeWidth; ///< Fine line stroke width, used throughout the HUD + float strongStrokeWidth; ///< Strong line stroke width, used throughout the HUD_old + float normalStrokeWidth; ///< Normal line stroke width, used throughout the HUD_old + float fineStrokeWidth; ///< Fine line stroke width, used throughout the HUD_old - QString waypointName; ///< Waypoint name displayed in HUD + QString waypointName; ///< Waypoint name displayed in HUD_old float roll; float pitch; float yaw; @@ -218,7 +218,7 @@ protected: float load; QString offlineDirectory; QString nextOfflineImage; - bool hudInstrumentsEnabled; + bool HUDInstrumentsEnabled; bool videoEnabled; bool dataStreamEnabled; bool imageLoggingEnabled; @@ -235,4 +235,4 @@ protected: unsigned int imageLogCounter; }; -#endif // HUD_H +#endif // HUD_old_H diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index 1f70763..8470d69 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -59,6 +59,7 @@ This file is part of the QGROUNDCONTROL project #include "QGCFirmwareUpdate.h" #include "QGCStatusBar.h" #include "UASQuickView.h" +#include "PrimaryFlightDisplay.h" #ifdef QGC_OSG_ENABLED #include "Q3DWidgetFactory.h" @@ -566,11 +567,14 @@ void MainWindow::buildCommonWidgets() connect(tempAction,SIGNAL(triggered(bool)),this, SLOT(showTool(bool))); } - - createDockWidget(simView,new HUD(320,240,this),tr("Head Up Display"),"HEAD_UP_DISPLAY_DOCKWIDGET",VIEW_SIMULATION,Qt::RightDockWidgetArea,this->width()/1.5); + // createDockWidget(simView,new HUD(320,240,this),tr("Head Up Display"),"HEAD_UP_DISPLAY_DOCKWIDGET",VIEW_SIMULATION,Qt::RightDockWidgetArea,this->width()/1.5); + createDockWidget(simView,new PrimaryFlightDisplay(320,240,this),tr("Primary Flight Display"),"PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET",VIEW_SIMULATION,Qt::RightDockWidgetArea,this->width()/1.5); createDockWidget(pilotView,new UASListWidget(this),tr("Unmanned Systems"),"UNMANNED_SYSTEM_LIST_DOCKWIDGET",VIEW_FLIGHT,Qt::RightDockWidgetArea); - createDockWidget(pilotView,new HUD(320,240,this),tr("Head Up Display"),"HEAD_UP_DISPLAY_DOCKWIDGET",VIEW_FLIGHT,Qt::LeftDockWidgetArea,this->width()/1.8); + + //createDockWidget(pilotView,new HUD(320,240,this),tr("Head Up Display"),"HEAD_UP_DISPLAY_DOCKWIDGET",VIEW_FLIGHT,Qt::LeftDockWidgetArea,this->width()/1.8); + createDockWidget(pilotView,new PrimaryFlightDisplay(320,240,this),tr("Primary Flight Display"),"PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET",VIEW_FLIGHT,Qt::LeftDockWidgetArea,this->width()/1.8); + createDockWidget(pilotView,new UASQuickView(this),tr("Quick View"),"UAS_INFO_QUICKVIEW_DOCKWIDGET",VIEW_FLIGHT,Qt::LeftDockWidgetArea); createDockWidget(pilotView,new HSIDisplay(this),tr("Horizontal Situation"),"HORIZONTAL_SITUATION_INDICATOR_DOCKWIDGET",VIEW_FLIGHT,Qt::LeftDockWidgetArea); pilotView->setTabPosition(Qt::LeftDockWidgetArea,QTabWidget::North); @@ -780,9 +784,10 @@ void MainWindow::loadDockWidget(QString name) qDebug() << "Error loading window:" << name << "Unknown window type"; //createDockWidget(centerStack->currentWidget(),hddisplay,tr("Actuator Status"),"HEADS_DOWN_DISPLAY_2_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); } - else if (name == "HEAD_UP_DISPLAY_DOCKWIDGET") + else if (name == "PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET") { - createDockWidget(centerStack->currentWidget(),new HUD(320,240,this),tr("Head Up Display"),"HEAD_UP_DISPLAY_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); + // createDockWidget(centerStack->currentWidget(),new HUD(320,240,this),tr("Head Up Display"),"PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); + createDockWidget(centerStack->currentWidget(),new PrimaryFlightDisplay(320,240,this),tr("Primary Flight Display"),"HEAD_UP_DISPLAY_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); } else if (name == "UAS_INFO_QUICKVIEW_DOCKWIDGET") { diff --git a/src/ui/PrimaryFlightDisplay.cpp b/src/ui/PrimaryFlightDisplay.cpp new file mode 100644 index 0000000..0990174 --- /dev/null +++ b/src/ui/PrimaryFlightDisplay.cpp @@ -0,0 +1,1124 @@ +#include "PrimaryFlightDisplay.h" +#include "UASManager.h" + +//#include "ui_primaryflightdisplay.h" +#include +#include +#include +#include +#include +#include +#include +#include + +/* + *@TODO: + * global fixed pens + * repaint on demand multiple canvases + * multi implementation with shared model class + */ + +const int PrimaryFlightDisplay::tickValues[] = {10, 20, 30, 45, 60}; +const QString PrimaryFlightDisplay::compassWindNames[] = { + QString("N"), + QString("NE"), + QString("E"), + QString("SE"), + QString("S"), + QString("SW"), + QString("W"), + QString("NW") +}; + +PrimaryFlightDisplay::PrimaryFlightDisplay(int width, int height, QWidget *parent) : + QWidget(parent), + + roll(0), + pitch(0), + heading(NAN), + aboveASLAltitude(0), + GPSAltitude(0), + aboveHomeAltitude(0), + groundSpeed(0), + airSpeed(0), + + mode(""), + state(""), + + load(0), + + HUDInstrumentBackground(QColor::fromHsvF(0, 0, 0.8, 0.3)), + + font("Bitstream Vera Sans"), + refreshTimer(new QTimer(this)), + uas(NULL), +// energyStatus(tr("??.?V (??m:??s)")) + batteryVoltage(UNKNOWN_BATTERY), + batteryCharge(UNKNOWN_BATTERY), + + + whitePen(Qt::white), + redPen(QColor::fromHsvF(0, 0.6, 0.8)), + amberPen(QColor::fromHsvF(0.12, 0.6, 1.0)), + greenPen(QColor::fromHsvF(0.25, 0.8, 0.8)), + blackPen(QColor::fromHsvF(0, 0, 0.2)), + +#ifdef SEPARATE_LAYOUT + instrumentEdgePen(QColor::fromHsvF(0, 0, 0.65, 1.0)), + instrumentBackground(QColor::fromHsvF(0, 0, 0.3, 1.0)) +#else + instrumentEdgePen(QColor::fromHsvF(0, 0, 0.3, 0.5)), + instrumentBackground(QColor::fromHsvF(0, 0, 0.3, 0.3)) +#endif + { + setMinimumSize(120, 80); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + // Connect with UAS + connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*))); + if (UASManager::instance()->getActiveUAS() != NULL) setActiveUAS(UASManager::instance()->getActiveUAS()); + + // Refresh timer + refreshTimer->setInterval(updateInterval); + connect(refreshTimer, SIGNAL(timeout()), this, SLOT(paintHUD())); +} + +PrimaryFlightDisplay::~PrimaryFlightDisplay() +{ + refreshTimer->stop(); +} + + +QSize PrimaryFlightDisplay::sizeHint() const +{ + return QSize(width(), (width()*3.0f)/4); +} + +void PrimaryFlightDisplay::showEvent(QShowEvent* event) +{ + // React only to internal (pre-display) + // events + QWidget::showEvent(event); + refreshTimer->start(updateInterval); + emit visibilityChanged(true); +} + +void PrimaryFlightDisplay::hideEvent(QHideEvent* event) +{ + // React only to internal (pre-display) + // events + refreshTimer->stop(); + QWidget::hideEvent(event); + emit visibilityChanged(false); +} + +/* + * Interface against qgroundcontrol + */ + + +/** + * + * @param uas the UAS/MAV to monitor/display with the HUD + */ +void PrimaryFlightDisplay::setActiveUAS(UASInterface* uas) +{ + if (this->uas != NULL) { + // Disconnect any previously connected active MAV + disconnect(this->uas, SIGNAL(attitudeChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateAttitude(UASInterface*, double, double, double, quint64))); + disconnect(this->uas, SIGNAL(attitudeChanged(UASInterface*,int,double,double,double,quint64)), this, SLOT(updateAttitude(UASInterface*,int,double, double, double, quint64))); + disconnect(this->uas, SIGNAL(batteryChanged(UASInterface*, double, double, int)), this, SLOT(updateBattery(UASInterface*, double, double, int))); + disconnect(this->uas, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*,QString))); + disconnect(this->uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString))); + disconnect(this->uas, SIGNAL(heartbeat(UASInterface*)), this, SLOT(receiveHeartbeat(UASInterface*))); + + disconnect(this->uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateLocalPosition(UASInterface*,double,double,double,quint64))); + disconnect(this->uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,quint64))); + disconnect(this->uas, SIGNAL(speedChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64))); + disconnect(this->uas, SIGNAL(waypointSelected(int,int)), this, SLOT(selectWaypoint(int, int))); + } + + if (uas) { + // Now connect the new UAS + // Setup communication + connect(uas, SIGNAL(attitudeChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateAttitude(UASInterface*, double, double, double, quint64))); + connect(uas, SIGNAL(attitudeChanged(UASInterface*,int,double,double,double,quint64)), this, SLOT(updateAttitude(UASInterface*,int,double, double, double, quint64))); + connect(uas, SIGNAL(batteryChanged(UASInterface*, double, double, int)), this, SLOT(updateBattery(UASInterface*, double, double, int))); + connect(uas, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*,QString))); + connect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString))); + connect(uas, SIGNAL(heartbeat(UASInterface*)), this, SLOT(receiveHeartbeat(UASInterface*))); + + connect(uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateLocalPosition(UASInterface*,double,double,double,quint64))); + connect(uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,quint64))); + connect(uas, SIGNAL(speedChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64))); + connect(uas, SIGNAL(waypointSelected(int,int)), this, SLOT(selectWaypoint(int, int))); + + // Set new UAS + this->uas = uas; + } +} + +void PrimaryFlightDisplay::updateAttitude(UASInterface* uas, double roll, double pitch, double yaw, quint64 timestamp) +{ + Q_UNUSED(uas); + Q_UNUSED(timestamp); + if (!isnan(roll) && !isinf(roll) && !isnan(pitch) && !isinf(pitch) && !isnan(yaw) && !isinf(yaw)) + { + // TODO: Units conversion? + this->roll = roll; + this->pitch = pitch; + this->heading = yaw; + } + // TODO: Else-part. We really should have an "attitude bad or unknown" indication instead of just freezing. +} + +/* + * TODO! Implementation or removal of this. + * Currently a dummy. + */ +void PrimaryFlightDisplay::updateAttitude(UASInterface* uas, int component, double roll, double pitch, double yaw, quint64 timestamp) +{ + Q_UNUSED(uas); + Q_UNUSED(component); + Q_UNUSED(roll); + Q_UNUSED(pitch); + Q_UNUSED(yaw); + Q_UNUSED(timestamp); +} + +void PrimaryFlightDisplay::updateBattery(UASInterface* uas, double voltage, double percent, int seconds) +{ + Q_UNUSED(uas); + Q_UNUSED(seconds); + /* + energyStatus = tr("BAT [%1V | %2V%]").arg(voltage, 4, 'f', 1, QChar('0')).arg(percent, 2, 'f', 0, QChar('0')); + if (percent < 20.0f) { + fuelColor = warningColor; + } else if (percent < 10.0f) { + fuelColor = criticalColor; + } else { + fuelColor = infoColor; + } + */ + batteryVoltage = voltage; + batteryCharge = percent; +} + +void PrimaryFlightDisplay::receiveHeartbeat(UASInterface*) +{ +} + +void PrimaryFlightDisplay::updateThrust(UASInterface* uas, double thrust) +{ + Q_UNUSED(uas); + Q_UNUSED(thrust); +} + +/* + * TODO! Implementation or removal of this. + * Currently a dummy. + */ +void PrimaryFlightDisplay::updateLocalPosition(UASInterface* uas,double x,double y,double z,quint64 timestamp) +{ + Q_UNUSED(uas); + Q_UNUSED(x); + Q_UNUSED(y); + Q_UNUSED(z); + Q_UNUSED(timestamp); +} + +void PrimaryFlightDisplay::updateGlobalPosition(UASInterface* uas,double lat, double lon, double altitude, quint64 timestamp) +{ + Q_UNUSED(uas); + Q_UNUSED(lat); + Q_UNUSED(lon); + Q_UNUSED(timestamp); + + // TODO: Examine whether this is really the GPS alt or the mix-alt coming in. + GPSAltitude = altitude; +} + +/* + * TODO! Examine what data comes with this call, should we consider it airspeed, ground speed or + * should we not consider it at all? + */ +void PrimaryFlightDisplay::updateSpeed(UASInterface* uas,double x,double y,double z,quint64 timestamp) +{ + Q_UNUSED(uas); + Q_UNUSED(timestamp); + Q_UNUSED(z); + /* + this->xSpeed = x; + this->ySpeed = y; + this->zSpeed = z; + */ + + double newTotalSpeed = sqrt(x*x + y*y/*+ zSpeed*zSpeed */); + // totalAcc = (newTotalSpeed - totalSpeed) / ((double)(lastSpeedUpdate - timestamp)/1000.0); + + groundSpeed = newTotalSpeed; +} + +void PrimaryFlightDisplay::updateState(UASInterface* uas,QString state) +{ + // Only one UAS is connected at a time + Q_UNUSED(uas); + this->state = state; +} + +void PrimaryFlightDisplay::updateMode(int id, QString mode, QString description) +{ + // Only one UAS is connected at a time + Q_UNUSED(id); + Q_UNUSED(description); + this->mode = mode; +} + +void PrimaryFlightDisplay::updateLoad(UASInterface* uas, double load) +{ + Q_UNUSED(uas); + this->load = load; + //updateValue(uas, "load", load, MG::TIME::getGroundTimeNow()); +} + +void PrimaryFlightDisplay::selectWaypoint(int uasId, int id) { +} + +//void paintEvent(QPaintEvent *event); +//void resizeEvent(QResizeEvent *e); + +/* + * Private and such + */ +void PrimaryFlightDisplay::resizeEvent(QResizeEvent *e) { + QWidget::resizeEvent(e); + whitePen.setWidthF(LINEWIDTH * e->size().height()); + redPen.setWidthF(LINEWIDTH * e->size().height()); + greenPen.setWidthF(LINEWIDTH * e->size().height()); + instrumentEdgePen.setWidthF(LINEWIDTH * e->size().height()); + //doPaint(); +} + +void PrimaryFlightDisplay::paintEvent(QPaintEvent *event) +{ + // Event is not needed + // the event is ignored as this widget + // is refreshed automatically + Q_UNUSED(event); + makeDummyData(); + doPaint(); +} + +void PrimaryFlightDisplay::paintOnTimer() { + /* + *TODO: if not visible, exit (well OK not critical, the timer should get stopped anyways) + *The whole tainted-flag shebang. + *well not really so critical. Worst problem is deletion? + */ + makeDummyData(); + doPaint(); +} + +void PrimaryFlightDisplay::drawTextCenter ( + QPainter& painter, + QString text, + float fontSize, + float x, + float y) +{ + font.setPixelSize(fontSize*height()); + painter.setFont(font); + + QFontMetrics metrics = QFontMetrics(font); + QRect bounds = metrics.boundingRect(text); + int flags = Qt::AlignCenter | Qt::TextDontClip; // For some reason the bounds rect is too small! + painter.drawText(x /*+bounds.x()*/ -bounds.width()/2, y /*+bounds.y()*/ -bounds.height()/2, bounds.width(), bounds.height(), flags, text); +} + +void PrimaryFlightDisplay::drawTextLeftCenter ( + QPainter& painter, + QString text, + float fontSize, + float x, + float y) +{ + font.setPixelSize(fontSize*height()); + painter.setFont(font); + + QFontMetrics metrics = QFontMetrics(font); + QRect bounds = metrics.boundingRect(text); + int flags = Qt::AlignLeft | Qt::TextDontClip; // For some reason the bounds rect is too small! + painter.drawText(x /*+bounds.x()*/, y /*+bounds.y()*/ -bounds.height()/2, bounds.width(), bounds.height(), flags, text); +} + +void PrimaryFlightDisplay::drawTextRightCenter ( + QPainter& painter, + QString text, + float fontSize, + float x, + float y) +{ + font.setPixelSize(fontSize*height()); + painter.setFont(font); + + QFontMetrics metrics = QFontMetrics(font); + QRect bounds = metrics.boundingRect(text); + int flags = Qt::AlignRight | Qt::TextDontClip; // For some reason the bounds rect is too small! + painter.drawText(x /*+bounds.x()*/ -bounds.width(), y /*+bounds.y()*/ -bounds.height()/2, bounds.width(), bounds.height(), flags, text); +} + +void PrimaryFlightDisplay::drawTextCenterTop ( + QPainter& painter, + QString text, + float fontSize, + float x, + float y) +{ + font.setPixelSize(fontSize*height()); + painter.setFont(font); + + QFontMetrics metrics = QFontMetrics(font); + QRect bounds = metrics.boundingRect(text); + int flags = Qt::AlignCenter | Qt::TextDontClip; // For some reason the bounds rect is too small! + painter.drawText(x /*+bounds.x()*/ -bounds.width()/2, y+bounds.height() /*+bounds.y()*/, bounds.width(), bounds.height(), flags, text); +} + +void PrimaryFlightDisplay::drawTextCenterBottom ( + QPainter& painter, + QString text, + float fontSize, + float x, + float y) +{ + font.setPixelSize(fontSize*height()); + painter.setFont(font); + + QFontMetrics metrics = QFontMetrics(font); + QRect bounds = metrics.boundingRect(text); + int flags = Qt::AlignCenter; + painter.drawText(x /*+bounds.x()*/ -bounds.width()/2, y /*+bounds.y()*/, bounds.width(), bounds.height(), flags, text); +} + +void PrimaryFlightDisplay::drawInstrumentBackground(QPainter& painter, QRectF edge) { + painter.setPen(instrumentEdgePen); + painter.drawRect(edge); +} + +void PrimaryFlightDisplay::fillInstrumentBackground(QPainter& painter, QRectF edge) { + painter.setPen(instrumentEdgePen); + painter.setBrush(instrumentBackground); + painter.drawRect(edge); + painter.setBrush(Qt::NoBrush); +} + +/* +void PrimaryFlightDisplay::prepareTransform(QPainter& painter, qreal width, qreal height) { + painter.resetTransform(); + painter.translate(width/2, height/2); +} + +void PrimaryFlightDisplay::transformToGlobalSystem(QPainter& painter, qreal width, qreal height, float roll, float pitch) { + prepareTransform(painter, width, height); + painter.rotate(roll); + painter.translate(0, pitch*height/PITCHTRANSLATION); +} +*/ + +qreal pitchAngleToTranslation(qreal viewHeight, float pitch) { + return pitch*viewHeight/PITCHTRANSLATION; +} + +void PrimaryFlightDisplay::drawAIAirframeFixedFeatures(QPainter& painter, QRectF area) { + // red line from -7/10 to -5/10 half-width + // red line from 7/10 to 5/10 half-width + // red slanted line from -2/10 half-width to 0 + // red slanted line from 2/10 half-width to 0 + // red arrow thing under roll scale + // prepareTransform(painter, width, height); + painter.resetTransform(); + painter.translate(area.center()); + + qreal w = area.width(); + qreal h = area.height(); + + painter.setPen(redPen); + QPointF start(-0.35*w, 0); + QPointF end(-0.25*w, 0); + painter.drawLine(start, end); + + start = QPointF(0.35*w, 0); + end = QPointF(0.25*w, 0); + painter.drawLine(start, end); + + start = QPointF(0.0894*w, 0.894*0.05*w); + end = QPoint(0, 0); +// end = QPointF(-0.0894*width, -0.894*0.05*width); + painter.drawLine(start, end); + + start = QPointF(-0.0894*w, 0.894*0.05*w); + end = QPoint(0, 0); + // end = QPointF(0.0894*width, -0.894*0.05*width); + painter.drawLine(start, end); + + painter.setPen(redPen); +// painter.setBrush(Qt::SolidPattern); + + QPainterPath markerPath(QPointF(0, -h*ROLL_SCALE_RADIUS+1)); + markerPath.lineTo(-h*ROLL_SCALE_MARKERWIDTH/2, -h*(ROLL_SCALE_RADIUS-ROLL_SCALE_MARKERHEIGHT)+1); + markerPath.lineTo(h*ROLL_SCALE_MARKERWIDTH/2, -h*(ROLL_SCALE_RADIUS-ROLL_SCALE_MARKERHEIGHT)+1); + markerPath.closeSubpath(); + painter.drawPath(markerPath); +} + +void PrimaryFlightDisplay::drawAIGlobalFeatures( + QPainter& painter, + QRectF area) { + + painter.resetTransform(); + painter.translate(area.center()); + + painter.rotate(roll); + painter.translate(0, pitchAngleToTranslation(area.height(), pitch)); + + qreal w = area.width(); + qreal h = area.height(); + + qreal halfsize= 90/PITCHTRANSLATION*h + w*sqrt(2)/2; + + QPainterPath skyPath(QPointF(-w, 0)); + skyPath.lineTo(-halfsize, -halfsize); + skyPath.lineTo(halfsize, -halfsize); + skyPath.lineTo(halfsize, 0); + skyPath.closeSubpath(); + + QLinearGradient skyGradient(0, -halfsize, 0, 0); + skyGradient.setColorAt(0, QColor::fromHsvF(0.6, 1.0, 0.7)); + skyGradient.setColorAt(1, QColor::fromHsvF(0.6, 0.25, 0.9)); + QBrush skyBrush(skyGradient); + painter.fillPath(skyPath, skyBrush); + + QPainterPath groundPath(QPointF(-halfsize, 0)); + groundPath.lineTo(-halfsize, halfsize); + groundPath.lineTo(halfsize, halfsize); + groundPath.lineTo(halfsize, 0); + groundPath.closeSubpath(); + + QLinearGradient groundGradient(0, h, 0, 0); + groundGradient.setColorAt(0, QColor::fromHsvF(0.25, 1, 0.5)); + groundGradient.setColorAt(1, QColor::fromHsvF(0.25, 0.25, 0.5)); + QBrush groundBrush(groundGradient); + painter.fillPath(groundPath, groundBrush); + + painter.setPen(greenPen); + QPointF start(-w, 0); + QPoint end(w, 0); + painter.drawLine(start, end); + + painter.resetTransform(); + drawInstrumentBackground(painter, area); +} + +void PrimaryFlightDisplay::drawPitchScale( + QPainter& painter, + QRectF area, + bool drawNumbersLeft, + bool drawNumbersRight + ) { + + // We should really do these transforms but they are assumed done by caller. + // painter.resetTransform(); + // painter.translate(area.center()); + // painter.rotate(roll); + + painter.setPen(whitePen); + + QTransform savedTransform = painter.transform(); + + qreal h = area.height(); + + // find the mark nearest center + int snap = round(pitch/PITCH_SCALE_RESOLUTION)*PITCH_SCALE_RESOLUTION; + int _min = snap-PITCH_SCALE_HALFRANGE; + int _max = snap+PITCH_SCALE_HALFRANGE; + for (int degrees=_min; degrees<=_max; degrees+=PITCH_SCALE_RESOLUTION) { + bool isMajor = degrees % (PITCH_SCALE_RESOLUTION*2) == 0; + float linewidth = isMajor ? PITCH_SCALE_MAJORLENGTH : PITCH_SCALE_MINORLENGTH; + float shift = pitchAngleToTranslation(h, pitch-degrees); + painter.translate(0, shift); + QPointF start(-linewidth*h, 0); + QPointF end(linewidth*h, 0); + painter.drawLine(start, end); + + if (isMajor && (drawNumbersLeft||drawNumbersRight)) { + int displayDegrees = degrees; + if(displayDegrees>90) displayDegrees = 180-displayDegrees; + else if (displayDegrees<-90) displayDegrees = -180 - displayDegrees; + if (SHOW_ZERO_ON_SCALES || degrees) { + QString s_number; //= QString("%d").arg(degrees); + s_number.sprintf("%d", displayDegrees); + if (drawNumbersLeft) drawTextRightCenter(painter, s_number, SCALE_TEXT_SIZE, -PITCH_SCALE_MAJORLENGTH * h-10, 0); + if (drawNumbersRight) drawTextLeftCenter(painter, s_number, SCALE_TEXT_SIZE, PITCH_SCALE_MAJORLENGTH * h+10, 0); + } + } + + painter.setTransform(savedTransform); + } +} + +void PrimaryFlightDisplay::drawRollScale( + QPainter& painter, + QRectF area, + bool drawTicks, + bool drawNumbers) { + + qreal h = area.height(); + + painter.setPen(whitePen); + + // We should really do these transforms but they are assumed done by caller. + // painter.resetTransform(); + // painter.translate(area.center()); + // painter.rotate(roll); + + qreal _size = h * ROLL_SCALE_RADIUS*2; + + QRectF arcArea(-_size/2, -h * ROLL_SCALE_RADIUS, _size, _size); + painter.drawArc(arcArea, (90-ROLL_SCALE_RANGE)*16, ROLL_SCALE_RANGE*2*16); + if (drawTicks) { + int length = sizeof(tickValues)/sizeof(int); + qreal previousRotation = 0; + for (int i=0; ilength) ?-tickValues[i-length-1] : tickValues[i]; + //degrees = 180 - degrees; + painter.rotate(degrees - previousRotation); + previousRotation = degrees; + + QPointF start(0, -_size/2); + QPointF end(0, -(1.0+ROLL_SCALE_TICKMARKLENGTH)*_size/2); + + painter.drawLine(start, end); + + QString s_number; //= QString("%d").arg(degrees); + if (SHOW_ZERO_ON_SCALES || degrees) + s_number.sprintf("%d", abs(degrees)); + + if (drawNumbers) { + drawTextCenterBottom(painter, s_number, SCALE_TEXT_SIZE, 0, -(ROLL_SCALE_RADIUS+ROLL_SCALE_TICKMARKLENGTH*1.7)*h); + } + } + } +} + +void PrimaryFlightDisplay::drawAIAttitudeScales( + QPainter& painter, + QRectF area + ) { + // To save computations, we do these transformations once for both scales: + painter.resetTransform(); + painter.translate(area.center()); + painter.rotate(roll); + QTransform saved = painter.transform(); + + drawRollScale(painter, area, true, true); + + painter.setTransform(saved); + drawPitchScale(painter, area, true, true); +} + +#ifdef USE_DISK_COMPASS +void PrimaryFlightDisplay::drawCompassDisk( + QPainter& painter, + QRect area, // the area where to draw the disk, assumed quadratic. + float heading) { + float start = heading - COMPASS_DISK_SPAN/2; + float end = heading + COMPASS_DISK_SPAN/2; + int firstTick = ceil(start / COMPASS_DISK_RESOLUTION) * COMPASS_DISK_RESOLUTION; + int lastTick = floor(end / COMPASS_DISK_RESOLUTION) * COMPASS_DISK_RESOLUTION; + + float radius = area.width()/2; + painter.resetTransform(); + + painter.setPen(instrumentEdgePen); + painter.setBrush(HUDInstrumentBackground); + painter.drawEllipse(area); + painter.setBrush(Qt::NoBrush); + painter.setPen(whitePen); + + for (int tickYaw = firstTick; tickYaw <= lastTick; tickYaw += COMPASS_DISK_RESOLUTION) { + int displayTick = tickYaw; + if (displayTick < 0) displayTick+=360; + else if (displayTick>=360) displayTick-=360; + + // yaw is in center. + float off = tickYaw - heading; + // wrap that to ]-180..180] + if (off<=-180) off+= 360; else if (off>180) off += 360; + + painter.translate(area.center()); + painter.rotate(off); + + if (displayTick % 45 == 0) { + // draw a wind label + QString name = compassWindNames[displayTick / 45]; + drawText(painter, name, Qt::AlignCenter | Qt::TextWordWrap, SCALE_TEXT_SIZE, 0, -radius*0.83); + } + QPointF p_start = QPointF(0, -radius); + painter.drawPoint(p_start); + // QPointF p_end = QPointF(0, radius); + // painter.drawLine(p_start, p_end); + painter.resetTransform(); + } + + painter.setPen(redPen); + painter.translate(area.center()); + QPainterPath markerPath(QPointF(0, -radius-2)); + markerPath.lineTo(radius*COMPASS_DISK_MARKERWIDTH/2, -radius-radius*COMPASS_DISK_MARKERHEIGHT-2); + markerPath.lineTo(-radius*COMPASS_DISK_MARKERWIDTH/2, -radius-radius*COMPASS_DISK_MARKERHEIGHT-2); + markerPath.closeSubpath(); + painter.drawPath(markerPath); + + float yshift = -radius*3/4; + + QRectF compassRect(-radius/3, -radius/2, radius*2/3, radius/3); + painter.setPen(instrumentEdgePen); + painter.drawRoundedRect(compassRect, 3, 3); + + if (heading < 0) heading += 360; + else if (heading >= 360) heading -= 360; + /* final safeguard for really stupid systems */ + int yawCompass = static_cast(heading) % 360; + + QString yawAngle; + yawAngle.sprintf("%03d", yawCompass); + + painter.setPen(whitePen); + drawText(painter, yawAngle, Qt::AlignCenter | Qt::TextWordWrap, SCALE_TEXT_SIZE*1.41, 0, yshift/2); +} + +#endif + +#ifdef USE_DISK2_COMPASS +void PrimaryFlightDisplay::drawCompassDisk(QPainter& painter, QRectF area) { + float start = heading - COMPASS_DISK2_SPAN/2; + float end = heading + COMPASS_DISK2_SPAN/2; + int firstTick = ceil(start / COMPASS_DISK2_RESOLUTION) * COMPASS_DISK2_RESOLUTION; + int lastTick = floor(end / COMPASS_DISK2_RESOLUTION) * COMPASS_DISK2_RESOLUTION; + + float radius = area.width()/2; + float innerRadius = radius * 0.96; + painter.resetTransform(); + + float save = instrumentEdgePen.widthF(); + instrumentEdgePen.setWidthF(save/2); + painter.setPen(instrumentEdgePen); + painter.setBrush(HUDInstrumentBackground); + painter.drawEllipse(area); + instrumentEdgePen.setWidthF(save); + painter.setBrush(Qt::NoBrush); + + blackPen.setWidthF(2); + + for (int tickYaw = firstTick; tickYaw <= lastTick; tickYaw += COMPASS_DISK2_RESOLUTION) { + int displayTick = tickYaw; + if (displayTick < 0) displayTick+=360; + else if (displayTick>=360) displayTick-=360; + + // yaw is in center. + float off = tickYaw - heading; + // wrap that to ]-180..180] + if (off<=-180) off+= 360; else if (off>180) off += 360; + + painter.translate(area.center()); + painter.rotate(off); + bool drewArrow = false; + bool isMajor = displayTick % COMPASS_DISK2_MAJORTICK == 0; + + if (displayTick==30 || displayTick==60 || + displayTick==120 || displayTick==150 || + displayTick==210 || displayTick==240 || + displayTick==300 || displayTick==330) { + // draw a number + QString s_number; + s_number.sprintf("%d", displayTick/10); + painter.setPen(blackPen); + drawTextCenter(painter, s_number, COMPASS_SCALE_TEXT_SIZE, 0, -innerRadius*0.75); + } else { + if (displayTick % COMPASS_DISK2_ARROWTICK == 0) { + if (displayTick!=0) { + QPainterPath markerPath(QPointF(0, -innerRadius*(1-COMPASS_DISK_MARKERHEIGHT/2))); + markerPath.lineTo(innerRadius*COMPASS_DISK_MARKERWIDTH/4, -innerRadius); + markerPath.lineTo(-innerRadius*COMPASS_DISK_MARKERWIDTH/4, -innerRadius); + markerPath.closeSubpath(); + painter.setPen(blackPen); + painter.setBrush(Qt::SolidPattern); + painter.drawPath(markerPath); + painter.setBrush(Qt::NoBrush); + drewArrow = true; + } + if (displayTick%90 == 0) { + // Also draw a label + QString name = compassWindNames[displayTick / 45]; + painter.setPen(blackPen); + drawTextCenter(painter, name, COMPASS_SCALE_TEXT_SIZE*1.2, 0, -innerRadius*0.75); + } + } +} + // draw the scale lines. If an arrow was drawn, stay off from it. + + QPointF p_start = drewArrow ? QPoint(0, -innerRadius*0.94) : QPoint(0, -innerRadius); + QPoint p_end = isMajor ? QPoint(0, -innerRadius*0.86) : QPoint(0, -innerRadius*0.90); + + painter.setPen(blackPen); + painter.drawLine(p_start, p_end); + painter.resetTransform(); + } + + painter.setPen(blackPen); + //painter.setBrush(Qt::SolidPattern); + painter.translate(area.center()); + QPainterPath markerPath(QPointF(0, -radius-2)); + markerPath.lineTo(radius*COMPASS_DISK_MARKERWIDTH/2, -radius-radius*COMPASS_DISK_MARKERHEIGHT-2); + markerPath.lineTo(-radius*COMPASS_DISK_MARKERWIDTH/2, -radius-radius*COMPASS_DISK_MARKERHEIGHT-2); + markerPath.closeSubpath(); + painter.drawPath(markerPath); + + QRectF compassRect(-radius/3, -radius*0.52, radius*2/3, radius*0.28); + painter.setPen(instrumentEdgePen); + painter.drawRoundedRect(compassRect, instrumentEdgePen.widthF()*2/3, instrumentEdgePen.widthF()*2/3); + + if (heading < 0) heading += 360; + else if (heading >= 360) heading -= 360; + /* final safeguard for really stupid systems */ + int yawCompass = static_cast(heading) % 360; + + QString yawAngle; + yawAngle.sprintf("%03d", yawCompass); + + painter.setPen(whitePen); + drawTextCenter(painter, yawAngle, SCALE_TEXT_SIZE*1.2, 0, -radius*0.38); +} +#endif + +#ifdef USE_TAPE_COMPASS +void PrimaryFlightDisplay::drawCompassTape( + QPainter& painter, + float heading, + qreal width, + qreal y, + qreal height + ) { + float start = heading - COMPASS_TAPE_SPAN/2; + float end = heading + COMPASS_TAPE_SPAN/2; + int firstTick = ceil(start / COMPASS_TAPE_RESOLUTION) * COMPASS_TAPE_RESOLUTION; + int lastTick = floor(end / COMPASS_TAPE_RESOLUTION) * COMPASS_TAPE_RESOLUTION; + painter.setPen(whitePen); + + for (int tickYaw = firstTick; tickYaw <= lastTick; tickYaw += COMPASS_TAPE_RESOLUTION) { + int displayTick = tickYaw; + if (displayTick < 0) displayTick+=360; + else if (displayTick>=360) displayTick-=360; + + // yaw is in center. + float off = tickYaw - heading; + // wrap that to ]-180..180] + if (off<=-180) off+= 360; else if (off>180) off += 360; + + float x = width/2 + off*width/COMPASS_TAPE_SPAN; + + QPointF p_start = QPointF(x, y-height/2); + QPointF p_end = QPointF(x, y+height/2); + + if (displayTick % 45 == 0) { + // draw a wind label + QString name = compassWindNames[displayTick / 45]; + drawText(painter, name, Qt::AlignLeft | Qt::TextWordWrap, SCALE_TEXT_SIZE, x, y); + painter.drawPoint(p_start); + painter.drawPoint(p_end); + } else { + QPointF p_start(x, y-height/2); + QPointF p_endQPointF(x, y+height/2); + painter.drawLine(p_start, p_end); + } + } + + painter.setPen(redPen); + QPointF p_start(width/2, y-height/2); + QPointF p_end(width/2, y+height/2); + painter.drawLine(p_start, p_end); +} +#endif + +void PrimaryFlightDisplay::drawAltimeter( + QPainter& painter, + QRectF area, // the area where to draw the tape. +// float width, +// float height, + float altitude, + float maxAltitude, + float vv + ) { + + Q_UNUSED(vv) + Q_UNUSED(maxAltitude) + + painter.resetTransform(); + fillInstrumentBackground(painter, area); + + painter.setPen(whitePen); + + float height = area.height(); + float width = area.width(); + float effectiveHalfHeight = height*0.45; + float tickmarkLeft = 0.3*width; + float tickmarkRight = 0.4*width; + float numbersLeft = 0.42*width; + float markerHalfHeight = 0.06*height; + float rightEdge = area.width()-instrumentEdgePen.widthF()*2; + float markerTip = tickmarkLeft; + + // altitude scale +#ifdef ALTIMETER_PROJECTED + float range = 1.2; + float start = altitude - ALTIMETER_PROJECTED_SPAN/2; + float end = altitude + ALTIMETER_PROJECTED_SPAN/2; + int firstTick = ceil(start / ALTIMETER_PROJECTED_RESOLUTION) * ALTIMETER_PROJECTED_RESOLUTION; + int lastTick = floor(end / ALTIMETER_PROJECTED_RESOLUTION) * ALTIMETER_PROJECTED_RESOLUTION; + for (int tickAlt = firstTick; tickAlt <= lastTick; tickAlt += ALTIMETER_PROJECTED_RESOLUTION) { + // a number between 0 and 1. Use as radians directly. + float r = range*(tickAlt-altitude)/(ALTIMETER_PROJECTED_SPAN/2); + float y = effectiveHalfHeight * sin(r); + scale = cos(r); + if (scale<0) scale = -scale; + bool hasText = tickAlt % ALTIMETER_PROJECTED_MAJOR_RESOLUTION == 0; +#else + float start = altitude - ALTIMETER_LINEAR_SPAN/2; + float end = altitude + ALTIMETER_LINEAR_SPAN/2; + int firstTick = ceil(start / ALTIMETER_LINEAR_RESOLUTION) * ALTIMETER_LINEAR_RESOLUTION; + int lastTick = floor(end / ALTIMETER_LINEAR_RESOLUTION) * ALTIMETER_LINEAR_RESOLUTION; + for (int tickAlt = firstTick; tickAlt <= lastTick; tickAlt += ALTIMETER_LINEAR_RESOLUTION) { + float y = (tickAlt-altitude)*effectiveHalfHeight/(ALTIMETER_LINEAR_SPAN/2); + bool hasText = tickAlt % ALTIMETER_LINEAR_MAJOR_RESOLUTION == 0; +#endif + painter.resetTransform(); + painter.translate(area.left(), area.center().y() - y); + //painter.scale(1, scale); + painter.drawLine(tickmarkLeft, 0, tickmarkRight, 0); + if (hasText) { + QString s_alt; + s_alt.sprintf("%d", tickAlt); + drawTextLeftCenter(painter, s_alt, SCALE_TEXT_SIZE, numbersLeft, 0); + } + } + + QPainterPath markerPath(QPoint(markerTip, 0)); + markerPath.lineTo(markerTip+markerHalfHeight, markerHalfHeight); + markerPath.lineTo(rightEdge, markerHalfHeight); + markerPath.lineTo(rightEdge, -markerHalfHeight); + markerPath.lineTo(markerTip+markerHalfHeight, -markerHalfHeight); + markerPath.closeSubpath(); + + painter.resetTransform(); + painter.translate(area.left(), area.center().y()); + painter.setPen(blackPen); + painter.setBrush(Qt::SolidPattern); + painter.drawPath(markerPath); + painter.setBrush(Qt::NoBrush); + + painter.setPen(whitePen); + QString s_alt; + s_alt.sprintf("%3.0f", altitude); + float xCenter = (markerTip+rightEdge)/2; + drawTextCenter(painter, s_alt, SCALE_TEXT_SIZE, xCenter, 0); +} + +void PrimaryFlightDisplay::drawSysStatsPanel ( + QPainter& painter, + QRectF area) { + // Timer + // Battery + // Armed/not + QString s_volts("12.4V 21A"); + QString s_arm("Armed"); + + painter.resetTransform(); + + drawInstrumentBackground(painter, area); + painter.translate(area.center()); + + painter.setPen(amberPen); + drawTextCenter(painter, s_volts, SMALL_TEXT_SIZE, 0, -area.height()/6); + painter.setPen(redPen); + drawTextCenter(painter, s_arm, SCALE_TEXT_SIZE, 0, area.height()/6); +} + +void PrimaryFlightDisplay::drawLinkStatsPanel ( + QPainter& painter, + QRectF area) { + // UAV Id + // Droprates up, down + QString s_linkStat("100%"); + QString s_upTime("01:23:34"); + + painter.resetTransform(); + + drawInstrumentBackground(painter, area); + painter.translate(area.center()); + + painter.setPen(amberPen); + drawTextCenter(painter, s_linkStat, SMALL_TEXT_SIZE, 0, -area.height()/6); + drawTextCenter(painter, s_upTime, SMALL_TEXT_SIZE, 0, area.height()/6); +} + +void PrimaryFlightDisplay::drawMissionStatsPanel ( + QPainter& painter, + QRectF area) { + // Flight mode + // next WP + // next WP dist + QString s_flightMode("Auto"); + QString s_nextWP("1234m\u21924"); + + painter.resetTransform(); + + drawInstrumentBackground(painter, area); + painter.translate(area.center()); + + painter.setPen(amberPen); + drawTextCenter(painter, s_flightMode, SMALL_TEXT_SIZE, 0, -area.height()/6); + drawTextCenter(painter, s_nextWP, SMALL_TEXT_SIZE, 0, area.height()/6); +} + +void PrimaryFlightDisplay::drawSensorsStatsPanel ( + QPainter& painter, + QRectF area) { + // GPS fixmode and #sats + // Home alt.? + // Groundspeed? + QString s_GPS("GPS 3D(8)"); + QString s_homealt("H.alt 472m"); + + painter.resetTransform(); + + drawInstrumentBackground(painter, area); + painter.translate(area.center()); + + painter.setPen(amberPen); + drawTextCenter(painter, s_GPS, SMALL_TEXT_SIZE, 0, -area.height()/6); + drawTextCenter(painter, s_homealt, SMALL_TEXT_SIZE, 0, area.height()/6); +} + +void PrimaryFlightDisplay::paintSeparate() { + QPainter painter; + painter.begin(this); + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setRenderHint(QPainter::HighQualityAntialiasing, true); + + qreal margin = 5; + +#if defined(USE_DISK_COMPASS) || defined(USE_DISK2_COMPASS) + + // Centered and square. Margin is outside and single. + QRectF AIArea((width()-height())/2 + margin, margin, height()-2 * margin, height()-2 * margin); +#else + QRectF AIArea(0, 0, width(), height()*0.95); + qreal compassHeight = height() - AIArea.height(); +#endif + painter.fillRect(rect(), Qt::black); + + painter.setClipping(true); + painter.setClipRect(AIArea); + + drawAIGlobalFeatures(painter, AIArea); + drawAIAttitudeScales(painter, AIArea); + drawAIAirframeFixedFeatures(painter, AIArea); + +#if defined(USE_DISK_COMPASS) || defined(USE_DISK2_COMPASS) + qreal h = AIArea.height(); + QRectF compassArea(AIArea.x()+h*0.60, AIArea.y()+h*0.80, h/2, h/2); + drawCompassDisk(painter, compassArea); +#else + drawCompassTape(painter, yaw, width(), y, compassHeight); +#endif + + painter.setClipping(false); + + qreal tapeGaugesWidth = width()-AIArea.width() - 4*margin; + + // Hack: Lower bound of corner instruments coincide with upper bounds of altimeter/airspeed meter + qreal sidePanelsHeight = height()-2*margin; + + // X: To the right of AI and with single margin again. That is, 3 single margins plus width of AI. + // Y: 1 single margin below above gadget. + + QRectF altimeterArea(AIArea.width()+AIArea.x()+margin, height()*1/5+margin, tapeGaugesWidth/2, sidePanelsHeight*3/5); + drawAltimeter(painter, altimeterArea, aboveASLAltitude, 1000, 0); + + QRectF velocityArea(margin, height()*1/5+margin, tapeGaugesWidth/2, sidePanelsHeight*3/5); + drawAltimeter(painter, velocityArea, aboveASLAltitude, 1000, 0); + + QRectF sensorsStatsArea(margin, margin, tapeGaugesWidth/2, sidePanelsHeight/5); + drawSensorsStatsPanel(painter, sensorsStatsArea); + + QRectF linkStatsArea(AIArea.width()+AIArea.x()+margin, margin, tapeGaugesWidth/2, sidePanelsHeight/5); + drawLinkStatsPanel(painter, linkStatsArea); + + QRectF sysStatsArea(margin, sidePanelsHeight*4/5+margin, tapeGaugesWidth/2, sidePanelsHeight/5); + drawSysStatsPanel(painter, sysStatsArea); + + QRectF missionStatsArea(AIArea.width()+AIArea.x()+margin, sidePanelsHeight*4/5+margin, tapeGaugesWidth/2, sidePanelsHeight/5); + drawMissionStatsPanel(painter, missionStatsArea); + + painter.end(); +} + +void PrimaryFlightDisplay::paintAllInOne() { + // QT PAINTING + + QPainter painter; + painter.begin(this); + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setRenderHint(QPainter::HighQualityAntialiasing, true); + painter.setRenderHint(QPainter::TextAntialiasing); + +#if defined(USE_DISK_COMPASS) || defined(USE_DISK2_COMPASS) + //QRectF AIArea(0, 0, width(), height()); + QRectF AIArea(0, 0, width(), height()); +#else + QRectF AIArea(0, 0, width(), height()*0.95); + qreal compassHeight = height() - AIArea.height(); +#endif + + drawAIGlobalFeatures(painter, AIArea); + drawAIAttitudeScales(painter, AIArea); + drawAIAirframeFixedFeatures(painter, AIArea); + +#if defined(USE_DISK_COMPASS) || defined(USE_DISK2_COMPASS) + QRectF compassArea(width()-275, AIArea.height()-68, 170, 170); + drawCompassDisk(painter, compassArea); +#else + drawCompassTape(painter, yaw, width(), y, compassHeight); +#endif + + QRectF altimeterArea(AIArea.width()*7/8, AIArea.height()*1/5, AIArea.width()/8, AIArea.height()*3/5); + drawAltimeter(painter, altimeterArea, aboveASLAltitude, 1000, 0); + + QRectF velocityArea(0, AIArea.height()*1/5, AIArea.width()/8, AIArea.height()*3/5); + drawAltimeter(painter, velocityArea, aboveASLAltitude, 1000, 0); + + painter.end(); +} + +void PrimaryFlightDisplay::makeDummyData() { + roll = -15; + pitch = 10; + heading = 28; + aboveASLAltitude = 123; +} + +void PrimaryFlightDisplay::doPaint() { +#ifdef SEPARATE_LAYOUT + paintSeparate(); +#else + paintAllInOne(); +#endif +} diff --git a/src/ui/PrimaryFlightDisplay.h b/src/ui/PrimaryFlightDisplay.h new file mode 100644 index 0000000..33cb8b1 --- /dev/null +++ b/src/ui/PrimaryFlightDisplay.h @@ -0,0 +1,217 @@ +#ifndef PRIMARYFLIGHTDISPLAY_H +#define PRIMARYFLIGHTDISPLAY_H + +#include +#include +#include "UASInterface.h" + +#define SEPARATE_LAYOUT +#define LINEWIDTH 0.007 + +// all in units of display height +#define ROLL_SCALE_RADIUS 0.42 +#define ROLL_SCALE_TICKMARKLENGTH 0.04 +#define ROLL_SCALE_MARKERWIDTH 0.06 +#define ROLL_SCALE_MARKERHEIGHT 0.04 +// scale max. degrees +#define ROLL_SCALE_RANGE 60 + +// fraction of height to translate for each degree of pitch. +#define PITCHTRANSLATION 65.0 +// 10 degrees for each line +#define PITCH_SCALE_RESOLUTION 5 +#define PITCH_SCALE_MAJORLENGTH 0.08 +#define PITCH_SCALE_MINORLENGTH 0.04 +#define PITCH_SCALE_HALFRANGE 20 + +//#define USE_TAPE_COMPASS +//#define USE_DISK_COMPASS +#define USE_DISK2_COMPASS + +// We want no numbers on the scale, just principal winds or half-winds and ticks. +// With whole winds there are 45 deg per wind, with half-winds 22.5 +#define COMPASS_TAPE_RESOLUTION 15 +// number of degrees side to side +#define COMPASS_TAPE_SPAN 120 + +// The number of degrees to either side of the heading to draw the compass disk. +// 180 is valid, this will draw a complete disk. If the disk is partly clipped +// away, less will do. +#define COMPASS_DISK_SPAN 180 +#define COMPASS_DISK_RESOLUTION 15 +#define COMPASS_DISK_MARKERWIDTH 0.2 +#define COMPASS_DISK_MARKERHEIGHT 0.133 + +#define COMPASS_DISK2_SPAN 180 +#define COMPASS_DISK2_RESOLUTION 5 +#define COMPASS_DISK2_MAJORTICK 10 +#define COMPASS_DISK2_ARROWTICK 45 +#define COMPASS_DISK2_MAJORLINEWIDTH 0.006 +#define COMPASS_DISK2_MINORLINEWIDTH 0.004 +#define COMPASS_SCALE_TEXT_SIZE 0.03 + +// The altitude difference between top and bottom of scale +#define ALTIMETER_LINEAR_SPAN 35 +// every 5 meters there is a tick mark +#define ALTIMETER_LINEAR_RESOLUTION 5 +// every 10 meters there is a number +#define ALTIMETER_LINEAR_MAJOR_RESOLUTION 10 +// min. and max. vertical velocity + +// The altitude difference between top and bottom of scale +#define ALTIMETER_PROJECTED_SPAN 50 +// every 5 meters there is a tick mark +#define ALTIMETER_PROJECTED_RESOLUTION 5 +// every 10 meters there is a number +#define ALTIMETER_PROJECTED_MAJOR_RESOLUTION 10 +// min. and max. vertical velocity + +//#define ALTIMETER_PROJECTED + +#define ALTIMETER_VVI_SPAN 10 +#define ALTIMETER_VVI_LOGARITHMIC true + +#define SHOW_ZERO_ON_SCALES true +#define SCALE_TEXT_SIZE 0.042 +#define SMALL_TEXT_SIZE 0.035 + +#define UNKNOWN_BATTERY -1 + +class PrimaryFlightDisplay : public QWidget +{ + Q_OBJECT +public: + PrimaryFlightDisplay(int width = 640, int height = 480, QWidget* parent = NULL); + ~PrimaryFlightDisplay(); + + /** @brief Attitude from main autopilot / system state */ + void updateAttitude(UASInterface* uas, double roll, double pitch, double yaw, quint64 timestamp); + /** @brief Attitude from one specific component / redundant autopilot */ + void updateAttitude(UASInterface* uas, int component, double roll, double pitch, double yaw, quint64 timestamp); +// void updateAttitudeThrustSetPoint(UASInterface*, double rollDesired, double pitchDesired, double yawDesired, double thrustDesired, quint64 usec); + void updateBattery(UASInterface*, double, double, int); + void receiveHeartbeat(UASInterface*); + void updateThrust(UASInterface*, double); + void updateLocalPosition(UASInterface*,double,double,double,quint64); + void updateGlobalPosition(UASInterface*,double,double,double,quint64); + void updateSpeed(UASInterface*,double,double,double,quint64); + void updateState(UASInterface*,QString); + void updateMode(int id,QString mode, QString description); + void updateLoad(UASInterface*, double); + void selectWaypoint(int uasId, int id); + + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *e); + + // from HUD.h: + + /** @brief Preferred Size */ + QSize sizeHint() const; + /** @brief Start updating widget */ + void showEvent(QShowEvent* event); + /** @brief Stop updating widget */ + void hideEvent(QHideEvent* event); + + // dongfang: We have no context menu. Viewonly. + // void contextMenuEvent (QContextMenuEvent* event); + + // dongfang: What is that? + void createActions(); + + static const int updateInterval = 40; + +public slots: + /** @brief Set the currently monitored UAS */ + virtual void setActiveUAS(UASInterface* uas); + +protected slots: + void paintOnTimer(); + +signals: + void visibilityChanged(bool visible); + +private: + //void prepareTransform(QPainter& painter, qreal width, qreal height); + //void transformToGlobalSystem(QPainter& painter, qreal width, qreal height, float roll, float pitch); + + void drawTextCenter(QPainter& painter, QString text, float fontSize, float x, float y); + void drawTextLeftCenter(QPainter& painter, QString text, float fontSize, float x, float y); + void drawTextRightCenter(QPainter& painter, QString text, float fontSize, float x, float y); + void drawTextCenterBottom(QPainter& painter, QString text, float fontSize, float x, float y); + void drawTextCenterTop(QPainter& painter, QString text, float fontSize, float x, float y); + void drawAIGlobalFeatures(QPainter& painter, QRectF area); + void drawAIAirframeFixedFeatures(QPainter& painter, QRectF area); + void drawPitchScale(QPainter& painter, QRectF area, bool drawNumbersLeft, bool drawNumbersRight); + void drawRollScale(QPainter& painter, QRectF area, bool drawTicks, bool drawNumbers); + void drawAIAttitudeScales(QPainter& painter, QRectF area); +#if defined(USE_DISK_COMPASS) || defined(USE_DISK2_COMPASS) + void drawCompassDisk(QPainter& painter, QRectF area); +#else + void drawCompassTape(QPainter& painter, QRectF area, float yaw); +#endif + void drawAltimeter(QPainter& painter, QRectF area, float altitude, float maxAltitude, float vv); + + void fillInstrumentBackground(QPainter& painter, QRectF edge); + void drawInstrumentBackground(QPainter& painter, QRectF edge); + + void drawLinkStatsPanel(QPainter& painter, QRectF area); + void drawSysStatsPanel(QPainter& painter, QRectF area); + void drawMissionStatsPanel(QPainter& painter, QRectF area); + void drawSensorsStatsPanel(QPainter& painter, QRectF area); + + void makeDummyData(); + void doPaint(); + void paintAllInOne(); + void paintSeparate(); + + float roll; + float pitch; + float heading; + + // APM: GPS and baro mix. From the GLOBAL_POSITION_INT or VFR_HUD messages. + float aboveASLAltitude; + float GPSAltitude; + + // APM: GPS and baro mix above home (GPS) altitude. This value comes from the GLOBAL_POSITION_INT message. + // Do !!!NOT!!! ever do altitude calculations at the ground station. There are enough pitfalls already. + // The MP "set home altitude" button will not be repeated here if it did that. + float aboveHomeAltitude; + + float groundSpeed; + float airSpeed; + + QString mode; + QString state; + + float load; + + QPen whitePen; + QPen redPen; + QPen amberPen; + QPen greenPen; + QPen blackPen; + + QPen instrumentEdgePen; + QBrush instrumentBackground; + QBrush HUDInstrumentBackground; + + QFont font; + + QTimer* refreshTimer; ///< The main timer, controls the update rate + + UASInterface* uas; ///< The uas currently monitored + + //QString energyStatus; ///< Current fuel level / battery voltage + double batteryVoltage; + double batteryCharge; + + static const int tickValues[]; + static const QString compassWindNames[]; + +signals: + +public slots: + +}; + +#endif // PRIMARYFLIGHTDISPLAY_H diff --git a/src/ui/QGCRGBDView.cc b/src/ui/QGCRGBDView.cc index 7a163b7..72d8c3a 100644 --- a/src/ui/QGCRGBDView.cc +++ b/src/ui/QGCRGBDView.cc @@ -6,7 +6,7 @@ #include "UASManager.h" QGCRGBDView::QGCRGBDView(int width, int height, QWidget *parent) : - HUD(width, height, parent), + HUD_old(width, height, parent), rgbEnabled(false), depthEnabled(false) { @@ -70,7 +70,7 @@ void QGCRGBDView::setActiveUAS(UASInterface* uas) connect(uas, SIGNAL(rgbdImageChanged(UASInterface*)), this, SLOT(updateData(UASInterface*))); } - HUD::setActiveUAS(uas); + HUD_old::setActiveUAS(uas); } void QGCRGBDView::clearData(void) @@ -85,7 +85,7 @@ void QGCRGBDView::contextMenuEvent(QContextMenuEvent* event) { QMenu menu(this); // Update actions - enableHUDAction->setChecked(hudInstrumentsEnabled); + enableHUDAction->setChecked(HUDInstrumentsEnabled); //enableVideoAction->setChecked(videoEnabled); enableRGBAction->setChecked(rgbEnabled); enableDepthAction->setChecked(depthEnabled); diff --git a/src/ui/QGCRGBDView.h b/src/ui/QGCRGBDView.h index 58b1503..9689566 100644 --- a/src/ui/QGCRGBDView.h +++ b/src/ui/QGCRGBDView.h @@ -3,7 +3,7 @@ #include "HUD.h" -class QGCRGBDView : public HUD +class QGCRGBDView : public HUD_old { Q_OBJECT public: From 44dc66196ad85d7f11ecd7f8407cf71b1c41c1b9 Mon Sep 17 00:00:00 2001 From: dongfang Date: Sat, 18 May 2013 20:15:13 +0200 Subject: [PATCH 07/10] Undone the HUD_old renaming and fixed public slots in PrimaryFlightDisply that were not. --- src/ui/HUD.cc | 144 ++++++++++++++++++++-------------------- src/ui/HUD.h | 46 ++++++------- src/ui/PrimaryFlightDisplay.cpp | 6 ++ src/ui/PrimaryFlightDisplay.h | 8 ++- src/ui/QGCRGBDView.cc | 4 +- src/ui/QGCRGBDView.h | 2 +- 6 files changed, 110 insertions(+), 100 deletions(-) diff --git a/src/ui/HUD.cc b/src/ui/HUD.cc index fdb28cc..7a4b56c 100644 --- a/src/ui/HUD.cc +++ b/src/ui/HUD.cc @@ -23,7 +23,7 @@ This file is part of the QGROUNDCONTROL project /** * @file - * @brief Head Up Display (HUD_old) + * @brief Head Up Display (HUD) * * @author Lorenz Meier * @@ -52,14 +52,14 @@ This file is part of the QGROUNDCONTROL project #endif /** - * @warning The HUD_old widget will not start painting its content automatically - * to update the view, start the auto-update by calling HUD_old::start(). + * @warning The HUD widget will not start painting its content automatically + * to update the view, start the auto-update by calling HUD::start(). * * @param width * @param height * @param parent */ -HUD_old::HUD_old(int width, int height, QWidget* parent) +HUD::HUD(int width, int height, QWidget* parent) : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), uas(NULL), yawInt(0.0f), @@ -151,7 +151,7 @@ HUD_old::HUD_old(int width, int height, QWidget* parent) // Refresh timer refreshTimer->setInterval(updateInterval); - connect(refreshTimer, SIGNAL(timeout()), this, SLOT(paintHUD_old())); + connect(refreshTimer, SIGNAL(timeout()), this, SLOT(paintHUD())); // Resize to correct size and fill with image resize(this->width(), this->height()); @@ -186,17 +186,17 @@ HUD_old::HUD_old(int width, int height, QWidget* parent) if (UASManager::instance()->getActiveUAS() != NULL) setActiveUAS(UASManager::instance()->getActiveUAS()); } -HUD_old::~HUD_old() +HUD::~HUD() { refreshTimer->stop(); } -QSize HUD_old::sizeHint() const +QSize HUD::sizeHint() const { return QSize(width(), (width()*3.0f)/4); } -void HUD_old::showEvent(QShowEvent* event) +void HUD::showEvent(QShowEvent* event) { // React only to internal (pre-display) // events @@ -205,7 +205,7 @@ void HUD_old::showEvent(QShowEvent* event) emit visibilityChanged(true); } -void HUD_old::hideEvent(QHideEvent* event) +void HUD::hideEvent(QHideEvent* event) { // React only to internal (pre-display) // events @@ -214,7 +214,7 @@ void HUD_old::hideEvent(QHideEvent* event) emit visibilityChanged(false); } -void HUD_old::contextMenuEvent (QContextMenuEvent* event) +void HUD::contextMenuEvent (QContextMenuEvent* event) { QMenu menu(this); // Update actions @@ -222,17 +222,17 @@ void HUD_old::contextMenuEvent (QContextMenuEvent* event) enableVideoAction->setChecked(videoEnabled); menu.addAction(enableHUDAction); - //menu.addAction(selectHUD_oldColorAction); + //menu.addAction(selectHUDColorAction); menu.addAction(enableVideoAction); menu.addAction(selectOfflineDirectoryAction); menu.addAction(selectSaveDirectoryAction); menu.exec(event->globalPos()); } -void HUD_old::createActions() +void HUD::createActions() { - enableHUDAction = new QAction(tr("Enable HUD_old"), this); - enableHUDAction->setStatusTip(tr("Show the HUD_old instruments in this window")); + enableHUDAction = new QAction(tr("Enable HUD"), this); + enableHUDAction->setStatusTip(tr("Show the HUD instruments in this window")); enableHUDAction->setCheckable(true); enableHUDAction->setChecked(HUDInstrumentsEnabled); connect(enableHUDAction, SIGNAL(triggered(bool)), this, SLOT(enableHUDInstruments(bool))); @@ -255,9 +255,9 @@ void HUD_old::createActions() /** * - * @param uas the UAS/MAV to monitor/display with the HUD_old + * @param uas the UAS/MAV to monitor/display with the HUD */ -void HUD_old::setActiveUAS(UASInterface* uas) +void HUD::setActiveUAS(UASInterface* uas) { if (this->uas != NULL) { // Disconnect any previously connected active MAV @@ -308,7 +308,7 @@ void HUD_old::setActiveUAS(UASInterface* uas) } } -//void HUD_old::updateAttitudeThrustSetPoint(UASInterface* uas, double rollDesired, double pitchDesired, double yawDesired, double thrustDesired, quint64 msec) +//void HUD::updateAttitudeThrustSetPoint(UASInterface* uas, double rollDesired, double pitchDesired, double yawDesired, double thrustDesired, quint64 msec) //{ //// updateValue(uas, "roll desired", rollDesired, msec); //// updateValue(uas, "pitch desired", pitchDesired, msec); @@ -316,7 +316,7 @@ void HUD_old::setActiveUAS(UASInterface* uas) //// updateValue(uas, "thrust desired", thrustDesired, msec); //} -void HUD_old::updateAttitude(UASInterface* uas, double roll, double pitch, double yaw, quint64 timestamp) +void HUD::updateAttitude(UASInterface* uas, double roll, double pitch, double yaw, quint64 timestamp) { Q_UNUSED(uas); Q_UNUSED(timestamp); @@ -328,7 +328,7 @@ void HUD_old::updateAttitude(UASInterface* uas, double roll, double pitch, doubl } } -void HUD_old::updateAttitude(UASInterface* uas, int component, double roll, double pitch, double yaw, quint64 timestamp) +void HUD::updateAttitude(UASInterface* uas, int component, double roll, double pitch, double yaw, quint64 timestamp) { Q_UNUSED(uas); Q_UNUSED(timestamp); @@ -338,7 +338,7 @@ void HUD_old::updateAttitude(UASInterface* uas, int component, double roll, doub } } -void HUD_old::updateBattery(UASInterface* uas, double voltage, double percent, int seconds) +void HUD::updateBattery(UASInterface* uas, double voltage, double percent, int seconds) { Q_UNUSED(uas); Q_UNUSED(seconds); @@ -352,18 +352,18 @@ void HUD_old::updateBattery(UASInterface* uas, double voltage, double percent, i } } -void HUD_old::receiveHeartbeat(UASInterface*) +void HUD::receiveHeartbeat(UASInterface*) { } -void HUD_old::updateThrust(UASInterface* uas, double thrust) +void HUD::updateThrust(UASInterface* uas, double thrust) { Q_UNUSED(uas); Q_UNUSED(thrust); // updateValue(uas, "thrust", thrust, MG::TIME::getGroundTimeNow()); } -void HUD_old::updateLocalPosition(UASInterface* uas,double x,double y,double z,quint64 timestamp) +void HUD::updateLocalPosition(UASInterface* uas,double x,double y,double z,quint64 timestamp) { Q_UNUSED(uas); Q_UNUSED(timestamp); @@ -372,7 +372,7 @@ void HUD_old::updateLocalPosition(UASInterface* uas,double x,double y,double z,q this->zPos = z; } -void HUD_old::updateGlobalPosition(UASInterface* uas,double lat, double lon, double altitude, quint64 timestamp) +void HUD::updateGlobalPosition(UASInterface* uas,double lat, double lon, double altitude, quint64 timestamp) { Q_UNUSED(uas); Q_UNUSED(timestamp); @@ -381,7 +381,7 @@ void HUD_old::updateGlobalPosition(UASInterface* uas,double lat, double lon, dou this->alt = altitude; } -void HUD_old::updateSpeed(UASInterface* uas,double x,double y,double z,quint64 timestamp) +void HUD::updateSpeed(UASInterface* uas,double x,double y,double z,quint64 timestamp) { Q_UNUSED(uas); Q_UNUSED(timestamp); @@ -397,9 +397,9 @@ void HUD_old::updateSpeed(UASInterface* uas,double x,double y,double z,quint64 t * Updates the current system state, but only if the uas matches the currently monitored uas. * * @param uas the system the state message originates from - * @param state short state text, displayed in HUD_old + * @param state short state text, displayed in HUD */ -void HUD_old::updateState(UASInterface* uas,QString state) +void HUD::updateState(UASInterface* uas,QString state) { // Only one UAS is connected at a time Q_UNUSED(uas); @@ -410,9 +410,9 @@ void HUD_old::updateState(UASInterface* uas,QString state) * Updates the current system mode, but only if the uas matches the currently monitored uas. * * @param uas the system the state message originates from - * @param mode short mode text, displayed in HUD_old + * @param mode short mode text, displayed in HUD */ -void HUD_old::updateMode(int id,QString mode, QString description) +void HUD::updateMode(int id,QString mode, QString description) { // Only one UAS is connected at a time Q_UNUSED(id); @@ -420,7 +420,7 @@ void HUD_old::updateMode(int id,QString mode, QString description) this->mode = mode; } -void HUD_old::updateLoad(UASInterface* uas, double load) +void HUD::updateLoad(UASInterface* uas, double load) { Q_UNUSED(uas); this->load = load; @@ -431,7 +431,7 @@ void HUD_old::updateLoad(UASInterface* uas, double load) * @param y coordinate in pixels to be converted to reference mm units * @return the screen coordinate relative to the QGLWindow origin */ -float HUD_old::refToScreenX(float x) +float HUD::refToScreenX(float x) { //qDebug() << "sX: " << (scalingFactor * x) << "Orig:" << x; return (scalingFactor * x); @@ -440,7 +440,7 @@ float HUD_old::refToScreenX(float x) * @param x coordinate in pixels to be converted to reference mm units * @return the screen coordinate relative to the QGLWindow origin */ -float HUD_old::refToScreenY(float y) +float HUD::refToScreenY(float y) { //qDebug() << "sY: " << (scalingFactor * y); return (scalingFactor * y); @@ -451,7 +451,7 @@ float HUD_old::refToScreenY(float y) * the x and y center offsets. * */ -void HUD_old::paintCenterBackground(float roll, float pitch, float yaw) +void HUD::paintCenterBackground(float roll, float pitch, float yaw) { Q_UNUSED(yaw); @@ -459,7 +459,7 @@ void HUD_old::paintCenterBackground(float roll, float pitch, float yaw) float referenceWidth = 70.0; float referenceHeight = 70.0; - // HUD_old is assumed to be 200 x 150 mm + // HUD is assumed to be 200 x 150 mm // so that positions can be hardcoded // but can of course be scaled. @@ -522,7 +522,7 @@ void HUD_old::paintCenterBackground(float roll, float pitch, float yaw) * @param refX position in reference units (mm of the real instrument). This is relative to the measurement unit position, NOT in pixels. * @param refY position in reference units (mm of the real instrument). This is relative to the measurement unit position, NOT in pixels. */ -void HUD_old::paintText(QString text, QColor color, float fontSize, float refX, float refY, QPainter* painter) +void HUD::paintText(QString text, QColor color, float fontSize, float refX, float refY, QPainter* painter) { QPen prevPen = painter->pen(); float pPositionX = refToScreenX(refX) - (fontSize*scalingFactor*0.072f); @@ -546,7 +546,7 @@ void HUD_old::paintText(QString text, QColor color, float fontSize, float refX, painter->setPen(prevPen); } -void HUD_old::initializeGL() +void HUD::initializeGL() { bool antialiasing = true; @@ -575,7 +575,7 @@ void HUD_old::initializeGL() * @param referenceWidth width in the reference mm-unit space * @param referenceHeight width in the reference mm-unit space */ -void HUD_old::setupGLView(float referencePositionX, float referencePositionY, float referenceWidth, float referenceHeight) +void HUD::setupGLView(float referencePositionX, float referencePositionY, float referenceWidth, float referenceHeight) { int pixelWidth = (int)(referenceWidth * scalingFactor); int pixelHeight = (int)(referenceHeight * scalingFactor); @@ -601,12 +601,12 @@ void HUD_old::setupGLView(float referencePositionX, float referencePositionY, fl //glScalef(scaleX, scaleY, 1.0f); } -void HUD_old::paintRollPitchStrips() +void HUD::paintRollPitchStrips() { } -void HUD_old::paintEvent(QPaintEvent *event) +void HUD::paintEvent(QPaintEvent *event) { // Event is not needed // the event is ignored as this widget @@ -614,7 +614,7 @@ void HUD_old::paintEvent(QPaintEvent *event) Q_UNUSED(event); } -void HUD_old::paintHUD_old() +void HUD::paintHUD() { if (isVisible()) { // static quint64 interval = 0; @@ -900,7 +900,7 @@ void HUD_old::paintHUD_old() /** * @param pitch pitch angle in degrees (-180 to 180) */ -void HUD_old::paintPitchLines(float pitch, QPainter* painter) +void HUD::paintPitchLines(float pitch, QPainter* painter) { QString label; @@ -967,7 +967,7 @@ void HUD_old::paintPitchLines(float pitch, QPainter* painter) } } -void HUD_old::paintPitchLinePos(QString text, float refPosX, float refPosY, QPainter* painter) +void HUD::paintPitchLinePos(QString text, float refPosX, float refPosY, QPainter* painter) { //painter->setPen(QPen(QBrush, normalStrokeWidth)); @@ -996,7 +996,7 @@ void HUD_old::paintPitchLinePos(QString text, float refPosX, float refPosY, QPai drawLine(refPosX+pitchWidth/2.0f, refPosY, refPosX+pitchGap/2.0f, refPosY, lineWidth, defaultColor, painter); } -void HUD_old::paintPitchLineNeg(QString text, float refPosX, float refPosY, QPainter* painter) +void HUD::paintPitchLineNeg(QString text, float refPosX, float refPosY, QPainter* painter) { const float pitchWidth = 30.0f; const float pitchGap = pitchWidth / 2.5f; @@ -1046,7 +1046,7 @@ void rotatePointClockWise(QPointF& p, float angle) p.setY((-1.0f * sin(angle) * p.x()) + cos(angle) * p.y()); } -float HUD_old::refLineWidthToPen(float line) +float HUD::refLineWidthToPen(float line) { return line * 2.50f; } @@ -1059,7 +1059,7 @@ float HUD_old::refLineWidthToPen(float line) * @param angle rotation angle, in radians * @return p Polygon p rotated by angle around the origin point */ -void HUD_old::rotatePolygonClockWiseRad(QPolygonF& p, float angle, QPointF origin) +void HUD::rotatePolygonClockWiseRad(QPolygonF& p, float angle, QPointF origin) { // Standard 2x2 rotation matrix, counter-clockwise // @@ -1078,7 +1078,7 @@ void HUD_old::rotatePolygonClockWiseRad(QPolygonF& p, float angle, QPointF origi } } -void HUD_old::drawPolygon(QPolygonF refPolygon, QPainter* painter) +void HUD::drawPolygon(QPolygonF refPolygon, QPainter* painter) { // Scale coordinates QPolygonF draw(refPolygon.size()); @@ -1091,7 +1091,7 @@ void HUD_old::drawPolygon(QPolygonF refPolygon, QPainter* painter) painter->drawPolygon(draw); } -void HUD_old::drawChangeRateStrip(float xRef, float yRef, float height, float minRate, float maxRate, float value, QPainter* painter,bool reverse) +void HUD::drawChangeRateStrip(float xRef, float yRef, float height, float minRate, float maxRate, float value, QPainter* painter,bool reverse) { float scaledValue = value; @@ -1154,7 +1154,7 @@ void HUD_old::drawChangeRateStrip(float xRef, float yRef, float height, float mi } } -//void HUD_old::drawSystemIndicator(float xRef, float yRef, int maxNum, float maxWidth, float maxHeight, QPainter* painter) +//void HUD::drawSystemIndicator(float xRef, float yRef, int maxNum, float maxWidth, float maxHeight, QPainter* painter) //{ // Q_UNUSED(maxWidth); // Q_UNUSED(maxHeight); @@ -1231,7 +1231,7 @@ void HUD_old::drawChangeRateStrip(float xRef, float yRef, float height, float mi // } //} -void HUD_old::drawChangeIndicatorGauge(float xRef, float yRef, float radius, float expectedMaxChange, float value, const QColor& color, QPainter* painter, bool solid) +void HUD::drawChangeIndicatorGauge(float xRef, float yRef, float radius, float expectedMaxChange, float value, const QColor& color, QPainter* painter, bool solid) { // Draw the circle QPen circlePen(Qt::SolidLine); @@ -1277,7 +1277,7 @@ void HUD_old::drawChangeIndicatorGauge(float xRef, float yRef, float radius, flo drawPolygon(p, painter); } -void HUD_old::drawLine(float refX1, float refY1, float refX2, float refY2, float width, const QColor& color, QPainter* painter) +void HUD::drawLine(float refX1, float refY1, float refX2, float refY2, float width, const QColor& color, QPainter* painter) { QPen pen(Qt::SolidLine); pen.setWidth(refLineWidthToPen(width)); @@ -1286,7 +1286,7 @@ void HUD_old::drawLine(float refX1, float refY1, float refX2, float refY2, float painter->drawLine(QPoint(refToScreenX(refX1), refToScreenY(refY1)), QPoint(refToScreenX(refX2), refToScreenY(refY2))); } -void HUD_old::drawEllipse(float refX, float refY, float radiusX, float radiusY, float startDeg, float endDeg, float lineWidth, const QColor& color, QPainter* painter) +void HUD::drawEllipse(float refX, float refY, float radiusX, float radiusY, float startDeg, float endDeg, float lineWidth, const QColor& color, QPainter* painter) { Q_UNUSED(startDeg); Q_UNUSED(endDeg); @@ -1297,12 +1297,12 @@ void HUD_old::drawEllipse(float refX, float refY, float radiusX, float radiusY, painter->drawEllipse(QPointF(refToScreenX(refX), refToScreenY(refY)), refToScreenX(radiusX), refToScreenY(radiusY)); } -void HUD_old::drawCircle(float refX, float refY, float radius, float startDeg, float endDeg, float lineWidth, const QColor& color, QPainter* painter) +void HUD::drawCircle(float refX, float refY, float radius, float startDeg, float endDeg, float lineWidth, const QColor& color, QPainter* painter) { drawEllipse(refX, refY, radius, radius, startDeg, endDeg, lineWidth, color, painter); } -void HUD_old::resizeGL(int w, int h) +void HUD::resizeGL(int w, int h) { if (isVisible()) { glViewport(0, 0, w, h); @@ -1312,17 +1312,17 @@ void HUD_old::resizeGL(int w, int h) glMatrixMode(GL_MODELVIEW); glPolygonMode(GL_FRONT, GL_FILL); //FIXME - paintHUD_old(); + paintHUD(); } } -void HUD_old::selectWaypoint(int uasId, int id) +void HUD::selectWaypoint(int uasId, int id) { Q_UNUSED(uasId); waypointName = tr("WP") + QString::number(id); } -void HUD_old::setImageSize(int width, int height, int depth, int channels) +void HUD::setImageSize(int width, int height, int depth, int channels) { // Allocate raw image in correct size if (width != receivedWidth || height != receivedHeight || depth != receivedDepth || channels != receivedChannels || image == NULL) { @@ -1378,10 +1378,10 @@ void HUD_old::setImageSize(int width, int height, int depth, int channels) } -void HUD_old::startImage(int imgid, int width, int height, int depth, int channels) +void HUD::startImage(int imgid, int width, int height, int depth, int channels) { Q_UNUSED(imgid); - //qDebug() << "HUD_old: starting image (" << width << "x" << height << ", " << depth << "bits) with " << channels << "channels"; + //qDebug() << "HUD: starting image (" << width << "x" << height << ", " << depth << "bits) with " << channels << "channels"; // Copy previous image to screen if it hasn't been finished properly finishImage(); @@ -1391,7 +1391,7 @@ void HUD_old::startImage(int imgid, int width, int height, int depth, int channe imageStarted = true; } -void HUD_old::finishImage() +void HUD::finishImage() { if (imageStarted) { commitRawDataToGL(); @@ -1399,7 +1399,7 @@ void HUD_old::finishImage() } } -void HUD_old::commitRawDataToGL() +void HUD::commitRawDataToGL() { qDebug() << __FILE__ << __LINE__ << "Copying raw data to GL buffer:" << rawImage << receivedWidth << receivedHeight << image->format(); if (image != NULL) { @@ -1429,19 +1429,19 @@ void HUD_old::commitRawDataToGL() update(); } -void HUD_old::saveImage(QString fileName) +void HUD::saveImage(QString fileName) { image->save(fileName); } -void HUD_old::saveImage() +void HUD::saveImage() { //Bring up popup QString fileName = "output.png"; saveImage(fileName); } -void HUD_old::startImage(quint64 timestamp) +void HUD::startImage(quint64 timestamp) { if (videoEnabled && offlineDirectory != "") { // Load and diplay image file @@ -1449,7 +1449,7 @@ void HUD_old::startImage(quint64 timestamp) } } -void HUD_old::selectOfflineDirectory() +void HUD::selectOfflineDirectory() { QString fileName = QFileDialog::getExistingDirectory(this, tr("Select image directory"), QDesktopServices::storageLocation(QDesktopServices::DesktopLocation)); if (fileName != "") { @@ -1457,17 +1457,17 @@ void HUD_old::selectOfflineDirectory() } } -void HUD_old::enableHUD_oldInstruments(bool enabled) +void HUD::enableHUDInstruments(bool enabled) { HUDInstrumentsEnabled = enabled; } -void HUD_old::enableVideo(bool enabled) +void HUD::enableVideo(bool enabled) { videoEnabled = enabled; } -void HUD_old::setPixels(int imgid, const unsigned char* imageData, int length, int startIndex) +void HUD::setPixels(int imgid, const unsigned char* imageData, int length, int startIndex) { Q_UNUSED(imgid); // qDebug() << "at" << __FILE__ << __LINE__ << ": Received startindex" << startIndex << "and length" << length << "(" << startIndex+length << "of" << rawExpectedBytes << "bytes)"; @@ -1478,7 +1478,7 @@ void HUD_old::setPixels(int imgid, const unsigned char* imageData, int length, i if (startIndex+length > rawExpectedBytes) { - qDebug() << "HUD_old: OVERFLOW! startIndex:" << startIndex << "length:" << length << "image raw size" << ((receivedWidth * receivedHeight * receivedChannels * receivedDepth) / 8) - 1; + qDebug() << "HUD: OVERFLOW! startIndex:" << startIndex << "length:" << length << "image raw size" << ((receivedWidth * receivedHeight * receivedChannels * receivedDepth) / 8) - 1; } else { @@ -1489,7 +1489,7 @@ void HUD_old::setPixels(int imgid, const unsigned char* imageData, int length, i // Check if we just reached the end of the image if (startIndex+length == rawExpectedBytes) { - //qDebug() << "HUD_old: END OF IMAGE REACHED!"; + //qDebug() << "HUD: END OF IMAGE REACHED!"; finishImage(); rawLastIndex = 0; } @@ -1507,11 +1507,11 @@ void HUD_old::setPixels(int imgid, const unsigned char* imageData, int length, i } } -void HUD_old::copyImage() +void HUD::copyImage() { if (isVisible() && HUDInstrumentsEnabled) { - //qDebug() << "HUD_old::copyImage()"; + //qDebug() << "HUD::copyImage()"; UAS* u = dynamic_cast(this->uas); if (u) { @@ -1527,7 +1527,7 @@ void HUD_old::copyImage() } } -void HUD_old::saveImages(bool save) +void HUD::saveImages(bool save) { if (save) { diff --git a/src/ui/HUD.h b/src/ui/HUD.h index d1c2130..720b1f0 100644 --- a/src/ui/HUD.h +++ b/src/ui/HUD.h @@ -29,8 +29,8 @@ This file is part of the QGROUNDCONTROL project * */ -#ifndef HUD_old_H -#define HUD_old_H +#ifndef HUD_H +#define HUD_H #include #include @@ -41,18 +41,18 @@ This file is part of the QGROUNDCONTROL project #include "UASInterface.h" /** - * @brief Displays a Head Up Display (HUD_old) + * @brief Displays a Head Up Display (HUD) * - * This class represents a head up display (HUD_old) and draws this HUD_old in an OpenGL widget (QGLWidget). - * It can superimpose the HUD_old over the current live image stream (any arriving image stream will be auto- + * This class represents a head up display (HUD) and draws this HUD in an OpenGL widget (QGLWidget). + * It can superimpose the HUD over the current live image stream (any arriving image stream will be auto- * matically used as background), or it draws the classic blue-brown background known from instruments. */ -class HUD_old : public QGLWidget +class HUD : public QGLWidget { Q_OBJECT public: - HUD_old(int width = 640, int height = 480, QWidget* parent = NULL); - ~HUD_old(); + HUD(int width = 640, int height = 480, QWidget* parent = NULL); + ~HUD(); void setImageSize(int width, int height, int depth, int channels); void resizeGL(int w, int h); @@ -90,7 +90,7 @@ public slots: /** @brief Select directory where to load the offline files from */ void selectOfflineDirectory(); /** @brief Enable the HUD instruments */ - void enableHUD_oldInstruments(bool enabled); + void enableHUDInstruments(bool enabled); /** @brief Enable Video */ void enableVideo(bool enabled); /** @brief Copy an image from the current active UAS */ @@ -103,9 +103,9 @@ protected slots: void paintPitchLines(float pitch, QPainter* painter); /** @brief Paint text on top of the image and OpenGL drawings */ void paintText(QString text, QColor color, float fontSize, float refX, float refY, QPainter* painter); - /** @brief Setup the OpenGL view for drawing a sub-component of the HUD_old */ + /** @brief Setup the OpenGL view for drawing a sub-component of the HUD */ void setupGLView(float referencePositionX, float referencePositionY, float referenceWidth, float referenceHeight); - void paintHUD_old(); + void paintHUD(); void paintPitchLinePos(QString text, float refPosX, float refPosY, QPainter* painter); void paintPitchLineNeg(QString text, float refPosX, float refPosY, QPainter* painter); @@ -156,8 +156,8 @@ protected: float vGaugeSpacing; ///< Virtual spacing of the gauges from the center, 50 mm per default float vPitchPerDeg; ///< Virtual pitch to mm conversion. Currently one degree is 3 mm up/down in the pitch markings - int xCenter; ///< Center of the HUD_old instrument in pixel coordinates. Allows to off-center the whole instrument in its OpenGL window, e.g. to fit another instrument - int yCenter; ///< Center of the HUD_old instrument in pixel coordinates. Allows to off-center the whole instrument in its OpenGL window, e.g. to fit another instrument + int xCenter; ///< Center of the HUD instrument in pixel coordinates. Allows to off-center the whole instrument in its OpenGL window, e.g. to fit another instrument + int yCenter; ///< Center of the HUD instrument in pixel coordinates. Allows to off-center the whole instrument in its OpenGL window, e.g. to fit another instrument // Image buffers unsigned char* rawBuffer1; ///< Double buffer 1 for the image @@ -172,8 +172,8 @@ protected: int receivedWidth; ///< Width in pixels of the current image int receivedHeight; ///< Height in pixels of the current image - // HUD_old colors - QColor defaultColor; ///< Color for most HUD_old elements, e.g. pitch lines, center cross, change rate gauges + // HUD colors + QColor defaultColor; ///< Color for most HUD elements, e.g. pitch lines, center cross, change rate gauges QColor setPointColor; ///< Color for the current control set point, e.g. yaw desired QColor warningColor; ///< Color for warning messages QColor criticalColor; ///< Color for caution messages @@ -184,17 +184,17 @@ protected: int warningBlinkRate; ///< Blink rate of warning messages, will be rounded to the refresh rate QTimer* refreshTimer; ///< The main timer, controls the update rate - QPainter* HUD_oldPainter; - QFont font; ///< The HUD_old font, per default the free Bitstream Vera SANS, which is very close to actual HUD_old fonts - QFontDatabase fontDatabase;///< Font database, only used to load the TrueType font file (the HUD_old font is directly loaded from file rather than from the system) + QPainter* HUDPainter; + QFont font; ///< The HUD font, per default the free Bitstream Vera SANS, which is very close to actual HUD fonts + QFontDatabase fontDatabase;///< Font database, only used to load the TrueType font file (the HUD font is directly loaded from file rather than from the system) bool noCamera; ///< No camera images available, draw the ground/sky box to indicate the horizon bool hardwareAcceleration; ///< Enable hardware acceleration - float strongStrokeWidth; ///< Strong line stroke width, used throughout the HUD_old - float normalStrokeWidth; ///< Normal line stroke width, used throughout the HUD_old - float fineStrokeWidth; ///< Fine line stroke width, used throughout the HUD_old + float strongStrokeWidth; ///< Strong line stroke width, used throughout the HUD + float normalStrokeWidth; ///< Normal line stroke width, used throughout the HUD + float fineStrokeWidth; ///< Fine line stroke width, used throughout the HUD - QString waypointName; ///< Waypoint name displayed in HUD_old + QString waypointName; ///< Waypoint name displayed in HUD float roll; float pitch; float yaw; @@ -235,4 +235,4 @@ protected: unsigned int imageLogCounter; }; -#endif // HUD_old_H +#endif // HUD_H diff --git a/src/ui/PrimaryFlightDisplay.cpp b/src/ui/PrimaryFlightDisplay.cpp index 0990174..e317895 100644 --- a/src/ui/PrimaryFlightDisplay.cpp +++ b/src/ui/PrimaryFlightDisplay.cpp @@ -170,6 +170,8 @@ void PrimaryFlightDisplay::updateAttitude(UASInterface* uas, double roll, double this->heading = yaw; } // TODO: Else-part. We really should have an "attitude bad or unknown" indication instead of just freezing. + + qDebug("r,p,y: %f,%f,%f", roll, pitch, yaw); } /* @@ -184,6 +186,8 @@ void PrimaryFlightDisplay::updateAttitude(UASInterface* uas, int component, doub Q_UNUSED(pitch); Q_UNUSED(yaw); Q_UNUSED(timestamp); + + qDebug("ignore (!!!) r,p,y: %f,%f,%f", roll, pitch, yaw); } void PrimaryFlightDisplay::updateBattery(UASInterface* uas, double voltage, double percent, int seconds) @@ -1122,3 +1126,5 @@ void PrimaryFlightDisplay::doPaint() { paintAllInOne(); #endif } + +void PrimaryFlightDisplay:: createActions() {} diff --git a/src/ui/PrimaryFlightDisplay.h b/src/ui/PrimaryFlightDisplay.h index 33cb8b1..cbfad8f 100644 --- a/src/ui/PrimaryFlightDisplay.h +++ b/src/ui/PrimaryFlightDisplay.h @@ -84,6 +84,7 @@ public: PrimaryFlightDisplay(int width = 640, int height = 480, QWidget* parent = NULL); ~PrimaryFlightDisplay(); +public slots: /** @brief Attitude from main autopilot / system state */ void updateAttitude(UASInterface* uas, double roll, double pitch, double yaw, quint64 timestamp); /** @brief Attitude from one specific component / redundant autopilot */ @@ -100,6 +101,7 @@ public: void updateLoad(UASInterface*, double); void selectWaypoint(int uasId, int id); +protected: void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent *e); @@ -115,11 +117,10 @@ public: // dongfang: We have no context menu. Viewonly. // void contextMenuEvent (QContextMenuEvent* event); +protected: // dongfang: What is that? void createActions(); - static const int updateInterval = 40; - public slots: /** @brief Set the currently monitored UAS */ virtual void setActiveUAS(UASInterface* uas); @@ -208,6 +209,9 @@ private: static const int tickValues[]; static const QString compassWindNames[]; + static const int updateInterval = 40; + + signals: public slots: diff --git a/src/ui/QGCRGBDView.cc b/src/ui/QGCRGBDView.cc index 72d8c3a..27f3e34 100644 --- a/src/ui/QGCRGBDView.cc +++ b/src/ui/QGCRGBDView.cc @@ -6,7 +6,7 @@ #include "UASManager.h" QGCRGBDView::QGCRGBDView(int width, int height, QWidget *parent) : - HUD_old(width, height, parent), + HUD(width, height, parent), rgbEnabled(false), depthEnabled(false) { @@ -70,7 +70,7 @@ void QGCRGBDView::setActiveUAS(UASInterface* uas) connect(uas, SIGNAL(rgbdImageChanged(UASInterface*)), this, SLOT(updateData(UASInterface*))); } - HUD_old::setActiveUAS(uas); + HUD::setActiveUAS(uas); } void QGCRGBDView::clearData(void) diff --git a/src/ui/QGCRGBDView.h b/src/ui/QGCRGBDView.h index 9689566..58b1503 100644 --- a/src/ui/QGCRGBDView.h +++ b/src/ui/QGCRGBDView.h @@ -3,7 +3,7 @@ #include "HUD.h" -class QGCRGBDView : public HUD_old +class QGCRGBDView : public HUD { Q_OBJECT public: From d3c13e6570be9f778d463dccd558d86acc788291 Mon Sep 17 00:00:00 2001 From: Michael Carpenter Date: Mon, 20 May 2013 18:36:22 -0400 Subject: [PATCH 08/10] Changes for compiling in windows and getting the AHRS working --- src/ui/PrimaryFlightDisplay.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/ui/PrimaryFlightDisplay.cpp b/src/ui/PrimaryFlightDisplay.cpp index e317895..f4e3c30 100644 --- a/src/ui/PrimaryFlightDisplay.cpp +++ b/src/ui/PrimaryFlightDisplay.cpp @@ -10,14 +10,17 @@ #include #include #include - +#include /* *@TODO: * global fixed pens * repaint on demand multiple canvases * multi implementation with shared model class */ - +double round(double value, int digits=0) +{ + return floor(value * pow(10, digits) + 0.5) / pow(10, digits); +} const int PrimaryFlightDisplay::tickValues[] = {10, 20, 30, 45, 60}; const QString PrimaryFlightDisplay::compassWindNames[] = { QString("N"), @@ -35,7 +38,7 @@ PrimaryFlightDisplay::PrimaryFlightDisplay(int width, int height, QWidget *paren roll(0), pitch(0), - heading(NAN), + heading(0), aboveASLAltitude(0), GPSAltitude(0), aboveHomeAltitude(0), @@ -80,7 +83,7 @@ PrimaryFlightDisplay::PrimaryFlightDisplay(int width, int height, QWidget *paren // Refresh timer refreshTimer->setInterval(updateInterval); - connect(refreshTimer, SIGNAL(timeout()), this, SLOT(paintHUD())); + connect(refreshTimer, SIGNAL(timeout()), this, SLOT(update())); } PrimaryFlightDisplay::~PrimaryFlightDisplay() @@ -165,9 +168,9 @@ void PrimaryFlightDisplay::updateAttitude(UASInterface* uas, double roll, double if (!isnan(roll) && !isinf(roll) && !isnan(pitch) && !isinf(pitch) && !isnan(yaw) && !isinf(yaw)) { // TODO: Units conversion? - this->roll = roll; - this->pitch = pitch; - this->heading = yaw; + this->roll = roll * (180.0 / M_PI); + this->pitch = pitch * (180.0 / M_PI); + this->heading = yaw * (180.0 / M_PI); } // TODO: Else-part. We really should have an "attitude bad or unknown" indication instead of just freezing. @@ -309,7 +312,7 @@ void PrimaryFlightDisplay::paintEvent(QPaintEvent *event) // the event is ignored as this widget // is refreshed automatically Q_UNUSED(event); - makeDummyData(); + //makeDummyData(); doPaint(); } @@ -319,7 +322,7 @@ void PrimaryFlightDisplay::paintOnTimer() { *The whole tainted-flag shebang. *well not really so critical. Worst problem is deletion? */ - makeDummyData(); + //makeDummyData(); doPaint(); } From 0049997b699676539caf7d2ae52f690ba374123c Mon Sep 17 00:00:00 2001 From: Michael Carpenter Date: Mon, 20 May 2013 18:41:37 -0400 Subject: [PATCH 09/10] Increment version number, since the new AHRS would break setting loading --- src/configuration.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/configuration.h b/src/configuration.h index f66f4b1..4d84f51 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -11,7 +11,7 @@ #define WITH_TEXT_TO_SPEECH 1 #define QGC_APPLICATION_NAME "QGroundControl" -#define QGC_APPLICATION_VERSION "v. 1.0.9 (beta)" +#define QGC_APPLICATION_VERSION "v. 1.0.10 (beta)" namespace QGC From f5d89a62fde894d0f564f338e3333555eccba0f3 Mon Sep 17 00:00:00 2001 From: Michael Carpenter Date: Tue, 21 May 2013 16:24:41 -0400 Subject: [PATCH 10/10] Change to how configuration view operates, menu on the left side rather than top --- files/styles/style-indoor.css | 4 +- files/styles/style-outdoor.css | 4 +- src/ui/QGCVehicleConfig.cc | 68 +- src/ui/QGCVehicleConfig.h | 9 +- src/ui/QGCVehicleConfig.ui | 1860 +++++++++++++++++++++------------------- 5 files changed, 1051 insertions(+), 894 deletions(-) diff --git a/files/styles/style-indoor.css b/files/styles/style-indoor.css index 301738b..595fcf8 100644 --- a/files/styles/style-indoor.css +++ b/files/styles/style-indoor.css @@ -178,8 +178,8 @@ QDoubleSpinBox::down-button { } QPushButton { - min-height: 20px; - max-height: 20px; + /*min-height: 20px;*/ + /*max-height: 20px;*/ border: 1px solid #465158; margin: 1px; border-radius: 2px; diff --git a/files/styles/style-outdoor.css b/files/styles/style-outdoor.css index c153f62..e6893c6 100644 --- a/files/styles/style-outdoor.css +++ b/files/styles/style-outdoor.css @@ -184,8 +184,8 @@ QDoubleSpinBox::down-button { QPushButton { font-weight: bold; - min-height: 18px; - max-height: 18px; + /*min-height: 18px;*/ + /*max-height: 18px;*/ border: 2px solid #4A4A4F; border-radius: 5px; padding-left: 10px; diff --git a/src/ui/QGCVehicleConfig.cc b/src/ui/QGCVehicleConfig.cc index 3bf8130..1f110b9 100644 --- a/src/ui/QGCVehicleConfig.cc +++ b/src/ui/QGCVehicleConfig.cc @@ -44,6 +44,12 @@ QGCVehicleConfig::QGCVehicleConfig(QWidget *parent) : setObjectName("QGC_VEHICLECONFIG"); ui->setupUi(this); + connect(ui->rcMenuButton,SIGNAL(clicked()),this,SLOT(rcMenuButtonClicked())); + connect(ui->sensorMenuButton,SIGNAL(clicked()),this,SLOT(sensorMenuButtonClicked())); + connect(ui->generalMenuButton,SIGNAL(clicked()),this,SLOT(generalMenuButtonClicked())); + connect(ui->advancedMenuButton,SIGNAL(clicked()),this,SLOT(advancedMenuButtonClicked())); + + requestCalibrationRC(); if (mav) mav->requestParameter(0, "RC_TYPE"); @@ -89,6 +95,25 @@ QGCVehicleConfig::QGCVehicleConfig(QWidget *parent) : connect(&updateTimer, SIGNAL(timeout()), this, SLOT(updateView())); updateTimer.start(); } +void QGCVehicleConfig::rcMenuButtonClicked() +{ + ui->stackedWidget->setCurrentIndex(0); +} + +void QGCVehicleConfig::sensorMenuButtonClicked() +{ + ui->stackedWidget->setCurrentIndex(1); +} + +void QGCVehicleConfig::generalMenuButtonClicked() +{ + ui->stackedWidget->setCurrentIndex(ui->stackedWidget->count()-2); +} + +void QGCVehicleConfig::advancedMenuButtonClicked() +{ + ui->stackedWidget->setCurrentIndex(ui->stackedWidget->count()-1); +} QGCVehicleConfig::~QGCVehicleConfig() { @@ -247,8 +272,18 @@ void QGCVehicleConfig::loadQgcConfig(bool primary) //Load tabs for general configuration foreach (QString dir,generaldir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { - QWidget *tab = new QWidget(ui->tabWidget); - ui->tabWidget->insertTab(2,tab,dir); + QPushButton *button = new QPushButton(ui->scrollAreaWidgetContents_3); + connect(button,SIGNAL(clicked()),this,SLOT(menuButtonClicked())); + ui->navBarLayout->insertWidget(2,button); + button->setMinimumHeight(100); + button->setMinimumWidth(100); + button->show(); + button->setText(dir); + //QWidget *tab = new QWidget(ui->tabWidget); + //ui->tabWidget->insertTab(2,tab,dir); + QWidget *tab = new QWidget(ui->stackedWidget); + ui->stackedWidget->insertWidget(2,tab); + buttonToWidgetMap[button] = tab; tab->setLayout(new QVBoxLayout()); tab->show(); QScrollArea *area = new QScrollArea(); @@ -283,8 +318,20 @@ void QGCVehicleConfig::loadQgcConfig(bool primary) //Load tabs for vehicle specific configuration foreach (QString dir,vehicledir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { - QWidget *tab = new QWidget(ui->tabWidget); - ui->tabWidget->insertTab(2,tab,dir); + //QWidget *tab = new QWidget(ui->tabWidget); + //ui->tabWidget->insertTab(2,tab,dir); + QPushButton *button = new QPushButton(ui->scrollAreaWidgetContents_3); + connect(button,SIGNAL(clicked()),this,SLOT(menuButtonClicked())); + ui->navBarLayout->insertWidget(2,button); + + QWidget *tab = new QWidget(ui->stackedWidget); + ui->stackedWidget->insertWidget(2,tab); + buttonToWidgetMap[button] = tab; + + button->setMinimumHeight(100); + button->setMinimumWidth(100); + button->show(); + button->setText(dir); tab->setLayout(new QVBoxLayout()); tab->show(); QScrollArea *area = new QScrollArea(); @@ -362,6 +409,19 @@ void QGCVehicleConfig::loadQgcConfig(bool primary) } +void QGCVehicleConfig::menuButtonClicked() +{ + QPushButton *button = qobject_cast(sender()); + if (!button) + { + return; + } + if (buttonToWidgetMap.contains(button)) + { + ui->stackedWidget->setCurrentWidget(buttonToWidgetMap[button]); + } + +} void QGCVehicleConfig::loadConfig() { diff --git a/src/ui/QGCVehicleConfig.h b/src/ui/QGCVehicleConfig.h index 242c11b..44e864b 100644 --- a/src/ui/QGCVehicleConfig.h +++ b/src/ui/QGCVehicleConfig.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "QGCToolWidget.h" #include "UASInterface.h" @@ -29,6 +30,11 @@ public: }; public slots: + void rcMenuButtonClicked(); + void sensorMenuButtonClicked(); + void generalMenuButtonClicked(); + void advancedMenuButtonClicked(); + /** Set the MAV currently being calibrated */ void setActiveUAS(UASInterface* active); /** Fallback function, automatically called by loadConfig() upon failure to find and xml file*/ @@ -125,6 +131,7 @@ public slots: } protected slots: + void menuButtonClicked(); /** Reset the RC calibration */ void resetCalibrationRC(); /** Write the RC calibration */ @@ -183,7 +190,7 @@ protected: private: Ui::QGCVehicleConfig *ui; - + QMap buttonToWidgetMap; signals: void visibilityChanged(bool visible); }; diff --git a/src/ui/QGCVehicleConfig.ui b/src/ui/QGCVehicleConfig.ui index 1ed13b2..69de361 100644 --- a/src/ui/QGCVehicleConfig.ui +++ b/src/ui/QGCVehicleConfig.ui @@ -6,994 +6,1084 @@ 0 0 - 760 - 541 + 1151 + 602 Form - - - 6 - - - 8 - - - 6 - - - - - Store to EEPROM + + + + + + 125 + 0 + - - - - - - No pending changes + + + 125 + 16777215 + - - - - - - 2 + + true - - - RC Calibration - - - - 20 - - - - - 0 - - - 100 - - - 0 - - - Qt::Vertical - - - - - - - 0 - - - 100 - - - 0 - - - Qt::Vertical + + + + 0 + 0 + 123 + 582 + + + + + + + QLayout::SetMinAndMaxSize - - - - - - - false - - - false - - - - Select transmitter model - - - - - - - - true - - - - Mode 1 - - - - - Mode 2 - - - - - Mode 3 - - - - - Mode 4 - - - - - - - - - - Qt::Vertical - - - - 598 - 5 - - - - - - - - - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Aux 3 - - - - - - - 0000 - - - Qt::AlignCenter - - - - - - - 0000 - - - Qt::AlignCenter - - - - - - - Pitch / Elevator - - - - - - - 0000 - - - Qt::AlignCenter - - - - - - - Aux 2 - - - - - - - Qt::Horizontal - - + + - 40 - 20 + 100 + 100 - - - - - - 0000 - - - Qt::AlignCenter - - - - - - - Invert - - - - - - - 1 - - - 8 - - - - - - - 1 - - - 8 - - - - - - - Qt::Horizontal - - + - 40 - 20 + 100 + 100 - - - - - - Throttle - - - - - - - Invert - - - - - - - 1 - - - 8 - - - - - - - 1 - - - 8 - - - - - - - Mode Switch - - - - - - - 0000 - - - Qt::AlignCenter - - - - - - - 1 - - - 8 - - - - - - - 1 - - - 8 - - - - - - - Aux 1 - - - - - - - 1 - - - 8 - - - - - - 0000 - - - Qt::AlignCenter - - - - - - - 1 - - - 8 + RC +Calibration - - - - Roll / Ailerons - - - - - - - Invert + + + + + 100 + 100 + - - - - - - Invert + + + 100 + 100 + - - - - - Invert + Sensor +Calibration - - - - 0000 + + + + + 100 + 100 + - - Qt::AlignCenter + + + 100 + 100 + - - - - - Invert + General +Config - - - - Qt::Horizontal + + + + + 100 + 100 + - + - 40 - 20 + 100 + 100 - - - - - Yaw / Rudder + Advanced +Config - - + + + + + + + + + + + + 0 + + + + + - 0000 - - - Qt::AlignCenter + RC Calibration - - + + + + + + false + + + false + + + + Select transmitter model + + + + + + + + true + + + + Mode 1 + + + + + Mode 2 + + + + + Mode 3 + + + + + Mode 4 + + + + + + + + - Qt::Horizontal + Qt::Vertical - 40 - 20 + 20 + 40 - - - - Invert - - - - - - - Invert - - - - - - - - - Qt::Horizontal - - - - 22 - 122 - - - - - - - - Qt::Vertical - - - - 598 - 17 - - - - - - - - - - - :/files/images/rc_stick.svg - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 1 - 1 - - - - - 10 - 10 - - - - - 100 - 100 - - - - - - - :/files/images/rc_stick.svg - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 0 - - - 100 - - - 0 - - - Qt::Horizontal - - - - - - - 0 - - - 100 - - - 0 - - - Qt::Horizontal - - - - - - - Start Calibration - - - - - - - Qt::Vertical - - - QSizePolicy::MinimumExpanding - - - - 20 - 10 - - - - - - - - 0 - - - 100 - - - Qt::Vertical - - - - - - - 0 - - - 100 - - - Qt::Vertical - - - - - - - 0 - - - 100 - - - Qt::Vertical - - - - - - - 0 - - - 100 - - - Qt::Vertical - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Set Trim - - - - - - - - Sensor Calibration - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html> - - + + + + + 0000 + + + Qt::AlignCenter + + + + + + + Invert + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Yaw / Rudder + + + + + + + 0000 + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Invert + + + + + + + Invert + + + + + + + 1 + + + 8 + + + + + + + 0000 + + + Qt::AlignCenter + + + + + + + 0000 + + + Qt::AlignCenter + + + + + + + Pitch / Elevator + + + + + + + 0000 + + + Qt::AlignCenter + + + + + + + Aux 2 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0000 + + + Qt::AlignCenter + + + + + + + Invert + + + + + + + 1 + + + 8 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Throttle + + + + + + + Invert + + + + + + + 1 + + + 8 + + + + + + + 1 + + + 8 + + + + + + + Mode Switch + + + + + + + 0000 + + + Qt::AlignCenter + + + + + + + 1 + + + 8 + + + + + + + 1 + + + 8 + + + + + + + Aux 1 + + + + + + + 1 + + + 8 + + + + + + + 0000 + + + Qt::AlignCenter + + + + + + + Aux 3 + + + + + + + Invert + + + + + + + 1 + + + 8 + + + + + + + Invert + + + + + + + Invert + + + + + + + Roll / Ailerons + + + + - + - - - true - - - - - 0 - 0 - 354 - 448 - - - + + + + + + 200 + 200 + + + + + + + :/files/images/rc_stick.svg + + + true + + + Qt::AlignCenter + + + + + + + 0 + + + 100 + + + 0 + + + Qt::Horizontal + + + + + + + 0 + + + 100 + + + 0 + + + Qt::Vertical + + + + + + + + + + + + 1 + 1 + + + + + 200 + 200 + + + + + 10 + 10 + + + + + 100 + 100 + + + + + + + :/files/images/rc_stick.svg + + + true + + + Qt::AlignCenter + + + + + + + 0 + + + 100 + + + 0 + + + Qt::Horizontal + + + + + + + 0 + + + 100 + + + 0 + + + Qt::Vertical + + + + + + + + + + + + + 0 + + + 100 + + + Qt::Vertical + + + - + + + 0 + + + 100 + + + Qt::Vertical + + + + + + + 0 + + + 100 + + + Qt::Vertical + + + + + + + 0 + + + 100 + + + Qt::Vertical + + - - + + + + + + + Start Calibration + + + + + + + Set Trim + + + + + + - - - - - - - General Config - - - - - + - Qt::Horizontal + Qt::Vertical - 40 - 20 + 20 + 40 + + + + - - - - + - Load Platform Defaults + Sensor Calibration - - - - - - - Configuration - - - - 0 - - - - - true - - - - - 0 - 0 - 354 - 404 - + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html> + + + + + + + + + true - - - 0 + + + + 0 + 0 + 314 + 508 + - - - - + + + + + + - - - - + + + + + + + + - - - Configuration + + + General Config - - - 0 - - - - - true - - - - - 0 - 0 - 354 - 404 - - - - - 0 - - - - - - - - - - - - - - - - Advanced Config - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Load Platform Defaults + + + + - + + + + + Configuration + + + + 0 + + + + + true + + + + + 0 + 0 + 314 + 434 + + + + + 0 + + + + + + + + + + + + + + + Configuration + + + + 0 + + + + + true + + + + + 0 + 0 + 313 + 434 + + + + + 0 + + + + + + + + + + + + + + + + - + - Load Platform Defaults + Advanced Config - - - - - - - Configuration - - - - 0 - - - - - true - - - - - 0 - 0 - 354 - 404 - - - - - 0 - - - - - - - - - - + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Load Platform Defaults + + + + - - - Configuration - - - - 0 - - - - - true + + + + + Configuration + + + + 0 - - - - 0 - 0 - 354 - 404 - - - - - 0 + + + + true - - - - - - - - - + + + + 0 + 0 + 161 + 446 + + + + + 0 + + + + + + + + + + + + + + + Configuration + + + + 0 + + + + + true + + + + + 0 + 0 + 160 + 446 + + + + + 0 + + + + + + + + + + + + + + + + + + + + + No pending changes + + + + + + + Store to EEPROM + + - - + + + + + + + Qt::Horizontal + + + + 40 + 20 + + +