Commit c5e1a67a authored by lm's avatar lm

Merged, improved UI when MAVs time out

parents 319623e5 3989ad94
......@@ -11,7 +11,7 @@ QT += network \
TEMPLATE = app
TARGET = tst_uasunittest
TARGET = qgcunittest
BASEDIR = $$IN_PWD
TESTDIR = $$BASEDIR/qgcunittest
......@@ -97,8 +97,7 @@ INCLUDEPATH += . \
$$BASEDIR/src/ui/ \
SOURCES += $$TESTDIR/tst_uasunittest.cc \
src/uas/UAS.cc \
SOURCES += src/uas/UAS.cc \
src/comm/MAVLinkProtocol.cc \
src/uas/UASWaypointManager.cc \
src/Waypoint.cc \
......@@ -111,6 +110,10 @@ SOURCES += $$TESTDIR/tst_uasunittest.cc \
src/comm/LinkManager.cc \
src/QGC.cc \
src/comm/SerialLink.cc \
$$TESTDIR/SlugsMavUnitTest.cc \
$$TESTDIR/testSuite.cc \
$$TESTDIR/UASUnitTest.cc
HEADERS += src/uas/UASInterface.h \
src/uas/UAS.h \
......@@ -129,6 +132,9 @@ HEADERS += src/uas/UASInterface.h \
src/QGC.h \
src/comm/SerialLinkInterface.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
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
{
......
......@@ -20,7 +20,7 @@ namespace QGC
quint64 groundTimeUsecs();
int applicationVersion();
const static int MAX_FLIGHT_TIME = 60 * 60 * 24 * 21;
class SLEEP : public QThread
{
......
......@@ -46,7 +46,6 @@ public slots:
mavlink_pwm_commands_t* getPwmCommands();
#endif
signals:
void slugsRawImu(int uasId, const mavlink_raw_imu_t& rawData);
......
......@@ -84,8 +84,8 @@ paramsOnceRequested(false)
{
color = UASInterface::getNextColor();
setBattery(LIPOLY, 3);
statusTimeout->setInterval(500);
connect(statusTimeout, SIGNAL(timeout()), this, SLOT(updateState()));
statusTimeout->start(500);
}
UAS::~UAS()
......@@ -101,6 +101,14 @@ int UAS::getUASID() const
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
// if no position lock is available, indicate an error
if (positionLock)
......@@ -144,6 +152,7 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
switch (message.msgid)
{
case MAVLINK_MSG_ID_HEARTBEAT:
lastHeartbeat = QGC::groundTimeUsecs();
emit heartbeat(this);
// Set new type if it has changed
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
}
}
void UAS::setUASName(const QString& name)
{
this->name = name;
emit nameChanged(name);
}
/**
* Sets an action
*
......
......@@ -152,6 +152,7 @@ protected: //COMMENTS FOR TEST UNIT
double roll;
double pitch;
double yaw;
quint64 lastHeartbeat; ///< Time of the last heartbeat message
QTimer* statusTimeout; ///< Timer for various status timeouts
QMap<int, QMap<QString, float>* > parameters; ///< All parameters
bool paramsOnceRequested; ///< If the parameter list has been read at least once
......@@ -174,7 +175,10 @@ public:
void setAutopilotType(int apType) { autopilot = apType;}
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);
/** @brief Launches the system **/
......
......@@ -92,7 +92,8 @@ public:
COMM_CONNECTED = 2,
/** The connection is closed **/
COMM_DISCONNECTING = 3,
COMM_FAIL = 4, ///< Communication link failed
COMM_FAIL = 4,
COMM_TIMEDOUT = 5///< Communication link failed
};
......@@ -162,6 +163,8 @@ public:
public slots:
/** @brief Set a new name for the system */
virtual void setUASName(const QString& name) = 0;
/** @brief Sets an action **/
virtual void setAction(MAV_ACTION action) = 0;
......@@ -409,9 +412,18 @@ signals:
*/
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()
UASManager::UASManager() :
activeUAS(NULL)
{
systems = QMap<int, UASInterface*>();
systems = QList<UASInterface*>();
start(QThread::LowPriority);
}
......@@ -90,9 +90,9 @@ void UASManager::addUAS(UASInterface* uas)
}
// 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);
}
......@@ -105,7 +105,7 @@ void UASManager::addUAS(UASInterface* uas)
QList<UASInterface*> UASManager::getUASList()
{
return systems.values();
return systems;
}
UASInterface* UASManager::getActiveUAS()
......@@ -176,8 +176,18 @@ void UASManager::configureActiveUAS()
UASInterface* UASManager::getUASForId(int id)
{
// Return NULL pointer if UAS does not exist
return systems.value(id, NULL);
UASInterface* system = NULL;
foreach(UASInterface* sys, systems)
{
if (sys->getUASID() == id)
{
system = sys;
}
}
// Return NULL if not found
return system;
}
void UASManager::setActiveUAS(UASInterface* uas)
......@@ -195,6 +205,7 @@ void UASManager::setActiveUAS(UASInterface* uas)
emit activeUASSet(uas);
emit activeUASSet(uas->getUASID());
emit activeUASSetListIndex(systems.indexOf(uas));
emit activeUASStatusChanged(uas, true);
emit activeUASStatusChanged(uas->getUASID(), true);
}
......
......@@ -162,7 +162,7 @@ public slots:
protected:
UASManager();
QMap<int, UASInterface*> systems;
QList<UASInterface*> systems;
UASInterface* activeUAS;
QMutex activeUASMutex;
......@@ -173,6 +173,8 @@ signals:
/** @brief The UAS currently under main operator control changed */
void activeUASSet(int systemId);
/** @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);
/** @brief The UAS currently under main operator control changed */
void activeUASStatusChanged(int systemId, bool active);
......
......@@ -436,10 +436,10 @@ void MainWindow::buildPxWidgets()
if (!parametersDockWidget)
{
parametersDockWidget = new QDockWidget(tr("Onboard Parameters"), this);
parametersDockWidget = new QDockWidget(tr("Calibration and Onboard Parameters"), this);
parametersDockWidget->setWidget( new ParameterInterface(this) );
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)
......@@ -1099,7 +1099,7 @@ void MainWindow::showStatusMessage(const QString& status)
void MainWindow::showCriticalMessage(const QString& title, const QString& message)
{
QMessageBox msgBox(MainWindow::instance());
QMessageBox msgBox(this);
msgBox.setIcon(QMessageBox::Critical);
msgBox.setText(title);
msgBox.setInformativeText(message);
......@@ -1110,7 +1110,7 @@ void MainWindow::showCriticalMessage(const QString& title, const QString& messag
void MainWindow::showInfoMessage(const QString& title, const QString& message)
{
QMessageBox msgBox(MainWindow::instance());
QMessageBox msgBox(this);
msgBox.setIcon(QMessageBox::Information);
msgBox.setText(title);
msgBox.setInformativeText(message);
......@@ -1152,6 +1152,9 @@ void MainWindow::connectCommonActions()
connect(ui.actionOnline_Documentation, SIGNAL(triggered()), this, SLOT(showHelp()));
connect(ui.actionDeveloper_Credits, SIGNAL(triggered()), this, SLOT(showCredits()));
connect(ui.actionProject_Roadmap_2, SIGNAL(triggered()), this, SLOT(showRoadMap()));
// Custom widget actions
connect(ui.actionNewCustomWidget, SIGNAL(triggered()), this, SLOT(createCustomWidget()));
}
void MainWindow::connectPxActions()
......
......@@ -46,10 +46,10 @@ ParameterInterface::ParameterInterface(QWidget *parent) :
m_ui->setupUi(this);
// Make sure the combo box is empty
// because else indices get messed up
m_ui->vehicleComboBox->clear();
//m_ui->vehicleComboBox->clear();
// 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
QList<UASInterface*> systems = UASManager::instance()->getUASList();
......@@ -62,6 +62,7 @@ ParameterInterface::ParameterInterface(QWidget *parent) :
// Setup MAV connections
connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)), this, SLOT(addUAS(UASInterface*)));
connect(UASManager::instance(), SIGNAL(activeUASSetListIndex(int)), this, SLOT(selectUAS(int)));
this->setVisible(false);
}
......@@ -72,9 +73,8 @@ ParameterInterface::~ParameterInterface()
void ParameterInterface::selectUAS(int index)
{
// FIXME plus 2 shouldn't be there
m_ui->stackedWidget->setCurrentIndex(index+2);
m_ui->sensorSettings->setCurrentIndex(index+2);
m_ui->stackedWidget->setCurrentIndex(index);
m_ui->sensorSettings->setCurrentIndex(index);
curr = index;
}
......@@ -84,7 +84,7 @@ void ParameterInterface::selectUAS(int index)
*/
void ParameterInterface::addUAS(UASInterface* uas)
{
m_ui->vehicleComboBox->addItem(uas->getUASName());
//m_ui->vehicleComboBox->addItem(uas->getUASName());
QGCParamWidget* param = new QGCParamWidget(uas, this);
paramWidgets->insert(uas->getUASID(), param);
......
......@@ -13,7 +13,7 @@
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout" rowstretch="2,10,5">
<layout class="QGridLayout" name="gridLayout" rowstretch="2,0">
<property name="horizontalSpacing">
<number>5</number>
</property>
......@@ -23,17 +23,7 @@
<property name="margin">
<number>6</number>
</property>
<item row="0" column="0">
<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">
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Onboard Parameters</string>
......@@ -45,26 +35,18 @@
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>0</number>
<number>-1</number>
</property>
<widget class="QWidget" name="page">
<layout class="QVBoxLayout" name="verticalLayout"/>
</widget>
<widget class="QWidget" name="page_2"/>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<item row="1" column="0" colspan="2">
<widget class="QStackedWidget" name="sensorSettings">
<property name="currentIndex">
<number>0</number>
<number>-1</number>
</property>
<widget class="QWidget" name="page_3">
<layout class="QVBoxLayout" name="verticalLayout_2"/>
</widget>
<widget class="QWidget" name="page_4"/>
</widget>
</item>
</layout>
......
......@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>222</width>
<height>172</height>
<width>200</width>
<height>150</height>
</rect>
</property>
<property name="sizePolicy">
......@@ -18,8 +18,8 @@
</property>
<property name="minimumSize">
<size>
<width>222</width>
<height>172</height>
<width>200</width>
<height>150</height>
</size>
</property>
<property name="maximumSize">
......@@ -34,8 +34,14 @@
<property name="toolTip">
<string>Control widget to send basic control actions to the micro air vehicle</string>
</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">
<item row="0" column="0" rowspan="6">
<layout class="QGridLayout" name="gridLayout" rowstretch="5,1,40,1,40,40,40" columnstretch="5,20,20,25,5">
<property name="margin">
<number>4</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="0" rowspan="7">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
......@@ -48,12 +54,12 @@
</property>
</spacer>
</item>
<item row="0" column="1" colspan="4">
<item row="0" column="1" rowspan="2" colspan="3">
<widget class="QLabel" name="controlStatusLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
<height>10</height>
</size>
</property>
<property name="text">
......@@ -67,140 +73,143 @@
</property>
</widget>
</item>
<item row="0" column="5" rowspan="6">
<spacer name="horizontalSpacer_2">
<item row="3" column="1" colspan="3">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>30</width>
<height>159</height>
<width>216</width>
<height>17</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1" colspan="4">
<widget class="QPushButton" name="controlButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>12</height>
</size>
</property>
<property name="text">
<string>Activate Engine</string>
</property>
</widget>
<item row="4" column="1" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>6</number>
</property>
<item>
<widget class="QPushButton" name="liftoffButton">
<property name="minimumSize">
<size>
<width>25</width>
<height>16</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>
<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 row="2" column="1">
<widget class="QPushButton" name="liftoffButton">
<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">
<item row="5" column="1" colspan="2">
<widget class="QComboBox" name="modeComboBox">
<property name="minimumSize">
<size>
<width>40</width>
<height>12</height>
<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 row="2" column="4">
<widget class="QPushButton" name="shutdownButton">
<item row="5" column="3">
<widget class="QPushButton" name="setModeButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>12</height>
<width>25</width>
<height>16</height>
</size>
</property>
<property name="text">
<string>Halt</string>
<string>Set</string>
</property>
<property name="icon">
<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>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QComboBox" name="modeComboBox">
<item row="6" column="1" colspan="3">
<widget class="QLabel" name="lastActionLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>12</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>
<height>10</height>
</size>
</property>
<property name="text">
<string>Set Mode</string>
<string>No actions executed so far</string>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/devices/network-wireless.svg</normaloff>:/images/devices/network-wireless.svg</iconset>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="4" column="3" colspan="2">
<widget class="QPushButton" name="setHomeButton">
<property name="minimumSize">
<item row="1" column="4" rowspan="6">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>16</height>
<width>30</width>
<height>159</height>
</size>
</property>
<property name="text">
<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>
</spacer>
</item>
<item row="5" column="1" colspan="4">
<widget class="QLabel" name="lastActionLabel">
<item row="2" column="1" colspan="3">
<widget class="QPushButton" name="controlButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>12</height>
<height>30</height>
</size>
</property>
<property name="text">
<string>No actions executed so far</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
<string>Activate Engine</string>
</property>
</widget>
</item>
......
......@@ -35,8 +35,9 @@ void XMLCommProtocolWidget::selectXMLFile()
QSettings settings(QGC::COMPANYNAME, QGC::APPNAME);
const QString mavlinkXML = "MAVLINK_XML_FILE";
QString dirPath = settings.value(mavlinkXML, QCoreApplication::applicationDirPath() + "../").toString();
QFileInfo dir(dirPath);
QFileDialog dialog;
dialog.setDirectory(dirPath);
dialog.setDirectory(dir.absoluteDir());
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setFilter(tr("MAVLink XML (*.xml)"));
dialog.setViewMode(QFileDialog::Detail);
......@@ -100,7 +101,6 @@ void XMLCommProtocolWidget::selectOutputDirectory()
QFileDialog dialog;
dialog.setDirectory(dirPath);
dialog.setFileMode(QFileDialog::Directory);
dialog.setFilter(tr("MAVLink XML (*.xml)"));
dialog.setViewMode(QFileDialog::Detail);
QStringList fileNames;
if (dialog.exec())
......
......@@ -97,7 +97,7 @@ void UASControlWidget::setUAS(UASInterface* uas)
disconnect(ui.liftoffButton, SIGNAL(clicked()), oldUAS, SLOT(launch()));
disconnect(ui.landButton, SIGNAL(clicked()), oldUAS, SLOT(home()));
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(statusChanged(int)), this, SLOT(updateState(int)));
}
......@@ -107,28 +107,28 @@ void UASControlWidget::setUAS(UASInterface* uas)
connect(ui.liftoffButton, SIGNAL(clicked()), uas, SLOT(launch()));
connect(ui.landButton, SIGNAL(clicked()), uas, SLOT(home()));
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(statusChanged(int)), this, SLOT(updateState(int)));
ui.controlStatusLabel->setText(tr("Connected to ") + uas->getUASName());
// Check if additional controls should be loaded
UAS* mav = dynamic_cast<UAS*>(uas);
if (mav)
{
QPushButton* startRecButton = new QPushButton(tr("Record"));
connect(startRecButton, SIGNAL(clicked()), mav, SLOT(startDataRecording()));
ui.gridLayout->addWidget(startRecButton, 7, 1);
QPushButton* pauseRecButton = new QPushButton(tr("Pause"));
connect(pauseRecButton, SIGNAL(clicked()), mav, SLOT(pauseDataRecording()));
ui.gridLayout->addWidget(pauseRecButton, 7, 3);
QPushButton* stopRecButton = new QPushButton(tr("Stop"));
connect(stopRecButton, SIGNAL(clicked()), mav, SLOT(stopDataRecording()));
ui.gridLayout->addWidget(stopRecButton, 7, 4);
}
// // Check if additional controls should be loaded
// UAS* mav = dynamic_cast<UAS*>(uas);
// if (mav)
// {
// QPushButton* startRecButton = new QPushButton(tr("Record"));
// connect(startRecButton, SIGNAL(clicked()), mav, SLOT(startDataRecording()));
// ui.gridLayout->addWidget(startRecButton, 7, 1);
// QPushButton* pauseRecButton = new QPushButton(tr("Pause"));
// connect(pauseRecButton, SIGNAL(clicked()), mav, SLOT(pauseDataRecording()));
// ui.gridLayout->addWidget(pauseRecButton, 7, 3);
// QPushButton* stopRecButton = new QPushButton(tr("Stop"));
// connect(stopRecButton, SIGNAL(clicked()), mav, SLOT(stopDataRecording()));
// ui.gridLayout->addWidget(stopRecButton, 7, 4);
// }
this->uas = uas->getUASID();
......@@ -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
* currently actively controlled system, the frame color is highlighted
......@@ -258,16 +271,20 @@ void UASControlWidget::cycleContextButton()
if (!engineOn)
{
ui.controlButton->setText(tr("Stop Engine"));
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
{
ui.controlButton->setText(tr("Activate Engine"));
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("KILL VEHICLE"));
}
......
......@@ -63,6 +63,8 @@ public slots:
void updateMode(int uas,QString mode,QString description);
/** @brief Update state */
void updateState(int state);
/** @brief Update internal state machine */
void updateStatemachine();
protected slots:
/** @brief Set the background color for the widget */
......
......@@ -32,6 +32,7 @@ This file is part of the PIXHAWK project
#include <QDateTime>
#include <QDebug>
#include <QMenu>
#include <QInputDialog>
#include "QGC.h"
#include "MG.h"
......@@ -43,7 +44,7 @@ This file is part of the PIXHAWK project
UASView::UASView(UASInterface* uas, QWidget *parent) :
QWidget(parent),
startTime(0),
lastHeartbeat(0),
timeout(false),
iconIsRed(true),
timeRemaining(0),
chargeLevel(0),
......@@ -63,7 +64,8 @@ UASView::UASView(UASInterface* uas, QWidget *parent) :
alt(0),
groundDistance(0),
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->setupUi(this);
......@@ -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(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString)));
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->getWaypointManager()), SIGNAL(currentWaypointChanged(quint16)), this, SLOT(currentWaypointUpdated(quint16)));
connect(uas, SIGNAL(systemTypeSet(UASInterface*,uint)), this, SLOT(setSystemType(UASInterface*,uint)));
......@@ -99,7 +101,11 @@ UASView::UASView(UASInterface* uas, QWidget *parent) :
// Allow to delete this widget
connect(removeAction, SIGNAL(triggered()), this, SLOT(deleteLater()));
connect(renameAction, SIGNAL(triggered()), this, SLOT(rename()));
connect(uas, SIGNAL(systemRemoved()), this, SLOT(deleteLater()));
// Name changes
connect(uas, SIGNAL(nameChanged(QString)), this, SLOT(updateName(QString)));
// Set static values
......@@ -138,6 +144,11 @@ UASView::~UASView()
delete m_ui;
}
void UASView::heartbeatTimeout()
{
timeout = true;
}
/**
* 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
......@@ -241,8 +252,13 @@ void UASView::receiveHeartbeat(UASInterface* uas)
heartbeatColor = QColor(20, 200, 20);
QString colorstyle("QGroupBox { border-radius: 5px; padding: 2px; margin: 2px; border: 0px; background-color: %1; }");
m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
lastHeartbeat = QGC::groundTimeUsecs();
//m_ui->heartbeatIcon->setAutoFillBackground(true);
if (timeout) setBackgroundColor();
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)
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.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()
// Thrust
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
static double filterTime = static_cast<int>(this->timeRemaining);
......@@ -513,41 +543,40 @@ void UASView::refresh()
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
QString borderColor = "#FFFF00";
if (isActive)
{
borderColor = "#FA4A4F";
}
if (iconIsRed)
{
QColor warnColor(Qt::red);
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);
}
else
{
QColor warnColor(Qt::black);
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);
}
iconIsRed = !iconIsRed;
}
else
{
// Break alert once everything is back to normal
if (!iconIsRed)
{
setBackgroundColor();
iconIsRed = true;
}
// Fade heartbeat icon
// Make color darker
heartbeatColor = heartbeatColor.darker(150);
// Fade heartbeat icon
// Make color darker
heartbeatColor = heartbeatColor.darker(150);
//m_ui->heartbeatIcon->setAutoFillBackground(true);
m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
//m_ui->heartbeatIcon->setAutoFillBackground(true);
m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
}
//setUpdatesEnabled(true);
......
......@@ -50,6 +50,8 @@ public:
~UASView();
public slots:
/** @brief Update the name of the system */
void updateName(const QString& name);
void receiveHeartbeat(UASInterface* uas);
void updateThrust(UASInterface* uas, double thrust);
void updateBattery(UASInterface* uas, double voltage, double percent, int seconds);
......@@ -74,15 +76,19 @@ public slots:
void setUASasActive(bool);
/** @brief Update the view if an UAS has been set to active */
void updateActiveUAS(UASInterface* uas, bool active);
/** @brief Set the widget into critical mode */
void heartbeatTimeout();
/** @brief Set the background color for the widget */
void setBackgroundColor();
/** @brief Bring up the dialog to rename the system */
void rename();
protected:
void changeEvent(QEvent *e);
QTimer* refreshTimer;
QColor heartbeatColor;
quint64 startTime;
quint64 lastHeartbeat;
bool timeout;
bool iconIsRed;
int timeRemaining;
float chargeLevel;
......@@ -103,6 +109,7 @@ protected:
float groundDistance;
bool localFrame;
QAction* removeAction;
QAction* renameAction;
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