HUD.cc 55.8 KB
Newer Older
pixhawk's avatar
pixhawk committed
1
2
/*=====================================================================

3
QGroundControl Open Source Ground Control Station
pixhawk's avatar
pixhawk committed
4

5
(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
pixhawk's avatar
pixhawk committed
6

7
This file is part of the QGROUNDCONTROL project
pixhawk's avatar
pixhawk committed
8

9
    QGROUNDCONTROL is free software: you can redistribute it and/or modify
pixhawk's avatar
pixhawk committed
10
11
12
13
    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.

14
    QGROUNDCONTROL is distributed in the hope that it will be useful,
pixhawk's avatar
pixhawk committed
15
16
17
18
19
    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
20
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
pixhawk's avatar
pixhawk committed
21
22
23
24
25
26
27
28
29
30
31

======================================================================*/

/**
 * @file
 *   @brief Head Up Display (HUD)
 *
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *
 */

32
#include <QShowEvent>
33
34
35
36
#include <QContextMenuEvent>
#include <QMenu>
#include <QDesktopServices>
#include <QFileDialog>
37

pixhawk's avatar
pixhawk committed
38
39
#include <QDebug>
#include <cmath>
pixhawk's avatar
pixhawk committed
40
#include <qmath.h>
pixhawk's avatar
pixhawk committed
41
#include <limits>
pixhawk's avatar
pixhawk committed
42
43

#include "UASManager.h"
44
#include "UAS.h"
pixhawk's avatar
pixhawk committed
45
46
#include "HUD.h"
#include "MG.h"
47
#include "QGC.h"
pixhawk's avatar
pixhawk committed
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

// Fix for some platforms, e.g. windows
#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE  0x809D
#endif

/**
 * @warning The HUD widget will not start painting its content automatically
 *          to update the view, start the auto-update by calling HUD::start().
 *
 * @param width
 * @param height
 * @param parent
 */
HUD::HUD(int width, int height, QWidget* parent)
63
    : QGLWidget(QGLFormat(QGL::SampleBuffers), parent),
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
      uas(NULL),
      yawInt(0.0f),
      mode(tr("UNKNOWN MODE")),
      state(tr("UNKNOWN STATE")),
      fuelStatus(tr("00.0V (00m:00s)")),
      xCenterOffset(0.0f),
      yCenterOffset(0.0f),
      vwidth(200.0f),
      vheight(150.0f),
      vGaugeSpacing(50.0f),
      vPitchPerDeg(6.0f), ///< 4 mm y translation per degree)
      rawBuffer1(NULL),
      rawBuffer2(NULL),
      rawImage(NULL),
      rawLastIndex(0),
      rawExpectedBytes(0),
      bytesPerLine(1),
      imageStarted(false),
      receivedDepth(8),
      receivedChannels(1),
      receivedWidth(640),
      receivedHeight(480),
      defaultColor(QColor(70, 200, 70)),
      setPointColor(QColor(200, 20, 200)),
      warningColor(Qt::yellow),
      criticalColor(Qt::red),
      infoColor(QColor(20, 200, 20)),
      fuelColor(criticalColor),
      warningBlinkRate(5),
      refreshTimer(new QTimer(this)),
      noCamera(true),
      hardwareAcceleration(true),
      strongStrokeWidth(1.5f),
      normalStrokeWidth(1.0f),
      fineStrokeWidth(0.5f),
      waypointName(""),
      roll(0.0f),
      pitch(0.0f),
      yaw(0.0f),
      rollLP(0.0f),
      pitchLP(0.0f),
      yawLP(0.0f),
      yawDiff(0.0f),
      xPos(0.0),
      yPos(0.0),
      zPos(0.0),
      xSpeed(0.0),
      ySpeed(0.0),
      zSpeed(0.0),
      lastSpeedUpdate(0),
      totalSpeed(0.0),
      totalAcc(0.0),
      lat(0.0),
      lon(0.0),
      alt(0.0),
      load(0.0f),
      offlineDirectory(""),
      nextOfflineImage(""),
      hudInstrumentsEnabled(true),
      videoEnabled(false),
      xImageFactor(1.0),
125
126
      yImageFactor(1.0),
      imageRequested(false)
pixhawk's avatar
pixhawk committed
127
128
129
130
{
    // Set auto fill to false
    setAutoFillBackground(false);

131
132
    // Set minimum size
    setMinimumSize(80, 60);
133
134
    // Set preferred size
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
LM's avatar
LM committed
135
    scalingFactor = this->width()/vwidth;
136

pixhawk's avatar
pixhawk committed
137
138
139
140
141
142
143
144
    // Fill with black background
    QImage fill = QImage(width, height, QImage::Format_Indexed8);
    fill.setNumColors(3);
    fill.setColor(0, qRgb(0, 0, 0));
    fill.setColor(1, qRgb(0, 0, 0));
    fill.setColor(2, qRgb(0, 0, 0));
    fill.fill(0);

pixhawk's avatar
pixhawk committed
145
146
147
    //QString imagePath = "/Users/user/Desktop/frame0000.png";
    //qDebug() << __FILE__ << __LINE__ << "template image:" << imagePath;
    //fill = QImage(imagePath);
pixhawk's avatar
pixhawk committed
148

LM's avatar
LM committed
149
    glImage = QGLWidget::convertToGLFormat(fill);
pixhawk's avatar
pixhawk committed
150
151

    // Refresh timer
152
    refreshTimer->setInterval(updateInterval);
153
    connect(refreshTimer, SIGNAL(timeout()), this, SLOT(paintHUD()));
pixhawk's avatar
pixhawk committed
154
155

    // Resize to correct size and fill with image
pixhawk's avatar
pixhawk committed
156
    //glDrawPixels(glImage.width(), glImage.height(), GL_RGBA, GL_UNSIGNED_BYTE, glImage.bits());
pixhawk's avatar
pixhawk committed
157
158
159
160
161
162
163
164
165
166
167
168
169
170

    // Set size once
    //setFixedSize(fill.size());
    //setMinimumSize(fill.size());
    //setMaximumSize(fill.size());
    // Lock down the size
    //setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));

    fontDatabase = QFontDatabase();
    const QString fontFileName = ":/general/vera.ttf"; ///< Font file is part of the QRC file and compiled into the app
    const QString fontFamilyName = "Bitstream Vera Sans";
    if(!QFile::exists(fontFileName)) qDebug() << "ERROR! font file: " << fontFileName << " DOES NOT EXIST!";

    fontDatabase.addApplicationFont(fontFileName);
lm's avatar
lm committed
171
172
    font = fontDatabase.font(fontFamilyName, "Roman", qMax(5,(int)(10.0f*scalingFactor*1.2f+0.5f)));
    QFont* fontPtr = &font;
173
    if (!fontPtr) {
lm's avatar
lm committed
174
        qDebug() << "ERROR! FONT NOT LOADED!";
175
    } else {
lm's avatar
lm committed
176
177
        if (font.family() != fontFamilyName) qDebug() << "ERROR! WRONG FONT LOADED: " << fontFamilyName;
    }
pixhawk's avatar
pixhawk committed
178
179

    // Connect with UAS
180
181
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));

