UASView.cc 22.3 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4 5 6 7 8 9 10 11
/*=====================================================================
PIXHAWK Micro Air Vehicle Flying Robotics Toolkit

(c) 2009, 2010 PIXHAWK PROJECT  <http://pixhawk.ethz.ch>

This file is part of the PIXHAWK project

    PIXHAWK is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
12

pixhawk's avatar
pixhawk committed
13 14 15 16
    PIXHAWK is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
17

pixhawk's avatar
pixhawk committed
18 19
    You should have received a copy of the GNU General Public License
    along with PIXHAWK. If not, see <http://www.gnu.org/licenses/>.
20

pixhawk's avatar
pixhawk committed
21 22 23 24
======================================================================*/

/**
 * @file
pixhawk's avatar
pixhawk committed
25
 *   @brief Implementation of one airstrip
pixhawk's avatar
pixhawk committed
26 27 28 29 30 31 32 33
 *
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *
 */

#include <cmath>
#include <QDateTime>
#include <QDebug>
34
#include <QMenu>
35
#include <QInputDialog>
pixhawk's avatar
pixhawk committed
36

37
#include "QGC.h"
pixhawk's avatar
pixhawk committed
38 39
#include "UASManager.h"
#include "UASView.h"
40
#include "UASWaypointManager.h"
41
#include "MainWindow.h"
pixhawk's avatar
pixhawk committed
42 43 44
#include "ui_UASView.h"

UASView::UASView(UASInterface* uas, QWidget *parent) :
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
        QWidget(parent),
        startTime(0),
        timeout(false),
        iconIsRed(true),
        timeRemaining(0),
        chargeLevel(0),
        uas(uas),
        load(0),
        state("UNKNOWN"),
        stateDesc(tr("Unknown state")),
        mode("MAV_MODE_UNKNOWN"),
        thrust(0),
        isActive(false),
        x(0),
        y(0),
        z(0),
        totalSpeed(0),
        lat(0),
        lon(0),
        alt(0),
        groundDistance(0),
        localFrame(false),
67
        globalFrameKnown(false),
68 69 70
        removeAction(new QAction("Delete this system", this)),
        renameAction(new QAction("Rename..", this)),
        selectAction(new QAction("Control this system", this )),
71 72
        hilAction(new QAction("Enable Flightgear Hardware-in-the-Loop Simulation", this )),
        hilXAction(new QAction("Enable X-Plane Hardware-in-the-Loop Simulation", this )),
73 74
        selectAirframeAction(new QAction("Choose Airframe", this)),
        setBatterySpecsAction(new QAction("Set Battery Options", this)),
75
        lowPowerModeEnabled(true),
76 77
        generalUpdateCount(0),
        filterTime(0),
78 79 80 81 82
        m_ui(new Ui::UASView)
{
    // FIXME XXX
    lowPowerModeEnabled = MainWindow::instance()->lowPowerModeEnabled();

lm's avatar
lm committed
83
    hilAction->setCheckable(true);
84 85 86
    // Flightgear is not ready for prime time
    hilAction->setEnabled(false);
    hilXAction->setCheckable(true);
87

pixhawk's avatar
pixhawk committed
88
    m_ui->setupUi(this);
89

pixhawk's avatar
pixhawk committed
90
    // Setup communication
pixhawk's avatar
pixhawk committed
91
    //connect(uas, SIGNAL(valueChanged(int,QString,double,quint64)), this, SLOT(receiveValue(int,QString,double,quint64)));
pixhawk's avatar
pixhawk committed
92 93 94 95 96 97 98
    connect(uas, SIGNAL(batteryChanged(UASInterface*, double, double, int)), this, SLOT(updateBattery(UASInterface*, double, double, int)));
    connect(uas, SIGNAL(heartbeat(UASInterface*)), this, SLOT(receiveHeartbeat(UASInterface*)));
    connect(uas, SIGNAL(thrustChanged(UASInterface*, double)), this, SLOT(updateThrust(UASInterface*, double)));
    connect(uas, SIGNAL(localPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateLocalPosition(UASInterface*,double,double,double,quint64)));
    connect(uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,quint64)));
    connect(uas, SIGNAL(speedChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64)));
    connect(uas, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*,QString,QString)));
