Newer
Older
/*=====================================================================
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 Implementation of Horizontal Situation Indicator class
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#include <QFile>
#include <QStringList>
#include <QGraphicsScene>
#include <QHBoxLayout>
#include <QDoubleSpinBox>
#include "UASManager.h"
#include "HSIDisplay.h"
#include "UASWaypointManager.h"
#include "MAV2DIcon.h"
Bryant
committed
#include "MainWindow.h"
HSIDisplay::HSIDisplay(QWidget *parent) :
John Tapsell
committed
HDDisplay(QStringList(), "HSI", parent),
dragStarted(false),
leftDragStarted(false),
mouseHasMoved(false),
startX(0.0f),
startY(0.0f),
actionPending(false),
directSending(false),
gpsSatellites(),
satellitesUsed(0),
attXSet(0.0f),
attYSet(0.0f),
attYawSet(0.0f),
altitudeSet(1.0f),
posXSet(0.0f),
posYSet(0.0f),
posZSet(0.0f),
attXSaturation(0.2f),
attYSaturation(0.2f),
attYawSaturation(0.5f),
posXSaturation(0.05f),
posYSaturation(0.05f),
altitudeSaturation(1.0f),
lat(0.0f),
lon(0.0f),
alt(0.0f),
globalAvailable(0),
x(0.0f),
y(0.0f),
z(0.0f),
vx(0.0f),
vy(0.0f),
vz(0.0f),
speed(0.0f),
localAvailable(0),
roll(0.0f),
pitch(0.0f),
yaw(0.0f),
bodyXSetCoordinate(0.0f),
bodyYSetCoordinate(0.0f),
bodyZSetCoordinate(0.0f),
bodyYawSet(0.0f),
uiXSetCoordinate(0.0f),
uiYSetCoordinate(0.0f),
uiYawSet(0.0f),
metricWidth(4.0),
positionLock(false),
attControlEnabled(false),
xyControlEnabled(false),
zControlEnabled(false),
yawControlEnabled(false),
positionFix(0),
gpsFix(0),
visionFix(0),
laserFix(0),
topMargin(20.0f),
bottomMargin(14.0f),
attControlKnown(false),
xyControlKnown(false),
zControlKnown(false),
yawControlKnown(false),
positionFixKnown(false),
visionFixKnown(false),
gpsFixKnown(false),
iruFixKnown(false),
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
gyroKnown(false),
gyroON(false),
gyroOK(false),
accelKnown(false),
accelON(false),
accelOK(false),
magKnown(false),
magON(false),
magOK(false),
pressureKnown(false),
pressureON(false),
pressureOK(false),
diffPressureKnown(false),
diffPressureON(false),
diffPressureOK(false),
flowKnown(false),
flowON(false),
flowOK(false),
laserKnown(false),
laserON(false),
laserOK(false),
viconKnown(false),
viconON(false),
viconOK(false),
actuatorsKnown(false),
actuatorsON(false),
actuatorsOK(false),
setPointKnown(false),
positionSetPointKnown(false),
userSetPointSet(false),
userXYSetPointSet(false),
userZSetPointSet(false),
userYawSetPointSet(false)
refreshTimer->setInterval(updateInterval);
this->setAutoFillBackground(true);
QPalette pal = palette();
pal.setColor(backgroundRole(), QGC::colorBlack);
setPalette(pal);
yCenterPos = vheight/2.0f + topMargin - bottomMargin;
uas = NULL;
resetMAVState();
// Do first update
setMetricWidth(metricWidth);
// Set tooltip
setToolTip(tr("View from top in body frame. Scroll with mouse wheel to change the horizontal field of view of the widget."));
setStatusTip(tr("View from top in body frame. Scroll with mouse wheel to change the horizontal field of view of the widget."));
// XXX this looks a potential recursive issue
//connect(&statusClearTimer, SIGNAL(timeout()), this, SLOT(clearStatusMessage()));
Michael Carpenter
committed
if (UASManager::instance()->getActiveUAS())
{
setActiveUAS(UASManager::instance()->getActiveUAS());
}
connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
this, SLOT(setActiveUAS(UASInterface*)));
connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
this, SLOT(setActiveUAS(UASInterface*)));
HSIDisplay::~HSIDisplay()
{
}
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
void HSIDisplay::resetMAVState()
{
mavInitialized = false;
attControlKnown = false;
attControlEnabled = false;
xyControlKnown = false;
xyControlEnabled = false;
zControlKnown = false;
zControlEnabled = false;
yawControlKnown = false;
yawControlEnabled = false;
// Draw position lock indicators
positionFixKnown = false;
positionFix = 0;
visionFixKnown = false;
visionFix = 0;
gpsFixKnown = false;
gpsFix = 0;
iruFixKnown = false;
iruFix = 0;
// Data
setPointKnown = false;
localAvailable = 0;
globalAvailable = 0;
// Setpoints
positionSetPointKnown = false;
setPointKnown = false;
void HSIDisplay::paintEvent(QPaintEvent * event)
{
Q_UNUSED(event);
//paintGL();
// static quint64 interval = 0;
// //qDebug() << "INTERVAL:" << MG::TIME::getGroundTimeNow() - interval << __FILE__ << __LINE__;
// interval = MG::TIME::getGroundTimeNow();
renderOverlay();
void HSIDisplay::renderOverlay()
if (!isVisible() || !uas) return;
#if (QGC_EVENTLOOP_DEBUG)
qDebug() << "EVENTLOOP:" << __FILE__ << __LINE__;
#endif
// Center location of the HSI gauge items
//const float margin = 0.1f; // 10% margin of total width on each side
float baseRadius = (vheight - topMargin - bottomMargin) / 2.0f - (topMargin + bottomMargin) / 2.8f;
// Draw instruments
// TESTING THIS SHOULD BE MOVED INTO A QGRAPHICSVIEW
// Update scaling factor
// adjust scaling to fit both horizontally and vertically
scalingFactor = this->width()/vwidth;
double scalingFactorH = this->height()/vheight;
if (scalingFactorH < scalingFactor) scalingFactor = scalingFactorH;
QPainter painter(viewport());
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setRenderHint(QPainter::HighQualityAntialiasing, true);
// Draw base instrument
// ----------------------
Bryant
committed
// Set the color scheme depending on the light/dark theme employed.
QColor ringColor;
QColor positionColor;
QColor setpointColor;
QColor labelColor;
QColor valueColor;
QColor statusColor;
QColor waypointLineColor;
QColor attitudeColor;
if (MainWindow::instance()->getStyle() == MainWindow::QGC_MAINWINDOW_STYLE_LIGHT)
{
ringColor = QGC::colorBlack;
positionColor = QColor(20, 20, 200);
setpointColor = QColor(150, 250, 150);
labelColor = QColor(26, 75, 95);
Bryant
committed
valueColor = QColor(40, 40, 40);
statusColor = QGC::colorOrange;
waypointLineColor = QGC::colorDarkYellow;
attitudeColor = QColor(200, 20, 20);
}
else
{
ringColor = QColor(255, 255, 255);
Bryant
committed
positionColor = QColor(20, 20, 200);
setpointColor = QColor(150, 250, 150);
labelColor = QGC::colorCyan;
valueColor = QColor(255, 255, 255);
statusColor = QGC::colorOrange;
waypointLineColor = QGC::colorYellow;
attitudeColor = QColor(200, 20, 20);
}
pen.setWidth(refLineWidthToPen(1.0f));
for (int i = 0; i < ringCount; i++)
{
float radius = (vwidth - (topMargin + bottomMargin)*0.3f) / (1.35f * i+1) / 2.0f - bottomMargin / 2.0f;
drawCircle(xCenterPos, yCenterPos, radius, 1.0f, ringColor, &painter);
Bryant
committed
paintText(tr("%1 m").arg(refToMetric(radius), 5, 'f', 1, ' '), valueColor, 1.6f, vwidth/2-4, vheight/2+radius+7, &painter);
// Draw orientation labels
// Translate and rotate coordinate frame
painter.translate((xCenterPos)*scalingFactor, (yCenterPos)*scalingFactor);
const float yawDeg = ((yaw/M_PI)*180.0f);
int yawRotate = static_cast<int>(yawDeg) % 360;
painter.rotate(-yawRotate);
paintText(tr("N"), ringColor, 3.5f, - 1.0f, - baseRadius - 5.5f, &painter);
paintText(tr("S"), ringColor, 3.5f, - 1.0f, + baseRadius + 1.5f, &painter);
paintText(tr("E"), ringColor, 3.5f, + baseRadius + 3.0f, - 1.25f, &painter);
paintText(tr("W"), ringColor, 3.5f, - baseRadius - 5.5f, - 1.75f, &painter);
painter.rotate(+yawRotate);
painter.translate(-(xCenterPos)*scalingFactor, -(yCenterPos)*scalingFactor);
// QPointF m(bodyXSetCoordinate, bodyYSetCoordinate);
// // Transform from body to world coordinates
// m = metricWorldToBody(m);
// // Scale from metric body to screen reference units
// QPointF s = metricBodyToRef(m);
// drawLine(s.x(), s.y(), xCenterPos, yCenterPos, 1.5f, uas->getColor(), &painter);
// QPolygonF p(3);
// p.replace(0, QPointF(xCenterPos, yCenterPos-4.0f));
// p.replace(1, QPointF(xCenterPos-4.0f, yCenterPos+3.5f));
// p.replace(2, QPointF(xCenterPos+4.0f, yCenterPos+3.5f));
// drawPolygon(p, &painter);
if (uas)
{
// Translate to center
painter.translate((xCenterPos)*scalingFactor, (yCenterPos)*scalingFactor);
QColor uasColor = uas->getColor();
MAV2DIcon::drawAirframePolygon(uas->getAirframe(), painter, static_cast<int>((vwidth/4.0f)*scalingFactor*1.1f), uasColor, 0.0f);
//MAV2DIcon::drawAirframePolygon(uas->getAirframe(), painter, static_cast<int>((vwidth/4.0f)*scalingFactor*1.1f), uasColor, 0.0f);
// Translate back
painter.translate(-(xCenterPos)*scalingFactor, -(yCenterPos)*scalingFactor);
}
// Draw satellites
drawGPS(painter);
// Draw state indicator
// Draw position
drawPositionDirection(xCenterPos, yCenterPos, baseRadius, positionColor, &painter);
drawAttitudeDirection(xCenterPos, yCenterPos, baseRadius, attitudeColor, &painter);
// Draw position setpoints in body coordinates
float xSpDiff = uiXSetCoordinate - bodyXSetCoordinate;
float ySpDiff = uiYSetCoordinate - bodyYSetCoordinate;
float zSpDiff = uiZSetCoordinate - bodyZSetCoordinate;
float setPointDist = sqrt(xSpDiff*xSpDiff + ySpDiff*ySpDiff + zSpDiff*zSpDiff);
float angleDiff = uiYawSet - bodyYawSet;
float normAngleDiff = fabs(atan2(sin(angleDiff), cos(angleDiff)));
// Labels on outer part and bottom
// Draw waypoints
drawWaypoints(painter);
// Draw status flags
drawStatusFlag(1, 1, tr("RAT"), rateControlEnabled, rateControlKnown, painter);
drawStatusFlag(17, 1, tr("ATT"), attControlEnabled, attControlKnown, painter);
drawStatusFlag(33, 1, tr("PXY"), xyControlEnabled, xyControlKnown, painter);
drawStatusFlag(49, 1, tr("PZ"), zControlEnabled, zControlKnown, painter);
drawStatusFlag(65, 1, tr("YAW"), yawControlEnabled, yawControlKnown, painter);
// Draw position lock indicators
drawPositionLock(1, 6, tr("POS"), positionFix, positionFixKnown, painter);
drawPositionLock(17, 6, tr("GPS"), gpsFix, gpsFixKnown, painter);
drawStatusFlag(33, 6, tr("FLO"), flowON, flowKnown, flowOK, painter);
drawPositionLock(49, 6, tr("VIS"), visionFix, visionFixKnown, painter);
drawPositionLock(65, 6, tr("IRU"), iruFix, iruFixKnown, painter);
drawStatusFlag(1, 11, tr("GYR"), gyroON, gyroKnown, gyroOK, painter);
drawStatusFlag(17, 11, tr("ACC"), accelON, accelKnown, accelOK, painter);
drawStatusFlag(33, 11, tr("MAG"), magON, magKnown, magOK, painter);
drawStatusFlag(49, 11, tr("BAR"), pressureON, pressureKnown, pressureOK, painter);
drawStatusFlag(65, 11, tr("PIT"), diffPressureON, diffPressureKnown, diffPressureOK, painter);
drawStatusFlag(1, 16, tr("ACT"), actuatorsON, actuatorsKnown, actuatorsOK, painter);
drawStatusFlag(17, 16, tr("LAS"), laserON, laserKnown, laserOK, painter);
drawStatusFlag(33, 16, tr("VCN"), viconON, viconKnown, viconOK, painter);
// Draw speed to top left
Bryant
committed
paintText(tr("SPEED"), labelColor, 2.2f, 2, topMargin+2, &painter);
paintText(tr("%1 m/s").arg(speed, 5, 'f', 2, '0'), valueColor, 2.2f, 12, topMargin+2, &painter);
// Draw crosstrack error to top right
float crossTrackError = 0;
Bryant
committed
paintText(tr("XTRACK"), labelColor, 2.2f, 54, topMargin+2, &painter);
paintText(tr("%1 m").arg(crossTrackError, 5, 'f', 2, '0'), valueColor, 2.2f, 67, topMargin+2, &painter);
// Draw position to bottom left
if (localAvailable > 0)
{
// Position
QString str;
float offset = (globalAvailable > 0) ? -3.0f : 0.0f;
str.sprintf("%05.2f %05.2f %05.2f m", x, y, z);
Bryant
committed
paintText(tr("POS"), labelColor, 2.6f, 2, vheight - offset - 4.0f, &painter);
paintText(str, valueColor, 2.6f, 10, vheight - offset - 4.0f, &painter);
if (globalAvailable > 0)
{
// Position
QString str;
str.sprintf("lat: %05.2f lon: %06.2f alt: %06.2f", lat, lon, alt);
Bryant
committed
paintText(tr("GPS"), labelColor, 2.6f, 2, vheight- 4.0f, &painter);
paintText(str, valueColor, 2.6f, 10, vheight - 4.0f, &painter);
// Draw Safety
double x1, y1, z1, x2, y2, z2;
UASManager::instance()->getLocalNEDSafetyLimits(&x1, &y1, &z1, &x2, &y2, &z2);
// drawSafetyArea(QPointF(x1, y1), QPointF(x2, y2), QGC::colorYellow, painter);
// Draw status message
Bryant
committed
paintText(statusMessage, statusColor, 2.8f, 8, 15, &painter);
// Draw setpoint over waypoints
if (positionSetPointKnown || setPointKnown)
{
// Draw setpoint
Bryant
committed
drawSetpointXYZYaw(bodyXSetCoordinate, bodyYSetCoordinate, bodyZSetCoordinate, bodyYawSet, setpointColor, painter);
// Draw travel direction line
QPointF m(bodyXSetCoordinate, bodyYSetCoordinate);
// Transform from body to world coordinates
m = metricWorldToBody(m);
// Scale from metric body to screen reference units
QPointF s = metricBodyToRef(m);
Bryant
committed
drawLine(s.x(), s.y(), xCenterPos, yCenterPos, 1.5f, setpointColor, &painter);
}
if ((userSetPointSet || dragStarted) && ((normAngleDiff > 0.05f) || !(setPointDist < 0.08f && mavInitialized)))
{
Bryant
committed
drawSetpointXYZYaw(uiXSetCoordinate, uiYSetCoordinate, uiZSetCoordinate, uiYawSet, setpointColor, painter);
void HSIDisplay::drawStatusFlag(float x, float y, QString label, bool status, bool known, QPainter& painter)
{
drawStatusFlag(x, y, label, status, known, true, painter);
}
void HSIDisplay::drawStatusFlag(float x, float y, QString label, bool status, bool known, bool ok, QPainter& painter)
Bryant
committed
QColor statusColor;
QColor labelColor;
Bryant
committed
if (MainWindow::instance()->getStyle() == MainWindow::QGC_MAINWINDOW_STYLE_LIGHT)
{
statusColor = QColor(40, 40, 40);
labelColor = QColor(26, 75, 95);
Bryant
committed
}
else
{
statusColor = QColor(250, 250, 250);
labelColor = QGC::colorCyan;
Bryant
committed
}
// Draw the label.
paintText(label, labelColor, 2.6f, x, y+0.8f, &painter);
// Determine color of status rectangle.
painter.setBrush(QGC::colorDarkYellow);
} else {
if(status) {
painter.setBrush(QGC::colorGreen);
} else {
painter.setBrush(Qt::darkGray);
}
}
painter.setPen(Qt::NoPen);
// Draw the status rectangle.
float indicatorWidth = refToScreenX(7.0f);
float indicatorHeight = refToScreenY(4.0f);
painter.drawRect(QRect(refToScreenX(x+7.3f), refToScreenY(y+0.05), indicatorWidth, indicatorHeight));
paintText((status) ? tr("ON") : tr("OFF"), statusColor, 2.6f, x+7.9f, y+0.8f, &painter);
// Cross out instrument if state unknown
painter.setPen(pen);
// Top left to bottom right
QPointF p1, p2, p3, p4;
p1.setX(refToScreenX(x));
p1.setY(refToScreenX(y));
p2.setX(p1.x()+indicatorWidth+refToScreenX(7.3f));
p2.setY(p1.y()+indicatorHeight);
painter.drawLine(p1, p2);
// Bottom left to top right
p3.setX(refToScreenX(x));
p3.setY(refToScreenX(y)+indicatorHeight);
p4.setX(p1.x()+indicatorWidth+refToScreenX(7.3f));
p4.setY(p1.y());
painter.drawLine(p3, p4);
}
void HSIDisplay::drawPositionLock(float x, float y, QString label, int status, bool known, QPainter& painter)
// Select color scheme based on light or dark window theme.
QColor labelColor;
QColor negStatusColor(200, 20, 20);
QColor intermediateStatusColor (Qt::yellow);
QColor posStatusColor(20, 200, 20);
Bryant
committed
QColor statusColor;
if (MainWindow::instance()->getStyle() == MainWindow::QGC_MAINWINDOW_STYLE_LIGHT)
{
statusColor = QColor(40, 40, 40);
labelColor = QColor(26, 75, 95);
Bryant
committed
}
else
{
statusColor = QColor(250, 250, 250);
labelColor = QGC::colorCyan;
// Draw the label.
paintText(label, labelColor, 2.6f, x, y+0.8f, &painter);
// based on the status, choose both the coloring and lock text.
QString lockText;
switch (status) {
case 1:
painter.setBrush(intermediateStatusColor.dark(150));
lockText = tr("LOC");
break;
case 2:
painter.setBrush(intermediateStatusColor.dark(150));
lockText = tr("2D");
break;
case 3:
painter.setBrush(posStatusColor);
lockText = tr("3D");
break;
default:
painter.setBrush(negStatusColor);
lockText = tr("NO");
break;
}
float indicatorWidth = refToScreenX(7.0f);
float indicatorHeight = refToScreenY(4.0f);
painter.setPen(Qt::NoPen);
painter.drawRect(QRect(refToScreenX(x+7.3f), refToScreenY(y+0.05), refToScreenX(7.0f), refToScreenY(4.0f)));
paintText(lockText, statusColor, 2.6f, x+7.9f, y+0.8f, &painter);
// Cross out instrument if state unknown
if (!known) {
QPen pen(Qt::yellow);
painter.setPen(pen);
// Top left to bottom right
QPointF p1, p2, p3, p4;
p1.setX(refToScreenX(x));
p1.setY(refToScreenX(y));
p2.setX(p1.x()+indicatorWidth+refToScreenX(7.3f));
p2.setY(p1.y()+indicatorHeight);
painter.drawLine(p1, p2);
// Bottom left to top right
p3.setX(refToScreenX(x));
p3.setY(refToScreenX(y)+indicatorHeight);
p4.setX(p1.x()+indicatorWidth+refToScreenX(7.3f));
p4.setY(p1.y());
painter.drawLine(p3, p4);
}
void HSIDisplay::updatePositionLock(UASInterface* uas, bool lock)
{
bool changed = positionLock != lock;
if (changed)
{
update();
}
void HSIDisplay::updateAttitudeControllerEnabled(bool enabled)
bool changed = attControlEnabled != enabled;
if (changed)
{
update();
}
void HSIDisplay::updatePositionXYControllerEnabled(bool enabled)
bool changed = xyControlEnabled != enabled;
if (changed)
{
update();
}
void HSIDisplay::updatePositionZControllerEnabled(bool enabled)
bool changed = zControlEnabled != enabled;
if (changed)
{
update();
}
void HSIDisplay::updateObjectPosition(unsigned int time, int id, int type, const QString& name, int quality, float bearing, float distance)
{
Q_UNUSED(quality);
Q_UNUSED(name);
Q_UNUSED(type);
Q_UNUSED(id);
Q_UNUSED(time);
// FIXME add multi-object support
QPainter painter(this);
QColor color(Qt::yellow);
float radius = vwidth / 20.0f;
QPen pen(color);
pen.setWidthF(refLineWidthToPen(0.4f));
pen.setColor(color);
painter.setPen(pen);
painter.setBrush(Qt::NoBrush);
QPointF in(cos(bearing)-sin(bearing)*distance, sin(bearing)+cos(bearing)*distance);
// Scale from metric to screen reference coordinates
QPointF p = metricBodyToRef(in);
drawCircle(p.x(), p.y(), radius, 0.4f, color, &painter);
}
QPointF HSIDisplay::metricWorldToBody(QPointF world)
{
// First translate to body-centered coordinates
// Rotate around -yaw
QPointF result(cos(angle) * (x - world.x()) - sin(angle) * (y - world.y()), sin(angle) * (x - world.x()) + cos(angle) * (y - world.y()));
return result;
}
QPointF HSIDisplay::metricBodyToWorld(QPointF body)
{
// First rotate into world coordinates
// then translate to world position
QPointF result((cos(-yaw) * body.x()) + (sin(-yaw) * body.y()) + x, (-sin(-yaw) * body.x()) + (cos(-yaw) * body.y()) + y);
QPointF HSIDisplay::screenToMetricBody(QPointF ref)
{
return QPointF(-((screenToRefY(ref.y()) - yCenterPos)/ vwidth) * metricWidth, ((screenToRefX(ref.x()) - xCenterPos) / vwidth) * metricWidth);
}
QPointF HSIDisplay::refToMetricBody(QPointF &ref)
{
return QPointF(-((ref.y() - yCenterPos)/ vwidth) * metricWidth - x, ((ref.x() - xCenterPos) / vwidth) * metricWidth - y);
}
/**
* @see refToScreenX()
*/
QPointF HSIDisplay::metricBodyToRef(QPointF &metric)
{
return QPointF(((metric.y())/ metricWidth) * vwidth + xCenterPos, ((-metric.x()) / metricWidth) * vwidth + yCenterPos);
}
double HSIDisplay::metricToRef(double metric)
{
return (metric / metricWidth) * vwidth;
}
double HSIDisplay::refToMetric(double ref)
{
return (ref/vwidth) * metricWidth;
}
QPointF HSIDisplay::metricBodyToScreen(QPointF metric)
{
QPointF ref = metricBodyToRef(metric);
ref.setX(refToScreenX(ref.x()));
ref.setY(refToScreenY(ref.y()));
return ref;
}
void HSIDisplay::mouseDoubleClickEvent(QMouseEvent * event)
{
if (event->type() == QMouseEvent::MouseButtonDblClick)
{
QPointF p = screenToMetricBody(event->posF());
if (!directSending)
{
setBodySetpointCoordinateXY(p.x(), p.y());
if (!userZSetPointSet) setBodySetpointCoordinateZ(0.0);
}
// qDebug() << "Double click at x: " << screenToRefX(event->x()) - xCenterPos << "y:" << screenToRefY(event->y()) - yCenterPos;
}
}
void HSIDisplay::mouseReleaseEvent(QMouseEvent * event)
{
if (mouseHasMoved)
if (event->type() == QMouseEvent::MouseButtonRelease && event->button() == Qt::RightButton)
{
if (dragStarted)
{
if (!directSending) setBodySetpointCoordinateYaw(uiYawSet);
dragStarted = false;
}
}
if (event->type() == QMouseEvent::MouseButtonRelease && event->button() == Qt::LeftButton)
{
if (leftDragStarted)
{
if (!directSending) setBodySetpointCoordinateZ(uiZSetCoordinate);
mouseHasMoved = false;
}
void HSIDisplay::mousePressEvent(QMouseEvent * event)
{
if (event->type() == QMouseEvent::MouseButtonPress)
{
if (event->button() == Qt::RightButton)
{
startX = event->x();
// Start tracking mouse move
dragStarted = true;
}
else if (event->button() == Qt::LeftButton)
{
startY = event->y();
leftDragStarted = true;
mouseHasMoved = false;
void HSIDisplay::mouseMoveEvent(QMouseEvent * event)
{
if (event->type() == QMouseEvent::MouseMove)
{
if (dragStarted) uiYawSet -= 0.06f*(startX - event->x()) / this->frameSize().width();
if (leftDragStarted)
{
// uiZSetCoordinate -= 0.06f*(startY - event->y()) / this->frameSize().height();
// setBodySetpointCoordinateZ(uiZSetCoordinate);
if (leftDragStarted || dragStarted) mouseHasMoved = true;
QPointF bodySP = metricWorldToBody(QPointF(uiXSetCoordinate, uiYSetCoordinate));
if ((event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) && actionPending)
{
actionPending = false;
statusMessage = "SETPOINT SENT";
statusClearTimer.start();
sendBodySetPointCoordinates();
}
// FIXME hardcode yaw to current value
setBodySetpointCoordinateYaw(0);
// Reset setpoints to current position / orientation
// if not initialized
if (!userYawSetPointSet)
setBodySetpointCoordinateXY(qBound(-1.5, bodySP.x()+0.2, +1.5), bodySP.y());
setBodySetpointCoordinateXY(qBound(-1.5, bodySP.x()-0.2, +1.5), bodySP.y());
{
setBodySetpointCoordinateXY(bodySP.x(), qBound(-1.5, bodySP.y()-0.2, +1.5));
}
{
setBodySetpointCoordinateXY(bodySP.x(), qBound(-1.5, bodySP.y()+0.2, +1.5));
}
// Overwrite any existing non-zero body setpoints
// for escape
if ((event->key() == Qt::Key_Escape) || (event->key() == Qt::Key_R))
setBodySetpointCoordinateZ(0);
setBodySetpointCoordinateYaw(0);
statusMessage = "CANCELLED, PRESS <ENTER> TO SEND";
if ((event->key() == Qt::Key_T))
directSending = !directSending;
statusMessage = (directSending) ? "DIRECT SEND ON" : "DIRECT SEND OFF";
statusClearTimer.start();
if (actionPending && (directSending || (event->key() == Qt::Key_Escape)))
actionPending = false;
statusMessage = "SETPOINT SENT";
statusClearTimer.start();
sendBodySetPointCoordinates();
HDDisplay::keyPressEvent(event);
void HSIDisplay::contextMenuEvent (QContextMenuEvent* event)
{
event->ignore();
}
void HSIDisplay::setMetricWidth(double width)
{
metricWidth = width;
emit metricWidthChanged(metricWidth);
}
}
/**
*
* @param uas the UAS/MAV to monitor/display with the HUD
*/
void HSIDisplay::setActiveUAS(UASInterface* uas)
{
if (this->uas != NULL) {
disconnect(this->uas, SIGNAL(gpsSatelliteStatusChanged(int,int,float,float,float,bool)), this, SLOT(updateSatellite(int,int,float,float,float,bool)));
disconnect(this->uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateLocalPosition(UASInterface*,double,double,double,quint64)));
disconnect(this->uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,quint64)));
disconnect(this->uas, SIGNAL(attitudeThrustSetPointChanged(UASInterface*,double,double,double,double,quint64)), this, SLOT(updateAttitudeSetpoints(UASInterface*,double,double,double,double,quint64)));
disconnect(this->uas, SIGNAL(positionSetPointsChanged(int,float,float,float,float,quint64)), this, SLOT(updatePositionSetpoints(int,float,float,float,float,quint64)));
disconnect(uas, SIGNAL(userPositionSetPointsChanged(int,float,float,float,float)), this, SLOT(updateUserPositionSetpoints(int,float,float,float,float)));
disconnect(this->uas, SIGNAL(velocityChanged_NED(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64)));
disconnect(this->uas, SIGNAL(attitudeChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateAttitude(UASInterface*,double,double,double,quint64)));
disconnect(this->uas, SIGNAL(attitudeControlEnabled(bool)), this, SLOT(updateAttitudeControllerEnabled(bool)));
disconnect(this->uas, SIGNAL(positionXYControlEnabled(bool)), this, SLOT(updatePositionXYControllerEnabled(bool)));
disconnect(this->uas, SIGNAL(positionZControlEnabled(bool)), this, SLOT(updatePositionZControllerEnabled(bool)));
disconnect(this->uas, SIGNAL(positionYawControlEnabled(bool)), this, SLOT(updatePositionYawControllerEnabled(bool)));
disconnect(this->uas, SIGNAL(localizationChanged(UASInterface*,int)), this, SLOT(updateLocalization(UASInterface*,int)));
disconnect(this->uas, SIGNAL(visionLocalizationChanged(UASInterface*,int)), this, SLOT(updateVisionLocalization(UASInterface*,int)));
disconnect(this->uas, SIGNAL(gpsLocalizationChanged(UASInterface*,int)), this, SLOT(updateGpsLocalization(UASInterface*,int)));
disconnect(this->uas, SIGNAL(irUltraSoundLocalizationChanged(UASInterface*,int)), this, SLOT(updateInfraredUltrasoundLocalization(UASInterface*,int)));
disconnect(this->uas, SIGNAL(objectDetected(uint,int,int,QString,int,float,float)), this, SLOT(updateObjectPosition(uint,int,int,QString,int,float,float)));
disconnect(this->uas, SIGNAL(gyroStatusChanged(bool,bool,bool)), this, SLOT(updateGyroStatus(bool,bool,bool)));
disconnect(this->uas, SIGNAL(accelStatusChanged(bool,bool,bool)), this, SLOT(updateAccelStatus(bool,bool,bool)));
disconnect(this->uas, SIGNAL(magSensorStatusChanged(bool,bool,bool)), this, SLOT(updateMagSensorStatus(bool,bool,bool)));
disconnect(this->uas, SIGNAL(baroStatusChanged(bool,bool,bool)), this, SLOT(updateBaroStatus(bool,bool,bool)));
disconnect(this->uas, SIGNAL(airspeedStatusChanged(bool,bool,bool)), this, SLOT(updateAirspeedStatus(bool,bool,bool)));
disconnect(this->uas, SIGNAL(opticalFlowStatusChanged(bool,bool,bool)), this, SLOT(updateOpticalFlowStatus(bool,bool,bool)));
disconnect(this->uas, SIGNAL(laserStatusChanged(bool,bool,bool)), this, SLOT(updateLaserStatus(bool,bool,bool)));
disconnect(this->uas, SIGNAL(groundTruthSensorStatusChanged(bool,bool,bool)), this, SLOT(updateGroundTruthSensorStatus(bool,bool,bool)));
disconnect(this->uas, SIGNAL(actuatorStatusChanged(bool,bool,bool)), this, SLOT(updateActuatorStatus(bool,bool,bool)));
if (uas)
{
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
connect(uas, SIGNAL(gpsSatelliteStatusChanged(int,int,float,float,float,bool)),
this, SLOT(updateSatellite(int,int,float,float,float,bool)));
connect(uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)),
this, SLOT(updateLocalPosition(UASInterface*,double,double,double,quint64)));
connect(uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)),
this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,quint64)));
connect(uas, SIGNAL(attitudeThrustSetPointChanged(UASInterface*,double,double,double,double,quint64)),
this, SLOT(updateAttitudeSetpoints(UASInterface*,double,double,double,double,quint64)));
connect(uas, SIGNAL(positionSetPointsChanged(int,float,float,float,float,quint64)),
this, SLOT(updatePositionSetpoints(int,float,float,float,float,quint64)));
connect(uas, SIGNAL(userPositionSetPointsChanged(int,float,float,float,float)),
this, SLOT(updateUserPositionSetpoints(int,float,float,float,float)));
connect(uas, SIGNAL(velocityChanged_NED(UASInterface*,double,double,double,quint64)),
this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64)));
connect(uas, SIGNAL(attitudeChanged(UASInterface*,double,double,double,quint64)),
this, SLOT(updateAttitude(UASInterface*,double,double,double,quint64)));
connect(uas, SIGNAL(attitudeControlEnabled(bool)),
this, SLOT(updateAttitudeControllerEnabled(bool)));
connect(uas, SIGNAL(positionXYControlEnabled(bool)),
this, SLOT(updatePositionXYControllerEnabled(bool)));
connect(uas, SIGNAL(positionZControlEnabled(bool)),
this, SLOT(updatePositionZControllerEnabled(bool)));
connect(uas, SIGNAL(positionYawControlEnabled(bool)),
this, SLOT(updatePositionYawControllerEnabled(bool)));
connect(uas, SIGNAL(localizationChanged(UASInterface*,int)),
this, SLOT(updateLocalization(UASInterface*,int)));
connect(uas, SIGNAL(visionLocalizationChanged(UASInterface*,int)),
this, SLOT(updateVisionLocalization(UASInterface*,int)));
connect(uas, SIGNAL(gpsLocalizationChanged(UASInterface*,int)),
this, SLOT(updateGpsLocalization(UASInterface*,int)));
connect(uas, SIGNAL(irUltraSoundLocalizationChanged(UASInterface*,int)),
this, SLOT(updateInfraredUltrasoundLocalization(UASInterface*,int)));
connect(uas, SIGNAL(objectDetected(uint,int,int,QString,int,float,float)),
this, SLOT(updateObjectPosition(uint,int,int,QString,int,float,float)));
connect(uas, SIGNAL(gyroStatusChanged(bool,bool,bool)),
this, SLOT(updateGyroStatus(bool,bool,bool)));
connect(uas, SIGNAL(accelStatusChanged(bool,bool,bool)),
this, SLOT(updateAccelStatus(bool,bool,bool)));
connect(uas, SIGNAL(magSensorStatusChanged(bool,bool,bool)),
this, SLOT(updateMagSensorStatus(bool,bool,bool)));
connect(uas, SIGNAL(baroStatusChanged(bool,bool,bool)),
this, SLOT(updateBaroStatus(bool,bool,bool)));
connect(uas, SIGNAL(airspeedStatusChanged(bool,bool,bool)),
this, SLOT(updateAirspeedStatus(bool,bool,bool)));
connect(uas, SIGNAL(opticalFlowStatusChanged(bool,bool,bool)),
this, SLOT(updateOpticalFlowStatus(bool,bool,bool)));
connect(uas, SIGNAL(laserStatusChanged(bool,bool,bool)),
this, SLOT(updateLaserStatus(bool,bool,bool)));
connect(uas, SIGNAL(groundTruthSensorStatusChanged(bool,bool,bool)),
this, SLOT(updateGroundTruthSensorStatus(bool,bool,bool)));
connect(uas, SIGNAL(actuatorStatusChanged(bool,bool,bool)),
this, SLOT(updateActuatorStatus(bool,bool,bool)));
statusClearTimer.start(3000);
}
else
{
statusClearTimer.stop();
}
void HSIDisplay::updateSpeed(UASInterface* uas, double vx, double vy, double vz, quint64 time)
{
Q_UNUSED(uas);
Q_UNUSED(time);
this->vx = vx;
this->vy = vy;
this->vz = vz;
this->speed = sqrt(pow(vx, 2.0) + pow(vy, 2.0) + pow(vz, 2.0));
}
void HSIDisplay::setBodySetpointCoordinateXY(double x, double y)
{
if (uas)
{
userSetPointSet = true;
userXYSetPointSet = true;
// Set coordinates and send them out to MAV
QPointF sp(x, y);
sp = metricBodyToWorld(sp);
uiXSetCoordinate = sp.x();
uiYSetCoordinate = sp.y();
qDebug() << "Attempting to set new setpoint at x: " << x << "metric y:" << y;
//sendBodySetPointCoordinates();
statusMessage = "POSITION SET, PRESS <ENTER> TO SEND";
actionPending = true;
statusClearTimer.start();
}
void HSIDisplay::setBodySetpointCoordinateZ(double z)
{
if (uas)
{
userSetPointSet = true;
// Set coordinates and send them out to MAV
uiZSetCoordinate = z+uas->getLocalZ();
statusMessage = "Z SET, PRESS <ENTER> TO SEND";
actionPending = true;
statusClearTimer.start();
}
}
void HSIDisplay::setBodySetpointCoordinateYaw(double yaw)
{
if (uas)
{
if (!userXYSetPointSet && setPointKnown)
{
uiXSetCoordinate = bodyXSetCoordinate;
uiYSetCoordinate = bodyYSetCoordinate;
}
else if (!userXYSetPointSet && mavInitialized)
{
QPointF coord = metricBodyToWorld(QPointF(0.0, 0.0));
uiXSetCoordinate = coord.x();
uiYSetCoordinate = coord.y();
}
userSetPointSet = true;
// Set coordinates and send them out to MAV
uiYawSet = atan2(sin(yaw+uas->getYaw()), cos(yaw+uas->getYaw()));
statusMessage = "YAW SET, PRESS <ENTER> TO SEND";
statusClearTimer.start();
actionPending = true;
}
}
void HSIDisplay::sendBodySetPointCoordinates()
{
// Send the coordinates to the MAV
if (uas)
{
uas->setLocalPositionSetpoint(uiXSetCoordinate, uiYSetCoordinate, uiZSetCoordinate, uiYawSet);
}
void HSIDisplay::updateAttitudeSetpoints(UASInterface* uas, double rollDesired, double pitchDesired, double yawDesired, double thrustDesired, quint64 usec)
Q_UNUSED(uas);
Q_UNUSED(usec);
attXSet = pitchDesired;
attYSet = rollDesired;
attYawSet = yawDesired;
altitudeSet = thrustDesired;
void HSIDisplay::updateAttitude(UASInterface* uas, double roll, double pitch, double yaw, quint64 time)
{
Q_UNUSED(uas);
Q_UNUSED(time);
this->roll = roll;
this->pitch = pitch;
this->yaw = yaw;
}
void HSIDisplay::updateUserPositionSetpoints(int uasid, float xDesired, float yDesired, float zDesired, float yawDesired)
{
Q_UNUSED(uasid);
uiXSetCoordinate = xDesired;
uiYSetCoordinate = yDesired;
uiZSetCoordinate = zDesired;
uiYawSet = yawDesired;
userXYSetPointSet = true;
userZSetPointSet = true;
userYawSetPointSet = true;
userSetPointSet = true;
}
void HSIDisplay::updatePositionSetpoints(int uasid, float xDesired, float yDesired, float zDesired, float yawDesired, quint64 usec)
bodyXSetCoordinate = xDesired;
bodyYSetCoordinate = yDesired;
bodyZSetCoordinate = zDesired;
bodyYawSet = yawDesired;
positionSetPointKnown = true;
if (!userSetPointSet && !dragStarted)
{
uiXSetCoordinate = bodyXSetCoordinate;
uiYSetCoordinate = bodyYSetCoordinate;
// uiZSetCoordinate = bodyZSetCoordinate;
uiYawSet= bodyYawSet;
}
}
void HSIDisplay::updateLocalPosition(UASInterface*, double x, double y, double z, quint64 usec)
{
this->x = x;
this->y = y;
this->z = z;
localAvailable = usec;
}
void HSIDisplay::updateGlobalPosition(UASInterface*, double lat, double lon, double alt, quint64 usec)
{
this->lat = lat;
this->lon = lon;
this->alt = alt;
globalAvailable = usec;
void HSIDisplay::updateSatellite(int uasid, int satid, float elevation, float azimuth, float snr, bool used)
Bryant
committed
if (satid != 0) { // Satellite PRNs currently range from 1-32, but are never zero
if (gpsSatellites.contains(satid)) {
gpsSatellites.value(satid)->update(satid, elevation, azimuth, snr, used);
} else {
gpsSatellites.insert(satid, new GPSSatellite(satid, elevation, azimuth, snr, used));
}
void HSIDisplay::updatePositionYawControllerEnabled(bool enabled)
{
yawControlEnabled = enabled;
}
/**
* @param fix 0: lost, 1: 2D local position hold, 2: 2D localization, 3: 3D localization
*/
void HSIDisplay::updateLocalization(UASInterface* uas, int fix)
{
Q_UNUSED(uas);
positionFix = fix;
//qDebug() << "LOCALIZATION FIX CALLED";
}
/**
* @param fix 0: lost, 1: at least one satellite, but no GPS fix, 2: 2D localization, 3: 3D localization
*/
void HSIDisplay::updateGpsLocalization(UASInterface* uas, int fix)
{
Q_UNUSED(uas);
gpsFix = fix;
}
/**
* @param fix 0: lost, 1: 2D local position hold, 2: 2D localization, 3: 3D localization
*/
void HSIDisplay::updateVisionLocalization(UASInterface* uas, int fix)
{
Q_UNUSED(uas);
visionFix = fix;
//qDebug() << "VISION FIX GOT CALLED";
/**
* @param fix 0: lost, 1-N: Localized with N ultrasound or infrared sensors
*/
void HSIDisplay::updateInfraredUltrasoundLocalization(UASInterface* uas, int fix)
{
Q_UNUSED(uas);
iruFix = fix;
} else if (snr >= 30 && snr < 35) {
} else if (snr >= 35 && snr < 40) {
void HSIDisplay::drawSetpointXYZYaw(float x, float y, float z, float yaw, const QColor &color, QPainter &painter)
if (uas)
{
float radius = vwidth / 18.0f;
pen.setWidthF(refLineWidthToPen(1.6f));
pen.setColor(color);
painter.setPen(pen);
painter.setBrush(Qt::NoBrush);
QPointF in(x, y);
// Transform from body to world coordinates
in = metricWorldToBody(in);
// Scale from metric to screen reference coordinates
QPointF p = metricBodyToRef(in);
QPolygonF poly(4);
// Top point
poly.replace(0, QPointF(p.x()-radius, p.y()-radius));
// Right point
poly.replace(1, QPointF(p.x()+radius, p.y()-radius));
// Bottom point
poly.replace(2, QPointF(p.x()+radius, p.y()+radius));
poly.replace(3, QPointF(p.x()-radius, p.y()+radius));
paintText(QString("z: %1").arg(z, 3, 'f', 1, QChar(' ')), color, 2.1f, p.x()-radius, p.y()-radius-3.5f, &painter);
drawPolygon(poly, &painter);
drawLine(p.x(), p.y(), p.x()+sin(-yaw + uas->getYaw() + M_PI) * radius, p.y()+cos(-yaw + uas->getYaw() + M_PI) * radius, refLineWidthToPen(0.6f), color, &painter);
painter.setBrush(color);
drawCircle(p.x(), p.y(), radius * 0.1f, 0.1f, color, &painter);
}
Bryant
committed
void HSIDisplay::drawWaypoint(QPainter& painter, const QColor& color, float width, const Waypoint *w, const QPointF& p)
{
painter.setBrush(Qt::NoBrush);
// Setup pen for foreground
QPen pen(color);
pen.setWidthF(width);
// DRAW WAYPOINT
float waypointSize = vwidth / 20.0f * 2.0f;
QPolygonF poly(4);
// Top point
poly.replace(0, QPointF(p.x(), p.y()-waypointSize/2.0f));
// Right point
poly.replace(1, QPointF(p.x()+waypointSize/2.0f, p.y()));
// Bottom point
poly.replace(2, QPointF(p.x(), p.y() + waypointSize/2.0f));
poly.replace(3, QPointF(p.x() - waypointSize/2.0f, p.y()));
float radius = (waypointSize/2.0f) * 0.8 * (1/sqrt(2.0f));
Bryant
committed
float acceptRadius = w->getAcceptanceRadius();
double yawDiff = w->getYaw()/180.0*M_PI-yaw;
// Draw background
pen.setColor(Qt::black);
painter.setPen(pen);
Bryant
committed
drawLine(p.x(), p.y(), p.x()+sin(yawDiff) * radius, p.y()-cos(yawDiff) * radius, refLineWidthToPen(0.4f*3.0f), Qt::black, &painter);
drawCircle(p.x(), p.y(), metricToRef(acceptRadius), 3.0, Qt::black, &painter);
// Draw foreground
pen.setColor(color);
painter.setPen(pen);
Bryant
committed
drawLine(p.x(), p.y(), p.x()+sin(yawDiff) * radius, p.y()-cos(yawDiff) * radius, refLineWidthToPen(0.4f), color, &painter);
drawPolygon(poly, &painter);
drawCircle(p.x(), p.y(), metricToRef(acceptRadius), 1.0, Qt::green, &painter);
}
void HSIDisplay::drawWaypoints(QPainter& painter)
{
Bryant
committed
// Grab all waypoints.
const QList<Waypoint*>& list = uas->getWaypointManager()->getWaypointEditableList();
Bryant
committed
const int numWaypoints = list.size();
Bryant
committed
if (list.size() == 0)
{
return;
}
Bryant
committed
// Make sure any drawn shapes are not filled-in.
painter.setBrush(Qt::NoBrush);
QPointF lastWaypoint;
Bryant
committed
for (int i = 0; i < numWaypoints; i++)
Bryant
committed
const Waypoint *w = list.at(i);
Bryant
committed
// Use local coordinates as-is.
int frameRef = w->getFrame();
if (frameRef == MAV_FRAME_LOCAL_NED)
{
in = QPointF(w->getX(), w->getY());
}
else if (frameRef == MAV_FRAME_LOCAL_ENU)
Bryant
committed
in = QPointF(w->getY(), w->getX());
}
// Convert global coordinates into the local ENU frame, then display them.
else if (frameRef == MAV_FRAME_GLOBAL || frameRef == MAV_FRAME_GLOBAL_RELATIVE_ALT) {
// Get the position of the GPS origin for the MAV.
// Transform the lat/lon for this waypoint into the local frame
double e, n, u;
UASManager::instance()->wgs84ToEnu(w->getX(), w->getY(),w->getZ(), &e, &n, &u);
in = QPointF(n, e);
}
// Otherwise we don't process this waypoint.
// FIXME: This code will probably fail if the last waypoint found is not a valid one.
else {
continue;
Bryant
committed
// Transform from world to body coordinates
in = metricWorldToBody(in);
// Scale from metric to screen reference coordinates
QPointF p = metricBodyToRef(in);
Bryant
committed
// Select color based on if this is the current waypoint.
if (w->getCurrent())
Bryant
committed
drawWaypoint(painter, QGC::colorYellow, refLineWidthToPen(0.8f), w, p);
Bryant
committed
drawWaypoint(painter, QGC::colorCyan, refLineWidthToPen(0.4f), w, p);
Bryant
committed
// Draw connecting line from last waypoint to this one.
if (!lastWaypoint.isNull())
{
drawLine(lastWaypoint.x(), lastWaypoint.y(), p.x(), p.y(), refLineWidthToPen(0.4f*2.0f), Qt::black, &painter);
drawLine(lastWaypoint.x(), lastWaypoint.y(), p.x(), p.y(), refLineWidthToPen(0.4f), QGC::colorCyan, &painter);
}
lastWaypoint = p;
void HSIDisplay::drawSafetyArea(const QPointF &topLeft, const QPointF &bottomRight, const QColor &color, QPainter &painter)
{
QPen pen(color);
pen.setWidthF(refLineWidthToPen(0.1f));
pen.setColor(color);
pen.setBrush(Qt::NoBrush);
painter.drawRect(QRectF(metricBodyToScreen(metricWorldToBody(topLeft)), metricBodyToScreen(metricWorldToBody(bottomRight))));
void HSIDisplay::drawGPS(QPainter &painter)
{
float xCenter = xCenterPos;
float yCenter = yCenterPos;
const float yawDeg = ((yaw/M_PI)*180.0f);
int yawRotate = static_cast<int>(yawDeg) % 360;
// XXX check rotation direction
// Max satellite circle radius
const float margin = 0.15f; // 20% margin of total width on each side
float radius = (vwidth - vwidth * 2.0f * margin) / 2.0f;
quint64 currTime = MG::TIME::getGroundTimeNowUsecs();
// Draw satellite labels
// QString label;
// label.sprintf("%05.1f", value);
// paintText(label, color, 4.5f, xRef-7.5f, yRef-2.0f, painter);
// Check if update is not older than 10 seconds, else delete satellite
if (sat->lastUpdate + 10000000 < currTime) {
// Delete and go to next satellite
gpsSatellites.remove(i.key());
// Draw satellite
QBrush brush;
QColor color = getColorForSNR(sat->snr);
brush.setColor(color);
brush.setStyle(Qt::NoBrush);
}
painter.setPen(Qt::SolidLine);
painter.setPen(color);
painter.setBrush(brush);
float xPos = xCenter + (sin(((sat->azimuth/255.0f)*360.0f-yawRotate)/180.0f * M_PI) * cos(sat->elevation/180.0f * M_PI)) * radius;
float yPos = yCenter - (cos(((sat->azimuth/255.0f)*360.0f-yawRotate)/180.0f * M_PI) * cos(sat->elevation/180.0f * M_PI)) * radius;
// Draw circle for satellite, filled for used satellites
paintText(QString::number(sat->id), QColor(255, 255, 255), 2.9f, xPos+1.7f, yPos+2.0f, &painter);
void HSIDisplay::drawObjects(QPainter &painter)
void HSIDisplay::drawPositionDirection(float xRef, float yRef, float radius, const QColor& color, QPainter* painter)
if (xyControlKnown && xyControlEnabled) {
// Draw the needle
const float minWidth = maxWidth * 0.3f;
float angle = atan2(posXSet, -posYSet);
angle -= (float)M_PI/2.0f;
QPolygonF p(6);
//radius *= ((posXSaturation + posYSaturation) - sqrt(pow(posXSet, 2), pow(posYSet, 2))) / (2*posXSaturation);
radius *= sqrt(pow(posXSet, 2) + pow(posYSet, 2)) / sqrt(posXSaturation + posYSaturation);
p.replace(0, QPointF(xRef-maxWidth/2.0f, yRef-radius * 0.4f));
p.replace(1, QPointF(xRef-minWidth/2.0f, yRef-radius * 0.9f));
p.replace(2, QPointF(xRef+minWidth/2.0f, yRef-radius * 0.9f));
p.replace(3, QPointF(xRef+maxWidth/2.0f, yRef-radius * 0.4f));
p.replace(4, QPointF(xRef, yRef-radius * 0.36f));
p.replace(5, QPointF(xRef-maxWidth/2.0f, yRef-radius * 0.4f));
rotatePolygonClockWiseRad(p, angle, QPointF(xRef, yRef));
QBrush indexBrush;
indexBrush.setColor(color);
indexBrush.setStyle(Qt::SolidPattern);
painter->setPen(Qt::SolidLine);
painter->setPen(color);
painter->setBrush(indexBrush);
drawPolygon(p, painter);
//qDebug() << "DRAWING POS SETPOINT X:" << posXSet << "Y:" << posYSet << angle;
}
void HSIDisplay::drawAttitudeDirection(float xRef, float yRef, float radius, const QColor& color, QPainter* painter)
if (attControlKnown && attControlEnabled) {
// Draw the needle
const float maxWidth = radius / 10.0f;
const float minWidth = maxWidth * 0.3f;
radius *= sqrt(attXSet*attXSet + attYSet*attYSet) / sqrt(attXSaturation*attXSaturation + attYSaturation*attYSaturation);
QPolygonF p(6);
p.replace(0, QPointF(xRef-maxWidth/2.0f, yRef-radius * 0.4f));
p.replace(1, QPointF(xRef-minWidth/2.0f, yRef-radius * 0.9f));
p.replace(2, QPointF(xRef+minWidth/2.0f, yRef-radius * 0.9f));
p.replace(3, QPointF(xRef+maxWidth/2.0f, yRef-radius * 0.4f));
p.replace(4, QPointF(xRef, yRef-radius * 0.36f));
p.replace(5, QPointF(xRef-maxWidth/2.0f, yRef-radius * 0.4f));
rotatePolygonClockWiseRad(p, angle, QPointF(xRef, yRef));
QBrush indexBrush;
indexBrush.setColor(color);
indexBrush.setStyle(Qt::SolidPattern);
painter->setPen(Qt::SolidLine);
painter->setPen(color);
painter->setBrush(indexBrush);
drawPolygon(p, painter);
// TODO Draw Yaw indicator
//qDebug() << "DRAWING ATT SETPOINT X:" << attXSet << "Y:" << attYSet << angle;
}
}
void HSIDisplay::drawAltitudeSetpoint(float xRef, float yRef, float radius, const QColor& color, QPainter* painter)
{
if (zControlKnown && zControlEnabled) {
// Draw the circle
QPen circlePen(Qt::SolidLine);
circlePen.setWidth(refLineWidthToPen(0.5f));
circlePen.setColor(color);
painter->setBrush(Qt::NoBrush);
painter->setPen(circlePen);
drawCircle(xRef, yRef, radius, 200.0f, color, painter);
//drawCircle(xRef, yRef, radius, 200.0f, 170.0f, 1.0f, color, painter);
// // Draw the value
// QString label;
// label.sprintf("%05.1f", value);
// paintText(label, color, 4.5f, xRef-7.5f, yRef-2.0f, painter);
}
void HSIDisplay::wheelEvent(QWheelEvent* event)
{
double zoomScale = 0.005; // Scaling of zoom value
// Reduce width -> Zoom in
metricWidth -= event->delta() * zoomScale;
// Increase width -> Zoom out
metricWidth -= event->delta() * zoomScale;
}
metricWidth = qBound(0.5, metricWidth, 9999.0);
emit metricWidthChanged(metricWidth);
}
void HSIDisplay::showEvent(QShowEvent* event)
{
// React only to internal (pre-display)
// events
refreshTimer->start(updateInterval);
}
}
void HSIDisplay::hideEvent(QHideEvent* event)
{
// React only to internal (post-display)
// events
refreshTimer->stop();
}
}
void HSIDisplay::updateJoystick(double roll, double pitch, double yaw, double thrust, int xHat, int yHat)
{
Q_UNUSED(roll);
Q_UNUSED(pitch);
Q_UNUSED(yaw);
Q_UNUSED(thrust);
Q_UNUSED(xHat);
Q_UNUSED(yHat);
}
void HSIDisplay::pressKey(int key)
{