182
183
184
    createActions();

    if (UASManager::instance()->getActiveUAS() != NULL) setActiveUAS(UASManager::instance()->getActiveUAS());
pixhawk's avatar
pixhawk committed
185
186
187
188
}

HUD::~HUD()
{
pixhawk's avatar
pixhawk committed
189
    refreshTimer->stop();
pixhawk's avatar
pixhawk committed
190
191
}

192
193
QSize HUD::sizeHint() const
{
194
    return QSize(width(), (width()*3.0f)/4);
195
196
}

197
198
void HUD::showEvent(QShowEvent* event)
{
199
200
    // React only to internal (pre-display)
    // events
201
    QGLWidget::showEvent(event);
202
    refreshTimer->start(updateInterval);
LM's avatar
LM committed
203
    emit visibilityChanged(true);
204
205
206
207
208
209
}

void HUD::hideEvent(QHideEvent* event)
{
    // React only to internal (pre-display)
    // events
210
    refreshTimer->stop();
LM's avatar
LM committed
211
212
    QGLWidget::hideEvent(event);
    emit visibilityChanged(false);
pixhawk's avatar
pixhawk committed
213
214
}

215
216
217
void HUD::contextMenuEvent (QContextMenuEvent* event)
{
    QMenu menu(this);
218
219
220
221
    // Update actions
    enableHUDAction->setChecked(hudInstrumentsEnabled);
    enableVideoAction->setChecked(videoEnabled);

222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
    menu.addAction(enableHUDAction);
    //menu.addAction(selectHUDColorAction);
    menu.addAction(enableVideoAction);
    menu.addAction(selectOfflineDirectoryAction);
    //menu.addAction(selectVideoChannelAction);
    menu.exec(event->globalPos());
}

void HUD::createActions()
{
    enableHUDAction = new QAction(tr("Enable HUD"), this);
    enableHUDAction->setStatusTip(tr("Show the HUD instruments in this window"));
    enableHUDAction->setCheckable(true);
    enableHUDAction->setChecked(hudInstrumentsEnabled);
    connect(enableHUDAction, SIGNAL(triggered(bool)), this, SLOT(enableHUDInstruments(bool)));

    enableVideoAction = new QAction(tr("Enable Video Live feed"), this);
    enableVideoAction->setStatusTip(tr("Show the video live feed"));
    enableVideoAction->setCheckable(true);
    enableVideoAction->setChecked(videoEnabled);
    connect(enableVideoAction, SIGNAL(triggered(bool)), this, SLOT(enableVideo(bool)));

    selectOfflineDirectoryAction = new QAction(tr("Select image log"), this);
    selectOfflineDirectoryAction->setStatusTip(tr("Load previously logged images into simulation / replay"));
    connect(selectOfflineDirectoryAction, SIGNAL(triggered()), this, SLOT(selectOfflineDirectory()));
}

pixhawk's avatar
pixhawk committed
249
250
251
252
253
254
/**
 *
 * @param uas the UAS/MAV to monitor/display with the HUD
 */
void HUD::setActiveUAS(UASInterface* uas)
{
255
    if (this->uas != NULL) {
pixhawk's avatar
pixhawk committed
256
        // Disconnect any previously connected active MAV
257
258
259
260
261
        disconnect(this->uas, SIGNAL(attitudeChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateAttitude(UASInterface*, double, double, double, quint64)));
        disconnect(this->uas, SIGNAL(batteryChanged(UASInterface*, double, double, int)), this, SLOT(updateBattery(UASInterface*, double, double, int)));
        disconnect(this->uas, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*,QString)));
        disconnect(this->uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString)));
        disconnect(this->uas, SIGNAL(heartbeat(UASInterface*)), this, SLOT(receiveHeartbeat(UASInterface*)));
262

263
        disconnect(this->uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateLocalPosition(UASInterface*,double,double,double,quint64)));
pixhawk's avatar
pixhawk committed
264
        disconnect(this->uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,quint64)));
265
266
        disconnect(this->uas, SIGNAL(speedChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64)));
        disconnect(this->uas, SIGNAL(waypointSelected(int,int)), this, SLOT(selectWaypoint(int, int)));
pixhawk's avatar
pixhawk committed
267

268
        // Try to disconnect the image link
269
        UAS* u = dynamic_cast<UAS*>(this->uas);
270
        if (u) {
271
            disconnect(u, SIGNAL(imageStarted(quint64)), this, SLOT(startImage(quint64)));
LM's avatar
LM committed
272
            disconnect(u, SIGNAL(imageReady(UASInterface*)), this, SLOT(copyImage()));
273
274
        }
    }
pixhawk's avatar
pixhawk committed
275

276
    if (uas) {
277
278
279
280
281
282
283
284
285
        // 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(batteryChanged(UASInterface*, double, double, int)), this, SLOT(updateBattery(UASInterface*, double, double, int)));
        connect(uas, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*,QString)));
        connect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString)));
        connect(uas, SIGNAL(heartbeat(UASInterface*)), this, SLOT(receiveHeartbeat(UASInterface*)));

        connect(uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateLocalPosition(UASInterface*,double,double,double,quint64)));
pixhawk's avatar
pixhawk committed
286
        connect(uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,quint64)));
287
288
289
290
291
        connect(uas, SIGNAL(speedChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64)));
        connect(uas, SIGNAL(waypointSelected(int,int)), this, SLOT(selectWaypoint(int, int)));

        // Try to connect the image link
        UAS* u = dynamic_cast<UAS*>(uas);
292
        if (u) {
293
            connect(u, SIGNAL(imageStarted(quint64)), this, SLOT(startImage(quint64)));
LM's avatar
LM committed
294
            connect(u, SIGNAL(imageReady(UASInterface*)), this, SLOT(copyImage()));
295
        }
296

297
298
299
        // Set new UAS
        this->uas = uas;
    }
pixhawk's avatar
pixhawk committed
300
301
}

302
303
304
305
306
307
308
//void HUD::updateAttitudeThrustSetPoint(UASInterface* uas, double rollDesired, double pitchDesired, double yawDesired, double thrustDesired, quint64 msec)
//{
////    updateValue(uas, "roll desired", rollDesired, msec);
////    updateValue(uas, "pitch desired", pitchDesired, msec);
////    updateValue(uas, "yaw desired", yawDesired, msec);
////    updateValue(uas, "thrust desired", thrustDesired, msec);
//}
pixhawk's avatar
pixhawk committed
309
310
311

void HUD::updateAttitude(UASInterface* uas, double roll, double pitch, double yaw, quint64 timestamp)
{
312
313
314
315
316
    Q_UNUSED(uas);
    Q_UNUSED(timestamp);
    this->roll = roll;
    this->pitch = pitch;
    this->yaw = yaw;
pixhawk's avatar
pixhawk committed
317
318
319
320
}

void HUD::updateBattery(UASInterface* uas, double voltage, double percent, int seconds)
{
321
    Q_UNUSED(uas);
pixhawk's avatar
pixhawk committed
322
    fuelStatus = tr("BAT [%1% | %2V] (%3:%4)").arg(percent, 2, 'f', 0, QChar('0')).arg(voltage, 4, 'f', 1, QChar('0')).arg(seconds/60, 2, 10, QChar('0')).arg(seconds%60, 2, 10, QChar('0'));
323
    if (percent < 20.0f) {
pixhawk's avatar
pixhawk committed
324
        fuelColor = warningColor;
325
    } else if (percent < 10.0f) {
pixhawk's avatar
pixhawk committed
326
        fuelColor = criticalColor;
327
    } else {
pixhawk's avatar
pixhawk committed
328
329
330
331
332
333
334
335
        fuelColor = infoColor;
    }
}

void HUD::receiveHeartbeat(UASInterface*)
{
}

336
void HUD::updateThrust(UASInterface* uas, double thrust)
pixhawk's avatar
pixhawk committed
337
{
338
339
340
    Q_UNUSED(uas);
    Q_UNUSED(thrust);
//    updateValue(uas, "thrust", thrust, MG::TIME::getGroundTimeNow());
pixhawk's avatar
pixhawk committed
341
342
343
344
}

void HUD::updateLocalPosition(UASInterface* uas,double x,double y,double z,quint64 timestamp)
{
345
346
347
348
349
    Q_UNUSED(uas);
    Q_UNUSED(timestamp);
    this->xPos = x;
    this->yPos = y;
    this->zPos = z;
pixhawk's avatar
pixhawk committed
350
351
}

pixhawk's avatar
pixhawk committed
352
void HUD::updateGlobalPosition(UASInterface* uas,double lat, double lon, double altitude, quint64 timestamp)
pixhawk's avatar
pixhawk committed
353
{
354
355
356
357
358
    Q_UNUSED(uas);
    Q_UNUSED(timestamp);
    this->lat = lat;
    this->lon = lon;
    this->alt = altitude;
pixhawk's avatar
pixhawk committed
359
360
361
362
}

void HUD::updateSpeed(UASInterface* uas,double x,double y,double z,quint64 timestamp)
{
363
364
365
366
367
    Q_UNUSED(uas);
    Q_UNUSED(timestamp);
    this->xSpeed = x;
    this->ySpeed = y;
    this->zSpeed = z;
pixhawk's avatar
pixhawk committed
368
369
370
    double newTotalSpeed = sqrt(xSpeed*xSpeed + ySpeed*ySpeed + zSpeed*zSpeed);
    totalAcc = (newTotalSpeed - totalSpeed) / ((double)(lastSpeedUpdate - timestamp)/1000.0);
    totalSpeed = newTotalSpeed;
pixhawk's avatar
pixhawk committed
371
372
373
374
375
376
377
378
}

/**
 * Updates the current system state, but only if the uas matches the currently monitored uas.
 *
 * @param uas the system the state message originates from
 * @param state short state text, displayed in HUD
 */
379
void HUD::updateState(UASInterface* uas,QString state)
pixhawk's avatar
pixhawk committed
380
{
381
382
    // Only one UAS is connected at a time
    Q_UNUSED(uas);
383
384
385
386
387
388
389
390
391
    this->state = state;
}

/**
 * Updates the current system mode, but only if the uas matches the currently monitored uas.
 *
 * @param uas the system the state message originates from
 * @param mode short mode text, displayed in HUD
 */
392
void HUD::updateMode(int id,QString mode, QString description)
393
{
394
    // Only one UAS is connected at a time
395
396
    Q_UNUSED(id);
    Q_UNUSED(description);
397
    this->mode = mode;
pixhawk's avatar
pixhawk committed
398
399
400
401
}

void HUD::updateLoad(UASInterface* uas, double load)
{
402
403
404
    Q_UNUSED(uas);
    this->load = load;
    //updateValue(uas, "load", load, MG::TIME::getGroundTimeNow());
pixhawk's avatar
pixhawk committed
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
}

/**
 * @param y coordinate in pixels to be converted to reference mm units
 * @return the screen coordinate relative to the QGLWindow origin
 */
float HUD::refToScreenX(float x)
{
    //qDebug() << "sX: " << (scalingFactor * x);
    return (scalingFactor * x);
}
/**
 * @param x coordinate in pixels to be converted to reference mm units
 * @return the screen coordinate relative to the QGLWindow origin
 */
float HUD::refToScreenY(float y)
{
    //qDebug() << "sY: " << (scalingFactor * y);
    return (scalingFactor * y);
}

/**
 * This functions works in the OpenGL view, which is already translated by
 * the x and y center offsets.
 *
 */
void HUD::paintCenterBackground(float roll, float pitch, float yaw)
{
    // Center indicator is 100 mm wide
    float referenceWidth = 70.0;
    float referenceHeight = 70.0;

    // HUD is assumed to be 200 x 150 mm
    // so that positions can be hardcoded
    // but can of course be scaled.

    double referencePositionX = vwidth / 2.0 - referenceWidth/2.0;
    double referencePositionY = vheight / 2.0 - referenceHeight/2.0;

    //this->width()/2.0+(xCenterOffset*scalingFactor), this->height()/2.0+(yCenterOffset*scalingFactor);

    setupGLView(referencePositionX, referencePositionY, referenceWidth, referenceHeight);

    // Store current position in the model view
    // the position will be restored after drawing
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();

    // Move to the center of the window
    glTranslatef(referenceWidth/2.0f,referenceHeight/2.0f,0);
455
456
457
458

    // Move based on the yaw difference
    glTranslatef(yaw, 0.0f, 0.0f);

pixhawk's avatar
pixhawk committed
459
    // Rotate based on the bank
460
    glRotatef((roll/M_PI)*180.0f, 0.0f, 0.0f, 1.0f);
pixhawk's avatar
pixhawk committed
461
462
463

    // Translate in the direction of the rotation based
    // on the pitch. On the 777, a pitch of 1 degree = 2 mm
464
    //glTranslatef(0, ((-pitch/M_PI)*180.0f * vPitchPerDeg), 0);
pixhawk's avatar
pixhawk committed
465
    glTranslatef(0.0f, (-pitch * vPitchPerDeg * 16.5f), 0.0f);
pixhawk's avatar
pixhawk committed
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505

    // Ground
    glColor3ub(179,102,0);

    glBegin(GL_POLYGON);
    glVertex2f(-300,-300);
    glVertex2f(-300,0);
    glVertex2f(300,0);
    glVertex2f(300,-300);
    glVertex2f(-300,-300);
    glEnd();

    // Sky
    glColor3ub(0,153,204);

    glBegin(GL_POLYGON);
    glVertex2f(-300,0);
    glVertex2f(-300,300);
    glVertex2f(300,300);
    glVertex2f(300,0);
    glVertex2f(-300,0);

    glEnd();
}

/**
 * Paint text on top of the image and OpenGL drawings
 *
 * @param text chars to write
 * @param color text color
 * @param fontSize text size in mm
 * @param refX position in reference units (mm of the real instrument). This is relative to the measurement unit position, NOT in pixels.
 * @param refY position in reference units (mm of the real instrument). This is relative to the measurement unit position, NOT in pixels.
 */
void HUD::paintText(QString text, QColor color, float fontSize, float refX, float refY, QPainter* painter)
{
    QPen prevPen = painter->pen();
    float pPositionX = refToScreenX(refX) - (fontSize*scalingFactor*0.072f);
    float pPositionY = refToScreenY(refY) - (fontSize*scalingFactor*0.212f);

506
507
    QFont font("Bitstream Vera Sans");
    // Enforce minimum font size of 5 pixels
508
    int fSize = qMax(5, (int)(fontSize*scalingFactor*1.26f));
509
    font.setPixelSize(fSize);
pixhawk's avatar
pixhawk committed
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

    QFontMetrics metrics = QFontMetrics(font);
    int border = qMax(4, metrics.leading());
    QRect rect = metrics.boundingRect(0, 0, width() - 2*border, int(height()*0.125),
                                      Qt::AlignLeft | Qt::TextWordWrap, text);
    painter->setPen(color);
    painter->setFont(font);
    painter->setRenderHint(QPainter::TextAntialiasing);
    painter->drawText(pPositionX, pPositionY,
                      rect.width(), rect.height(),
                      Qt::AlignCenter | Qt::TextWordWrap, text);
    painter->setPen(prevPen);
}

void HUD::initializeGL()
{
    bool antialiasing = true;

    // Antialiasing setup
529
    if(antialiasing) {
pixhawk's avatar
pixhawk committed
530
        glEnable(GL_MULTISAMPLE);
pixhawk's avatar
pixhawk committed
531
532
533
534
535
536
537
538
539
        glEnable(GL_BLEND);

        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

        glEnable(GL_POINT_SMOOTH);
        glEnable(GL_LINE_SMOOTH);

        glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
540
    } else {
541
542
543
        glDisable(GL_BLEND);
        glDisable(GL_POINT_SMOOTH);
        glDisable(GL_LINE_SMOOTH);
pixhawk's avatar
pixhawk committed
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
    }
}

/**
 * @param referencePositionX horizontal position in the reference mm-unit space
 * @param referencePositionY horizontal position in the reference mm-unit space
 * @param referenceWidth width in the reference mm-unit space
 * @param referenceHeight width in the reference mm-unit space
 */
void HUD::setupGLView(float referencePositionX, float referencePositionY, float referenceWidth, float referenceHeight)
{
    int pixelWidth  = (int)(referenceWidth * scalingFactor);
    int pixelHeight = (int)(referenceHeight * scalingFactor);
    // Translate and scale the GL view in the virtual reference coordinate units on the screen
    int pixelPositionX = (int)((referencePositionX * scalingFactor) + xCenterOffset);
    int pixelPositionY = this->height() - (referencePositionY * scalingFactor) + yCenterOffset - pixelHeight;

    //qDebug() << "Pixel x" << pixelPositionX << "pixelY" << pixelPositionY;
    //qDebug() << "xCenterOffset:" << xCenterOffset << "yCenterOffest" << yCenterOffset


    //The viewport is established at the correct pixel position and clips everything
    // out of the desired instrument location
    glViewport(pixelPositionX, pixelPositionY, pixelWidth, pixelHeight);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // The ortho projection is setup in a way that so that the drawing is done in the
    // reference coordinate space
    glOrtho(0, referenceWidth, 0, referenceHeight, -1, 1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    //glScalef(scaleX, scaleY, 1.0f);
}

void HUD::paintRollPitchStrips()
{
}


pixhawk's avatar
pixhawk committed
584
void HUD::paintEvent(QPaintEvent *event)
pixhawk's avatar
pixhawk committed
585
{
586
    // Event is not needed
587
588
    // the event is ignored as this widget
    // is refreshed automatically
589
    Q_UNUSED(event);
590
591
592
593
}

void HUD::paintHUD()
{
594
    if (isVisible()) {
pixhawk's avatar
pixhawk committed
595
596
597
        //    static quint64 interval = 0;
        //    qDebug() << "INTERVAL:" << MG::TIME::getGroundTimeNow() - interval << __FILE__ << __LINE__;
        //    interval = MG::TIME::getGroundTimeNow();
lm's avatar
lm committed
598

599
#if (QGC_EVENTLOOP_DEBUG)
pixhawk's avatar
pixhawk committed
600
        qDebug() << "EVENTLOOP:" << __FILE__ << __LINE__;
601
602
#endif

pixhawk's avatar
pixhawk committed
603
604
605
606
607
        // Read out most important values to limit hash table lookups
        // Low-pass roll, pitch and yaw
        rollLP = rollLP * 0.2f + 0.8f * roll;
        pitchLP = pitchLP * 0.2f + 0.8f * pitch;
        yawLP = yawLP * 0.2f + 0.8f * yaw;
pixhawk's avatar
pixhawk committed
608

pixhawk's avatar
pixhawk committed
609
610
        // Translate for yaw
        const float maxYawTrans = 60.0f;
pixhawk's avatar
pixhawk committed
611

pixhawk's avatar
pixhawk committed
612
613
614
        float newYawDiff = yawDiff;
        if (isinf(newYawDiff)) newYawDiff = yawDiff;
        if (newYawDiff > M_PI) newYawDiff = newYawDiff - M_PI;
615

pixhawk's avatar
pixhawk committed
616
        if (newYawDiff < -M_PI) newYawDiff = newYawDiff + M_PI;
617

pixhawk's avatar
pixhawk committed
618
        newYawDiff = yawDiff * 0.8 + newYawDiff * 0.2;
619

pixhawk's avatar
pixhawk committed
620
        yawDiff = newYawDiff;
621

pixhawk's avatar
pixhawk committed
622
        yawInt += newYawDiff;
623

624
625
        if (yawInt > M_PI) yawInt = (float)M_PI;
        if (yawInt < -M_PI) yawInt = (float)-M_PI;
626

627
        float yawTrans = yawInt * (float)maxYawTrans;
pixhawk's avatar
pixhawk committed
628
        yawInt *= 0.6f;
lm's avatar
lm committed
629

pixhawk's avatar
pixhawk committed
630
        if ((yawTrans < 5.0) && (yawTrans > -5.0)) yawTrans = 0;
lm's avatar
lm committed
631

pixhawk's avatar
pixhawk committed
632
633
        // Negate to correct direction
        yawTrans = -yawTrans;
lm's avatar
lm committed
634

pixhawk's avatar
pixhawk committed
635
        //qDebug() << "yaw translation" << yawTrans << "integral" << yawInt << "difference" << yawDiff << "yaw" << yaw;
636

pixhawk's avatar
pixhawk committed
637
638
639
640
641
        // 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;
pixhawk's avatar
pixhawk committed
642
643
644



pixhawk's avatar
pixhawk committed
645
646
647
648
649
650
651
652
        // OPEN GL PAINTING
        // Store model view matrix to be able to reset it to the previous state
        makeCurrent();
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Fill with black background
653
654
        if (videoEnabled) {
            if (nextOfflineImage != "" && QFileInfo(nextOfflineImage).exists()) {
655
656
                qDebug() << __FILE__ << __LINE__ << "template image:" << nextOfflineImage;
                QImage fill = QImage(nextOfflineImage);
pixhawk's avatar
pixhawk committed
657

658
                glImage = QGLWidget::convertToGLFormat(fill);
pixhawk's avatar
pixhawk committed
659

660
661
662
                // Reset to save load efforts
                nextOfflineImage = "";
            }
pixhawk's avatar
pixhawk committed
663

pixhawk's avatar
pixhawk committed
664
665
            glRasterPos2i(0, 0);

LM's avatar
LM committed
666
667
668
669
            xImageFactor = width() / (float)glImage.width();
            yImageFactor = height() / (float)glImage.height();
            float imageFactor = qMin(xImageFactor, yImageFactor);
            glPixelZoom(imageFactor, imageFactor);
pixhawk's avatar
pixhawk committed
670
671
            // Resize to correct size and fill with image
            glDrawPixels(glImage.width(), glImage.height(), GL_RGBA, GL_UNSIGNED_BYTE, glImage.bits());
LM's avatar
LM committed
672
            //qDebug() << "DRAWING GL IMAGE";
673
        } else {
674
675
            // Blue / brown background
            paintCenterBackground(roll, pitch, yawTrans);
pixhawk's avatar
pixhawk committed
676
677
678
679
680
681
682
        }

        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();

        // END OF OPENGL PAINTING

683
        if (hudInstrumentsEnabled) {
pixhawk's avatar
pixhawk committed
684

685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
            //glEnable(GL_MULTISAMPLE);

            // QT PAINTING
            //makeCurrent();
            QPainter painter;
            painter.begin(this);
            painter.setRenderHint(QPainter::Antialiasing, true);
            painter.setRenderHint(QPainter::HighQualityAntialiasing, true);
            painter.translate((this->vwidth/2.0+xCenterOffset)*scalingFactor, (this->vheight/2.0+yCenterOffset)*scalingFactor);



            // COORDINATE FRAME IS NOW (0,0) at CENTER OF WIDGET


            // Draw all fixed indicators
            // MODE
            paintText(mode, infoColor, 2.0f, (-vwidth/2.0) + 10, -vheight/2.0 + 10, &painter);
            // STATE
            paintText(state, infoColor, 2.0f, (-vwidth/2.0) + 10, -vheight/2.0 + 15, &painter);
            // BATTERY
            paintText(fuelStatus, fuelColor, 2.0f, (-vwidth/2.0) + 10, -vheight/2.0 + 20, &painter);
            // Waypoint
            paintText(waypointName, defaultColor, 2.0f, (-vwidth/3.0) + 10, +vheight/3.0 + 15, &painter);
pixhawk's avatar
pixhawk committed
709

710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
            // YAW INDICATOR
            //
            //      .
            //    .   .
            //   .......
            //
            const float yawIndicatorWidth = 4.0f;
            const float yawIndicatorY = vheight/2.0f - 10.0f;
            QPolygon yawIndicator(4);
            yawIndicator.setPoint(0, QPoint(refToScreenX(0.0f), refToScreenY(yawIndicatorY)));
            yawIndicator.setPoint(1, QPoint(refToScreenX(yawIndicatorWidth/2.0f), refToScreenY(yawIndicatorY+yawIndicatorWidth)));
            yawIndicator.setPoint(2, QPoint(refToScreenX(-yawIndicatorWidth/2.0f), refToScreenY(yawIndicatorY+yawIndicatorWidth)));
            yawIndicator.setPoint(3, QPoint(refToScreenX(0.0f), refToScreenY(yawIndicatorY)));
            painter.setPen(defaultColor);
            painter.drawPolyline(yawIndicator);
pixhawk's avatar
pixhawk committed
725

726
            // CENTER
pixhawk's avatar
pixhawk committed
727

728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
            // HEADING INDICATOR
            //
            //    __      __
            //       \/\/
            //
            const float hIndicatorWidth = 7.0f;
            const float hIndicatorY = -25.0f;
            const float hIndicatorYLow = hIndicatorY + hIndicatorWidth / 6.0f;
            const float hIndicatorSegmentWidth = hIndicatorWidth / 7.0f;
            QPolygon hIndicator(7);
            hIndicator.setPoint(0, QPoint(refToScreenX(0.0f-hIndicatorWidth/2.0f), refToScreenY(hIndicatorY)));
            hIndicator.setPoint(1, QPoint(refToScreenX(0.0f-hIndicatorWidth/2.0f+hIndicatorSegmentWidth*1.75f), refToScreenY(hIndicatorY)));
            hIndicator.setPoint(2, QPoint(refToScreenX(0.0f-hIndicatorSegmentWidth*1.0f), refToScreenY(hIndicatorYLow)));
            hIndicator.setPoint(3, QPoint(refToScreenX(0.0f), refToScreenY(hIndicatorY)));
            hIndicator.setPoint(4, QPoint(refToScreenX(0.0f+hIndicatorSegmentWidth*1.0f), refToScreenY(hIndicatorYLow)));
            hIndicator.setPoint(5, QPoint(refToScreenX(0.0f+hIndicatorWidth/2.0f-hIndicatorSegmentWidth*1.75f), refToScreenY(hIndicatorY)));
            hIndicator.setPoint(6, QPoint(refToScreenX(0.0f+hIndicatorWidth/2.0f), refToScreenY(hIndicatorY)));
            painter.setPen(defaultColor);
            painter.drawPolyline(hIndicator);
pixhawk's avatar
pixhawk committed
747
748


749
750
751
752
753
754
            // SETPOINT
            const float centerWidth = 4.0f;
            painter.setPen(defaultColor);
            painter.setBrush(Qt::NoBrush);
            // TODO
            //painter.drawEllipse(QPointF(refToScreenX(qMin(10.0f, values.value("roll desired", 0.0f) * 10.0f)), refToScreenY(qMin(10.0f, values.value("pitch desired", 0.0f) * 10.0f))), refToScreenX(centerWidth/2.0f), refToScreenX(centerWidth/2.0f));
pixhawk's avatar
pixhawk committed
755

756
757
758
759
760
761
762
            const float centerCrossWidth = 10.0f;
            // left
            painter.drawLine(QPointF(refToScreenX(-centerWidth / 2.0f), refToScreenY(0.0f)), QPointF(refToScreenX(-centerCrossWidth / 2.0f), refToScreenY(0.0f)));
            // right
            painter.drawLine(QPointF(refToScreenX(centerWidth / 2.0f), refToScreenY(0.0f)), QPointF(refToScreenX(centerCrossWidth / 2.0f), refToScreenY(0.0f)));
            // top
            painter.drawLine(QPointF(refToScreenX(0.0f), refToScreenY(-centerWidth / 2.0f)), QPointF(refToScreenX(0.0f), refToScreenY(-centerCrossWidth / 2.0f)));
pixhawk's avatar
pixhawk committed
763

764

pixhawk's avatar
pixhawk committed
765

766
767
768
769
770
771
772
773
            // COMPASS
            const float compassY = -vheight/2.0f + 10.0f;
            QRectF compassRect(QPointF(refToScreenX(-5.0f), refToScreenY(compassY)), QSizeF(refToScreenX(10.0f), refToScreenY(5.0f)));
            painter.setBrush(Qt::NoBrush);
            painter.setPen(Qt::SolidLine);
            painter.setPen(defaultColor);
            painter.drawRoundedRect(compassRect, 2, 2);
            QString yawAngle;
pixhawk's avatar
pixhawk committed
774

775
            //    const float yawDeg = ((values.value("yaw", 0.0f)/M_PI)*180.0f)+180.f;
pixhawk's avatar
pixhawk committed
776

777
            // YAW is in compass-human readable format, so 0 - 360deg. This is normal in aviation, not -180 - +180.
778
779
780
781
            const float yawDeg = ((yawLP/M_PI)*180.0f)+180.0f+180.0f;
            int yawCompass = static_cast<int>(yawDeg) % 360;
            yawAngle.sprintf("%03d", yawCompass);
            paintText(yawAngle, defaultColor, 3.5f, -4.3f, compassY+ 0.97f, &painter);
pixhawk's avatar
pixhawk committed
782

783
784
            // CHANGE RATE STRIPS
            drawChangeRateStrip(-51.0f, -50.0f, 15.0f, -1.0f, 1.0f, -zSpeed, &painter);
pixhawk's avatar
pixhawk committed
785

786
            // CHANGE RATE STRIPS
pixhawk's avatar
pixhawk committed
787
            drawChangeRateStrip(49.0f, -50.0f, 15.0f, -1.0f, 1.0f, totalAcc, &painter);
788
789

            // GAUGES
pixhawk's avatar
pixhawk committed
790

791
            // Left altitude gauge
pixhawk's avatar
pixhawk committed
792
793
            float gaugeAltitude;

794
            if (this->alt != 0) {
pixhawk's avatar
pixhawk committed
795
                gaugeAltitude = alt;
796
            } else {
pixhawk's avatar
pixhawk committed
797
798
799
800
                gaugeAltitude = -zPos;
            }

            drawChangeIndicatorGauge(-vGaugeSpacing, -15.0f, 10.0f, 2.0f, gaugeAltitude, defaultColor, &painter, false);
801

802
            // Right speed gauge
pixhawk's avatar
pixhawk committed
803
            drawChangeIndicatorGauge(vGaugeSpacing, -15.0f, 10.0f, 5.0f, totalSpeed, defaultColor, &painter, false);
pixhawk's avatar
pixhawk committed
804
805


806
807
808
809
810
811
812
813
814
815
816
            // Waypoint name
            if (waypointName != "") paintText(waypointName, defaultColor, 2.0f, (-vwidth/3.0) + 10, +vheight/3.0 + 15, &painter);

            // MOVING PARTS


            painter.translate(refToScreenX(yawTrans), 0);

            // Rotate view and draw all roll-dependent indicators
            painter.rotate((rollLP/M_PI)* -180.0f);

817
            painter.translate(0, (-pitchLP/(float)M_PI)* -180.0f * refToScreenY(1.8f));
818
819
820
821

            //qDebug() << "ROLL" << roll << "PITCH" << pitch << "YAW DIFF" << valuesDot.value("roll", 0.0f);

            // PITCH
pixhawk's avatar
pixhawk committed
822

823
824
            paintPitchLines(pitchLP, &painter);
            painter.end();
825
        } else {
826
827
828
829
            QPainter painter;
            painter.begin(this);
            painter.end();
        }
pixhawk's avatar
pixhawk committed
830
831
        //glDisable(GL_MULTISAMPLE);

832
833


pixhawk's avatar
pixhawk committed
834
835
        //glFlush();
    }
pixhawk's avatar
pixhawk committed
836
837
838
839
840
841
842
843
844
845
846
847
848
}

/*
void HUD::paintGL()
{
    static float roll = 0.0;
    static float pitch = 0.0;
    static float yaw = 0.0;

    // Read out most important values to limit hash table lookups
    roll = roll * 0.5 + 0.5 * values.value("roll", 0.0f);
    pitch = pitch * 0.5 + 0.5 * values.value("pitch", 0.0f);
    yaw = yaw * 0.5 + 0.5 * values.value("yaw", 0.0f);
pixhawk's avatar
pixhawk committed
849
850
851
852
853
854
855
856
857
858

    //qDebug() << __FILE__ << __LINE__ << "ROLL:" << roll << "PITCH:" << pitch << "YAW:" << yaw;


    // 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;

pixhawk's avatar
pixhawk committed
859
    makeCurrent();
pixhawk's avatar
pixhawk committed
860
861
    glClear(GL_COLOR_BUFFER_BIT);
    //if(!noCamera) glDrawPixels(glImage.width(), glImage.height(), GL_RGBA, GL_UNSIGNED_BYTE, glImage.bits());
pixhawk's avatar
pixhawk committed
862
    //glDrawPixels(glImage.width(), glImage.height(), GL_RGBA, GL_UNSIGNED_BYTE, glImage.bits()); // FIXME Remove after testing
pixhawk's avatar
pixhawk committed
863
864
865
866
867


    // Blue / Brown background
    if (noCamera) paintCenterBackground(roll, pitch, yaw);

pixhawk's avatar
pixhawk committed
868
    glFlush();
pixhawk's avatar
pixhawk committed
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885

    //    // Store current GL model view
    //    glMatrixMode(GL_MODELVIEW);
    //    glPushMatrix();
    //
    //    // Setup GL view
    //    setupGLView(0.0f, 0.0f, vwidth, vheight);
    //
    //    // Restore previous view
    //    glPopMatrix();

    // Now draw QPainter overlay

    //painter.setRenderHint(QPainter::Antialiasing);

    // Position the coordinate frame according to the setup

pixhawk's avatar
pixhawk committed
886
    makeOverlayCurrent();
pixhawk's avatar
pixhawk committed
887
    QPainter painter(this);
pixhawk's avatar
pixhawk committed
888
    //painter.setRenderHint(QPainter::Antialiasing, true);
pixhawk's avatar
pixhawk committed
889
    //painter.setRenderHint(QPainter::HighQualityAntialiasing, true);
pixhawk's avatar
pixhawk committed
890
891
892
893
894
895
896
897
    painter.translate((this->vwidth/2.0+xCenterOffset)*scalingFactor, (this->vheight/2.0+yCenterOffset)*scalingFactor);

    // COORDINATE FRAME IS NOW (0,0) at CENTER OF WIDGET


    // Draw all fixed indicators
    // MODE
    paintText(mode, infoColor, 2.0f, (-vwidth/2.0) + 10, -vheight/2.0 + 10, &painter);
898
899
    // STATE
    paintText(state, infoColor, 2.0f, (-vwidth/2.0) + 10, -vheight/2.0 + 15, &painter);
pixhawk's avatar
pixhawk committed
900
    // BATTERY
901
    paintText(fuelStatus, fuelColor, 2.0f, (-vwidth/2.0) + 10, -vheight/2.0 + 20, &painter);
pixhawk's avatar
pixhawk committed
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
    // Waypoint
    paintText(waypointName, defaultColor, 2.0f, (-vwidth/3.0) + 10, +vheight/3.0 + 15, &painter);

    // YAW INDICATOR
    //
    //      .
    //    .   .
    //   .......
    //
    const float yawIndicatorWidth = 4.0f;
    const float yawIndicatorY = vheight/2.0f - 10.0f;
    QPolygon yawIndicator(4);
    yawIndicator.setPoint(0, QPoint(refToScreenX(0.0f), refToScreenY(yawIndicatorY)));
    yawIndicator.setPoint(1, QPoint(refToScreenX(yawIndicatorWidth/2.0f), refToScreenY(yawIndicatorY+yawIndicatorWidth)));
    yawIndicator.setPoint(2, QPoint(refToScreenX(-yawIndicatorWidth/2.0f), refToScreenY(yawIndicatorY+yawIndicatorWidth)));
    yawIndicator.setPoint(3, QPoint(refToScreenX(0.0f), refToScreenY(yawIndicatorY)));
    painter.setPen(defaultColor);
    painter.drawPolyline(yawIndicator);

lm's avatar
lm committed
921
922
    // CENTER

pixhawk's avatar
pixhawk committed
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
    // HEADING INDICATOR
    //
    //    __      __
    //       \/\/
    //
    const float hIndicatorWidth = 7.0f;
    const float hIndicatorY = -25.0f;
    const float hIndicatorYLow = hIndicatorY + hIndicatorWidth / 6.0f;
    const float hIndicatorSegmentWidth = hIndicatorWidth / 7.0f;
    QPolygon hIndicator(7);
    hIndicator.setPoint(0, QPoint(refToScreenX(0.0f-hIndicatorWidth/2.0f), refToScreenY(hIndicatorY)));
    hIndicator.setPoint(1, QPoint(refToScreenX(0.0f-hIndicatorWidth/2.0f+hIndicatorSegmentWidth*1.75f), refToScreenY(hIndicatorY)));
    hIndicator.setPoint(2, QPoint(refToScreenX(0.0f-hIndicatorSegmentWidth*1.0f), refToScreenY(hIndicatorYLow)));
    hIndicator.setPoint(3, QPoint(refToScreenX(0.0f), refToScreenY(hIndicatorY)));
    hIndicator.setPoint(4, QPoint(refToScreenX(0.0f+hIndicatorSegmentWidth*1.0f), refToScreenY(hIndicatorYLow)));
    hIndicator.setPoint(5, QPoint(refToScreenX(0.0f+hIndicatorWidth/2.0f-hIndicatorSegmentWidth*1.75f), refToScreenY(hIndicatorY)));
    hIndicator.setPoint(6, QPoint(refToScreenX(0.0f+hIndicatorWidth/2.0f), refToScreenY(hIndicatorY)));
    painter.setPen(defaultColor);
    painter.drawPolyline(hIndicator);


lm's avatar
lm committed
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
    // SETPOINT
    const float centerWidth = 4.0f;
    painter.setPen(defaultColor);
    painter.setBrush(Qt::NoBrush);
    // TODO
    //painter.drawEllipse(QPointF(refToScreenX(qMin(10.0f, values.value("roll desired", 0.0f) * 10.0f)), refToScreenY(qMin(10.0f, values.value("pitch desired", 0.0f) * 10.0f))), refToScreenX(centerWidth/2.0f), refToScreenX(centerWidth/2.0f));

    const float centerCrossWidth = 10.0f;
    // left
    painter.drawLine(QPointF(refToScreenX(-centerWidth / 2.0f), refToScreenY(0.0f)), QPointF(refToScreenX(-centerCrossWidth / 2.0f), refToScreenY(0.0f)));
    // right
    painter.drawLine(QPointF(refToScreenX(centerWidth / 2.0f), refToScreenY(0.0f)), QPointF(refToScreenX(centerCrossWidth / 2.0f), refToScreenY(0.0f)));
    // top
    painter.drawLine(QPointF(refToScreenX(0.0f), refToScreenY(-centerWidth / 2.0f)), QPointF(refToScreenX(0.0f), refToScreenY(-centerCrossWidth / 2.0f)));



pixhawk's avatar
pixhawk committed
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
    // COMPASS
    const float compassY = -vheight/2.0f + 10.0f;
    QRectF compassRect(QPointF(refToScreenX(-5.0f), refToScreenY(compassY)), QSizeF(refToScreenX(10.0f), refToScreenY(5.0f)));
    painter.setBrush(Qt::NoBrush);
    painter.setPen(Qt::SolidLine);
    painter.setPen(defaultColor);
    painter.drawRoundedRect(compassRect, 2, 2);
    QString yawAngle;

    const float yawDeg = ((values.value("yaw", 0.0f)/M_PI)*180.0f)+180.f;
    //qDebug() << "YAW: " << yawDeg;
    yawAngle.sprintf("%03d", (int)yawDeg);
    paintText(yawAngle, defaultColor, 3.5f, -3.7f, compassY+ 0.9f, &painter);

    // CHANGE RATE STRIPS
    drawChangeRateStrip(-51.0f, -50.0f, 15.0f, -1.0f, 1.0f, valuesDot.value("z", 0.0f), &painter);

    // CHANGE RATE STRIPS
    drawChangeRateStrip(49.0f, -50.0f, 15.0f, -1.0f, 1.0f, valuesDot.value("x", 0.0f), &painter);

    // GAUGES

    // Left altitude gauge
    drawChangeIndicatorGauge(-vGaugeSpacing, -15.0f, 10.0f, 2.0f, -values.value("z", 0.0f), defaultColor, &painter, false);

    // Right speed gauge
    drawChangeIndicatorGauge(vGaugeSpacing, -15.0f, 10.0f, 5.0f, values.value("xSpeed", 0.0f), defaultColor, &painter, false);

pixhawk's avatar
pixhawk committed
989
    glFlush();
pixhawk's avatar
pixhawk committed
990
991
992
993
994


    // MOVING PARTS

    // Translate for yaw
pixhawk's avatar
pixhawk committed
995
    const float maxYawTrans = 60.0f;
pixhawk's avatar
pixhawk committed
996
    float yawDiff = valuesDot.value("yaw", 0.0f);
pixhawk's avatar
pixhawk committed
997
998
    if (isinf(yawDiff)) yawDiff = 0.0f;
    if (yawDiff > M_PI) yawDiff = yawDiff - M_PI;
pixhawk's avatar
pixhawk committed
999

pixhawk's avatar
pixhawk committed
1000
    if (yawDiff < -M_PI) yawDiff = yawDiff + M_PI;
For faster browsing, not all history is shown. View entire blame