pixhawk's avatar
pixhawk committed
99
    connect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString)));
pixhawk's avatar
pixhawk committed
100
    connect(uas, SIGNAL(loadChanged(UASInterface*, double)), this, SLOT(updateLoad(UASInterface*, double)));
101
    connect(uas, SIGNAL(heartbeatTimeout(bool, unsigned int)), this, SLOT(heartbeatTimeout(bool, unsigned int)));
pixhawk's avatar
pixhawk committed
102
    connect(uas, SIGNAL(waypointSelected(int,int)), this, SLOT(selectWaypoint(int,int)));
pixhawk's avatar
pixhawk committed
103
    connect(uas->getWaypointManager(), SIGNAL(currentWaypointChanged(quint16)), this, SLOT(currentWaypointUpdated(quint16)));
pixhawk's avatar
pixhawk committed
104
    connect(uas, SIGNAL(systemTypeSet(UASInterface*,uint)), this, SLOT(setSystemType(UASInterface*,uint)));
105
    connect(UASManager::instance(), SIGNAL(activeUASStatusChanged(UASInterface*,bool)), this, SLOT(updateActiveUAS(UASInterface*,bool)));
106 107 108
    connect(uas, SIGNAL(textMessageReceived(int,int,int,QString)), this, SLOT(showStatusText(int, int, int, QString)));
    connect(uas, SIGNAL(navModeChanged(int, int, QString)), this, SLOT(updateNavMode(int, int, QString)));

pixhawk's avatar
pixhawk committed
109
    // Setup UAS selection
110
    connect(m_ui->uasViewFrame, SIGNAL(clicked(bool)), this, SLOT(setUASasActive(bool)));
111

pixhawk's avatar
pixhawk committed
112 113 114 115
    // Setup user interaction
    connect(m_ui->liftoffButton, SIGNAL(clicked()), uas, SLOT(launch()));
    connect(m_ui->haltButton, SIGNAL(clicked()), uas, SLOT(halt()));
    connect(m_ui->continueButton, SIGNAL(clicked()), uas, SLOT(go()));
116
    connect(m_ui->landButton, SIGNAL(clicked()), uas, SLOT(land()));
pixhawk's avatar
pixhawk committed
117
    connect(m_ui->abortButton, SIGNAL(clicked()), uas, SLOT(emergencySTOP()));
pixhawk's avatar
pixhawk committed
118 119
    connect(m_ui->killButton, SIGNAL(clicked()), uas, SLOT(emergencyKILL()));
    connect(m_ui->shutdownButton, SIGNAL(clicked()), uas, SLOT(shutdown()));
120 121 122

    // Allow to delete this widget
    connect(removeAction, SIGNAL(triggered()), this, SLOT(deleteLater()));
123
    connect(renameAction, SIGNAL(triggered()), this, SLOT(rename()));
124
    connect(selectAction, SIGNAL(triggered()), uas, SLOT(setSelected()));
lm's avatar
lm committed
125
    connect(hilAction, SIGNAL(triggered(bool)), uas, SLOT(enableHil(bool)));
126
    connect(hilXAction, SIGNAL(triggered(bool)), uas, SLOT(enableHil(bool)));
127
    connect(selectAirframeAction, SIGNAL(triggered()), this, SLOT(selectAirframe()));
128
    connect(setBatterySpecsAction, SIGNAL(triggered()), this, SLOT(setBatterySpecs()));
129
    connect(uas, SIGNAL(systemRemoved()), this, SLOT(deleteLater()));
130 131 132

    // Name changes
    connect(uas, SIGNAL(nameChanged(QString)), this, SLOT(updateName(QString)));
133

pixhawk's avatar
pixhawk committed
134
    // Set static values
135

pixhawk's avatar
pixhawk committed
136
    // Name
137 138
    if (uas->getUASName() == "")
    {
pixhawk's avatar
pixhawk committed
139
        m_ui->nameLabel->setText(tr("UAS") + QString::number(uas->getUASID()));
140 141 142
    }
    else
    {
pixhawk's avatar
pixhawk committed
143 144
        m_ui->nameLabel->setText(uas->getUASName());
    }
