Commit eb3eb94a authored by dogmaphobic's avatar dogmaphobic

Primary Flight Display

New version using QtQuick along with an experimental Map Background
parent a251c07d
......@@ -264,6 +264,7 @@ INCLUDEPATH += \
src/ui/px4_configuration \
src/ui/main \
src/ui/toolbar \
src/ui/flightdisplay \
src/VehicleSetup \
src/AutoPilotPlugins \
src/QmlControls
......@@ -490,7 +491,8 @@ HEADERS += \
src/uas/UASMessageHandler.h \
src/ui/toolbar/MainToolBar.h \
src/QmlControls/ScreenTools.h \
src/QGCLoggingCategory.h
src/QGCLoggingCategory.h \
src/ui/flightdisplay/QGCFlightDisplay.h
SOURCES += \
src/main.cc \
......@@ -631,7 +633,8 @@ SOURCES += \
src/uas/UASMessageHandler.cc \
src/ui/toolbar/MainToolBar.cc \
src/QmlControls/ScreenTools.cc \
src/QGCLoggingCategory.cc
src/QGCLoggingCategory.cc \
src/ui/flightdisplay/QGCFlightDisplay.cc
#
# Unit Test specific configuration goes here
......
......@@ -305,6 +305,21 @@
<file alias="PowerComponentBattery_05cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_05cell.svg</file>
<file alias="PowerComponentBattery_06cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_06cell.svg</file>
<file alias="MainToolBar.qml">src/ui/toolbar/MainToolBar.qml</file>
<file alias="FlightDisplay.qml">src/ui/flightdisplay/FlightDisplay.qml</file>
<file alias="QGroundControl/HUDControls/qmldir">src/ui/flightdisplay/components/qmldir</file>
<file alias="QGroundControl/HUDControls/QGCAltitudeWidget.qml">src/ui/flightdisplay/components/QGCAltitudeWidget.qml</file>
<file alias="QGroundControl/HUDControls/QGCAttitudeWidget.qml">src/ui/flightdisplay/components/QGCAttitudeWidget.qml</file>
<file alias="QGroundControl/HUDControls/QGCCompass.qml">src/ui/flightdisplay/components/QGCCompass.qml</file>
<file alias="QGroundControl/HUDControls/QGCCurrentAltitude.qml">src/ui/flightdisplay/components/QGCCurrentAltitude.qml</file>
<file alias="QGroundControl/HUDControls/QGCCurrentSpeed.qml">src/ui/flightdisplay/components/QGCCurrentSpeed.qml</file>
<file alias="QGroundControl/HUDControls/QGCMapBackground.qml">src/ui/flightdisplay/components/QGCMapBackground.qml</file>
<file alias="QGroundControl/HUDControls/QGCPitchWidget.qml">src/ui/flightdisplay/components/QGCPitchWidget.qml</file>
<file alias="QGroundControl/HUDControls/QGCSpeedWidget.qml">src/ui/flightdisplay/components/QGCSpeedWidget.qml</file>
<file alias="compass.svg">src/ui/flightdisplay/components/compass.svg</file>
<file alias="compassNeedle.svg">src/ui/flightdisplay/components/compassNeedle.svg</file>
<file alias="crossHair.svg">src/ui/flightdisplay/components/crossHair.svg</file>
<file alias="rollDial.svg">src/ui/flightdisplay/components/rollDial.svg</file>
<file alias="rollPointer.svg">src/ui/flightdisplay/components/rollPointer.svg</file>
</qresource>
<qresource prefix="/AutoPilotPlugins/PX4">
<file alias="ParameterFactMetaData.xml">src/AutoPilotPlugins/PX4/ParameterFactMetaData.xml</file>
......
......@@ -49,6 +49,7 @@ public:
// Implemented UASInterface overrides
virtual int getSystemType(void) { return _systemType; }
virtual int getUASID(void) const { return _systemId; }
virtual bool isAirplane() { return false; }
virtual QGCUASParamManagerInterface* getParamManager() { return &_paramManager; };
// sendMessage is only supported if a mavlink plugin is installed.
......
......@@ -2673,6 +2673,21 @@ int UAS::getSystemType()
return this->type;
}
/** @brief Is it an airplane (or like one)?,..)*/
bool UAS::isAirplane()
{
switch(this->type) {
case MAV_TYPE_GENERIC:
case MAV_TYPE_FIXED_WING:
case MAV_TYPE_AIRSHIP:
case MAV_TYPE_FLAPPING_WING:
return true;
default:
break;
}
return false;
}
/**
* Halt the uas.
*/
......
......@@ -508,7 +508,8 @@ public:
}
int getSystemType();
int getSystemType();
bool isAirplane();
/**
* @brief Returns true for systems that can reverse. If the system has no control over position, it returns false as
......
......@@ -213,6 +213,8 @@ public:
/** @brief Get the type of the system (airplane, quadrotor, helicopter,..)*/
virtual int getSystemType() = 0;
/** @brief Is it an airplane (or like one)?,..)*/
virtual bool isAirplane() = 0;
/** @brief Indicates whether this system is capable of controlling a reverse velocity.
* Used for, among other things, altering joystick input to either -1:1 or 0:1 range.
*/
......
......@@ -60,6 +60,7 @@ This file is part of the QGROUNDCONTROL project
#include "QGCTabbedInfoView.h"
#include "UASRawStatusView.h"
#include "PrimaryFlightDisplay.h"
#include "QGCFlightDisplay.h"
#include "SetupView.h"
#include "SerialSettingsDialog.h"
#include "terminalconsole.h"
......@@ -447,7 +448,8 @@ void MainWindow::_buildPlannerView(void)
void MainWindow::_buildPilotView(void)
{
if (!_pilotView) {
_pilotView = new PrimaryFlightDisplay(this);
//_pilotView = new PrimaryFlightDisplay(this);
_pilotView = new QGCFlightDisplay(this);
_pilotView->setVisible(false);
}
}
......@@ -560,7 +562,8 @@ void MainWindow::_createInnerDockWidget(const QString& widgetName)
widget = hddisplay;
} else if (widgetName == _pfdDockWidgetName) {
widget = new PrimaryFlightDisplay(this);
widget = new QGCFlightDisplay(this);
//widget = new PrimaryFlightDisplay(this);
} else if (widgetName == _hudDockWidgetName) {
widget = new HUD(320,240,this);
} else if (widgetName == _uasInfoViewDockWidgetName) {
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 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 QGC Main Tool Bar
* @author Gus Grubba <mavlink@grubba.com>
*/
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QGroundControl.HUDControls 1.0
Rectangle {
id: root
color: Qt.rgba(0,0,0,0);
property real roll: isNaN(flightDisplay.roll) ? 0 : flightDisplay.roll
property real pitch: isNaN(flightDisplay.pitch) ? 0 : flightDisplay.pitch
Component.onCompleted:
{
mapBackground.visible = flightDisplay.loadSetting("enableMapBackground", false);
mapBackground.alwaysNorth = flightDisplay.loadSetting("mapAlwaysNorth", false);
attitudeWidget.visible = flightDisplay.loadSetting("enableattitudeWidget", true);
attitudeWidget.displayBackground = flightDisplay.loadSetting("displayRollPitchBackground", true);
pitchWidget.visible = flightDisplay.loadSetting("enablepitchWidget", true);
altitudeWidget.visible = flightDisplay.loadSetting("enablealtitudeWidget", true);
speedWidget.visible = flightDisplay.loadSetting("enablespeedWidget", true);
compassIndicator.visible = flightDisplay.loadSetting("enableCompassIndicator", true);
currentSpeed.showAirSpeed = flightDisplay.loadSetting("showAirSpeed", true);
currentSpeed.showGroundSpeed = flightDisplay.loadSetting("showGroundSpeed", true);
currentAltitude.showClimbRate = flightDisplay.loadSetting("showCurrentClimbRate", true);
currentAltitude.showAltitude = flightDisplay.loadSetting("showCurrentAltitude", true);
mapTypeMenu.update();
}
Rectangle {
id: windowBackground
anchors.fill: parent
anchors.centerIn: parent
visible: !attitudeWidget.visible && !mapBackground.visible
color: Qt.hsla(0.25, 0.5, 0.45)
z: 0
}
Menu {
id: mapTypeMenu
function setCurrentMap(map) {
for (var i = 0; i < mapBackground.mapItem.supportedMapTypes.length; i++) {
if (map === mapBackground.mapItem.supportedMapTypes[i].name) {
mapBackground.mapItem.activeMapType = mapBackground.mapItem.supportedMapTypes[i]
return;
}
}
}
function addMap(map) {
var mItem = mapTypeMenu.addItem(map);
var menuSlot = function() {setCurrentMap(map);};
mItem.triggered.connect(menuSlot);
}
function update() {
clear()
for (var i = 0; i < mapBackground.mapItem.supportedMapTypes.length; i++) {
addMap(mapBackground.mapItem.supportedMapTypes[i].name);
}
if (mapBackground.mapItem.supportedMapTypes.length > 0)
setCurrentMap(mapBackground.mapItem.activeMapType.name);
}
}
Menu {
id: contextMenu
MenuItem {
text: "Roll/Pitch Indicators"
checkable: true
checked: attitudeWidget.visible
onTriggered:
{
attitudeWidget.visible = !attitudeWidget.visible;
flightDisplay.saveSetting("enableattitudeWidget", attitudeWidget.visible);
}
}
MenuItem {
text: "Display Roll/Pitch Background"
checkable: true
checked: attitudeWidget.displayBackground
onTriggered:
{
attitudeWidget.displayBackground = !attitudeWidget.displayBackground;
flightDisplay.saveSetting("displayRollPitchBackground", attitudeWidget.displayBackground);
}
}
MenuItem {
text: "Pitch Indicator"
checkable: true
checked: pitchWidget.visible
onTriggered:
{
pitchWidget.visible = !pitchWidget.visible;
flightDisplay.saveSetting("enablepitchWidget", pitchWidget.visible);
}
}
MenuItem {
text: "Altitude Indicator"
checkable: true
checked: altitudeWidget.visible
onTriggered:
{
altitudeWidget.visible = !altitudeWidget.visible;
flightDisplay.saveSetting("enablealtitudeWidget", altitudeWidget.visible);
}
}
MenuItem {
text: "Current Altitude"
checkable: true
checked: currentAltitude.showAltitude
onTriggered:
{
currentAltitude.showAltitude = !currentAltitude.showAltitude;
flightDisplay.saveSetting("showCurrentAltitude", currentAltitude.showAltitude);
}
}
MenuItem {
text: "Current Climb Rate"
checkable: true
checked: currentAltitude.showClimbRate
onTriggered:
{
currentAltitude.showClimbRate = !currentAltitude.showClimbRate;
flightDisplay.saveSetting("showCurrentClimbRate", currentAltitude.showClimbRate);
}
}
MenuItem {
text: "Speed Indicator"
checkable: true
checked: speedWidget.visible
onTriggered:
{
speedWidget.visible = !speedWidget.visible;
flightDisplay.saveSetting("enablespeedWidget", speedWidget.visible);
}
}
MenuItem {
text: "Current Air Speed"
checkable: true
checked: currentSpeed.showAirSpeed
onTriggered:
{
currentSpeed.showAirSpeed = !currentSpeed.showAirSpeed;
flightDisplay.saveSetting("showAirSpeed", currentSpeed.showAirSpeed);
}
}
MenuItem {
text: "Current Ground Speed"
checkable: true
checked: currentSpeed.showGroundSpeed
onTriggered:
{
currentSpeed.showGroundSpeed = !currentSpeed.showGroundSpeed;
flightDisplay.saveSetting("showGroundSpeed", currentSpeed.showGroundSpeed);
}
}
MenuItem {
text: "Compass"
checkable: true
checked: compassIndicator.visible
onTriggered:
{
compassIndicator.visible = !compassIndicator.visible;
flightDisplay.saveSetting("enableCompassIndicator", compassIndicator.visible);
}
}
MenuSeparator {}
MenuItem {
text: "Map Background"
checkable: true
checked: mapBackground.visible
onTriggered:
{
mapBackground.visible = !mapBackground.visible;
flightDisplay.saveSetting("enableMapBackground", mapBackground.visible);
}
}
MenuItem {
text: "Map Follows Heading"
checkable: true
checked: !mapBackground.alwaysNorth
onTriggered:
{
mapBackground.alwaysNorth = !mapBackground.alwaysNorth;
flightDisplay.saveSetting("mapAlwaysNorth", mapBackground.alwaysNorth);
}
}
MenuItem {
text: "Map Type..."
checkable: false
onTriggered:
{
mapTypeMenu.popup();
}
}
MenuSeparator {}
MenuItem {
text: "Restore Defaults"
onTriggered:
{
attitudeWidget.visible = true;
flightDisplay.saveSetting("enableattitudeWidget", attitudeWidget.visible);
attitudeWidget.displayBackground = true;
flightDisplay.saveSetting("displayRollPitchBackground", attitudeWidget.displayBackground);
pitchWidget.visible = true;
flightDisplay.saveSetting("enablepitchWidget", pitchWidget.visible);
altitudeWidget.visible = true;
flightDisplay.saveSetting("enablealtitudeWidget", altitudeWidget.visible);
currentAltitude.showAltitude = true;
flightDisplay.saveSetting("showCurrentAltitude", currentAltitude.showAltitude);
currentAltitude.showClimbRate = true;
flightDisplay.saveSetting("showCurrentClimbRate", currentAltitude.showClimbRate);
speedWidget.visible = true;
flightDisplay.saveSetting("enablespeedWidget", speedWidget.visible);
currentSpeed.showAirSpeed = true;
flightDisplay.saveSetting("showAirSpeed", currentSpeed.showAirSpeed);
currentSpeed.showGroundSpeed = true;
flightDisplay.saveSetting("showGroundSpeed", currentSpeed.showGroundSpeed);
compassIndicator.visible = true;
flightDisplay.saveSetting("enableCompassIndicator", compassIndicator.visible);
mapBackground.visible = false;
flightDisplay.saveSetting("enableMapBackground", mapBackground.visible);
mapBackground.alwaysNorth = false;
flightDisplay.saveSetting("mapAlwaysNorth", mapBackground.alwaysNorth);
}
}
}
QGCMapBackground {
id: mapBackground
anchors.centerIn: parent
visible: false
heading: isNaN(flightDisplay.heading) ? 0 : flightDisplay.heading
latitude: flightDisplay.latitude
longitude: flightDisplay.longitude
z: 5
}
QGCAttitudeWidget {
id: attitudeWidget
anchors.centerIn: parent
rollAngle: roll
pitchAngle: pitch
backgroundOpacity: mapBackground.visible ? 0.25 : 1.0
z: 10
}
QGCPitchWidget {
id: pitchWidget
anchors.verticalCenter: parent.verticalCenter
opacity: 0.5
pitchAngle: pitch
rollAngle: roll
z: 20
}
QGCAltitudeWidget {
id: altitudeWidget
anchors.right: parent.right
width: 40
altitude: flightDisplay.altitudeWGS84
z: 30
}
QGCSpeedWidget {
id: speedWidget
anchors.left: parent.left
width: 40
speed: flightDisplay.groundSpeed
z: 40
}
QGCCurrentSpeed {
id: currentSpeed
anchors.left: parent.left
width: 80
airspeed: flightDisplay.airSpeed
groundspeed: flightDisplay.groundSpeed
showAirSpeed: true
showGroundSpeed: true
visible: currentSpeed.showGroundSpeed || currentSpeed.showAirSpeed
z: 50
}
QGCCurrentAltitude {
id: currentAltitude
anchors.right: parent.right
width: 80
altitude: flightDisplay.altitudeWGS84
vertZ: flightDisplay.climbRate
showAltitude: true
showClimbRate: true
visible: (currentAltitude.showAltitude || currentAltitude.showClimbRate)
z: 60
}
QGCCompass {
id: compassIndicator
y: root.height * 0.65
anchors.horizontalCenter: parent.horizontalCenter
heading: isNaN(flightDisplay.heading) ? 0 : flightDisplay.heading
z: 70
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked: {
if (mouse.button == Qt.RightButton)
{
contextMenu.popup()
}
}
z: 100
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 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 QGC Main Flight Display
* @author Gus Grubba <mavlink@grubba.com>
*/
#include <QQmlContext>
#include <QQmlEngine>
#include <QSettings>
#include "QGCFlightDisplay.h"
#include "UASManager.h"
#define UPDATE_TIMER 50
const char* kMainFlightDisplayGroup = "MainFlightDisplay";
QGCFlightDisplay::QGCFlightDisplay(QWidget *parent)
: QGCQmlWidgetHolder(parent)
, _mav(NULL)
, _roll(0.0)
, _pitch(0.0)
, _heading(0.0)
, _altitudeAMSL(0.0)
, _altitudeWGS84(0.0)
, _altitudeRelative(0.0)
, _groundSpeed(0.0)
, _airSpeed(0.0)
, _climbRate(0.0)
, _navigationAltitudeError(0.0)
, _navigationSpeedError(0.0)
, _navigationCrosstrackError(0.0)
, _navigationTargetBearing(0.0)
, _latitude(37.803784)
, _longitude(-122.462276)
, _refreshTimer(new QTimer(this))
, _valuesChanged(false)
, _valuesLastPainted(0)
{
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
setObjectName("MainFlightDisplay");
// Get rid of layout default margins
QLayout* pl = layout();
if(pl) {
pl->setContentsMargins(0,0,0,0);
}
setMinimumWidth(270);
setMinimumHeight(300);
setContextPropertyObject("flightDisplay", this);
setSource(QUrl::fromUserInput("qrc:/qml/FlightDisplay.qml"));
setVisible(true);
// Connect with UAS signal
_setActiveUAS(UASManager::instance()->getActiveUAS());
connect(UASManager::instance(), SIGNAL(UASDeleted(UASInterface*)), this, SLOT(_forgetUAS(UASInterface*)));
connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(_setActiveUAS(UASInterface*)));
// Refresh timer
_refreshTimer->setInterval(UPDATE_TIMER);
connect(_refreshTimer, SIGNAL(timeout()), this, SLOT(_checkUpdate()));
}
QGCFlightDisplay::~QGCFlightDisplay()
{
_refreshTimer->stop();
}
void QGCFlightDisplay::saveSetting(const QString& name, bool value)
{
QSettings settings;
QString key(kMainFlightDisplayGroup);
key += "/" + name;
settings.setValue(key, value);
}
bool QGCFlightDisplay::loadSetting(const QString& name, bool defaultValue)
{
QSettings settings;
QString key(kMainFlightDisplayGroup);
key += "/" + name;
return settings.value(key, defaultValue).toBool();
}
void QGCFlightDisplay::_forgetUAS(UASInterface* uas)
{
if (_mav != NULL && _mav == uas) {
// Disconnect any previously connected active MAV
disconnect(_mav, SIGNAL(attitudeChanged (UASInterface*, double,double,double,quint64)), this, SLOT(_updateAttitude(UASInterface*, double, double, double, quint64)));
disconnect(_mav, SIGNAL(attitudeChanged (UASInterface*, int,double,double,double,quint64)), this, SLOT(_updateAttitude(UASInterface*,int,double, double, double, quint64)));
disconnect(_mav, SIGNAL(speedChanged (UASInterface*, double, double, quint64)), this, SLOT(_updateSpeed(UASInterface*, double, double, quint64)));
disconnect(_mav, SIGNAL(altitudeChanged (UASInterface*, double, double, double, double, quint64)), this, SLOT(_updateAltitude(UASInterface*, double, double, double, double, quint64)));
disconnect(_mav, SIGNAL(navigationControllerErrorsChanged(UASInterface*, double, double, double)), this, SLOT(_updateNavigationControllerErrors(UASInterface*, double, double, double)));
disconnect(_mav, &UASInterface::NavigationControllerDataChanged, this, &QGCFlightDisplay::_updateNavigationControllerData);
}
_mav = NULL;
}
void QGCFlightDisplay::_setActiveUAS(UASInterface* uas)
{
if (uas == _mav)
return;
// Disconnect the previous one (if any)
if(_mav) {
_forgetUAS(_mav);
}
if (uas) {
// Now connect the new UAS
// Setup communication
connect(uas, SIGNAL(attitudeChanged (UASInterface*,double,double,double,quint64)), this, SLOT(_updateAttitude(UASInterface*, double, double, double, quint64)));
connect(uas, SIGNAL(attitudeChanged (UASInterface*,int,double,double,double,quint64)), this, SLOT(_updateAttitude(UASInterface*,int,double, double, double, quint64)));
connect(uas, SIGNAL(speedChanged (UASInterface*, double, double, quint64)), this, SLOT(_updateSpeed(UASInterface*, double, double, quint64)));
connect(uas, SIGNAL(altitudeChanged (UASInterface*, double, double, double, double, quint64)), this, SLOT(_updateAltitude(UASInterface*, double, double, double, double, quint64)));
connect(uas, SIGNAL(navigationControllerErrorsChanged (UASInterface*, double, double, double)), this, SLOT(_updateNavigationControllerErrors(UASInterface*, double, double, double)));
connect(uas, &UASInterface::NavigationControllerDataChanged, this, &QGCFlightDisplay::_updateNavigationControllerData);
// Set new UAS
_mav = uas;
}
}
void QGCFlightDisplay::_updateAttitude(UASInterface*, double roll, double pitch, double yaw, quint64)
{
if (isinf(roll)) {
_roll = std::numeric_limits<double>::quiet_NaN();
} else {
bool update = false;
float rolldeg = roll * (180.0 / M_PI);
if (fabsf(roll - rolldeg) > 2.5f) {
update = true;
}
_roll = rolldeg;
if (update)
{
if(_refreshTimer->isActive()) emit rollChanged();
_valuesChanged = true;
}
}
if (isinf(pitch)) {
_pitch = std::numeric_limits<double>::quiet_NaN();
} else {
bool update = false;
float pitchdeg = pitch * (180.0 / M_PI);
if (fabsf(pitch - pitchdeg) > 2.5f) {
update = true;
}
_pitch = pitchdeg;
if (update)
{
if(_refreshTimer->isActive()) emit pitchChanged();
_valuesChanged = true;
}
}
if (isinf(yaw)) {
_heading = std::numeric_limits<double>::quiet_NaN();
} else {
bool update = false;
yaw = yaw * (180.0 / M_PI);
if (yaw < 0) yaw += 360;
if (fabsf(_heading - yaw) > 10.0f) {
update = true;
}
_heading = yaw;
if (update)
{
if(_refreshTimer->isActive()) emit headingChanged();
_valuesChanged = true;
}
}
}
void QGCFlightDisplay::_updateAttitude(UASInterface* uas, int, double roll, double pitch, double yaw, quint64 timestamp)
{
_updateAttitude(uas, roll, pitch, yaw, timestamp);
}
void QGCFlightDisplay::_updateSpeed(UASInterface*, double groundSpeed, double airSpeed, quint64)
{
double oldgroundSpeed = _groundSpeed;
double oldairSpeed = _airSpeed;
_groundSpeed = groundSpeed;
_airSpeed = airSpeed;
if (fabsf(oldgroundSpeed - groundSpeed) > 0.5f) {
if(_refreshTimer->isActive()) emit groundSpeedChanged();
_valuesChanged = true;
}
if (fabsf(oldairSpeed - airSpeed) > 1.0f) {
if(_refreshTimer->isActive()) emit airSpeedChanged();
_valuesChanged = true;
}
}
void QGCFlightDisplay::_updateAltitude(UASInterface*, double altitudeAMSL, double altitudeWGS84, double altitudeRelative, double climbRate, quint64) {
double oldclimbRate = _climbRate;
double oldaltitudeRelative = _altitudeRelative;
double oldaltitudeWGS84 = _altitudeWGS84;
double oldaltitudeAMSL = _altitudeAMSL;
_climbRate = climbRate;
_altitudeRelative = altitudeRelative;
_altitudeWGS84 = altitudeWGS84;
_altitudeAMSL = altitudeAMSL;
if(_climbRate > -0.01 && _climbRate < 0.01) {
_climbRate = 0.0;
}
if (fabsf(oldaltitudeAMSL - altitudeAMSL) > 0.5f) {
if(_refreshTimer->isActive()) emit altitudeAMSLChanged();
_valuesChanged = true;
}
if (fabsf(oldaltitudeWGS84 - altitudeWGS84) > 0.5f) {
if(_refreshTimer->isActive()) emit altitudeWGS84Changed();
_valuesChanged = true;
}
if (fabsf(oldaltitudeRelative - altitudeRelative) > 0.5f) {
if(_refreshTimer->isActive()) emit altitudeRelativeChanged();
_valuesChanged = true;
}
if (fabsf(oldclimbRate - climbRate) > 0.5f) {
if(_refreshTimer->isActive()) emit climbRateChanged();
_valuesChanged = true;
}
}
void QGCFlightDisplay::_updateNavigationControllerErrors(UASInterface*, double altitudeError, double speedError, double xtrackError) {
_navigationAltitudeError = altitudeError;
_navigationSpeedError = speedError;
_navigationCrosstrackError = xtrackError;
}
void QGCFlightDisplay::_updateNavigationControllerData(UASInterface *uas, float, float, float, float targetBearing, float) {
if (_mav == uas) {
_navigationTargetBearing = targetBearing;
}
}
/*
* Internal
*/
bool QGCFlightDisplay::_isAirplane() {
if (_mav)
return _mav->isAirplane();
return false;
}
// TODO: Implement. Should return true when navigating.
// That would be (PX4) in AUTO and RTL modes.
// This could forward to a virtual on UAS bool isNavigatingAutonomusly() or whatever.
bool QGCFlightDisplay::_shouldDisplayNavigationData() {
return true;
}
void QGCFlightDisplay::showEvent(QShowEvent* event)
{
// React only to internal (pre-display) events
QWidget::showEvent(event);
_refreshTimer->start(UPDATE_TIMER);
}
void QGCFlightDisplay::hideEvent(QHideEvent* event)
{
// React only to internal (pre-display) events
_refreshTimer->stop();
QWidget::hideEvent(event);
}
void QGCFlightDisplay::_checkUpdate()
{
if (_mav && (_valuesChanged || (QGC::groundTimeMilliseconds() - _valuesLastPainted) > 260)) {
_valuesChanged = false;
_valuesLastPainted = QGC::groundTimeMilliseconds();
emit rollChanged();
emit pitchChanged();
emit headingChanged();
emit altitudeAMSLChanged();
emit altitudeWGS84Changed();
emit altitudeRelativeChanged();
emit climbRateChanged();
emit groundSpeedChanged();
emit airSpeedChanged();
emit repaintRequestedChanged();
emit latitudeChanged();
emit longitudeChanged();
}
if(_mav) {
_latitude = _mav->getLatitude();
_longitude = _mav->getLongitude();
if(_latitude) emit latitudeChanged();
if(_longitude) emit longitudeChanged();
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 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 QGC Main Flight Display
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef QGCFLIGHTDISPLAY_H
#define QGCFLIGHTDISPLAY_H
#include "QGCQmlWidgetHolder.h"
class UASInterface;
class QGCFlightDisplay : public QGCQmlWidgetHolder
{
Q_OBJECT
public:
QGCFlightDisplay(QWidget* parent = NULL);
~QGCFlightDisplay();
Q_PROPERTY(float roll READ roll NOTIFY rollChanged)
Q_PROPERTY(float pitch READ pitch NOTIFY pitchChanged)
Q_PROPERTY(float heading READ heading NOTIFY headingChanged)
Q_PROPERTY(float groundSpeed READ groundSpeed NOTIFY groundSpeedChanged)
Q_PROPERTY(float airSpeed READ airSpeed NOTIFY airSpeedChanged)
Q_PROPERTY(float climbRate READ climbRate NOTIFY climbRateChanged)
Q_PROPERTY(float altitudeRelative READ altitudeRelative NOTIFY altitudeRelativeChanged)
Q_PROPERTY(float altitudeWGS84 READ altitudeWGS84 NOTIFY altitudeWGS84Changed)
Q_PROPERTY(float altitudeAMSL READ altitudeAMSL NOTIFY altitudeAMSLChanged)
Q_PROPERTY(bool repaintRequested READ repaintRequested NOTIFY repaintRequestedChanged)
Q_PROPERTY(float latitude READ latitude NOTIFY latitudeChanged)
Q_PROPERTY(float longitude READ longitude NOTIFY longitudeChanged)
Q_INVOKABLE void saveSetting (const QString &key, bool value);
Q_INVOKABLE bool loadSetting (const QString &key, bool defaultValue);
float roll () { return _roll; }
float pitch () { return _pitch; }
float heading () { return _heading; }
float groundSpeed () { return _groundSpeed; }
float airSpeed () { return _airSpeed; }
float climbRate () { return _climbRate; }
float altitudeRelative () { return _altitudeRelative; }
float altitudeWGS84 () { return _altitudeWGS84; }
float altitudeAMSL () { return _altitudeAMSL; }
float latitude () { return _latitude; }
float longitude () { return _longitude; }
bool repaintRequested () { return true; }
/** @brief Start updating widget */
void showEvent(QShowEvent* event);
/** @brief Stop updating widget */
void hideEvent(QHideEvent* event);
signals:
void rollChanged ();
void pitchChanged ();
void headingChanged ();
void groundSpeedChanged ();
void airSpeedChanged ();
void climbRateChanged ();
void altitudeRelativeChanged();
void altitudeWGS84Changed ();
void altitudeAMSLChanged ();
void repaintRequestedChanged();
void latitudeChanged ();
void longitudeChanged ();
private slots:
/** @brief Attitude from main autopilot / system state */
void _updateAttitude (UASInterface* uas, double roll, double pitch, double yaw, quint64 timestamp);
/** @brief Attitude from one specific component / redundant autopilot */
void _updateAttitude (UASInterface* uas, int component, double roll, double pitch, double yaw, quint64 timestamp);
/** @brief Speed */
void _updateSpeed (UASInterface* uas, double _groundSpeed, double _airSpeed, quint64 timestamp);
/** @brief Altitude */
void _updateAltitude (UASInterface* uas, double _altitudeAMSL, double _altitudeWGS84, double _altitudeRelative, double _climbRate, quint64 timestamp);
void _updateNavigationControllerErrors (UASInterface* uas, double altitudeError, double speedError, double xtrackError);
void _updateNavigationControllerData (UASInterface *uas, float navRoll, float navPitch, float navBearing, float targetBearing, float targetDistance);
void _forgetUAS (UASInterface* uas);
void _setActiveUAS (UASInterface* uas);
void _checkUpdate ();
private:
bool _isAirplane ();
bool _shouldDisplayNavigationData ();
private:
UASInterface* _mav;
float _roll;
float _pitch;
float _heading;
float _altitudeAMSL;
float _altitudeWGS84;
float _altitudeRelative;
float _groundSpeed;
float _airSpeed;
float _climbRate;
float _navigationAltitudeError;
float _navigationSpeedError;
float _navigationCrosstrackError;
float _navigationTargetBearing;
float _latitude;
float _longitude;
QTimer* _refreshTimer;
bool _valuesChanged;
quint64 _valuesLastPainted;
};
#endif // QGCFLIGHTDISPLAY_H
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 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 QGC Altitude Indicator
* @author Gus Grubba <mavlink@grubba.com>
*/
// TODO: This is temporary until I find a better way to display a large range of numbers
import QtQuick 2.4
Rectangle {
id: root
property real altitude: 50
property real _reticleSpacing: 29
property real _reticleHeight: 1
property real _reticleSlot: _reticleSpacing + _reticleHeight
property var _speedArray: []
property int _currentCenter: 0
property int _currentStart: -100
function updateArray() {
var tmpArray = [];
_currentCenter = Math.floor(altitude / 5) * 5;
_currentStart = _currentCenter + 100;
for(var i = 0; i < 40; i++) {
tmpArray[i] = _currentStart - (i * 5);
}
_speedArray = tmpArray;
}
Component.onCompleted:
{
updateArray() ;
}
onAltitudeChanged: {
if(Math.abs(_currentCenter - altitude) > 50) {
updateArray() ;
}
}
anchors.verticalCenter: parent.verticalCenter
height: parent.height * 0.75 > 280 ? 280 : parent.height * 0.75
clip: true
smooth: true
border.color: Qt.rgba(1,1,1,0.25)
gradient: Gradient {
GradientStop { position: 0.0; color: Qt.rgba(0,0,0,0.35) }
GradientStop { position: 0.5; color: Qt.rgba(0,0,0,0.15) }
GradientStop { position: 1.0; color: Qt.rgba(0,0,0,0.35) }
}
Column{
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
spacing: _reticleSpacing
Repeater {
model: _speedArray
Rectangle {
width: root.width
height: _reticleHeight
color: Qt.rgba(1,1,1,0.1)
Text {
property real _alt: modelData
visible: (_alt % 10 === 0)
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
antialiasing: true
font.weight: _alt < 0 ? Font.Light : Font.DemiBold
text: _alt < 0 ? -_alt : _alt
color: _alt < 0 ? "#ef2526" : "white"
style: Text.Outline
styleColor: Qt.rgba(0,0,0,0.25)
}
}
}
transform: Translate {
y: ((altitude - _currentCenter) * _reticleSlot / 5) - (_reticleSlot / 2)
}
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 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 QGC Main Flight Display
* @author Gus Grubba <mavlink@grubba.com>
*/
import QtQuick 2.4
Item {
id: root
property real rollAngle : 0
property real pitchAngle: 0
property real backgroundOpacity: 1
property bool displayBackground: true
anchors.fill: parent
Item {
id: background
width: parent.width * 4
height: parent.height * 4
anchors.centerIn: parent
Rectangle {
anchors.fill: parent
color: Qt.rgba(0,0,0,0)
visible: displayBackground
Rectangle {
id: sky
visible: displayBackground
anchors.fill: parent
smooth: true
antialiasing: true
gradient: Gradient {
GradientStop { position: 0.25; color: Qt.hsla(0.6, 1.0, 0.25, backgroundOpacity) }
GradientStop { position: 0.5; color: Qt.hsla(0.6, 0.5, 0.75, backgroundOpacity) }
}
}
Rectangle {
id: ground
visible: displayBackground
height: sky.height / 2
anchors {
left: sky.left;
right: sky.right;
bottom: sky.bottom
}
smooth: true
antialiasing: true
gradient: Gradient {
GradientStop { position: 0.0; color: Qt.hsla(0.25, 0.5, 0.45, backgroundOpacity) }
GradientStop { position: 0.25; color: Qt.hsla(0.25, 0.75, 0.25, backgroundOpacity) }
}
}
transform: [
Translate {
y: (root.visible && root.displayBackground) ? pitchAngle * 4 : 0
},
Rotation {
origin.x: background.width / 2
origin.y: background.height / 2
angle: (root.visible && root.displayBackground) ? -rollAngle : 0
}]
}
}
Image {
id: rollDial
anchors { bottom: root.verticalCenter; horizontalCenter: parent.horizontalCenter}
source: "/qml/rollDial.svg"
mipmap: true
width: 250
fillMode: Image.PreserveAspectFit
transform: Rotation {
origin.x: rollDial.width / 2
origin.y: rollDial.height
angle: -rollAngle
}
}
Image {
id: pointer
anchors { bottom: root.verticalCenter; horizontalCenter: parent.horizontalCenter}
source: "/qml/rollPointer.svg"
smooth: true
width: rollDial.width
fillMode: Image.PreserveAspectFit
}
Image {
anchors.centerIn: parent
source: "/qml/crossHair.svg"
mipmap: true
width: rollDial.width
fillMode: Image.PreserveAspectFit
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 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 QGC Compass
* @author Gus Grubba <mavlink@grubba.com>
*/
import QtQuick 2.4
Item {
id: root
width: parent.width * 0.25 > 150 ? parent.width * 0.25 : 150
height: width
property real heading : 0
Image {
id: compass
anchors.centerIn: parent
source: "/qml/compass.svg"
mipmap: true
width: root.width
fillMode: Image.PreserveAspectFit
transform: Rotation {
origin.x: compass.width / 2
origin.y: compass.height / 2
angle: -heading
}
}
Image {
id: pointer
anchors.bottom: compass.top
anchors.horizontalCenter: root.horizontalCenter
source: "/qml/compassNeedle.svg"
smooth: true
width: compass.width * 0.1
fillMode: Image.PreserveAspectFit
}
Rectangle {
anchors.centerIn: compass
width: 40
height: 25
border.color: Qt.rgba(1,1,1,0.25)
color: Qt.rgba(1,1,1,0.1)
Text {
text: heading.toFixed(0)
font.weight: Font.DemiBold
color: "white"
anchors.centerIn: parent
}
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 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 QGC Current Altitude Indicator
* @author Gus Grubba <mavlink@grubba.com>
*/
import QtQuick 2.1
Rectangle {
id: root
property real altitude: 0
property real vertZ: 0
property bool showAltitude: true
property bool showClimbRate: true
anchors.verticalCenter: parent.verticalCenter
width: parent.width
height: (showAltitude && showClimbRate) ? 50 : 25
color: "black"
border.color: Qt.rgba(1,1,1,0.25)
opacity: 1.0
Column{
anchors.centerIn: parent
spacing: 4
Text {
text: 'h: ' + altitude.toFixed(1)
font.weight: Font.DemiBold
color: "white"
anchors.right: parent.right
visible: showAltitude
}
Text {
text: 'vZ: ' + vertZ.toFixed(1)
color: "white"
font.weight: showAltitude ? Font.Normal : Font.DemiBold
anchors.right: parent.right
visible: showClimbRate
}
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 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 QGC Current Speed Indicator
* @author Gus Grubba <mavlink@grubba.com>
*/
import QtQuick 2.1
Rectangle {
id: root
property real airspeed: 0
property real groundspeed: 0
property bool showAirSpeed: true
property bool showGroundSpeed: true
anchors.verticalCenter: parent.verticalCenter
width: parent.width
height: (showAirSpeed && showGroundSpeed) ? 50 : 25
color: "black"
border.color: Qt.rgba(1,1,1,0.25)
opacity: 1.0
Column{
anchors.centerIn: parent
spacing: 4
Text {
text: 'GS: ' + groundspeed.toFixed(1)
font.weight: Font.DemiBold
color: "white"
anchors.right: parent.right
visible: showGroundSpeed
}
Text {
text: 'AS: ' + airspeed.toFixed(1)
color: "white"
anchors.right: parent.right
font.weight: showAirSpeed ? Font.Normal : Font.DemiBold
visible: showAirSpeed
}
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 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 QGC Map Background
* @author Gus Grubba <mavlink@grubba.com>
*/
import QtQuick 2.4
import QtPositioning 5.3
import QtLocation 5.3
Rectangle {
id: root
property real latitude: 37.803784
property real longitude : -122.462276
property real zoomLevel: 12
property real heading: 0
property bool alwaysNorth: true
property alias mapItem: map
anchors.fill: parent
color: Qt.rgba(0,0,0,0)
clip: true
function adjustSize() {
if(root.visible) {
if(alwaysNorth) {
map.width = root.width;
map.height = root.height;
} else {
var diag = Math.ceil(Math.sqrt((root.width * root.width) + (root.height * root.height)));
map.width = diag;
map.height = diag;
}
} else {
map.width = 1;
map.height = 1;
}
}
Plugin {
id: mapPlugin
name: "osm"
}
Map {
id: map
plugin: mapPlugin
width: 1
height: 1
zoomLevel: zoomLevel
anchors.centerIn: parent
center: map.visible ? QtPositioning.coordinate(latitude, longitude) : QtPositioning.coordinate(0,0)
transform: Rotation {
origin.x: map.width / 2
origin.y: map.height / 2
angle: map.visible ? (alwaysNorth ? 0 : -heading) : 0
}
gesture.flickDeceleration: 3000
gesture.enabled: true
}
onVisibleChanged: adjustSize();
onWidthChanged: adjustSize();
onHeightChanged: adjustSize();
onAlwaysNorthChanged: adjustSize();
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 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 QGC Pitch Indicator
* @author Gus Grubba <mavlink@grubba.com>
*/
import QtQuick 2.1
Rectangle {
property real pitchAngle: 0
property real rollAngle: 0
property real _reticleHeight: 1
property real _reticleSpacing: 20
property real _reticleSlot: _reticleSpacing + _reticleHeight
height: 130
width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
clip: true
color: Qt.rgba(0,0,0,0)
Item {
height: parent.height
width: parent.width
Column{
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
spacing: _reticleSpacing
Repeater {
model: 36
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
width: ((modelData * 5 - 90) % 10) === 0 ? 50 : 30
height: _reticleHeight
color: "white"
antialiasing: true
smooth: true
Text {
anchors.horizontalCenter: parent.horizontalCenter
anchors.horizontalCenterOffset: -40
anchors.verticalCenter: parent.verticalCenter
smooth: true
font.weight: Font.DemiBold
text: -(modelData * 5 - 90)
color: "white"
visible: ((modelData * 5 - 90) % 10) === 0
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
anchors.horizontalCenterOffset: 40
anchors.verticalCenter: parent.verticalCenter
smooth: true
font.weight: Font.DemiBold
text: -(modelData * 5 - 90)
color: "white"
visible: ((modelData * 5 - 90) % 10) === 0
}
}
}
}
transform: [ Translate {
y: (pitchAngle * _reticleSlot / 5) - (_reticleSlot / 2)
}]
}
transform: [
Rotation {
origin.x: width / 2
origin.y: height / 2
angle: -rollAngle
}
]
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 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 QGC Speed Indicator
* @author Gus Grubba <mavlink@grubba.com>
*/
import QtQuick 2.4
Rectangle {
id: root
property real speed: 0
property real _reticleSpacing: 14
property real _reticleHeight: 1
property real _reticleSlot: _reticleSpacing + _reticleHeight
anchors.verticalCenter: parent.verticalCenter
height: parent.height * 0.75 > 280 ? 280 : parent.height * 0.75
clip: true
smooth: true
border.color: Qt.rgba(1,1,1,0.25)
gradient: Gradient {
GradientStop { position: 0.0; color: Qt.rgba(0,0,0,0.35) }
GradientStop { position: 0.5; color: Qt.rgba(0,0,0,0.15) }
GradientStop { position: 1.0; color: Qt.rgba(0,0,0,0.35) }
}
Column{
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
spacing: _reticleSpacing
Repeater {
model: 40
Rectangle {
width: root.width
height: _reticleHeight
color: Qt.rgba(1,1,1,0.1)
Text {
property real _speed: -(index - 20)
visible: (_speed % 5 === 0)
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
antialiasing: true
font.weight: _speed < 0 ? Font.Light : Font.DemiBold
text: _speed < 0 ? -_speed : _speed
color: _speed < 0 ? "#ef2526" : "white"
style: Text.Outline
styleColor: Qt.rgba(0,0,0,0.25)
}
}
}
transform: Translate {
y: (speed * _reticleSlot) - (_reticleSlot / 2)
}
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 288 158.4" enable-background="new 0 0 288 158.4" xml:space="preserve">
<g id="Layer_2">
<polygon opacity="0.5" fill="#FFFFFF" points="272.25,9 144,149.4 15.75,9 "/>
</g>
<g id="Layer_1">
<polygon opacity="0.75" fill="none" stroke="#000000" stroke-width="12" stroke-linejoin="round" stroke-miterlimit="10" points="
279,7.2 144,151.2 9,7.2 "/>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 288 36" enable-background="new 0 0 288 36" xml:space="preserve">
<rect fill="none" width="288" height="36"/>
<line fill="none" stroke="#D32027" stroke-width="2" stroke-miterlimit="10" x1="0" y1="18" x2="72" y2="18"/>
<line fill="none" stroke="#D32027" stroke-width="2" stroke-miterlimit="10" x1="288" y1="18" x2="216" y2="18"/>
<polyline fill="none" stroke="#D32027" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" points="194.488,31.07
144,18 93.512,31.07 "/>
</svg>
Module QGroundControl.HUDControls
QGCAltitudeWidget 1.0 QGCAltitudeWidget.qml
QGCAttitudeWidget 1.0 QGCAttitudeWidget.qml
QGCCompass 1.0 QGCCompass.qml
QGCCurrentAltitude 1.0 QGCCurrentAltitude.qml
QGCCurrentSpeed 1.0 QGCCurrentSpeed.qml
QGCMapBackground 1.0 QGCMapBackground.qml
QGCPitchWidget 1.0 QGCPitchWidget.qml
QGCSpeedWidget 1.0 QGCSpeedWidget.qml
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 288 159.854" enable-background="new 0 0 288 159.854" xml:space="preserve">
<g id="Layer_1">
<text transform="matrix(1 0 0 1 136.0895 12.201)" fill="#E0E0E0" font-family="'Arial-BoldMT'" font-size="14.2222">00</text>
<text transform="matrix(0.9659 -0.2588 0.2588 0.9659 98.1424 19.2784)" fill="#E0E0E0" font-family="'Arial-BoldMT'" font-size="14.2218">15</text>
<text transform="matrix(0.866 -0.5 0.5 0.866 63.3229 35.9389)" fill="#E0E0E0" font-family="'Arial-BoldMT'" font-size="14.2219">30</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 33.9995 61.0398)" fill="#E0E0E0" font-family="'Arial-BoldMT'" font-size="14.2221">45</text>
<text transform="matrix(0.5 -0.866 0.866 0.5 12.1723 92.8793)" fill="#E0E0E0" font-family="'Arial-BoldMT'" font-size="14.2219">60</text>
<text transform="matrix(0.9659 0.2588 -0.2588 0.9659 174.5744 15.1842)" fill="#E0E0E0" font-family="'Arial-BoldMT'" font-size="14.2218">15</text>
<text transform="matrix(0.866 0.5 -0.5 0.866 210.9767 28.0287)" fill="#E0E0E0" font-family="'Arial-BoldMT'" font-size="14.2219">30</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 242.8152 49.8557)" fill="#E0E0E0" font-family="'Arial-BoldMT'" font-size="14.2221">45</text>
<text transform="matrix(0.5 0.866 -0.866 0.5 267.9185 79.1788)" fill="#E0E0E0" font-family="'Arial-BoldMT'" font-size="14.2219">60</text>
</g>
<g id="Layer_3">
<rect id="rect5769" y="153.455" fill="none" width="288" height="6.4"/>
</g>
<g id="Layer_2">
<line fill="none" stroke="#E0E0E0" stroke-width="4" x1="144.1" y1="23.855" x2="144.1" y2="16.355"/>
<line fill="none" stroke="#E0E0E0" stroke-width="4" x1="108.9" y1="28.455" x2="107" y2="21.255"/>
<line fill="none" stroke="#E0E0E0" stroke-width="4" x1="76.1" y1="41.955" x2="72.4" y2="35.455"/>
<line fill="none" stroke="#E0E0E0" stroke-width="4" x1="47.9" y1="63.555" x2="42.7" y2="58.355"/>
<line fill="none" stroke="#E0E0E0" stroke-width="4" x1="26.3" y1="91.755" x2="19.8" y2="88.055"/>
<line fill="none" stroke="#E0E0E0" stroke-width="4" x1="179.3" y1="28.455" x2="181.2" y2="21.255"/>
<line fill="none" stroke="#E0E0E0" stroke-width="4" x1="212.1" y1="42.155" x2="215.8" y2="35.655"/>
<line fill="none" stroke="#E0E0E0" stroke-width="4" x1="240.3" y1="63.755" x2="245.5" y2="58.555"/>
<line fill="none" stroke="#E0E0E0" stroke-width="4" x1="261.9" y1="91.955" x2="268.4" y2="88.255"/>
<path fill="none" stroke="#E0E0E0" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="M262.4,92.955
c-11.6-20.6-28.6-37.9-48.9-50s-44.1-19.1-69.5-19.1s-49.2,6.9-69.4,19s-37.2,29.3-48.9,50"/>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 288 288 129.6" enable-background="new 0 288 288 129.6" xml:space="preserve">
<g id="svg5772" sodipodi:docname="rollPointer.svg" inkscape:version="0.48.2 r9819" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
<sodipodi:namedview inkscape:window-x="0" inkscape:window-width="1920" inkscape:window-height="1152" inkscape:pageopacity="0.0" inkscape:document-units="px" inkscape:pageshadow="2" inkscape:current-layer="layer5" inkscape:window-y="22" inkscape:window-maximized="1" inkscape:showpageshadow="false" inkscape:guide-bbox="true" id="base" showguides="true" inkscape:zoom="3" borderopacity="1.0" inkscape:cy="66.806039" bordercolor="#666666" pagecolor="#ffffff" showgrid="true" inkscape:cx="74.271777">
<inkscape:grid type="xygrid" snapvisiblegridlinesonly="true" id="grid5780" empspacing="5" visible="true" enabled="true">
</inkscape:grid>
</sodipodi:namedview>
<rect id="rect5782" y="405.5" fill="none" width="288" height="12.1"/>
<path id="path6692" inkscape:connector-curvature="0" fill="#9F0022" d="M137.9,312.4C144,288,144,288,144,288l6.1,24.4l0,0H137.9z
"/>
</g>
<g id="Layer_2">
<path id="path6692_1_" inkscape:connector-curvature="0" opacity="0.5" fill="none" stroke="#FFFFFF" d="M137.7,312.8
c6.3-25.2,6.3-25.2,6.3-25.2l6.3,25.2l0,0H137.7z"/>
</g>
</svg>
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