Commit 62d95365 authored by Don Gagne's avatar Don Gagne

Replaced by toolbar dropdowns

parent 0641f7f2
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>uasControl</class>
<widget class="QWidget" name="uasControl">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>200</width>
<height>228</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>150</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>267</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="toolTip">
<string>Control widget to send basic control actions to the micro air vehicle</string>
</property>
<layout class="QGridLayout" name="gridLayout" rowstretch="5,1,40,1,40,40,40,1000" columnstretch="5,20,20,25,5">
<property name="margin">
<number>4</number>
</property>
<item row="0" column="0" rowspan="7">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>31</width>
<height>159</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1" rowspan="2" colspan="3">
<widget class="QLabel" name="controlStatusLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
<property name="toolTip">
<string>Currently controlled system</string>
</property>
<property name="statusTip">
<string>Currently controlled system</string>
</property>
<property name="text">
<string>UNCONNECTED</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="margin">
<number>0</number>
</property>
</widget>
</item>
<item row="3" column="1" colspan="3">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>216</width>
<height>17</height>
</size>
</property>
</spacer>
</item>
<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="toolTip">
<string>Liftoff / Launch</string>
</property>
<property name="statusTip">
<string>Liftoff / Launch</string>
</property>
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="landButton">
<property name="minimumSize">
<size>
<width>25</width>
<height>16</height>
</size>
</property>
<property name="toolTip">
<string>Fly straight to landing spot</string>
</property>
<property name="statusTip">
<string>Fly straight to landing spot</string>
</property>
<property name="text">
<string>Land</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="shutdownButton">
<property name="minimumSize">
<size>
<width>25</width>
<height>16</height>
</size>
</property>
<property name="toolTip">
<string>Only active on the ground: Poweroff system</string>
</property>
<property name="statusTip">
<string>Only active on the ground: Poweroff system</string>
</property>
<property name="text">
<string>Halt</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="1" colspan="2">
<widget class="QComboBox" name="modeComboBox">
<property name="minimumSize">
<size>
<width>25</width>
<height>16</height>
</size>
</property>
<property name="toolTip">
<string>Select MAV operation mode</string>
</property>
<property name="statusTip">
<string>Select MAV operation mode</string>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QPushButton" name="setModeButton">
<property name="minimumSize">
<size>
<width>25</width>
<height>16</height>
</size>
</property>
<property name="toolTip">
<string>Transmit and enable mode on MAV</string>
</property>
<property name="statusTip">
<string>Transmit and enable mode on MAV</string>
</property>
<property name="text">
<string>Set</string>
</property>
</widget>
</item>
<item row="6" column="1" colspan="3">
<widget class="QLabel" name="lastActionLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
<property name="toolTip">
<string>Status label</string>
</property>
<property name="statusTip">
<string>Status label</string>
</property>
<property name="text">
<string>No actions executed so far</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<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>30</width>
<height>159</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1" colspan="3">
<widget class="QPushButton" name="controlButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="toolTip">
<string>Main control button</string>
</property>
<property name="statusTip">
<string>Main control button</string>
</property>
<property name="text">
<string>Activate Engine</string>
</property>
</widget>
</item>
<item row="7" column="1" colspan="3">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UASList</class>
<widget class="QWidget" name="UASList">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>300</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>3</number>
</property>
</layout>
</widget>
<resources/>
<connections/>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UASView</class>
<widget class="QWidget" name="UASView">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>360</width>
<height>155</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>260</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>360</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="margin">
<number>5</number>
</property>
<item>
<layout class="QGridLayout" name="gridLayout">
<property name="topMargin">
<number>0</number>
</property>
<item row="1" column="0" rowspan="2">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="typeLabel">
<property name="toolTip">
<string>System type</string>
</property>
<property name="statusTip">
<string>System type</string>
</property>
<property name="whatsThis">
<string>System type</string>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../qgroundcontrol.qrc">:/res/mavs/Unknown</pixmap>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="heartBeatLabel">
<property name="toolTip">
<string>Heartbeat</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="batteryBar">
<property name="minimumSize">
<size>
<width>18</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>18</width>
<height>40</height>
</size>
</property>
<property name="font">
<font/>
</property>
<property name="toolTip">
<string>Battery Fuel</string>
</property>
<property name="statusTip">
<string>Battery Fuel</string>
</property>
<property name="value">
<number>0</number>
</property>
<property name="textVisible">
<bool>false</bool>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="2" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>2</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="waypointLabel">
<property name="font">
<font>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>Current Waypoint</string>
</property>
<property name="statusTip">
<string>Current Waypoint</string>
</property>
<property name="text">
<string>---</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="liftoffButton">
<property name="minimumSize">
<size>
<width>26</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>38</width>
<height>22</height>
</size>
</property>
<property name="toolTip">
<string>Liftoff / Launch</string>
</property>
<property name="statusTip">
<string>Liftoff / Launch</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../qgroundcontrol.qrc">
<normaloff>:/res/Launch</normaloff>:/res/Launch</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="abortButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>26</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>38</width>
<height>22</height>
</size>
</property>
<property name="toolTip">
<string>Emergency land system at closest possible site</string>
</property>
<property name="statusTip">
<string>Emergency land system at closest possible site</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../qgroundcontrol.qrc">
<normaloff>:/res/Stop</normaloff>:/res/Stop</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="haltButton">
<property name="minimumSize">
<size>
<width>26</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>38</width>
<height>22</height>
</size>
</property>
<property name="toolTip">
<string>Loiter / Wait at current position</string>
</property>
<property name="statusTip">
<string>Loiter / Wait at current position</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../qgroundcontrol.qrc">
<normaloff>:/res/Pause</normaloff>:/res/Pause</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="continueButton">
<property name="minimumSize">
<size>
<width>26</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>38</width>
<height>22</height>
</size>
</property>
<property name="toolTip">
<string>Continue flightplan</string>
</property>
<property name="statusTip">
<string>Continue flightplan</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../qgroundcontrol.qrc">
<normaloff>:/res/Play</normaloff>:/res/Play</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="landButton">
<property name="minimumSize">
<size>
<width>26</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>38</width>
<height>22</height>
</size>
</property>
<property name="toolTip">
<string>Fly straight to landing location</string>
</property>
<property name="statusTip">
<string>Fly straight to landing location</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../qgroundcontrol.qrc">
<normaloff>:/res/Land</normaloff>:/res/Land</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="killButton">
<property name="minimumSize">
<size>
<width>26</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>38</width>
<height>22</height>
</size>
</property>
<property name="toolTip">
<string>Kill immediately all onboard power</string>
</property>
<property name="statusTip">
<string>Kill immediately all onboard power</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../qgroundcontrol.qrc">
<normaloff>:/res/Kill</normaloff>:/res/Kill</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="shutdownButton">
<property name="maximumSize">
<size>
<width>38</width>
<height>22</height>
</size>
</property>
<property name="toolTip">
<string>Only in standby mode: Power off system</string>
</property>
<property name="statusTip">
<string>Only in standby mode: Power off system</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../qgroundcontrol.qrc">
<normaloff>:/res/Shutdown</normaloff>:/res/Shutdown</iconset>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>4</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
</layout>
</item>
</layout>
</item>
<item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="nameLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16</height>
</size>
</property>
<property name="font">
<font>
<weight>75</weight>
<italic>false</italic>
<bold>true</bold>
</font>
</property>
<property name="toolTip">
<string>System Name</string>
</property>
<property name="statusTip">
<string>System Name</string>
</property>
<property name="text">
<string>UAS001</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="timeRemainingLabel">
<property name="font">
<font>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>Remaining flight time</string>
</property>
<property name="statusTip">
<string>Remaining flight time</string>
</property>
<property name="text">
<string>00:00:00</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="timeElapsedLabel">
<property name="font">
<font>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>Uptime</string>
</property>
<property name="statusTip">
<string>Uptime</string>
</property>
<property name="text">
<string>00:00:00</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="groundDistanceLabel">
<property name="font">
<font>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>Altitude</string>
</property>
<property name="statusTip">
<string>Altitude</string>
</property>
<property name="text">
<string>00.00 m</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="speedLabel">
<property name="font">
<font>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>Ground Speed</string>
</property>
<property name="statusTip">
<string>Ground Speed</string>
</property>
<property name="text">
<string>00.0 m/s</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="stateLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>12</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>STATE</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="2">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="modeLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>MODE</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="positionLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>12</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>12</height>
</size>
</property>
<property name="font">
<font>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>Current Position</string>
</property>
<property name="statusTip">
<string>Current Position</string>
</property>
<property name="text">
<string>00.0 00.0 00.0 m</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="thrustBar">
<property name="font">
<font/>
</property>
<property name="toolTip">
<string>Current throttle</string>
</property>
<property name="statusTip">
<string>Current throttle</string>
</property>
<property name="value">
<number>0</number>
</property>
<property name="format">
<string>throttle %p%</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="navLabel">
<property name="font">
<font>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>NAV</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="statusTextLabel">
<property name="text">
<string>Waiting for first status update..</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../qgroundcontrol.qrc"/>
</resources>
<connections/>
</ui>
/*=====================================================================
PIXHAWK Micro Air Vehicle Flying Robotics Toolkit
(c) 2009, 2010 PIXHAWK PROJECT <http://pixhawk.ethz.ch>
This file is part of the PIXHAWK project
PIXHAWK is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PIXHAWK is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PIXHAWK. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Definition of widget controlling one MAV
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#include <QString>
#include <QTimer>
#include <QLabel>
#include <QProcess>
#include <QPalette>
#include "UASControlWidget.h"
#include "MultiVehicleManager.h"
#include "UAS.h"
#include "QGC.h"
#include "AutoPilotPluginManager.h"
#include "FirmwarePluginManager.h"
UASControlWidget::UASControlWidget(QWidget *parent) : QWidget(parent),
_uas(NULL),
armed(false)
{
ui.setupUi(this);
_activeVehicleChanged(MultiVehicleManager::instance()->activeVehicle());
connect(MultiVehicleManager::instance(), &MultiVehicleManager::activeVehicleChanged, this, &UASControlWidget::_activeVehicleChanged);
connect(ui.setModeButton, SIGNAL(clicked()), this, SLOT(transmitMode()));
ui.liftoffButton->hide();
ui.landButton->hide();
ui.shutdownButton->hide();
ui.gridLayout->setAlignment(Qt::AlignTop);
}
void UASControlWidget::updateModesList()
{
if (!_uas) {
return;
}
_modeList = FirmwarePluginManager::instance()->firmwarePluginForAutopilot((MAV_AUTOPILOT)_uas->getAutopilotType())->flightModes();
// Set combobox items
ui.modeComboBox->clear();
foreach (QString flightMode, _modeList) {
ui.modeComboBox->addItem(flightMode);
}
// Select first mode in list
ui.modeComboBox->setCurrentIndex(0);
ui.modeComboBox->update();
}
void UASControlWidget::_activeVehicleChanged(Vehicle* vehicle)
{
if (_uas) {
disconnect(ui.controlButton, SIGNAL(clicked()), _uas, SLOT(armSystem()));
disconnect(ui.liftoffButton, SIGNAL(clicked()), _uas, SLOT(launch()));
disconnect(ui.landButton, SIGNAL(clicked()), _uas, SLOT(home()));
disconnect(ui.shutdownButton, SIGNAL(clicked()), _uas, SLOT(shutdown()));
disconnect(_uas, SIGNAL(statusChanged(int)), this, SLOT(updateState(int)));
_uas = NULL;
}
// Connect user interface controls
if (vehicle) {
_uas = vehicle->uas();
connect(ui.controlButton, SIGNAL(clicked()), this, SLOT(cycleContextButton()));
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(_uas, SIGNAL(statusChanged(int)), this, SLOT(updateState(int)));
ui.controlStatusLabel->setText(tr("Connected to ") + _uas->getUASName());
setBackgroundColor(_uas->getColor());
this->updateModesList();
this->updateArmText();
}
}
UASControlWidget::~UASControlWidget()
{
}
void UASControlWidget::updateArmText()
{
if (armed) {
ui.controlButton->setText(tr("DISARM SYSTEM"));
} else {
ui.controlButton->setText(tr("ARM SYSTEM"));
}
}
/**
* 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
*/
void UASControlWidget::setBackgroundColor(QColor color)
{
// UAS color
QColor uasColor = color;
QString colorstyle;
QString borderColor = "#4A4A4F";
borderColor = "#FA4A4F";
uasColor = uasColor.darker(400);
colorstyle = colorstyle.sprintf("QLabel { border-radius: 3px; padding: 0px; margin: 0px; background-color: #%02X%02X%02X; border: 0px solid %s; }",
uasColor.red(), uasColor.green(), uasColor.blue(), borderColor.toStdString().c_str());
setStyleSheet(colorstyle);
QPalette palette = this->palette();
palette.setBrush(QPalette::Window, QBrush(uasColor));
setPalette(palette);
setAutoFillBackground(true);
}
void UASControlWidget::updateState(int state)
{
switch (state) {
case (int)MAV_STATE_ACTIVE:
armed = true;
break;
case (int)MAV_STATE_STANDBY:
armed = false;
break;
}
this->updateArmText();
}
void UASControlWidget::transmitMode()
{
if (_uas) {
uint8_t base_mode;
uint32_t custom_mode;
QString flightMode = ui.modeComboBox->itemText(ui.modeComboBox->currentIndex());
if (FirmwarePluginManager::instance()->firmwarePluginForAutopilot((MAV_AUTOPILOT)_uas->getAutopilotType())->setFlightMode(flightMode, &base_mode, &custom_mode)) {
if (armed) {
base_mode |= MAV_MODE_FLAG_SAFETY_ARMED;
}
if (_uas->isHilEnabled() || _uas->isHilActive()) {
base_mode |= MAV_MODE_FLAG_HIL_ENABLED;
}
_uas->setMode(base_mode, custom_mode);
QString modeText = ui.modeComboBox->currentText();
ui.lastActionLabel->setText(QString("Sent new mode %1 to %2").arg(flightMode).arg(_uas->getUASName()));
}
}
}
void UASControlWidget::cycleContextButton()
{
if (_uas) {
if (!armed) {
_uas->armSystem();
ui.lastActionLabel->setText(QString("Arm %1").arg(_uas->getUASName()));
} else {
_uas->disarmSystem();
ui.lastActionLabel->setText(QString("Disarm %1").arg(_uas->getUASName()));
}
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Definition of class UASControlWidget
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#ifndef _UASCONTROLWIDGET_H_
#define _UASCONTROLWIDGET_H_
#include <QWidget>
#include <QLineEdit>
#include <QString>
#include <QPushButton>
#include "ui_UASControl.h"
#include "UASInterface.h"
#include "Vehicle.h"
/**
* @brief Widget controlling one MAV
*/
class UASControlWidget : public QWidget
{
Q_OBJECT
public:
UASControlWidget(QWidget *parent = 0);
~UASControlWidget();
public slots:
/** @brief Update modes list for selected system */
void updateModesList();
/** @brief Trigger next context action */
void cycleContextButton();
/** @brief Transmit the operation mode */
void transmitMode();
/** @brief Update state */
void updateState(int state);
/** @brief Update internal state machine */
void updateArmText();
protected slots:
/** @brief Set the background color for the widget */
void setBackgroundColor(QColor color);
protected:
UAS* _uas;
QStringList _modeList; ///< Mode list for the current UAS
bool armed; ///< Engine state
private slots:
void _activeVehicleChanged(Vehicle* vehicle);
private:
Ui::uasControl ui;
};
#endif // _UASCONTROLWIDGET_H_
/*=====================================================================
PIXHAWK Micro Air Vehicle Flying Robotics Toolkit
(c) 2009, 2010 PIXHAWK PROJECT <http://pixhawk.ethz.ch>
This file is part of the PIXHAWK project
PIXHAWK is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PIXHAWK is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PIXHAWK. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief List of unmanned vehicles
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#include <QString>
#include <QTimer>
#include <QLabel>
#include <QDebug>
#include <QApplication>
#include "MG.h"
#include "UASListWidget.h"
#include "MultiVehicleManager.h"
#include "UAS.h"
#include "UASView.h"
#include "QGCUnconnectedInfoWidget.h"
#include "MainWindow.h"
#include "LinkManager.h"
UASListWidget::UASListWidget(QWidget *parent) : QWidget(parent),
uWidget(NULL),
m_ui(new Ui::UASList)
{
// Use a timer to update the link health display.
updateTimer = new QTimer(this);
connect(updateTimer,SIGNAL(timeout()),this,SLOT(updateStatus()));
m_ui->setupUi(this);
m_ui->verticalLayout->setAlignment(Qt::AlignTop);
this->setMinimumWidth(262);
linkToBoxMapping = QMap<LinkInterface*, QGroupBox*>();
uasToBoxMapping = QMap<UASInterface*, QGroupBox*>();
uasViews = QMap<UASInterface*, UASView*>();
this->setVisible(false);
connect(LinkManager::instance(), SIGNAL(linkDeleted(LinkInterface*)), this, SLOT(removeLink(LinkInterface*)));
connect(MultiVehicleManager::instance(), &MultiVehicleManager::vehicleAdded, this, &UASListWidget::_vehicleAdded);
connect(MultiVehicleManager::instance(), &MultiVehicleManager::vehicleRemoved, this, &UASListWidget::_vehicleRemoved);
// Get a list of all existing UAS
foreach (Vehicle* vehicle, MultiVehicleManager::instance()->vehicles())
{
_vehicleAdded(vehicle);
}
}
UASListWidget::~UASListWidget()
{
delete m_ui;
}
void UASListWidget::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
switch (e->type())
{
case QEvent::LanguageChange:
m_ui->retranslateUi(this);
break;
default:
break;
}
}
// XXX This is just to prevent
// upfront crashes, will probably need further inspection
void UASListWidget::removeLink(LinkInterface* link)
{
QGroupBox* box = linkToBoxMapping.value(link, NULL);
if (box) {
// Just stop updating the status for now - we should
// remove the UAS probably
linkToBoxMapping.remove(link);
}
}
void UASListWidget::updateStatus()
{
QMapIterator<LinkInterface*, QGroupBox*> i(linkToBoxMapping);
while (i.hasNext()) {
i.next();
LinkInterface* link = i.key();
// Paranoid sanity check
if (!LinkManager::instance()->containsLink(link))
continue;
if (!link)
continue;
MAVLinkProtocol* mavlink = MAVLinkProtocol::instance();
// Build the tooltip out of the protocol parsing data: received, dropped, and parsing errors.
QString displayString("");
int c;
if ((c = mavlink->getReceivedPacketCount(link)) != -1)
{
displayString += QString(tr("<br/>Received: %2")).arg(QString::number(c));
}
if ((c = mavlink->getDroppedPacketCount(link)) != -1)
{
displayString += QString(tr("<br/>Dropped: %2")).arg(QString::number(c));
}
if ((c = mavlink->getParsingErrorCount(link)) != -1)
{
displayString += QString(tr("<br/>Errors: %2")).arg(QString::number(c));
}
if (!displayString.isEmpty())
{
displayString = QString("<b>%1</b>").arg(i.key()->getName()) + displayString;
}
// qDebug() << p << ": " + displayString;
i.value()->setToolTip(displayString);
}
}
void UASListWidget::_vehicleAdded(Vehicle* vehicle)
{
UAS* uas = vehicle->uas();
// If the list was empty, remove the unconnected widget and start the update timer.
if (uasViews.isEmpty())
{
updateTimer->start(5000);
if (uWidget)
{
m_ui->verticalLayout->removeWidget(uWidget);
delete uWidget;
uWidget = NULL;
}
}
if (!uasViews.contains(uas))
{
// Only display the UAS in a single link.
QList<LinkInterface*> x = vehicle->links();
if (x.size())
{
LinkInterface* li = x.first();
// Find an existing QGroupBox for this LinkInterface or create a
// new one.
QGroupBox* newBox;
if (linkToBoxMapping.contains(li))
{
newBox = linkToBoxMapping[li];
}
else
{
newBox = new QGroupBox(li->getName(), this);
QVBoxLayout* boxLayout = new QVBoxLayout(newBox);
newBox->setLayout(boxLayout);
m_ui->verticalLayout->addWidget(newBox);
linkToBoxMapping[li] = newBox;
updateStatus(); // Update the link status for this GroupBox.
}
// And add the new UAS to the UASList
UASView* newView = new UASView(vehicle, newBox);
uasViews.insert(uas, newView);
uasToBoxMapping[uas] = newBox;
newBox->layout()->addWidget(newView);
}
}
UASView* view = uasViews.value(uas, NULL);
if (view) {
view->setUASasActive(true);
}
}
/**
* If the UAS was removed, check to see if it was the last one in the QGroupBox and delete
* the QGroupBox if so.
*/
void UASListWidget::_vehicleRemoved(Vehicle* vehicle)
{
UAS* uas = vehicle->uas();
// Remove the UASView and check if its parent GroupBox has any other children,
// delete it if it doesn't.
QGroupBox* box = uasToBoxMapping[uas];
uasToBoxMapping.remove(uas);
uasViews.remove(uas);
int otherViews = 0;
foreach (UASView* view, box->findChildren<UASView*>())
{
if (view->uas == uas)
{
view->deleteLater();
}
else
{
++otherViews;
}
}
if (otherViews == 0)
{
// Delete the groupbox.
QMap<LinkInterface*, QGroupBox*>::const_iterator i = linkToBoxMapping.constBegin();
while (i != linkToBoxMapping.constEnd()) {
if (i.value() == box)
{
linkToBoxMapping.remove(i.key());
break;
}
++i;
}
box->deleteLater();
// And if no other QGroupBoxes are left, put the initial widget back.
// We also stop the update timer as there's nothing to update at this point.
int otherBoxes = 0;
foreach (const QGroupBox* otherBox, findChildren<QGroupBox*>())
{
if (otherBox != box)
{
++otherBoxes;
}
}
if (otherBoxes == 0)
{
uWidget = new QGCUnconnectedInfoWidget(this);
m_ui->verticalLayout->addWidget(uWidget);
updateTimer->stop();
}
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief List of unmanned vehicles
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#ifndef _UASLISTWIDGET_H_
#define _UASLISTWIDGET_H_
#include <QWidget>
#include <QMap>
#include <QList>
#include <QVBoxLayout>
#include <QGroupBox>
#include "UASInterface.h"
#include "UASView.h"
#include "QGCUnconnectedInfoWidget.h"
#include "ui_UASList.h"
#include "Vehicle.h"
class UASListWidget : public QWidget
{
Q_OBJECT
public:
UASListWidget(QWidget *parent = 0);
~UASListWidget();
public slots:
void removeLink(LinkInterface* link);
protected:
// Keep a mapping from UASes to their GroupBox. Useful for determining when groupboxes are empty.
QMap<UASInterface*, QGroupBox*> uasToBoxMapping;
// Keep a mapping from Links to GroupBoxes for adding new links.
QMap<LinkInterface*, QGroupBox*> linkToBoxMapping;
// Tie each view to their UAS object so they can be removed easily.
QMap<UASInterface*, UASView*> uasViews;
QGCUnconnectedInfoWidget* uWidget;
QTimer* updateTimer;
void changeEvent(QEvent *e);
private slots:
void _vehicleAdded(Vehicle* vehicle);
void _vehicleRemoved(Vehicle* vehicle);
private:
Ui::UASList* m_ui;
private slots:
void updateStatus();
};
#endif // _UASLISTWIDGET_H_
/*=====================================================================
PIXHAWK Micro Air Vehicle Flying Robotics Toolkit
(c) 2009, 2010 PIXHAWK PROJECT <http://pixhawk.ethz.ch>
This file is part of the PIXHAWK project
PIXHAWK is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PIXHAWK is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PIXHAWK. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Implementation of one airstrip
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#include <cmath>
#include <QDateTime>
#include <QDebug>
#include <QMenu>
#include <QInputDialog>
#include "QGC.h"
#include "MultiVehicleManager.h"
#include "UASView.h"
#include "UASWaypointManager.h"
#include "MainWindow.h"
#include "ui_UASView.h"
#ifndef __mobile__
#include <QGCHilFlightGearConfiguration.h>
#endif
UASView::UASView(Vehicle* vehicle, QWidget *parent) :
QWidget(parent),
vehicle(vehicle),
uas(vehicle->uas()),
startTime(0),
timeout(false),
iconIsRed(true),
disconnected(false),
timeRemaining(0),
chargeLevel(0),
load(0),
state("UNKNOWN"),
stateDesc(tr("Unknown state")),
mode("MAV_MODE_UNKNOWN"),
thrust(0),
isActive(false),
x(0),
y(0),
z(0),
totalSpeed(0),
lat(0),
lon(0),
alt(0),
groundDistance(0),
localFrame(false),
globalFrameKnown(false),
removeAction(new QAction(tr("Delete this system"), this)),
renameAction(new QAction(tr("Rename.."), this)),
selectAction(new QAction(tr("Control this system"), this)),
hilAction(new QAction(tr("HIL - Hardware in the Loop"), this)),
selectAirframeAction(new QAction(tr("Choose Airframe"), this)),
setBatterySpecsAction(new QAction(tr("Set Battery Options"), this)),
lowPowerModeEnabled(true),
generalUpdateCount(0),
filterTime(0),
m_ui(new Ui::UASView)
{
m_ui->setupUi(this);
setToolTip(""); // Make sure the QGroupBox's tooltip doesn't seep through.
// FIXME XXX
lowPowerModeEnabled = MainWindow::instance()->lowPowerModeEnabled();
hilAction->setCheckable(true);
// Setup communication
//connect(uas, SIGNAL(valueChanged(int,QString,double,quint64)), this, SLOT(receiveValue(int,QString,double,quint64)));
connect(uas, SIGNAL(batteryChanged(UASInterface*, double, double, double, int)), this, SLOT(updateBattery(UASInterface*, double, double, double, int)));
connect(uas, SIGNAL(heartbeat(UASInterface*)), this, SLOT(receiveHeartbeat(UASInterface*)));
connect(uas, SIGNAL(thrustChanged(UASInterface*, double)), this, SLOT(updateThrust(UASInterface*, double)));
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,double,quint64)), this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,double,quint64)));
connect(uas, SIGNAL(velocityChanged_NED(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64)));
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(heartbeatTimeout(bool, unsigned int)), this, SLOT(heartbeatTimeout(bool, unsigned int)));
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)));
connect(uas, SIGNAL(textMessageReceived(int,int,int,QString)), this, SLOT(showStatusText(int, int, int, QString)));
connect(uas, SIGNAL(navModeChanged(int, int, QString)), this, SLOT(updateNavMode(int, int, QString)));
connect(MultiVehicleManager::instance(), &MultiVehicleManager::activeVehicleChanged, this, &UASView::_activeVehicleChanged);
// Setup user interaction
connect(m_ui->liftoffButton, SIGNAL(clicked()), uas, SLOT(launch()));
connect(m_ui->haltButton, SIGNAL(clicked()), uas, SLOT(halt()));
connect(m_ui->continueButton, SIGNAL(clicked()), uas, SLOT(go()));
connect(m_ui->landButton, SIGNAL(clicked()), uas, SLOT(land()));
connect(m_ui->abortButton, SIGNAL(clicked()), uas, SLOT(emergencySTOP()));
connect(m_ui->killButton, SIGNAL(clicked()), uas, SLOT(emergencyKILL()));
connect(m_ui->shutdownButton, SIGNAL(clicked()), uas, SLOT(shutdown()));
// Allow deleting this widget
connect(renameAction, SIGNAL(triggered()), this, SLOT(rename()));
connect(selectAction, &QAction::triggered, this, &UASView::_activateVehicle);
connect(selectAirframeAction, SIGNAL(triggered()), this, SLOT(selectAirframe()));
connect(setBatterySpecsAction, SIGNAL(triggered()), this, SLOT(setBatterySpecs()));
// Name changes
connect(uas, SIGNAL(nameChanged(QString)), this, SLOT(updateName(QString)));
// Set static values
// Name
if (uas->getUASName() == "")
{
m_ui->nameLabel->setText(tr("UAS") + QString::number(uas->getUASID()));
}
else
{
m_ui->nameLabel->setText(uas->getUASName());
}
// Heartbeat fade
refreshTimer = new QTimer(this);
connect(refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
if (lowPowerModeEnabled)
{
refreshTimer->start(updateInterval*3);
}
else
{
refreshTimer->start(updateInterval);
}
// Style some elements by default to the UAS' color.
heartbeatColor = uas->getColor();
QString colorstyle("QLabel { background-color: %1; }");
m_ui->typeLabel->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
_activeVehicleChanged(vehicle);
// Hide kill and shutdown buttons by default
m_ui->killButton->hide();
m_ui->shutdownButton->hide();
// Set state and mode
updateMode(uas->getUASID(), uas->getShortMode(), "");
updateState(uas, uas->getShortState(), "");
setSystemType(uas, uas->getSystemType());
}
UASView::~UASView()
{
delete m_ui;
}
void UASView::_activateVehicle(void)
{
MultiVehicleManager::instance()->setActiveVehicle(vehicle);
}
void UASView::heartbeatTimeout(bool timeout, unsigned int ms)
{
Q_UNUSED(ms);
this->timeout = timeout;
}
void UASView::updateNavMode(int uasid, int mode, const QString& text)
{
Q_UNUSED(uasid);
Q_UNUSED(mode);
m_ui->navLabel->setText(text);
}
void UASView::showStatusText(int uasid, int componentid, int severity, QString text)
{
Q_UNUSED(uasid);
Q_UNUSED(componentid);
Q_UNUSED(severity);
//m_ui->statusTextLabel->setText(text);
stateDesc = text;
}
void UASView::setUASasActive(bool active)
{
if (active)
{
MultiVehicleManager::instance()->setActiveVehicle(vehicle);
}
}
void UASView::_activeVehicleChanged(Vehicle* vehicle)
{
bool active = false;
if (vehicle) {
active = vehicle->uas() == this->uas;
}
this->isActive = active;
if (isActive)
{
setStyleSheet("UASView { border-width: 3px}");
}
else
{
setStyleSheet(QString("UASView { border-color: %1}").arg(heartbeatColor.name()));
}
}
void UASView::updateMode(int sysId, QString status, QString description)
{
Q_UNUSED(description);
//int aa=this->uas->getUASID();
if (sysId == this->uas->getUASID()) m_ui->modeLabel->setText(status);
m_ui->modeLabel->setText(status);
}
void UASView::mouseDoubleClickEvent (QMouseEvent * event)
{
Q_UNUSED(event);
MultiVehicleManager::instance()->setActiveVehicle(vehicle);
}
void UASView::receiveHeartbeat(UASInterface* uas)
{
heartbeatColor = uas->getColor();
QString colorstyle("QLabel { background-color: %1; }");
m_ui->heartBeatLabel->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
// If we're returning from a disconnection, recolor things properly.
if (disconnected)
{
_activeVehicleChanged(vehicle);
disconnected = false;
}
timeout = false;
}
void UASView::updateName(const QString& name)
{
if (uas) m_ui->nameLabel->setText(name);
}
/**
* The current system type is represented through the system icon.
*
* @param uas Source system, has to be the same as this->uas
* @param systemType type ID, following the MAVLink system type conventions
* @see http://pixhawk.ethz.ch/software/mavlink
*/
void UASView::setSystemType(UASInterface* uas, unsigned int systemType)
{
if (uas == this->uas)
{
// Set matching icon
switch (systemType)
{
case MAV_TYPE_GENERIC:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Generic"));
break;
case MAV_TYPE_FIXED_WING:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/FixedWing"));
break;
case MAV_TYPE_QUADROTOR:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/QuadRotor"));
break;
case MAV_TYPE_COAXIAL:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Coaxial"));
break;
case MAV_TYPE_HELICOPTER:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Helicopter"));
break;
case MAV_TYPE_ANTENNA_TRACKER:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Unknown"));
break;
case MAV_TYPE_GCS: {
// A groundstation is a special system type, update widget
QString result;
m_ui->nameLabel->setText(tr("GCS ") + result.sprintf("%03d", uas->getUASID()));
m_ui->waypointLabel->setText("");
m_ui->timeRemainingLabel->setText("Online:");
m_ui->batteryBar->hide();
m_ui->thrustBar->hide();
m_ui->stateLabel->hide();
m_ui->statusTextLabel->hide();
m_ui->waypointLabel->hide();
m_ui->liftoffButton->hide();
m_ui->haltButton->hide();
m_ui->landButton->hide();
m_ui->shutdownButton->hide();
m_ui->abortButton->hide();
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Groundstation"));
}
break;
case MAV_TYPE_AIRSHIP:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Airship"));
break;
case MAV_TYPE_FREE_BALLOON:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/FreeBalloon"));
break;
case MAV_TYPE_ROCKET:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Rocket"));
break;
case MAV_TYPE_GROUND_ROVER:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/GroundRover"));
break;
case MAV_TYPE_SURFACE_BOAT:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/SurfaceBoat"));
break;
case MAV_TYPE_SUBMARINE:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Submarine"));
break;
case MAV_TYPE_HEXAROTOR:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/HexaRotor"));
break;
case MAV_TYPE_OCTOROTOR:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/OctoRotor"));
break;
case MAV_TYPE_TRICOPTER:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/TriCopter"));
break;
case MAV_TYPE_FLAPPING_WING:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/FlappingWing"));
break;
case MAV_TYPE_KITE:
m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Kite"));
break;
default:
m_ui->typeLabel->setPixmap(QPixmap("://res/mavs/Unknown"));
break;
}
}
}
void UASView::updateLocalPosition(UASInterface* uas, double x, double y, double z, quint64 usec)
{
Q_UNUSED(usec);
Q_UNUSED(uas);
this->x = x;
this->y = y;
this->z = z;
localFrame = true;
}
void UASView::updateGlobalPosition(UASInterface* uas, double lat, double lon, double altAMSL, double altWGS84, quint64 usec)
{
Q_UNUSED(uas);
Q_UNUSED(usec);
Q_UNUSED(altAMSL);
this->lon = lon;
this->lat = lat;
this->alt = altWGS84;
globalFrameKnown = true;
}
void UASView::updateSpeed(UASInterface*, double x, double y, double z, quint64 usec)
{
Q_UNUSED(usec);
totalSpeed = sqrt(x*x + y*y + z*z);
}
void UASView::currentWaypointUpdated(quint16 waypoint)
{
m_ui->waypointLabel->setText(tr("WP") + QString::number(waypoint));
}
void UASView::setWaypoint(int uasId, int id, double x, double y, double z, double yaw, bool autocontinue, bool current)
{
Q_UNUSED(x);
Q_UNUSED(y);
Q_UNUSED(z);
Q_UNUSED(yaw);
Q_UNUSED(autocontinue);
if (uasId == this->uas->getUASID())
{
if (current)
{
m_ui->waypointLabel->setText(tr("WP") + QString::number(id));
}
}
}
void UASView::selectWaypoint(int uasId, int id)
{
if (uasId == this->uas->getUASID())
{
m_ui->waypointLabel->setText(tr("WP") + QString::number(id));
}
}
void UASView::updateThrust(UASInterface* uas, double thrust)
{
if (this->uas == uas)
{
this->thrust = thrust;
}
}
void UASView::updateBattery(UASInterface* uas, double voltage, double current, double percent, int seconds)
{
Q_UNUSED(voltage);
Q_UNUSED(current);
if (this->uas == uas)
{
timeRemaining = seconds;
chargeLevel = percent;
}
}
void UASView::updateState(UASInterface* uas, QString uasState, QString stateDescription)
{
if (this->uas == uas)
{
state = uasState;
stateDesc = stateDescription;
}
}
void UASView::updateLoad(UASInterface* uas, double load)
{
if (this->uas == uas)
{
this->load = load;
}
}
/**
* Right-clicking on the view provides a custom menu for interacting
* with the UAS.
*/
void UASView::contextMenuEvent (QContextMenuEvent* event)
{
QMenu menu(this);
menu.addAction(selectAction);
menu.addSeparator();
menu.addAction(renameAction);
/*
FIXME: The code below is incorrect. removeAction should only be available when link is
disconnected. fSee Issue #1275
if (timeout)
{
menu.addAction(removeAction);
}
*/
menu.addAction(hilAction);
menu.addAction(selectAirframeAction);
menu.addAction(setBatterySpecsAction);
menu.exec(event->globalPos());
}
void UASView::setBatterySpecs()
{
if (uas)
{
bool ok;
QString newName = QInputDialog::getText(this, tr("Set Battery Specifications for %1").arg(uas->getUASName()),
tr("Specs: (empty,warn,full), e.g. (9V,9.5V,12.6V) or just warn level in percent (e.g. 15%) to use estimate from MAV"), QLineEdit::Normal,
uas->getBatterySpecs(), &ok);
if (ok && !newName.isEmpty()) uas->setBatterySpecs(newName);
}
}
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);
}
}
void UASView::selectAirframe()
{
if (uas)
{
// Get list of airframes from UAS
QStringList airframes;
airframes << "Generic"
<< "Multiplex Easystar"
<< "Multiplex Twinstar"
<< "Multiplex Merlin"
<< "Pixhawk Cheetah"
<< "Mikrokopter"
<< "Reaper"
<< "Predator"
<< "Coaxial"
<< "Pteryx"
<< "Tricopter"
<< "Asctec Firefly"
<< "X8 Flying Wing"
<< "Viper 2.0 Flying Wing"
<< "Cam Flyer Q Flying Wing";
bool ok;
QString item = QInputDialog::getItem(this, tr("Select Airframe for %1").arg(uas->getUASName()),
tr("Airframe"), airframes, uas->getAirframe(), false, &ok);
if (ok && !item.isEmpty())
{
// Set this airframe as UAS airframe
uas->setAirframe(airframes.indexOf(item));
}
}
}
void UASView::refresh()
{
if (generalUpdateCount == 4)
{
#if (QGC_EVENTLOOP_DEBUG)
// qDebug() << "EVENTLOOP:" << __FILE__ << __LINE__;
#endif
generalUpdateCount = 0;
//// qDebug() << "UPDATING EVERYTHING";
// State
m_ui->stateLabel->setText(state);
m_ui->statusTextLabel->setText(stateDesc);
// Battery
m_ui->batteryBar->setValue(static_cast<int>(this->chargeLevel));
//m_ui->loadBar->setValue(static_cast<int>(this->load));
m_ui->thrustBar->setValue(this->thrust);
// Position
// If global position is known, prefer it over local coordinates
if (!globalFrameKnown && localFrame)
{
QString position;
position = position.sprintf("%05.1f %05.1f %06.1f m", x, y, z);
m_ui->positionLabel->setText(position);
}
if (globalFrameKnown)
{
QString globalPosition;
QString latIndicator;
if (lat > 0)
{
latIndicator = "N";
}
else
{
latIndicator = "S";
}
QString lonIndicator;
if (lon > 0)
{
lonIndicator = "E";
}
else
{
lonIndicator = "W";
}
globalPosition = globalPosition.sprintf("%6.2f%s %6.2f%s %6.1f m", fabs(lon), lonIndicator.toStdString().c_str(), fabs(lat), latIndicator.toStdString().c_str(), alt);
m_ui->positionLabel->setText(globalPosition);
}
// Altitude
if (groundDistance == 0 && alt != 0)
{
m_ui->groundDistanceLabel->setText(QString("%1 m").arg(alt, 6, 'f', 1, '0'));
}
else
{
m_ui->groundDistanceLabel->setText(QString("%1 m").arg(groundDistance, 6, 'f', 1, '0'));
}
// Speed
QString speed("%1 m/s");
m_ui->speedLabel->setText(speed.arg(totalSpeed, 4, 'f', 1, '0'));
// Thrust
m_ui->thrustBar->setValue(thrust * 100);
// Time Elapsed
//QDateTime time = MG::TIME::msecToQDateTime(uas->getUptime());
quint64 filterTime = uas->getUptime() / 1000;
int hours = static_cast<int>(filterTime / 3600);
int min = static_cast<int>((filterTime - 3600 * hours) / 60);
int sec = static_cast<int>(filterTime - 60 * min - 3600 * hours);
QString timeText;
timeText = timeText.sprintf("%02d:%02d:%02d", hours, min, sec);
m_ui->timeElapsedLabel->setText(timeText);
if(this->timeRemaining > 1 && this->timeRemaining < QGC::MAX_FLIGHT_TIME)
{
// Filter output to get a higher stability
filterTime = static_cast<int>(this->timeRemaining);
// filterTime = 0.8 * filterTime + 0.2 * static_cast<int>(this->timeRemaining);
hours = static_cast<int>(filterTime / 3600);
min = static_cast<int>((filterTime - 3600 * hours) / 60);
sec = static_cast<int>(filterTime - 60 * min - 3600 * hours);
timeText = timeText.sprintf("%02d:%02d:%02d", hours, min, sec);
m_ui->timeRemainingLabel->setText(timeText);
}
else
{
m_ui->timeRemainingLabel->setText(tr("Calc.."));
}
}
generalUpdateCount++;
if (timeout)
{
// CRITICAL CONDITION, NO HEARTBEAT
disconnected = true;
QColor warnColor;
if (iconIsRed)
{
warnColor = Qt::red;
}
else
{
warnColor = Qt::darkRed;
refreshTimer->setInterval(errorUpdateInterval);
refreshTimer->start();
}
QString style = QString("UASView {background-color: %1;}").arg(warnColor.name());
this->setStyleSheet(style);
iconIsRed = !iconIsRed;
}
else
{
// If we're not in low power mode, add the additional visual effect of
// fading out the color of the heartbeat for this UAS.
if (!lowPowerModeEnabled)
{
heartbeatColor = heartbeatColor.darker(110);
QString colorstyle("QLabel {background-color: %1;}");
m_ui->heartBeatLabel->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
refreshTimer->setInterval(updateInterval);
refreshTimer->start();
}
}
}
void UASView::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
switch (e->type())
{
case QEvent::LanguageChange:
m_ui->retranslateUi(this);
break;
default:
break;
}
}
void UASView::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Definition of class UASView
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#ifndef UASVIEW_H
#define UASVIEW_H
#include <QWidget>
#include <QString>
#include <QTimer>
#include <QMouseEvent>
#include "Vehicle.h"
#include "UASInterface.h"
namespace Ui
{
class UASView;
}
class UASView : public QWidget
{
Q_OBJECT
public:
UASView(Vehicle* vehicle, QWidget *parent = 0);
~UASView();
Vehicle* vehicle;
UASInterface* uas;
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 current, double percent, int seconds);
void updateLocalPosition(UASInterface*, double x, double y, double z, quint64 usec);
void updateGlobalPosition(UASInterface*, double lat, double lon, double altAMSL, double altWGS84, quint64 usec);
void updateSpeed(UASInterface*, double x, double y, double z, quint64 usec);
void updateState(UASInterface*, QString uasState, QString stateDescription);
/** @brief Update the MAV mode */
void updateMode(int sysId, QString status, QString description);
void updateLoad(UASInterface* uas, double load);
//void receiveValue(int uasid, QString id, double value, quint64 time);
void refresh();
/** @brief Receive new waypoint information */
void setWaypoint(int uasId, int id, double x, double y, double z, double yaw, bool autocontinue, bool current);
/** @brief Update the current active waypoint */
void currentWaypointUpdated(quint16 waypoint);
/** @brief Set waypoint as current target */
void selectWaypoint(int uasId, int id);
/** @brief Set the current system type */
void setSystemType(UASInterface* uas, unsigned int systemType);
/** @brief Set the current UAS as the globally active system */
void setUASasActive(bool);
/** @brief Set the widget into critical mode */
void heartbeatTimeout(bool timeout, unsigned int ms);
/** @brief Bring up the dialog to rename the system */
void rename();
/** @brief Select airframe for this vehicle */
void selectAirframe();
/** @brief Select the battery type */
void setBatterySpecs();
/** @brief Show a status text message */
void showStatusText(int uasid, int componentid, int severity, QString text);
/** @brief Update the navigation mode state */
void updateNavMode(int uasid, int mode, const QString& text);
protected:
void changeEvent(QEvent *e);
QTimer* refreshTimer;
QColor heartbeatColor;
quint64 startTime;
bool timeout;
bool iconIsRed;
bool disconnected;
int timeRemaining;
float chargeLevel;
float load;
QString state;
QString stateDesc;
QString mode;
double thrust; ///< Current vehicle thrust: 0 - 1.0 for 100% thrust
bool isActive; ///< Is this MAV selected by the user?
float x;
float y;
float z;
float totalSpeed;
float lat;
float lon;
float alt;
float groundDistance;
bool localFrame;
bool globalFrameKnown;
QAction* removeAction;
QAction* renameAction;
QAction* selectAction;
QAction* hilAction;
QAction* hilXAction;
QAction* selectAirframeAction;
QAction* setBatterySpecsAction;
static const int updateInterval = 800;
static const int errorUpdateInterval = 200;
bool lowPowerModeEnabled; ///< Low power mode reduces update rates
unsigned int generalUpdateCount; ///< Skip counter for updates
double filterTime; ///< Filter time estimate of battery
/**
* If a user double-clicks on this view, set the active UAS to this one.
*/
void mouseDoubleClickEvent(QMouseEvent *event);
/**
* Right-clicking on the view provides a custom menu for interacting
* with the UAS.
*/
void contextMenuEvent(QContextMenuEvent *event);
private slots:
void _activeVehicleChanged(Vehicle* vehicle);
void _activateVehicle(void);
private:
Ui::UASView *m_ui;
/**
* Implement paintEvent() so that stylesheets work for our custom widget.
*/
virtual void paintEvent(QPaintEvent *event);
};
#endif // UASVIEW_H
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