145

146
    setBackgroundColor();
147

pixhawk's avatar
pixhawk committed
148 149 150
    // Heartbeat fade
    refreshTimer = new QTimer(this);
    connect(refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
151 152
    if (lowPowerModeEnabled)
    {
153
        refreshTimer->start(updateInterval*3);
154 155 156
    }
    else
    {
157 158
        refreshTimer->start(updateInterval);
    }
159 160 161 162 163

    // Hide kill and shutdown buttons per default
    m_ui->killButton->hide();
    m_ui->shutdownButton->hide();

164 165 166
    // Set state and mode
    updateMode(uas->getUASID(), uas->getShortMode(), "");
    updateState(uas, uas->getShortState(), "");
167
    setSystemType(uas, uas->getSystemType());
pixhawk's avatar
pixhawk committed
168 169 170 171 172
}

UASView::~UASView()
{
    delete m_ui;
173 174 175
    delete removeAction;
    delete renameAction;
    delete selectAction;
pixhawk's avatar
pixhawk committed
176 177
}

178
void UASView::heartbeatTimeout(bool timeout, unsigned int ms)
179
{
180 181
    Q_UNUSED(ms);
    this->timeout = timeout;
182
}
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198

void UASView::updateNavMode(int uasid, int mode, const QString& text)
{
    Q_UNUSED(uasid);
    Q_UNUSED(mode);
    m_ui->navLabel->setText(text);
}

void UASView::showStatusText(int uasid, int componentid, int severity, QString text)
{
    Q_UNUSED(uasid);
    Q_UNUSED(componentid);
    Q_UNUSED(severity);
    //m_ui->statusTextLabel->setText(text);
    stateDesc = text;
}
199

200 201 202 203 204 205 206 207 208 209
/**
 * Set the background color based on the MAV color. If the MAV is selected as the
 * currently actively controlled system, the frame color is highlighted
 */
void UASView::setBackgroundColor()
{
    // UAS color
    QColor uasColor = uas->getColor();
    QString colorstyle;
    QString borderColor = "#4A4A4F";
210 211
    if (isActive)
    {
212 213
        borderColor = "#FA4A4F";
        uasColor = uasColor.darker(475);
214 215 216
    }
    else
    {
217 218
        uasColor = uasColor.darker(675);
    }
219
    colorstyle = colorstyle.sprintf("QGroupBox { border-radius: 12px; padding: 0px; margin: 0px; background-color: #%02X%02X%02X; border: 2px solid %s; }",
220 221 222 223 224
                                    uasColor.red(), uasColor.green(), uasColor.blue(), borderColor.toStdString().c_str());
    m_ui->uasViewFrame->setStyleSheet(colorstyle);
}

void UASView::setUASasActive(bool active)
pixhawk's avatar
pixhawk committed
225
{
226 227
    if (active)
    {
228 229 230 231 232 233
        UASManager::instance()->setActiveUAS(this->uas);
    }
}

void UASView::updateActiveUAS(UASInterface* uas, bool active)
{
234 235
    if (uas == this->uas)
    {
236 237 238
        this->isActive = active;
        setBackgroundColor();
    }
pixhawk's avatar
pixhawk committed
239 240
}

pixhawk's avatar
pixhawk committed
241 242
void UASView::updateMode(int sysId, QString status, QString description)
{
243
    Q_UNUSED(description);
244 245

    //int aa=this->uas->getUASID();
pixhawk's avatar
pixhawk committed
246
    if (sysId == this->uas->getUASID()) m_ui->modeLabel->setText(status);
247 248

    m_ui->modeLabel->setText(status);
pixhawk's avatar
pixhawk committed
249 250
}

pixhawk's avatar
pixhawk committed
251 252
void UASView::mouseDoubleClickEvent (QMouseEvent * event)
{
253
    Q_UNUSED(event);
pixhawk's avatar
pixhawk committed
254
    UASManager::instance()->setActiveUAS(uas);
255
    // qDebug() << __FILE__ << __LINE__ << "DOUBLECLICKED";
pixhawk's avatar
pixhawk committed
256 257 258 259
}

void UASView::enterEvent(QEvent* event)
{
260 261
    if (event->type() == QEvent::MouseMove)
    {
262
        emit uasInFocus(uas);
263 264
        if (uas != UASManager::instance()->getActiveUAS())
        {
265 266 267
            grabMouse(QCursor(Qt::PointingHandCursor));
        }
    }
268

269 270
    if (event->type() == QEvent::MouseButtonDblClick)
    {
271
        // qDebug() << __FILE__ << __LINE__ << "UAS CLICKED!";
272
    }
pixhawk's avatar
pixhawk committed
273 274 275 276
}

void UASView::leaveEvent(QEvent* event)
{
277 278
    if (event->type() == QEvent::MouseMove)
    {
279 280 281 282 283 284 285 286 287
        emit uasOutFocus(uas);
        releaseMouse();
    }
}

void UASView::showEvent(QShowEvent* event)
{
    // React only to internal (pre-display)
    // events
288
    Q_UNUSED(event);
289
    refreshTimer->start(updateInterval*10);
290 291 292 293 294 295 296 297
}

void UASView::hideEvent(QHideEvent* event)
{
    // React only to internal (pre-display)
    // events
    Q_UNUSED(event);
    refreshTimer->stop();
pixhawk's avatar
pixhawk committed
298 299 300 301
}

void UASView::receiveHeartbeat(UASInterface* uas)
{
302
    Q_UNUSED(uas);
303
    heartbeatColor = QColor(20, 200, 20);
lm's avatar
lm committed
304
    QString colorstyle("QGroupBox { border-radius: 5px; padding: 2px; margin: 0px; border: 0px; background-color: %1; }");
305
    m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
306 307 308 309 310 311
    if (timeout) setBackgroundColor();
    timeout = false;
}

void UASView::updateName(const QString& name)
{
312
    if (uas) m_ui->nameLabel->setText(name);
pixhawk's avatar
pixhawk committed
313 314 315 316 317 318 319 320 321 322 323
}

/**
 * The current system type is represented through the system icon.
 *
 * @param uas Source system, has to be the same as this->uas
 * @param systemType type ID, following the MAVLink system type conventions
 * @see http://pixhawk.ethz.ch/software/mavlink
 */
void UASView::setSystemType(UASInterface* uas, unsigned int systemType)
{
324 325
    if (uas == this->uas)
    {
pixhawk's avatar
pixhawk committed
326
        // Set matching icon
327 328
        switch (systemType)
        {
pixhawk's avatar
pixhawk committed
329
        case 0:
330
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/generic.svg"));
pixhawk's avatar
pixhawk committed
331 332
            break;
        case 1:
333
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/fixed-wing.svg"));
pixhawk's avatar
pixhawk committed
334 335
            break;
        case 2:
336
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/quadrotor.svg"));
pixhawk's avatar
pixhawk committed
337 338
            break;
        case 3:
339
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/coaxial.svg"));
pixhawk's avatar
pixhawk committed
340 341
            break;
        case 4:
342
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/helicopter.svg"));
pixhawk's avatar
pixhawk committed
343 344
            break;
        case 5:
345
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/unknown.svg"));
lm's avatar
lm committed
346
            break;
347
        case 6: {
348 349
                // A groundstation is a special system type, update widget
                QString result;
lm's avatar
lm committed
350
                m_ui->nameLabel->setText(tr("GCS ") + result.sprintf("%03d", uas->getUASID()));
351 352 353 354 355 356 357 358 359 360 361 362
                m_ui->waypointLabel->setText("");
                m_ui->timeRemainingLabel->setText("Online:");
                m_ui->batteryBar->hide();
                m_ui->thrustBar->hide();
                m_ui->stateLabel->hide();
                m_ui->statusTextLabel->hide();
                m_ui->waypointLabel->hide();
                m_ui->liftoffButton->hide();
                m_ui->haltButton->hide();
                m_ui->landButton->hide();
                m_ui->shutdownButton->hide();
                m_ui->abortButton->hide();
363
                m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/groundstation.svg"));
364 365
            }
            break;
pixhawk's avatar
pixhawk committed
366
        default:
367
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/unknown.svg"));
pixhawk's avatar
pixhawk committed
368 369 370 371 372 373 374
            break;
        }
    }
}

void UASView::updateLocalPosition(UASInterface* uas, double x, double y, double z, quint64 usec)
{
375
    Q_UNUSED(usec);
376 377 378 379
    Q_UNUSED(uas);
    this->x = x;
    this->y = y;
    this->z = z;
380
    localFrame = true;
pixhawk's avatar
pixhawk committed
381 382
}

383
void UASView::updateGlobalPosition(UASInterface* uas, double lon, double lat, double alt, quint64 usec)
pixhawk's avatar
pixhawk committed
384
{
385 386
    Q_UNUSED(uas);
    Q_UNUSED(usec);
pixhawk's avatar
pixhawk committed
387 388 389
    this->lon = lon;
    this->lat = lat;
    this->alt = alt;
390
    globalFrameKnown = true;
pixhawk's avatar
pixhawk committed
391 392 393 394
}

void UASView::updateSpeed(UASInterface*, double x, double y, double z, quint64 usec)
{
395
    Q_UNUSED(usec);
396
    totalSpeed = sqrt(x*x + y*y + z*z);
pixhawk's avatar
pixhawk committed
397 398
}

399 400 401 402 403
void UASView::currentWaypointUpdated(quint16 waypoint)
{
    m_ui->waypointLabel->setText(tr("WP") + QString::number(waypoint));
}

pixhawk's avatar
pixhawk committed
404 405
void UASView::setWaypoint(int uasId, int id, double x, double y, double z, double yaw, bool autocontinue, bool current)
{
406 407 408 409 410
    Q_UNUSED(x);
    Q_UNUSED(y);
    Q_UNUSED(z);
    Q_UNUSED(yaw);
    Q_UNUSED(autocontinue);
411 412 413 414
    if (uasId == this->uas->getUASID())
    {
        if (current)
        {
pixhawk's avatar
pixhawk committed
415 416 417 418 419 420 421
            m_ui->waypointLabel->setText(tr("WP") + QString::number(id));
        }
    }
}

void UASView::selectWaypoint(int uasId, int id)
{
422 423
    if (uasId == this->uas->getUASID())
    {
pixhawk's avatar
pixhawk committed
424 425 426 427 428 429
        m_ui->waypointLabel->setText(tr("WP") + QString::number(id));
    }
}

void UASView::updateThrust(UASInterface* uas, double thrust)
{
430 431
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
432
        this->thrust = thrust;
pixhawk's avatar
pixhawk committed
433 434 435 436 437
    }
}

void UASView::updateBattery(UASInterface* uas, double voltage, double percent, int seconds)
{
438
    Q_UNUSED(voltage);
439 440
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
441 442 443 444 445 446 447
        timeRemaining = seconds;
        chargeLevel = percent;
    }
}

void UASView::updateState(UASInterface* uas, QString uasState, QString stateDescription)
{
448 449
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
450 451 452 453 454 455 456
        state = uasState;
        stateDesc = stateDescription;
    }
}

void UASView::updateLoad(UASInterface* uas, double load)
{
457 458
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
459 460 461 462
        this->load = load;
    }
}

463 464
void UASView::contextMenuEvent (QContextMenuEvent* event)
{
465
    QMenu menu(this);
lm's avatar
lm committed
466 467
    menu.addAction(selectAction);
    menu.addSeparator();
468
    menu.addAction(renameAction);
469 470
    if (timeout)
    {
471
        menu.addAction(removeAction);
472
    }
473 474
    menu.addAction(hilXAction);
    // XXX Re-enable later menu.addAction(hilXAction);
475
    menu.addAction(selectAirframeAction);
476
    menu.addAction(setBatterySpecsAction);
477 478 479
    menu.exec(event->globalPos());
}

480 481
void UASView::setBatterySpecs()
{
482 483
    if (uas)
    {
484 485
        bool ok;
        QString newName = QInputDialog::getText(this, tr("Set Battery Specifications for %1").arg(uas->getUASName()),
486
                                                tr("Specs: (empty,warn,full), e.g. (9V,9.5V,12.6V) or just warn level in percent (e.g. 15%) to use estimate from MAV"), QLineEdit::Normal,
487 488 489 490 491 492
                                                uas->getBatterySpecs(), &ok);

        if (ok && !newName.isEmpty()) uas->setBatterySpecs(newName);
    }
}

493 494
void UASView::rename()
{
495 496
    if (uas)
    {
497 498 499 500 501 502
        bool ok;
        QString newName = QInputDialog::getText(this, tr("Rename System %1").arg(uas->getUASName()),
                                                tr("System Name:"), QLineEdit::Normal,
                                                uas->getUASName(), &ok);

        if (ok && !newName.isEmpty()) uas->setUASName(newName);
503 504 505
    }
}

506 507
void UASView::selectAirframe()
{
508 509
    if (uas)
    {
510 511 512
        // Get list of airframes from UAS
        QStringList airframes;
        airframes << "Generic"
513 514 515 516 517 518 519 520
                << "Multiplex Easystar"
                << "Multiplex Twinstar"
                << "Multiplex Merlin"
                << "Pixhawk Cheetah"
                << "Mikrokopter"
                << "Reaper"
                << "Predator"
                << "Coaxial"
521 522
                << "Pteryx"
                << "Asctec Firefly";
523 524 525 526

        bool ok;
        QString item = QInputDialog::getItem(this, tr("Select Airframe for %1").arg(uas->getUASName()),
                                             tr("Airframe"), airframes, uas->getAirframe(), false, &ok);
527 528
        if (ok && !item.isEmpty())
        {
529 530 531 532 533 534
            // Set this airframe as UAS airframe
            uas->setAirframe(airframes.indexOf(item));
        }
    }
}

pixhawk's avatar
pixhawk committed
535 536
void UASView::refresh()
{
537
    //setUpdatesEnabled(false);
538 539
    //setUpdatesEnabled(true);
    //repaint();
540
    //qDebug() << "UPDATING UAS WIDGET!" << uas->getUASName();
541 542


543 544 545
    quint64 lastupdate = 0;
    //// qDebug() << "UASVIEW update diff: " << MG::TIME::getGroundTimeNow() - lastupdate;
    lastupdate = QGC::groundTimeMilliseconds();
546

547 548
    if (generalUpdateCount == 4)
    {
549
#if (QGC_EVENTLOOP_DEBUG)
550
        // qDebug() << "EVENTLOOP:" << __FILE__ << __LINE__;
551
#endif
552
        generalUpdateCount = 0;
553
        //// qDebug() << "UPDATING EVERYTHING";
554 555 556 557 558 559 560 561 562 563
        // State
        m_ui->stateLabel->setText(state);
        m_ui->statusTextLabel->setText(stateDesc);

        // Battery
        m_ui->batteryBar->setValue(static_cast<int>(this->chargeLevel));
        //m_ui->loadBar->setValue(static_cast<int>(this->load));
        m_ui->thrustBar->setValue(this->thrust);

        // Position
564 565 566 567 568 569 570
        // If global position is known, prefer it over local coordinates

        if (!globalFrameKnown && localFrame)
        {
            QString position;
            position = position.sprintf("%05.1f %05.1f %06.1f m", x, y, z);
            m_ui->positionLabel->setText(position);
571
        }
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596

        if (globalFrameKnown)
        {
            QString globalPosition;
            QString latIndicator;
            if (lat > 0)
            {
                latIndicator = "N";
            }
            else
            {
                latIndicator = "S";
            }
            QString lonIndicator;
            if (lon > 0)
            {
                lonIndicator = "E";
            }
            else
            {
                lonIndicator = "W";
            }

            globalPosition = globalPosition.sprintf("%05.1f%s %05.1f%s %06.1f m", lon, lonIndicator.toStdString().c_str(), lat, latIndicator.toStdString().c_str(), alt);
            m_ui->positionLabel->setText(globalPosition);
597
        }
pixhawk's avatar
pixhawk committed
598

599
        // Altitude
600 601
        if (groundDistance == 0 && alt != 0)
        {
602
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(alt, 6, 'f', 1, '0'));
603 604 605
        }
        else
        {
606
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(groundDistance, 6, 'f', 1, '0'));
607
        }
608

609
        // Speed
610 611
        QString speed("%1 m/s");
        m_ui->speedLabel->setText(speed.arg(totalSpeed, 4, 'f', 1, '0'));
pixhawk's avatar
pixhawk committed
612

613 614
        // Thrust
        m_ui->thrustBar->setValue(thrust * 100);
pixhawk's avatar
pixhawk committed
615

616 617
        if(this->timeRemaining > 1 && this->timeRemaining < QGC::MAX_FLIGHT_TIME)
        {
618
            // Filter output to get a higher stability
619
            filterTime = static_cast<int>(this->timeRemaining);
620 621 622 623 624 625 626 627
            filterTime = 0.8 * filterTime + 0.2 * static_cast<int>(this->timeRemaining);
            int sec = static_cast<int>(filterTime - static_cast<int>(filterTime / 60.0f) * 60);
            int min = static_cast<int>(filterTime / 60);
            int hours = static_cast<int>(filterTime - min * 60 - sec);

            QString timeText;
            timeText = timeText.sprintf("%02d:%02d:%02d", hours, min, sec);
            m_ui->timeRemainingLabel->setText(timeText);
628 629 630
        }
        else
        {
631
            m_ui->timeRemainingLabel->setText(tr("Calc.."));
632 633 634 635 636 637 638
        }

        // Time Elapsed
        //QDateTime time = MG::TIME::msecToQDateTime(uas->getUptime());

        quint64 filterTime = uas->getUptime() / 1000;
        int sec = static_cast<int>(filterTime - static_cast<int>(filterTime / 60) * 60);
pixhawk's avatar
pixhawk committed
639 640 641 642
        int min = static_cast<int>(filterTime / 60);
        int hours = static_cast<int>(filterTime - min * 60 - sec);
        QString timeText;
        timeText = timeText.sprintf("%02d:%02d:%02d", hours, min, sec);
643
        m_ui->timeElapsedLabel->setText(timeText);
pixhawk's avatar
pixhawk committed
644
    }
645
    generalUpdateCount++;
pixhawk's avatar
pixhawk committed
646

lm's avatar
lm committed
647
    QString colorstyle("QGroupBox { border-radius: 5px; padding: 2px; margin: 0px; border: 0px; background-color: %1; }");
648

649 650
    if (timeout)
    {
651 652
        // CRITICAL CONDITION, NO HEARTBEAT

653
        QString borderColor = "#FFFF00";
654 655
        if (isActive)
        {
656 657 658
            borderColor = "#FA4A4F";
        }

659 660
        if (iconIsRed)
        {
661 662
            QColor warnColor(Qt::red);
            m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(warnColor.name()));
663
            QString style = QString("QGroupBox { border-radius: 12px; padding: 0px; margin: 0px; border: 2px solid %1; background-color: %2; }").arg(borderColor, warnColor.name());
664
            m_ui->uasViewFrame->setStyleSheet(style);
665 666 667
        }
        else
        {
668 669
            QColor warnColor(Qt::black);
            m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(warnColor.name()));
670
            QString style = QString("QGroupBox { border-radius: 12px; padding: 0px; margin: 0px; border: 2px solid %1; background-color: %2; }").arg(borderColor, warnColor.name());
671
            m_ui->uasViewFrame->setStyleSheet(style);
LM's avatar
LM committed
672 673

            refreshTimer->setInterval(errorUpdateInterval);
674
            refreshTimer->start();
675 676
        }
        iconIsRed = !iconIsRed;
677 678 679
    }
    else
    {
680 681 682 683
        if (!lowPowerModeEnabled)
        {
            // Fade heartbeat icon
            // Make color darker
LM's avatar
LM committed
684
            heartbeatColor = heartbeatColor.darker(210);
685 686 687

            //m_ui->heartbeatIcon->setAutoFillBackground(true);
            m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
LM's avatar
LM committed
688
            refreshTimer->setInterval(updateInterval);
689
            refreshTimer->start();
690
        }
691
    }
692
    //setUpdatesEnabled(true);
693 694

    //setUpdatesEnabled(false);
pixhawk's avatar
pixhawk committed
695 696 697 698 699
}

void UASView::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
700 701
    switch (e->type())
    {
pixhawk's avatar
pixhawk committed
702 703 704 705 706 707 708
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}