Commit c5e1a67a authored by lm's avatar lm

Merged, improved UI when MAVs time out

parents 319623e5 3989ad94
...@@ -11,7 +11,7 @@ QT += network \ ...@@ -11,7 +11,7 @@ QT += network \
TEMPLATE = app TEMPLATE = app
TARGET = tst_uasunittest TARGET = qgcunittest
BASEDIR = $$IN_PWD BASEDIR = $$IN_PWD
TESTDIR = $$BASEDIR/qgcunittest TESTDIR = $$BASEDIR/qgcunittest
...@@ -97,8 +97,7 @@ INCLUDEPATH += . \ ...@@ -97,8 +97,7 @@ INCLUDEPATH += . \
$$BASEDIR/src/ui/ \ $$BASEDIR/src/ui/ \
SOURCES += $$TESTDIR/tst_uasunittest.cc \ SOURCES += src/uas/UAS.cc \
src/uas/UAS.cc \
src/comm/MAVLinkProtocol.cc \ src/comm/MAVLinkProtocol.cc \
src/uas/UASWaypointManager.cc \ src/uas/UASWaypointManager.cc \
src/Waypoint.cc \ src/Waypoint.cc \
...@@ -111,6 +110,10 @@ SOURCES += $$TESTDIR/tst_uasunittest.cc \ ...@@ -111,6 +110,10 @@ SOURCES += $$TESTDIR/tst_uasunittest.cc \
src/comm/LinkManager.cc \ src/comm/LinkManager.cc \
src/QGC.cc \ src/QGC.cc \
src/comm/SerialLink.cc \ src/comm/SerialLink.cc \
$$TESTDIR/SlugsMavUnitTest.cc \
$$TESTDIR/testSuite.cc \
$$TESTDIR/UASUnitTest.cc
HEADERS += src/uas/UASInterface.h \ HEADERS += src/uas/UASInterface.h \
src/uas/UAS.h \ src/uas/UAS.h \
...@@ -129,6 +132,9 @@ HEADERS += src/uas/UASInterface.h \ ...@@ -129,6 +132,9 @@ HEADERS += src/uas/UASInterface.h \
src/QGC.h \ src/QGC.h \
src/comm/SerialLinkInterface.h \ src/comm/SerialLinkInterface.h \
src/comm/SerialLink.h \ src/comm/SerialLink.h \
$$TESTDIR//SlugsMavUnitTest.h \
$$TESTDIR/AutoTest.h \
$$TESTDIR/UASUnitTest.h
......
/**
* @author Rob Caldecott
* @note This was obtained from http://qtcreator.blogspot.com/2010/04/sample-multiple-unit-test-project.html
*
*/
#ifndef AUTOTEST_H
#define AUTOTEST_H
#include <QTest>
#include <QList>
#include <QString>
#include <QSharedPointer>
namespace AutoTest
{
typedef QList<QObject*> TestList;
inline TestList& testList()
{
static TestList list;
return list;
}
inline bool findObject(QObject* object)
{
TestList& list = testList();
if (list.contains(object))
{
return true;
}
foreach (QObject* test, list)
{
if (test->objectName() == object->objectName())
{
return true;
}
}
return false;
}
inline void addTest(QObject* object)
{
TestList& list = testList();
if (!findObject(object))
{
list.append(object);
}
}
inline int run(int argc, char *argv[])
{
int ret = 0;
foreach (QObject* test, testList())
{
ret += QTest::qExec(test, argc, argv);
}
return ret;
}
}
template <class T>
class Test
{
public:
QSharedPointer<T> child;
Test(const QString& name) : child(new T)
{
child->setObjectName(name);
AutoTest::addTest(child.data());
}
};
#define DECLARE_TEST(className) static Test<className> t(#className);
#define TEST_MAIN \
int main(int argc, char *argv[]) \
{ \
return AutoTest::run(argc, argv); \
}
#endif // AUTOTEST_H
#include "SlugsMavUnitTest.h"
SlugsMavUnitTest::SlugsMavUnitTest()
{
}
void SlugsMavUnitTest::initTestCase()
{
}
void SlugsMavUnitTest::cleanupTestCase()
{
}
void SlugsMavUnitTest::first_test()
{
QCOMPARE(1,2);
}
#ifndef SLUGSMAVUNITTEST_H
#define SLUGSMAVUNITTEST_H
#include <QObject>
#include <QtCore/QString>
#include <QtTest/QtTest>
#include "UAS.h"
#include "MAVLinkProtocol.h"
#include "UASInterface.h"
#include "AutoTest.h"
class SlugsMavUnitTest : public QObject
{
Q_OBJECT
public:
SlugsMavUnitTest();
signals:
private slots:
void initTestCase();
void cleanupTestCase();
void first_test();
};
DECLARE_TEST(SlugsMavUnitTest)
#endif // SLUGSMAVUNITTEST_H
#include "UASUnitTest.h"
UASUnitTest::UASUnitTest()
{
}
void UASUnitTest::initTestCase()
{
mav= new MAVLinkProtocol();
uas=new UAS(mav,UASID);
}
void UASUnitTest::cleanupTestCase()
{
delete uas;
delete mav;
}
void UASUnitTest::getUASID_test()
{
// Test a default ID of zero is assigned
UAS* uas2 = new UAS(mav);
QCOMPARE(uas2->getUASID(), 0);
delete uas2;
// Test that the chosen ID was assigned at construction
QCOMPARE(uas->getUASID(), UASID);
// Make sure that no other ID was sert
QEXPECT_FAIL("", "When you set an ID it does not use the default ID of 0", Continue);
QCOMPARE(uas->getUASID(), 0);
}
void UASUnitTest::getUASName_test()
{
// Test that the name is build as MAV + ID
QCOMPARE(uas->getUASName(), "MAV 0" + QString::number(UASID));
}
void UASUnitTest::getUpTime_test()
{
UAS* uas2 = new UAS(mav);
// Test that the uptime starts at zero to a
// precision of seconds
QCOMPARE(floor(uas2->getUptime()/1000.0), 0.0);
// Sleep for three seconds
QTest::qSleep(3000);
// Test that the up time is computed correctly to a
// precision of seconds
QCOMPARE(floor(uas2->getUptime()/1000.0), 3.0);
delete uas2;
}
void UASUnitTest::getCommunicationStatus_test()
{
// Verify that upon construction the Comm status is disconnected
QCOMPARE(uas->getCommunicationStatus(), static_cast<int>(UASInterface::COMM_DISCONNECTED));
}
void UASUnitTest::filterVoltage_test()
{
float verificar=uas->filterVoltage(0.4f);
// Verify that upon construction the Comm status is disconnected
QCOMPARE(verificar, 8.52f);
}
void UASUnitTest:: getAutopilotType_test()
{
int verificar=uas->getAutopilotType();
// Verify that upon construction the autopilot is set to -1
QCOMPARE(verificar, -1);
}
void UASUnitTest::setAutopilotType_test()
{
uas->setAutopilotType(2);
// Verify that the autopilot is set
QCOMPARE(uas->getAutopilotType(), 2);
}
void UASUnitTest::getStatusForCode_test()
{
QString state, desc;
state = "";
desc = "";
uas->getStatusForCode(MAV_STATE_UNINIT, state, desc);
QVERIFY(state == "UNINIT");
uas->getStatusForCode(MAV_STATE_UNINIT, state, desc);
QVERIFY(state == "UNINIT");
uas->getStatusForCode(MAV_STATE_BOOT, state, desc);
QVERIFY(state == "BOOT");
uas->getStatusForCode(MAV_STATE_CALIBRATING, state, desc);
QVERIFY(state == "CALIBRATING");
uas->getStatusForCode(MAV_STATE_ACTIVE, state, desc);
QVERIFY(state == "ACTIVE");
uas->getStatusForCode(MAV_STATE_STANDBY, state, desc);
QVERIFY(state == "STANDBY");
uas->getStatusForCode(MAV_STATE_CRITICAL, state, desc);
QVERIFY(state == "CRITICAL");
uas->getStatusForCode(MAV_STATE_EMERGENCY, state, desc);
QVERIFY(state == "EMERGENCY");
uas->getStatusForCode(MAV_STATE_POWEROFF, state, desc);
QVERIFY(state == "SHUTDOWN");
uas->getStatusForCode(5325, state, desc);
QVERIFY(state == "UNKNOWN");
}
void UASUnitTest::getLocalX_test()
{
QCOMPARE(uas->getLocalX(), 0.0);
}
void UASUnitTest::getLocalY_test()
{
QCOMPARE(uas->getLocalY(), 0.0);
}
void UASUnitTest::getLocalZ_test()
{
QCOMPARE(uas->getLocalZ(), 0.0);
}
void UASUnitTest::getLatitude_test()
{ QCOMPARE(uas->getLatitude(), 0.0);
}
void UASUnitTest::getLongitude_test()
{
QCOMPARE(uas->getLongitude(), 0.0);
}
void UASUnitTest::getAltitude_test()
{
QCOMPARE(uas->getAltitude(), 0.0);
}
void UASUnitTest::getRoll_test()
{
QCOMPARE(uas->getRoll(), 0.0);
}
void UASUnitTest::getPitch_test()
{
QCOMPARE(uas->getPitch(), 0.0);
}
void UASUnitTest::getYaw_test()
{
QCOMPARE(uas->getYaw(), 0.0);
}
#ifndef UASUNITTEST_H
#define UASUNITTEST_H
#include <QObject>
#include <QtCore/QString>
#include <QtTest/QtTest>
#include "UAS.h"
#include "MAVLinkProtocol.h"
#include "UASInterface.h"
#include "AutoTest.h"
class UASUnitTest : public QObject
{
Q_OBJECT
public:
#define UASID 50
MAVLinkProtocol* mav;
UAS* uas;
UASUnitTest();
signals:
private slots:
void initTestCase();
void cleanupTestCase();
void getUASID_test();
void getUASName_test();
void getUpTime_test();
void getCommunicationStatus_test();
void filterVoltage_test();
void getAutopilotType_test();
void setAutopilotType_test();
void getStatusForCode_test();
void getLocalX_test();
void getLocalY_test();
void getLocalZ_test();
void getLatitude_test();
void getLongitude_test();
void getAltitude_test();
void getRoll_test();
void getPitch_test();
void getYaw_test();
protected:
UAS *prueba;
};
DECLARE_TEST(UASUnitTest)
#endif // UASUNITTEST_H
/**
* @author Rob Caldecott
* @note This was obtained from http://qtcreator.blogspot.com/2010/04/sample-multiple-unit-test-project.html
*
*/
#include "AutoTest.h"
#include <QDebug>
#if 1
// This is all you need to run all the tests
TEST_MAIN
#else
// Or supply your own main function
int main(int argc, char *argv[])
{
int failures = AutoTest::run(argc, argv);
if (failures == 0)
{
qDebug() << "ALL TESTS PASSED";
}
else
{
qDebug() << failures << " TESTS FAILED!";
}
return failures;
}
#endif
...@@ -41,7 +41,7 @@ This file is part of the PIXHAWK project ...@@ -41,7 +41,7 @@ This file is part of the PIXHAWK project
namespace MG namespace MG
{ {
const static int MAX_FLIGHT_TIME = 60 * 60 * 24 * 365 * 2; const static int MAX_FLIGHT_TIME = 60 * 60 * 24 * 21;
class VERSION class VERSION
{ {
......
...@@ -20,7 +20,7 @@ namespace QGC ...@@ -20,7 +20,7 @@ namespace QGC
quint64 groundTimeUsecs(); quint64 groundTimeUsecs();
int applicationVersion(); int applicationVersion();
const static int MAX_FLIGHT_TIME = 60 * 60 * 24 * 21;
class SLEEP : public QThread class SLEEP : public QThread
{ {
......
...@@ -46,7 +46,6 @@ public slots: ...@@ -46,7 +46,6 @@ public slots:
mavlink_pwm_commands_t* getPwmCommands(); mavlink_pwm_commands_t* getPwmCommands();
#endif #endif
signals: signals:
void slugsRawImu(int uasId, const mavlink_raw_imu_t& rawData); void slugsRawImu(int uasId, const mavlink_raw_imu_t& rawData);
......
...@@ -84,8 +84,8 @@ paramsOnceRequested(false) ...@@ -84,8 +84,8 @@ paramsOnceRequested(false)
{ {
color = UASInterface::getNextColor(); color = UASInterface::getNextColor();
setBattery(LIPOLY, 3); setBattery(LIPOLY, 3);
statusTimeout->setInterval(500);
connect(statusTimeout, SIGNAL(timeout()), this, SLOT(updateState())); connect(statusTimeout, SIGNAL(timeout()), this, SLOT(updateState()));
statusTimeout->start(500);
} }
UAS::~UAS() UAS::~UAS()
...@@ -101,6 +101,14 @@ int UAS::getUASID() const ...@@ -101,6 +101,14 @@ int UAS::getUASID() const
void UAS::updateState() void UAS::updateState()
{ {
// Check if heartbeat timed out
quint64 heartbeatInterval = QGC::groundTimeUsecs() - lastHeartbeat;
if (heartbeatInterval > timeoutIntervalHeartbeat)
{
emit heartbeatTimeout(heartbeatInterval);
emit heartbeatTimeout();
}
// Position lock is set by the MAVLink message handler // Position lock is set by the MAVLink message handler
// if no position lock is available, indicate an error // if no position lock is available, indicate an error
if (positionLock) if (positionLock)
...@@ -144,6 +152,7 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message) ...@@ -144,6 +152,7 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
switch (message.msgid) switch (message.msgid)
{ {
case MAVLINK_MSG_ID_HEARTBEAT: case MAVLINK_MSG_ID_HEARTBEAT:
lastHeartbeat = QGC::groundTimeUsecs();
emit heartbeat(this); emit heartbeat(this);
// Set new type if it has changed // Set new type if it has changed
if (this->type != mavlink_msg_heartbeat_get_type(&message)) if (this->type != mavlink_msg_heartbeat_get_type(&message))
...@@ -1317,6 +1326,12 @@ void UAS::setParameter(const int component, const QString& id, const float value ...@@ -1317,6 +1326,12 @@ void UAS::setParameter(const int component, const QString& id, const float value
} }
} }
void UAS::setUASName(const QString& name)
{
this->name = name;
emit nameChanged(name);
}
/** /**
* Sets an action * Sets an action
* *
......
...@@ -152,6 +152,7 @@ protected: //COMMENTS FOR TEST UNIT ...@@ -152,6 +152,7 @@ protected: //COMMENTS FOR TEST UNIT
double roll; double roll;
double pitch; double pitch;
double yaw; double yaw;
quint64 lastHeartbeat; ///< Time of the last heartbeat message
QTimer* statusTimeout; ///< Timer for various status timeouts QTimer* statusTimeout; ///< Timer for various status timeouts
QMap<int, QMap<QString, float>* > parameters; ///< All parameters QMap<int, QMap<QString, float>* > parameters; ///< All parameters
bool paramsOnceRequested; ///< If the parameter list has been read at least once bool paramsOnceRequested; ///< If the parameter list has been read at least once
...@@ -174,7 +175,10 @@ public: ...@@ -174,7 +175,10 @@ public:
void setAutopilotType(int apType) { autopilot = apType;} void setAutopilotType(int apType) { autopilot = apType;}
public slots: public slots:
/** @brief Sets an action **/
/** @brief Set a new name **/
void setUASName(const QString& name);
/** @brief Executes an action **/
void setAction(MAV_ACTION action); void setAction(MAV_ACTION action);
/** @brief Launches the system **/ /** @brief Launches the system **/
......
...@@ -92,7 +92,8 @@ public: ...@@ -92,7 +92,8 @@ public:
COMM_CONNECTED = 2, COMM_CONNECTED = 2,
/** The connection is closed **/ /** The connection is closed **/
COMM_DISCONNECTING = 3, COMM_DISCONNECTING = 3,
COMM_FAIL = 4, ///< Communication link failed COMM_FAIL = 4,
COMM_TIMEDOUT = 5///< Communication link failed
}; };
...@@ -162,6 +163,8 @@ public: ...@@ -162,6 +163,8 @@ public:
public slots: public slots:
/** @brief Set a new name for the system */
virtual void setUASName(const QString& name) = 0;
/** @brief Sets an action **/ /** @brief Sets an action **/
virtual void setAction(MAV_ACTION action) = 0; virtual void setAction(MAV_ACTION action) = 0;
...@@ -409,9 +412,18 @@ signals: ...@@ -409,9 +412,18 @@ signals:
*/ */
void irUltraSoundLocalizationChanged(UASInterface* uas, int fix); void irUltraSoundLocalizationChanged(UASInterface* uas, int fix);
// ERROR AND STATUS SIGNALS
/** @brief Heartbeat timed out */
void heartbeatTimeout();
/** @brief Heartbeat timed out */
void heartbeatTimeout(unsigned int ms);
/** @brief Name of system changed */
void nameChanged(QString newName);
protected:
// TIMEOUT CONSTANTS
static const unsigned int timeoutIntervalHeartbeat = 2000 * 1000; ///< Heartbeat timeout is 1.5 seconds
}; };
......
...@@ -58,7 +58,7 @@ UASManager* UASManager::instance() ...@@ -58,7 +58,7 @@ UASManager* UASManager::instance()
UASManager::UASManager() : UASManager::UASManager() :
activeUAS(NULL) activeUAS(NULL)
{ {
systems = QMap<int, UASInterface*>(); systems = QList<UASInterface*>();
start(QThread::LowPriority); start(QThread::LowPriority);
} }
...@@ -90,9 +90,9 @@ void UASManager::addUAS(UASInterface* uas) ...@@ -90,9 +90,9 @@ void UASManager::addUAS(UASInterface* uas)
} }
// Only execute if there is no UAS at this index // Only execute if there is no UAS at this index
if (!systems.contains(uas->getUASID())) if (!systems.contains(uas))
{ {
systems.insert(uas->getUASID(), uas); systems.append(uas);
emit UASCreated(uas); emit UASCreated(uas);
} }
...@@ -105,7 +105,7 @@ void UASManager::addUAS(UASInterface* uas) ...@@ -105,7 +105,7 @@ void UASManager::addUAS(UASInterface* uas)
QList<UASInterface*> UASManager::getUASList() QList<UASInterface*> UASManager::getUASList()
{ {
return systems.values(); return systems;
} }
UASInterface* UASManager::getActiveUAS() UASInterface* UASManager::getActiveUAS()
...@@ -176,8 +176,18 @@ void UASManager::configureActiveUAS() ...@@ -176,8 +176,18 @@ void UASManager::configureActiveUAS()
UASInterface* UASManager::getUASForId(int id) UASInterface* UASManager::getUASForId(int id)
{ {
// Return NULL pointer if UAS does not exist UASInterface* system = NULL;
return systems.value(id, NULL);
foreach(UASInterface* sys, systems)
{
if (sys->getUASID() == id)
{
system = sys;
}
}
// Return NULL if not found
return system;
} }
void UASManager::setActiveUAS(UASInterface* uas) void UASManager::setActiveUAS(UASInterface* uas)
...@@ -195,6 +205,7 @@ void UASManager::setActiveUAS(UASInterface* uas) ...@@ -195,6 +205,7 @@ void UASManager::setActiveUAS(UASInterface* uas)
emit activeUASSet(uas); emit activeUASSet(uas);
emit activeUASSet(uas->getUASID()); emit activeUASSet(uas->getUASID());
emit activeUASSetListIndex(systems.indexOf(uas));
emit activeUASStatusChanged(uas, true); emit activeUASStatusChanged(uas, true);
emit activeUASStatusChanged(uas->getUASID(), true); emit activeUASStatusChanged(uas->getUASID(), true);
} }
......
...@@ -162,7 +162,7 @@ public slots: ...@@ -162,7 +162,7 @@ public slots:
protected: protected:
UASManager(); UASManager();
QMap<int, UASInterface*> systems; QList<UASInterface*> systems;
UASInterface* activeUAS; UASInterface* activeUAS;
QMutex activeUASMutex; QMutex activeUASMutex;
...@@ -173,6 +173,8 @@ signals: ...@@ -173,6 +173,8 @@ signals:
/** @brief The UAS currently under main operator control changed */ /** @brief The UAS currently under main operator control changed */
void activeUASSet(int systemId); void activeUASSet(int systemId);
/** @brief The UAS currently under main operator control changed */ /** @brief The UAS currently under main operator control changed */
void activeUASSetListIndex(int listIndex);
/** @brief The UAS currently under main operator control changed */
void activeUASStatusChanged(UASInterface* UAS, bool active); void activeUASStatusChanged(UASInterface* UAS, bool active);
/** @brief The UAS currently under main operator control changed */ /** @brief The UAS currently under main operator control changed */
void activeUASStatusChanged(int systemId, bool active); void activeUASStatusChanged(int systemId, bool active);
......
...@@ -436,10 +436,10 @@ void MainWindow::buildPxWidgets() ...@@ -436,10 +436,10 @@ void MainWindow::buildPxWidgets()
if (!parametersDockWidget) if (!parametersDockWidget)
{ {
parametersDockWidget = new QDockWidget(tr("Onboard Parameters"), this); parametersDockWidget = new QDockWidget(tr("Calibration and Onboard Parameters"), this);
parametersDockWidget->setWidget( new ParameterInterface(this) ); parametersDockWidget->setWidget( new ParameterInterface(this) );
parametersDockWidget->setObjectName("PARAMETER_INTERFACE_DOCKWIDGET"); parametersDockWidget->setObjectName("PARAMETER_INTERFACE_DOCKWIDGET");
addToToolsMenu (parametersDockWidget, tr("Onboard Parameters"), SLOT(showToolWidget()), MENU_PARAMETERS, Qt::RightDockWidgetArea); addToToolsMenu (parametersDockWidget, tr("Calibration and Parameters"), SLOT(showToolWidget()), MENU_PARAMETERS, Qt::RightDockWidgetArea);
} }
if (!watchdogControlDockWidget) if (!watchdogControlDockWidget)
...@@ -1099,7 +1099,7 @@ void MainWindow::showStatusMessage(const QString& status) ...@@ -1099,7 +1099,7 @@ void MainWindow::showStatusMessage(const QString& status)
void MainWindow::showCriticalMessage(const QString& title, const QString& message) void MainWindow::showCriticalMessage(const QString& title, const QString& message)
{ {
QMessageBox msgBox(MainWindow::instance()); QMessageBox msgBox(this);
msgBox.setIcon(QMessageBox::Critical); msgBox.setIcon(QMessageBox::Critical);
msgBox.setText(title); msgBox.setText(title);
msgBox.setInformativeText(message); msgBox.setInformativeText(message);
...@@ -1110,7 +1110,7 @@ void MainWindow::showCriticalMessage(const QString& title, const QString& messag ...@@ -1110,7 +1110,7 @@ void MainWindow::showCriticalMessage(const QString& title, const QString& messag
void MainWindow::showInfoMessage(const QString& title, const QString& message) void MainWindow::showInfoMessage(const QString& title, const QString& message)
{ {
QMessageBox msgBox(MainWindow::instance()); QMessageBox msgBox(this);
msgBox.setIcon(QMessageBox::Information); msgBox.setIcon(QMessageBox::Information);
msgBox.setText(title); msgBox.setText(title);
msgBox.setInformativeText(message); msgBox.setInformativeText(message);
...@@ -1152,6 +1152,9 @@ void MainWindow::connectCommonActions() ...@@ -1152,6 +1152,9 @@ void MainWindow::connectCommonActions()
connect(ui.actionOnline_Documentation, SIGNAL(triggered()), this, SLOT(showHelp())); connect(ui.actionOnline_Documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
connect(ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits())); connect(ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits()));
connect(ui.actionProject_Roadmap_2, SIGNAL(triggered()), this, SLOT(showRoadMap())); connect(ui.actionProject_Roadmap_2, SIGNAL(triggered()), this, SLOT(showRoadMap()));
// Custom widget actions
connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(createCustomWidget()));
} }
void MainWindow::connectPxActions() void MainWindow::connectPxActions()
......
...@@ -46,10 +46,10 @@ ParameterInterface::ParameterInterface(QWidget *parent) : ...@@ -46,10 +46,10 @@ ParameterInterface::ParameterInterface(QWidget *parent) :
m_ui->setupUi(this); m_ui->setupUi(this);
// Make sure the combo box is empty // Make sure the combo box is empty
// because else indices get messed up // because else indices get messed up
m_ui->vehicleComboBox->clear(); //m_ui->vehicleComboBox->clear();
// Setup UI connections // Setup UI connections
connect(m_ui->vehicleComboBox, SIGNAL(activated(int)), this, SLOT(selectUAS(int))); //connect(m_ui->vehicleComboBox, SIGNAL(activated(int)), this, SLOT(selectUAS(int)));
// Get current MAV list // Get current MAV list
QList<UASInterface*> systems = UASManager::instance()->getUASList(); QList<UASInterface*> systems = UASManager::instance()->getUASList();
...@@ -62,6 +62,7 @@ ParameterInterface::ParameterInterface(QWidget *parent) : ...@@ -62,6 +62,7 @@ ParameterInterface::ParameterInterface(QWidget *parent) :
// Setup MAV connections // Setup MAV connections
connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), this, SLOT(addUAS(UASInterface*))); connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), this, SLOT(addUAS(UASInterface*)));
connect(UASManager::instance(), SIGNAL(activeUASSetListIndex(int)), this, SLOT(selectUAS(int)));
this->setVisible(false); this->setVisible(false);
} }
...@@ -72,9 +73,8 @@ ParameterInterface::~ParameterInterface() ...@@ -72,9 +73,8 @@ ParameterInterface::~ParameterInterface()
void ParameterInterface::selectUAS(int index) void ParameterInterface::selectUAS(int index)
{ {
// FIXME plus 2 shouldn't be there m_ui->stackedWidget->setCurrentIndex(index);
m_ui->stackedWidget->setCurrentIndex(index+2); m_ui->sensorSettings->setCurrentIndex(index);
m_ui->sensorSettings->setCurrentIndex(index+2);
curr = index; curr = index;
} }
...@@ -84,7 +84,7 @@ void ParameterInterface::selectUAS(int index) ...@@ -84,7 +84,7 @@ void ParameterInterface::selectUAS(int index)
*/ */
void ParameterInterface::addUAS(UASInterface* uas) void ParameterInterface::addUAS(UASInterface* uas)
{ {
m_ui->vehicleComboBox->addItem(uas->getUASName()); //m_ui->vehicleComboBox->addItem(uas->getUASName());
QGCParamWidget* param = new QGCParamWidget(uas, this); QGCParamWidget* param = new QGCParamWidget(uas, this);
paramWidgets->insert(uas->getUASID(), param); paramWidgets->insert(uas->getUASID(), param);
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout" rowstretch="2,10,5"> <layout class="QGridLayout" name="gridLayout" rowstretch="2,0">
<property name="horizontalSpacing"> <property name="horizontalSpacing">
<number>5</number> <number>5</number>
</property> </property>
...@@ -23,17 +23,7 @@ ...@@ -23,17 +23,7 @@
<property name="margin"> <property name="margin">
<number>6</number> <number>6</number>
</property> </property>
<item row="0" column="0"> <item row="0" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>Vehicle</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="vehicleComboBox"/>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_2"> <widget class="QGroupBox" name="groupBox_2">
<property name="title"> <property name="title">
<string>Onboard Parameters</string> <string>Onboard Parameters</string>
...@@ -45,26 +35,18 @@ ...@@ -45,26 +35,18 @@
<item> <item>
<widget class="QStackedWidget" name="stackedWidget"> <widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>-1</number>
</property> </property>
<widget class="QWidget" name="page">
<layout class="QVBoxLayout" name="verticalLayout"/>
</widget>
<widget class="QWidget" name="page_2"/>
</widget> </widget>
</item> </item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="2" column="0" colspan="2"> <item row="1" column="0" colspan="2">
<widget class="QStackedWidget" name="sensorSettings"> <widget class="QStackedWidget" name="sensorSettings">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>-1</number>
</property> </property>
<widget class="QWidget" name="page_3">
<layout class="QVBoxLayout" name="verticalLayout_2"/>
</widget>
<widget class="QWidget" name="page_4"/>
</widget> </widget>
</item> </item>
</layout> </layout>
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>222</width> <width>200</width>
<height>172</height> <height>150</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
...@@ -18,8 +18,8 @@ ...@@ -18,8 +18,8 @@
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>222</width> <width>200</width>
<height>172</height> <height>150</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
...@@ -34,8 +34,14 @@ ...@@ -34,8 +34,14 @@
<property name="toolTip"> <property name="toolTip">
<string>Control widget to send basic control actions to the micro air vehicle</string> <string>Control widget to send basic control actions to the micro air vehicle</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout" rowstretch="60,150,80,80,80,100" columnstretch="1,100,40,40,100,1" rowminimumheight="0,0,0,0,0,0"> <layout class="QGridLayout" name="gridLayout" rowstretch="5,1,40,1,40,40,40" columnstretch="5,20,20,25,5">
<item row="0" column="0" rowspan="6"> <property name="margin">
<number>4</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="0" rowspan="7">
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
...@@ -48,12 +54,12 @@ ...@@ -48,12 +54,12 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="0" column="1" colspan="4"> <item row="0" column="1" rowspan="2" colspan="3">
<widget class="QLabel" name="controlStatusLabel"> <widget class="QLabel" name="controlStatusLabel">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>0</width> <width>0</width>
<height>0</height> <height>10</height>
</size> </size>
</property> </property>
<property name="text"> <property name="text">
...@@ -67,140 +73,143 @@ ...@@ -67,140 +73,143 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="5" rowspan="6"> <item row="3" column="1" colspan="3">
<spacer name="horizontalSpacer_2"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Vertical</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>30</width> <width>216</width>
<height>159</height> <height>17</height>
</size> </size>
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="1" column="1" colspan="4"> <item row="4" column="1" colspan="3">
<widget class="QPushButton" name="controlButton"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="minimumSize"> <property name="spacing">
<size> <number>6</number>
<width>0</width> </property>
<height>12</height> <item>
</size> <widget class="QPushButton" name="liftoffButton">
</property> <property name="minimumSize">
<property name="text"> <size>
<string>Activate Engine</string> <width>25</width>
</property> <height>16</height>
</widget> </size>
</property>
<property name="text">
<string>Start</string>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/control/launch.svg</normaloff>:/images/control/launch.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="landButton">
<property name="minimumSize">
<size>
<width>25</width>
<height>16</height>
</size>
</property>
<property name="text">
<string>Land</string>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/control/land.svg</normaloff>:/images/control/land.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="shutdownButton">
<property name="minimumSize">
<size>
<width>25</width>
<height>16</height>
</size>
</property>
<property name="text">
<string>Halt</string>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/actions/system-log-out.svg</normaloff>:/images/actions/system-log-out.svg</iconset>
</property>
</widget>
</item>
</layout>
</item> </item>
<item row="2" column="1"> <item row="5" column="1" colspan="2">
<widget class="QPushButton" name="liftoffButton"> <widget class="QComboBox" name="modeComboBox">
<property name="minimumSize">
<size>
<width>40</width>
<height>12</height>
</size>
</property>
<property name="text">
<string>Start</string>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/control/launch.svg</normaloff>:/images/control/launch.svg</iconset>
</property>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QPushButton" name="landButton">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>40</width> <width>25</width>
<height>12</height> <height>16</height>
</size> </size>
</property> </property>
<property name="text">
<string>Land</string>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/control/land.svg</normaloff>:/images/control/land.svg</iconset>
</property>
</widget> </widget>
</item> </item>
<item row="2" column="4"> <item row="5" column="3">
<widget class="QPushButton" name="shutdownButton"> <widget class="QPushButton" name="setModeButton">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>40</width> <width>25</width>
<height>12</height> <height>16</height>
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>Halt</string> <string>Set</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../../mavground.qrc"> <iconset resource="../../mavground.qrc">
<normaloff>:/images/actions/system-log-out.svg</normaloff>:/images/actions/system-log-out.svg</iconset> <normaloff>:/images/devices/network-wireless.svg</normaloff>:/images/devices/network-wireless.svg</iconset>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1" colspan="2"> <item row="6" column="1" colspan="3">
<widget class="QComboBox" name="modeComboBox"> <widget class="QLabel" name="lastActionLabel">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>0</width> <width>0</width>
<height>12</height> <height>10</height>
</size>
</property>
</widget>
</item>
<item row="3" column="3" colspan="2">
<widget class="QPushButton" name="setModeButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>12</height>
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>Set Mode</string> <string>No actions executed so far</string>
</property> </property>
<property name="icon"> <property name="alignment">
<iconset resource="../../mavground.qrc"> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
<normaloff>:/images/devices/network-wireless.svg</normaloff>:/images/devices/network-wireless.svg</iconset>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="3" colspan="2"> <item row="1" column="4" rowspan="6">
<widget class="QPushButton" name="setHomeButton"> <spacer name="horizontalSpacer_2">
<property name="minimumSize"> <property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size> <size>
<width>40</width> <width>30</width>
<height>16</height> <height>159</height>
</size> </size>
</property> </property>
<property name="text"> </spacer>
<string>Set Origin</string>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/actions/go-home.svg</normaloff>:/images/actions/go-home.svg</iconset>
</property>
</widget>
</item> </item>
<item row="5" column="1" colspan="4"> <item row="2" column="1" colspan="3">
<widget class="QLabel" name="lastActionLabel"> <widget class="QPushButton" name="controlButton">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>0</width> <width>0</width>
<height>12</height> <height>30</height>
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>No actions executed so far</string> <string>Activate Engine</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property> </property>
</widget> </widget>
</item> </item>
......
...@@ -35,8 +35,9 @@ void XMLCommProtocolWidget::selectXMLFile() ...@@ -35,8 +35,9 @@ void XMLCommProtocolWidget::selectXMLFile()
QSettings settings(QGC::COMPANYNAME, QGC::APPNAME); QSettings settings(QGC::COMPANYNAME, QGC::APPNAME);
const QString mavlinkXML = "MAVLINK_XML_FILE"; const QString mavlinkXML = "MAVLINK_XML_FILE";
QString dirPath = settings.value(mavlinkXML, QCoreApplication::applicationDirPath() + "../").toString(); QString dirPath = settings.value(mavlinkXML, QCoreApplication::applicationDirPath() + "../").toString();
QFileInfo dir(dirPath);
QFileDialog dialog; QFileDialog dialog;
dialog.setDirectory(dirPath); dialog.setDirectory(dir.absoluteDir());
dialog.setFileMode(QFileDialog::AnyFile); dialog.setFileMode(QFileDialog::AnyFile);
dialog.setFilter(tr("MAVLink XML (*.xml)")); dialog.setFilter(tr("MAVLink XML (*.xml)"));
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
...@@ -100,7 +101,6 @@ void XMLCommProtocolWidget::selectOutputDirectory() ...@@ -100,7 +101,6 @@ void XMLCommProtocolWidget::selectOutputDirectory()
QFileDialog dialog; QFileDialog dialog;
dialog.setDirectory(dirPath); dialog.setDirectory(dirPath);
dialog.setFileMode(QFileDialog::Directory); dialog.setFileMode(QFileDialog::Directory);
dialog.setFilter(tr("MAVLink XML (*.xml)"));
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
QStringList fileNames; QStringList fileNames;
if (dialog.exec()) if (dialog.exec())
......
...@@ -97,7 +97,7 @@ void UASControlWidget::setUAS(UASInterface* uas) ...@@ -97,7 +97,7 @@ void UASControlWidget::setUAS(UASInterface* uas)
disconnect(ui.liftoffButton, SIGNAL(clicked()), oldUAS, SLOT(launch())); disconnect(ui.liftoffButton, SIGNAL(clicked()), oldUAS, SLOT(launch()));
disconnect(ui.landButton, SIGNAL(clicked()), oldUAS, SLOT(home())); disconnect(ui.landButton, SIGNAL(clicked()), oldUAS, SLOT(home()));
disconnect(ui.shutdownButton, SIGNAL(clicked()), oldUAS, SLOT(shutdown())); disconnect(ui.shutdownButton, SIGNAL(clicked()), oldUAS, SLOT(shutdown()));
connect(ui.setHomeButton, SIGNAL(clicked()), uas, SLOT(setLocalOriginAtCurrentGPSPosition())); //connect(ui.setHomeButton, SIGNAL(clicked()), uas, SLOT(setLocalOriginAtCurrentGPSPosition()));
disconnect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString))); disconnect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString)));
disconnect(uas, SIGNAL(statusChanged(int)), this, SLOT(updateState(int))); disconnect(uas, SIGNAL(statusChanged(int)), this, SLOT(updateState(int)));
} }
...@@ -107,28 +107,28 @@ void UASControlWidget::setUAS(UASInterface* uas) ...@@ -107,28 +107,28 @@ void UASControlWidget::setUAS(UASInterface* uas)
connect(ui.liftoffButton, SIGNAL(clicked()), uas, SLOT(launch())); connect(ui.liftoffButton, SIGNAL(clicked()), uas, SLOT(launch()));
connect(ui.landButton, SIGNAL(clicked()), uas, SLOT(home())); connect(ui.landButton, SIGNAL(clicked()), uas, SLOT(home()));
connect(ui.shutdownButton, SIGNAL(clicked()), uas, SLOT(shutdown())); connect(ui.shutdownButton, SIGNAL(clicked()), uas, SLOT(shutdown()));
connect(ui.setHomeButton, SIGNAL(clicked()), uas, SLOT(setLocalOriginAtCurrentGPSPosition())); //connect(ui.setHomeButton, SIGNAL(clicked()), uas, SLOT(setLocalOriginAtCurrentGPSPosition()));
connect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString))); connect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString)));
connect(uas, SIGNAL(statusChanged(int)), this, SLOT(updateState(int))); connect(uas, SIGNAL(statusChanged(int)), this, SLOT(updateState(int)));
ui.controlStatusLabel->setText(tr("Connected to ") + uas->getUASName()); ui.controlStatusLabel->setText(tr("Connected to ") + uas->getUASName());
// Check if additional controls should be loaded // // Check if additional controls should be loaded
UAS* mav = dynamic_cast<UAS*>(uas); // UAS* mav = dynamic_cast<UAS*>(uas);
if (mav) // if (mav)
{ // {
QPushButton* startRecButton = new QPushButton(tr("Record")); // QPushButton* startRecButton = new QPushButton(tr("Record"));
connect(startRecButton, SIGNAL(clicked()), mav, SLOT(startDataRecording())); // connect(startRecButton, SIGNAL(clicked()), mav, SLOT(startDataRecording()));
ui.gridLayout->addWidget(startRecButton, 7, 1); // ui.gridLayout->addWidget(startRecButton, 7, 1);
QPushButton* pauseRecButton = new QPushButton(tr("Pause")); // QPushButton* pauseRecButton = new QPushButton(tr("Pause"));
connect(pauseRecButton, SIGNAL(clicked()), mav, SLOT(pauseDataRecording())); // connect(pauseRecButton, SIGNAL(clicked()), mav, SLOT(pauseDataRecording()));
ui.gridLayout->addWidget(pauseRecButton, 7, 3); // ui.gridLayout->addWidget(pauseRecButton, 7, 3);
QPushButton* stopRecButton = new QPushButton(tr("Stop")); // QPushButton* stopRecButton = new QPushButton(tr("Stop"));
connect(stopRecButton, SIGNAL(clicked()), mav, SLOT(stopDataRecording())); // connect(stopRecButton, SIGNAL(clicked()), mav, SLOT(stopDataRecording()));
ui.gridLayout->addWidget(stopRecButton, 7, 4); // ui.gridLayout->addWidget(stopRecButton, 7, 4);
} // }
this->uas = uas->getUASID(); this->uas = uas->getUASID();
...@@ -140,6 +140,19 @@ UASControlWidget::~UASControlWidget() ...@@ -140,6 +140,19 @@ UASControlWidget::~UASControlWidget()
} }
void UASControlWidget::updateStatemachine()
{
if (engineOn)
{
ui.controlButton->setText(tr("Stop Engine"));
}
else
{
ui.controlButton->setText(tr("Activate Engine"));
}
}
/** /**
* Set the background color based on the MAV color. If the MAV is selected as the * Set the background color based on the MAV color. If the MAV is selected as the
* currently actively controlled system, the frame color is highlighted * currently actively controlled system, the frame color is highlighted
...@@ -258,16 +271,20 @@ void UASControlWidget::cycleContextButton() ...@@ -258,16 +271,20 @@ void UASControlWidget::cycleContextButton()
if (!engineOn) if (!engineOn)
{ {
ui.controlButton->setText(tr("Stop Engine"));
mav->enable_motors(); mav->enable_motors();
ui.lastActionLabel->setText(QString("Attempted to enable motors on %1").arg(mav->getUASName())); ui.lastActionLabel->setText(QString("Enabled motors on %1").arg(mav->getUASName()));
} }
else else
{ {
ui.controlButton->setText(tr("Activate Engine"));
mav->disable_motors(); mav->disable_motors();
ui.lastActionLabel->setText(QString("Attempted to disable motors on %1").arg(mav->getUASName())); ui.lastActionLabel->setText(QString("Disabled motors on %1").arg(mav->getUASName()));
} }
// Update state now and in several intervals when MAV might have changed state
updateStatemachine();
QTimer::singleShot(50, this, SLOT(updateStatemachine()));
QTimer::singleShot(200, this, SLOT(updateStatemachine()));
//ui.controlButton->setText(tr("Force Landing")); //ui.controlButton->setText(tr("Force Landing"));
//ui.controlButton->setText(tr("KILL VEHICLE")); //ui.controlButton->setText(tr("KILL VEHICLE"));
} }
......
...@@ -63,6 +63,8 @@ public slots: ...@@ -63,6 +63,8 @@ public slots:
void updateMode(int uas,QString mode,QString description); void updateMode(int uas,QString mode,QString description);
/** @brief Update state */ /** @brief Update state */
void updateState(int state); void updateState(int state);
/** @brief Update internal state machine */
void updateStatemachine();
protected slots: protected slots:
/** @brief Set the background color for the widget */ /** @brief Set the background color for the widget */
......
...@@ -32,6 +32,7 @@ This file is part of the PIXHAWK project ...@@ -32,6 +32,7 @@ This file is part of the PIXHAWK project
#include <QDateTime> #include <QDateTime>
#include <QDebug> #include <QDebug>
#include <QMenu> #include <QMenu>
#include <QInputDialog>
#include "QGC.h" #include "QGC.h"
#include "MG.h" #include "MG.h"
...@@ -43,7 +44,7 @@ This file is part of the PIXHAWK project ...@@ -43,7 +44,7 @@ This file is part of the PIXHAWK project
UASView::UASView(UASInterface* uas, QWidget *parent) : UASView::UASView(UASInterface* uas, QWidget *parent) :
QWidget(parent), QWidget(parent),
startTime(0), startTime(0),
lastHeartbeat(0), timeout(false),
iconIsRed(true), iconIsRed(true),
timeRemaining(0), timeRemaining(0),
chargeLevel(0), chargeLevel(0),
...@@ -63,7 +64,8 @@ UASView::UASView(UASInterface* uas, QWidget *parent) : ...@@ -63,7 +64,8 @@ UASView::UASView(UASInterface* uas, QWidget *parent) :
alt(0), alt(0),
groundDistance(0), groundDistance(0),
localFrame(false), localFrame(false),
removeAction(new QAction("Remove this system", this)), removeAction(new QAction("Delete this system", this)),
renameAction(new QAction("Rename..", this)),
m_ui(new Ui::UASView) m_ui(new Ui::UASView)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
...@@ -79,7 +81,7 @@ UASView::UASView(UASInterface* uas, QWidget *parent) : ...@@ -79,7 +81,7 @@ UASView::UASView(UASInterface* uas, QWidget *parent) :
connect(uas, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*,QString,QString))); connect(uas, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*,QString,QString)));
connect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString))); connect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString)));
connect(uas, SIGNAL(loadChanged(UASInterface*, double)), this, SLOT(updateLoad(UASInterface*, double))); connect(uas, SIGNAL(loadChanged(UASInterface*, double)), this, SLOT(updateLoad(UASInterface*, double)));
//connect(uas, SIGNAL(waypointUpdated(int,int,double,double,double,double,bool,bool)), this, SLOT(setWaypoint(int,int,double,double,double,double,bool,bool))); connect(uas, SIGNAL(heartbeatTimeout()), this, SLOT(heartbeatTimeout()));
connect(uas, SIGNAL(waypointSelected(int,int)), this, SLOT(selectWaypoint(int,int))); connect(uas, SIGNAL(waypointSelected(int,int)), this, SLOT(selectWaypoint(int,int)));
connect(&(uas->getWaypointManager()), SIGNAL(currentWaypointChanged(quint16)), this, SLOT(currentWaypointUpdated(quint16))); connect(&(uas->getWaypointManager()), SIGNAL(currentWaypointChanged(quint16)), this, SLOT(currentWaypointUpdated(quint16)));
connect(uas, SIGNAL(systemTypeSet(UASInterface*,uint)), this, SLOT(setSystemType(UASInterface*,uint))); connect(uas, SIGNAL(systemTypeSet(UASInterface*,uint)), this, SLOT(setSystemType(UASInterface*,uint)));
...@@ -99,7 +101,11 @@ UASView::UASView(UASInterface* uas, QWidget *parent) : ...@@ -99,7 +101,11 @@ UASView::UASView(UASInterface* uas, QWidget *parent) :
// Allow to delete this widget // Allow to delete this widget
connect(removeAction, SIGNAL(triggered()), this, SLOT(deleteLater())); connect(removeAction, SIGNAL(triggered()), this, SLOT(deleteLater()));
connect(renameAction, SIGNAL(triggered()), this, SLOT(rename()));
connect(uas, SIGNAL(systemRemoved()), this, SLOT(deleteLater())); connect(uas, SIGNAL(systemRemoved()), this, SLOT(deleteLater()));
// Name changes
connect(uas, SIGNAL(nameChanged(QString)), this, SLOT(updateName(QString)));
// Set static values // Set static values
...@@ -138,6 +144,11 @@ UASView::~UASView() ...@@ -138,6 +144,11 @@ UASView::~UASView()
delete m_ui; delete m_ui;
} }
void UASView::heartbeatTimeout()
{
timeout = true;
}
/** /**
* Set the background color based on the MAV color. If the MAV is selected as the * Set the background color based on the MAV color. If the MAV is selected as the
* currently actively controlled system, the frame color is highlighted * currently actively controlled system, the frame color is highlighted
...@@ -241,8 +252,13 @@ void UASView::receiveHeartbeat(UASInterface* uas) ...@@ -241,8 +252,13 @@ void UASView::receiveHeartbeat(UASInterface* uas)
heartbeatColor = QColor(20, 200, 20); heartbeatColor = QColor(20, 200, 20);
QString colorstyle("QGroupBox { border-radius: 5px; padding: 2px; margin: 2px; border: 0px; background-color: %1; }"); QString colorstyle("QGroupBox { border-radius: 5px; padding: 2px; margin: 2px; border: 0px; background-color: %1; }");
m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(heartbeatColor.name())); m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
lastHeartbeat = QGC::groundTimeUsecs(); if (timeout) setBackgroundColor();
//m_ui->heartbeatIcon->setAutoFillBackground(true); timeout = false;
}
void UASView::updateName(const QString& name)
{
if (uas) m_ui->nameLabel->setText(uas->getUASName());
} }
/** /**
...@@ -400,11 +416,25 @@ void UASView::updateLoad(UASInterface* uas, double load) ...@@ -400,11 +416,25 @@ void UASView::updateLoad(UASInterface* uas, double load)
void UASView::contextMenuEvent (QContextMenuEvent* event) void UASView::contextMenuEvent (QContextMenuEvent* event)
{ {
if (QGC::groundTimeUsecs() - lastHeartbeat > 1500000) QMenu menu(this);
menu.addAction(renameAction);
if (timeout)
{ {
QMenu menu(this);
menu.addAction(removeAction); menu.addAction(removeAction);
menu.exec(event->globalPos()); }
menu.exec(event->globalPos());
}
void UASView::rename()
{
if (uas)
{
bool ok;
QString newName = QInputDialog::getText(this, tr("Rename System %1").arg(uas->getUASName()),
tr("System Name:"), QLineEdit::Normal,
uas->getUASName(), &ok);
if (ok && !newName.isEmpty()) uas->setUASName(newName);
} }
} }
...@@ -480,7 +510,7 @@ void UASView::refresh() ...@@ -480,7 +510,7 @@ void UASView::refresh()
// Thrust // Thrust
m_ui->thrustBar->setValue(thrust * 100); m_ui->thrustBar->setValue(thrust * 100);
if(this->timeRemaining > 1 && this->timeRemaining < MG::MAX_FLIGHT_TIME) if(this->timeRemaining > 1 && this->timeRemaining < QGC::MAX_FLIGHT_TIME)
{ {
// Filter output to get a higher stability // Filter output to get a higher stability
static double filterTime = static_cast<int>(this->timeRemaining); static double filterTime = static_cast<int>(this->timeRemaining);
...@@ -513,41 +543,40 @@ void UASView::refresh() ...@@ -513,41 +543,40 @@ void UASView::refresh()
QString colorstyle("QGroupBox { border-radius: 5px; padding: 2px; margin: 2px; border: 0px; background-color: %1; }"); QString colorstyle("QGroupBox { border-radius: 5px; padding: 2px; margin: 2px; border: 0px; background-color: %1; }");
if (QGC::groundTimeUsecs() - lastHeartbeat > 1500000) if (timeout)
{ {
// CRITICAL CONDITION, NO HEARTBEAT // CRITICAL CONDITION, NO HEARTBEAT
QString borderColor = "#FFFF00";
if (isActive)
{
borderColor = "#FA4A4F";
}
if (iconIsRed) if (iconIsRed)
{ {
QColor warnColor(Qt::red); QColor warnColor(Qt::red);
m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(warnColor.name())); m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(warnColor.name()));
QString style = QString("QGroupBox { border-radius: 12px; padding: 0px; margin: 0px; background-color: %1; }").arg(warnColor.name()); QString style = QString("QGroupBox { border-radius: 12px; padding: 0px; margin: 0px; border: 2px solid %1; background-color: %2; }").arg(borderColor, warnColor.name());
m_ui->uasViewFrame->setStyleSheet(style); m_ui->uasViewFrame->setStyleSheet(style);
} }
else else
{ {
QColor warnColor(Qt::black); QColor warnColor(Qt::black);
m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(warnColor.name())); m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(warnColor.name()));
QString style = QString("QGroupBox { border-radius: 12px; padding: 0px; margin: 0px; background-color: %1; }").arg(warnColor.name()); QString style = QString("QGroupBox { border-radius: 12px; padding: 0px; margin: 0px; border: 2px solid %1; background-color: %2; }").arg(borderColor, warnColor.name());
m_ui->uasViewFrame->setStyleSheet(style); m_ui->uasViewFrame->setStyleSheet(style);
} }
iconIsRed = !iconIsRed; iconIsRed = !iconIsRed;
} }
else else
{ {
// Break alert once everything is back to normal // Fade heartbeat icon
if (!iconIsRed) // Make color darker
{ heartbeatColor = heartbeatColor.darker(150);
setBackgroundColor();
iconIsRed = true;
}
// Fade heartbeat icon //m_ui->heartbeatIcon->setAutoFillBackground(true);
// Make color darker m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
heartbeatColor = heartbeatColor.darker(150);
//m_ui->heartbeatIcon->setAutoFillBackground(true);
m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
} }
//setUpdatesEnabled(true); //setUpdatesEnabled(true);
......
...@@ -50,6 +50,8 @@ public: ...@@ -50,6 +50,8 @@ public:
~UASView(); ~UASView();
public slots: public slots:
/** @brief Update the name of the system */
void updateName(const QString& name);
void receiveHeartbeat(UASInterface* uas); void receiveHeartbeat(UASInterface* uas);
void updateThrust(UASInterface* uas, double thrust); void updateThrust(UASInterface* uas, double thrust);
void updateBattery(UASInterface* uas, double voltage, double percent, int seconds); void updateBattery(UASInterface* uas, double voltage, double percent, int seconds);
...@@ -74,15 +76,19 @@ public slots: ...@@ -74,15 +76,19 @@ public slots:
void setUASasActive(bool); void setUASasActive(bool);
/** @brief Update the view if an UAS has been set to active */ /** @brief Update the view if an UAS has been set to active */
void updateActiveUAS(UASInterface* uas, bool active); void updateActiveUAS(UASInterface* uas, bool active);
/** @brief Set the widget into critical mode */
void heartbeatTimeout();
/** @brief Set the background color for the widget */ /** @brief Set the background color for the widget */
void setBackgroundColor(); void setBackgroundColor();
/** @brief Bring up the dialog to rename the system */
void rename();
protected: protected:
void changeEvent(QEvent *e); void changeEvent(QEvent *e);
QTimer* refreshTimer; QTimer* refreshTimer;
QColor heartbeatColor; QColor heartbeatColor;
quint64 startTime; quint64 startTime;
quint64 lastHeartbeat; bool timeout;
bool iconIsRed; bool iconIsRed;
int timeRemaining; int timeRemaining;
float chargeLevel; float chargeLevel;
...@@ -103,6 +109,7 @@ protected: ...@@ -103,6 +109,7 @@ protected:
float groundDistance; float groundDistance;
bool localFrame; bool localFrame;
QAction* removeAction; QAction* removeAction;
QAction* renameAction;
static const int updateInterval = 300; static const int updateInterval = 300;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment