UASView.cc 20.9 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 40
#include "MG.h"
#include "UASManager.h"
#include "UASView.h"
41
#include "UASWaypointManager.h"
42
#include "MainWindow.h"
pixhawk's avatar
pixhawk committed
43 44 45
#include "ui_UASView.h"

UASView::UASView(UASInterface* uas, QWidget *parent) :
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
        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),
        removeAction(new QAction("Delete this system", this)),
        renameAction(new QAction("Rename..", this)),
        selectAction(new QAction("Control this system", this )),
        selectAirframeAction(new QAction("Choose Airframe", this)),
        setBatterySpecsAction(new QAction("Set Battery Options", this)),
        lowPowerModeEnabled(false),
        m_ui(new Ui::UASView)
{
    // FIXME XXX
    lowPowerModeEnabled = MainWindow::instance()->lowPowerModeEnabled();


pixhawk's avatar
pixhawk committed
80
    m_ui->setupUi(this);
81

pixhawk's avatar
pixhawk committed
82
    // Setup communication
pixhawk's avatar
pixhawk committed
83
    //connect(uas, SIGNAL(valueChanged(int,QString,double,quint64)), this, SLOT(receiveValue(int,QString,double,quint64)));
pixhawk's avatar
pixhawk committed
84 85 86 87 88 89 90
    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
91
    connect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString)));
pixhawk's avatar
pixhawk committed
92
    connect(uas, SIGNAL(loadChanged(UASInterface*, double)), this, SLOT(updateLoad(UASInterface*, double)));
93
    connect(uas, SIGNAL(heartbeatTimeout()), this, SLOT(heartbeatTimeout()));
pixhawk's avatar
pixhawk committed
94
    connect(uas, SIGNAL(waypointSelected(int,int)), this, SLOT(selectWaypoint(int,int)));
pixhawk's avatar
pixhawk committed
95
    connect(uas->getWaypointManager(), SIGNAL(currentWaypointChanged(quint16)), this, SLOT(currentWaypointUpdated(quint16)));
pixhawk's avatar
pixhawk committed
96
    connect(uas, SIGNAL(systemTypeSet(UASInterface*,uint)), this, SLOT(setSystemType(UASInterface*,uint)));
97
    connect(UASManager::instance(), SIGNAL(activeUASStatusChanged(UASInterface*,bool)), this, SLOT(updateActiveUAS(UASInterface*,bool)));
98 99 100
    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
101
    // Setup UAS selection
102
    connect(m_ui->uasViewFrame, SIGNAL(clicked(bool)), this, SLOT(setUASasActive(bool)));
103

pixhawk's avatar
pixhawk committed
104 105 106 107
    // 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()));
pixhawk's avatar
pixhawk committed
108 109
    connect(m_ui->landButton, SIGNAL(clicked()), uas, SLOT(home()));
    connect(m_ui->abortButton, SIGNAL(clicked()), uas, SLOT(emergencySTOP()));
pixhawk's avatar
pixhawk committed
110 111
    connect(m_ui->killButton, SIGNAL(clicked()), uas, SLOT(emergencyKILL()));
    connect(m_ui->shutdownButton, SIGNAL(clicked()), uas, SLOT(shutdown()));
112 113 114

    // Allow to delete this widget
    connect(removeAction, SIGNAL(triggered()), this, SLOT(deleteLater()));
115
    connect(renameAction, SIGNAL(triggered()), this, SLOT(rename()));
116
    connect(selectAction, SIGNAL(triggered()), uas, SLOT(setSelected()));
117
    connect(selectAirframeAction, SIGNAL(triggered()), this, SLOT(selectAirframe()));
118
    connect(setBatterySpecsAction, SIGNAL(triggered()), this, SLOT(setBatterySpecs()));
119
    connect(uas, SIGNAL(systemRemoved()), this, SLOT(deleteLater()));
120 121 122

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

pixhawk's avatar
pixhawk committed
124
    // Set static values
125

pixhawk's avatar
pixhawk committed
126
    // Name
127
    if (uas->getUASName() == "") {
pixhawk's avatar
pixhawk committed
128
        m_ui->nameLabel->setText(tr("UAS") + QString::number(uas->getUASID()));
129
    } else {
pixhawk's avatar
pixhawk committed
130 131
        m_ui->nameLabel->setText(uas->getUASName());
    }
132

133
    setBackgroundColor();
134

pixhawk's avatar
pixhawk committed
135 136 137
    // Heartbeat fade
    refreshTimer = new QTimer(this);
    connect(refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
138 139 140 141 142 143
    if (lowPowerModeEnabled)
    {
        refreshTimer->start(updateInterval*10);
    } else {
        refreshTimer->start(updateInterval);
    }
144 145 146 147 148

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

149 150 151
    // Set state and mode
    updateMode(uas->getUASID(), uas->getShortMode(), "");
    updateState(uas, uas->getShortState(), "");
152
    setSystemType(uas, uas->getSystemType());
pixhawk's avatar
pixhawk committed
153 154 155 156 157
}

UASView::~UASView()
{
    delete m_ui;
158 159 160
    delete removeAction;
    delete renameAction;
    delete selectAction;
pixhawk's avatar
pixhawk committed
161 162
}

163 164 165 166
void UASView::heartbeatTimeout()
{
    timeout = true;
}
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182

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;
}
183

184 185 186 187 188 189 190 191 192 193
/**
 * 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";
194
    if (isActive) {
195 196
        borderColor = "#FA4A4F";
        uasColor = uasColor.darker(475);
197
    } else {
198 199
        uasColor = uasColor.darker(675);
    }
200
    colorstyle = colorstyle.sprintf("QGroupBox { border-radius: 12px; padding: 0px; margin: 0px; background-color: #%02X%02X%02X; border: 2px solid %s; }",
201 202 203 204 205
                                    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
206
{
207
    if (active) {
208 209 210 211 212 213
        UASManager::instance()->setActiveUAS(this->uas);
    }
}

void UASView::updateActiveUAS(UASInterface* uas, bool active)
{
214
    if (uas == this->uas) {
215 216 217
        this->isActive = active;
        setBackgroundColor();
    }
pixhawk's avatar
pixhawk committed
218 219
}

pixhawk's avatar
pixhawk committed
220 221
void UASView::updateMode(int sysId, QString status, QString description)
{
222
    Q_UNUSED(description);
223 224

    //int aa=this->uas->getUASID();
pixhawk's avatar
pixhawk committed
225
    if (sysId == this->uas->getUASID()) m_ui->modeLabel->setText(status);
226 227

    m_ui->modeLabel->setText(status);
pixhawk's avatar
pixhawk committed
228 229
}

pixhawk's avatar
pixhawk committed
230 231
void UASView::mouseDoubleClickEvent (QMouseEvent * event)
{
232
    Q_UNUSED(event);
pixhawk's avatar
pixhawk committed
233
    UASManager::instance()->setActiveUAS(uas);
234
    // qDebug() << __FILE__ << __LINE__ << "DOUBLECLICKED";
pixhawk's avatar
pixhawk committed
235 236 237 238
}

void UASView::enterEvent(QEvent* event)
{
239
    if (event->type() == QEvent::MouseMove) {
240
        emit uasInFocus(uas);
241
        if (uas != UASManager::instance()->getActiveUAS()) {
242 243 244
            grabMouse(QCursor(Qt::PointingHandCursor));
        }
    }
245
    // qDebug() << __FILE__ << __LINE__ << "IN FOCUS";
246 247

    if (event->type() == QEvent::MouseButtonDblClick) {
248
        // qDebug() << __FILE__ << __LINE__ << "UAS CLICKED!";
249
    }
pixhawk's avatar
pixhawk committed
250 251 252 253
}

void UASView::leaveEvent(QEvent* event)
{
254
    if (event->type() == QEvent::MouseMove) {
255 256 257 258 259 260 261 262 263
        emit uasOutFocus(uas);
        releaseMouse();
    }
}

void UASView::showEvent(QShowEvent* event)
{
    // React only to internal (pre-display)
    // events
264
    Q_UNUSED(event);
265
    refreshTimer->start(updateInterval*10);
266 267 268 269 270 271 272 273
}

void UASView::hideEvent(QHideEvent* event)
{
    // React only to internal (pre-display)
    // events
    Q_UNUSED(event);
    refreshTimer->stop();
pixhawk's avatar
pixhawk committed
274 275 276 277
}

void UASView::receiveHeartbeat(UASInterface* uas)
{
278
    Q_UNUSED(uas);
279
    heartbeatColor = QColor(20, 200, 20);
lm's avatar
lm committed
280
    QString colorstyle("QGroupBox { border-radius: 5px; padding: 2px; margin: 0px; border: 0px; background-color: %1; }");
281
    m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
282 283 284 285 286 287
    if (timeout) setBackgroundColor();
    timeout = false;
}

void UASView::updateName(const QString& name)
{
288
    if (uas) m_ui->nameLabel->setText(name);
pixhawk's avatar
pixhawk committed
289 290 291 292 293 294 295 296 297 298 299
}

/**
 * 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)
{
300
    if (uas == this->uas) {
pixhawk's avatar
pixhawk committed
301
        // Set matching icon
302
        switch (systemType) {
pixhawk's avatar
pixhawk committed
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
        case 0:
            m_ui->typeButton->setIcon(QIcon(":/images/mavs/generic.svg"));
            break;
        case 1:
            m_ui->typeButton->setIcon(QIcon(":/images/mavs/fixed-wing.svg"));
            break;
        case 2:
            m_ui->typeButton->setIcon(QIcon(":/images/mavs/quadrotor.svg"));
            break;
        case 3:
            m_ui->typeButton->setIcon(QIcon(":/images/mavs/coaxial.svg"));
            break;
        case 4:
            m_ui->typeButton->setIcon(QIcon(":/images/mavs/helicopter.svg"));
            break;
        case 5:
lm's avatar
lm committed
319 320
            m_ui->typeButton->setIcon(QIcon(":/images/mavs/unknown.svg"));
            break;
321
        case 6: {
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
                // A groundstation is a special system type, update widget
                QString result;
                m_ui->nameLabel->setText(tr("OCU ") + result.sprintf("%03d", uas->getUASID()));
                m_ui->waypointLabel->setText("");
                m_ui->timeRemainingLabel->setText("Online:");
                m_ui->batteryBar->hide();
                m_ui->thrustBar->hide();
                m_ui->stateLabel->hide();
                m_ui->statusTextLabel->hide();
                m_ui->waypointLabel->hide();
                m_ui->liftoffButton->hide();
                m_ui->haltButton->hide();
                m_ui->landButton->hide();
                m_ui->shutdownButton->hide();
                m_ui->abortButton->hide();
                m_ui->typeButton->setIcon(QIcon(":/images/mavs/groundstation.svg"));
            }
            break;
pixhawk's avatar
pixhawk committed
340 341 342 343 344 345 346 347 348
        default:
            m_ui->typeButton->setIcon(QIcon(":/images/mavs/unknown.svg"));
            break;
        }
    }
}

void UASView::updateLocalPosition(UASInterface* uas, double x, double y, double z, quint64 usec)
{
349
    Q_UNUSED(usec);
350 351 352 353
    Q_UNUSED(uas);
    this->x = x;
    this->y = y;
    this->z = z;
354
    if (!localFrame) {
355
        localFrame = true;
pixhawk's avatar
pixhawk committed
356 357 358
    }
}

359
void UASView::updateGlobalPosition(UASInterface* uas, double lon, double lat, double alt, quint64 usec)
pixhawk's avatar
pixhawk committed
360
{
361 362
    Q_UNUSED(uas);
    Q_UNUSED(usec);
pixhawk's avatar
pixhawk committed
363 364 365
    this->lon = lon;
    this->lat = lat;
    this->alt = alt;
pixhawk's avatar
pixhawk committed
366 367 368 369
}

void UASView::updateSpeed(UASInterface*, double x, double y, double z, quint64 usec)
{
370
    Q_UNUSED(usec);
371
    totalSpeed = sqrt(x*x + y*y + z*z);
pixhawk's avatar
pixhawk committed
372 373
}

374 375 376 377 378
void UASView::currentWaypointUpdated(quint16 waypoint)
{
    m_ui->waypointLabel->setText(tr("WP") + QString::number(waypoint));
}

pixhawk's avatar
pixhawk committed
379 380
void UASView::setWaypoint(int uasId, int id, double x, double y, double z, double yaw, bool autocontinue, bool current)
{
381 382 383 384 385
    Q_UNUSED(x);
    Q_UNUSED(y);
    Q_UNUSED(z);
    Q_UNUSED(yaw);
    Q_UNUSED(autocontinue);
386 387
    if (uasId == this->uas->getUASID()) {
        if (current) {
pixhawk's avatar
pixhawk committed
388 389 390 391 392 393 394
            m_ui->waypointLabel->setText(tr("WP") + QString::number(id));
        }
    }
}

void UASView::selectWaypoint(int uasId, int id)
{
395
    if (uasId == this->uas->getUASID()) {
pixhawk's avatar
pixhawk committed
396 397 398 399 400 401
        m_ui->waypointLabel->setText(tr("WP") + QString::number(id));
    }
}

void UASView::updateThrust(UASInterface* uas, double thrust)
{
402
    if (this->uas == uas) {
pixhawk's avatar
pixhawk committed
403
        this->thrust = thrust;
pixhawk's avatar
pixhawk committed
404 405 406 407 408
    }
}

void UASView::updateBattery(UASInterface* uas, double voltage, double percent, int seconds)
{
409
    Q_UNUSED(voltage);
410
    if (this->uas == uas) {
pixhawk's avatar
pixhawk committed
411 412 413 414 415 416 417
        timeRemaining = seconds;
        chargeLevel = percent;
    }
}

void UASView::updateState(UASInterface* uas, QString uasState, QString stateDescription)
{
418
    if (this->uas == uas) {
pixhawk's avatar
pixhawk committed
419 420 421 422 423 424 425
        state = uasState;
        stateDesc = stateDescription;
    }
}

void UASView::updateLoad(UASInterface* uas, double load)
{
426
    if (this->uas == uas) {
pixhawk's avatar
pixhawk committed
427 428 429 430
        this->load = load;
    }
}

431 432
void UASView::contextMenuEvent (QContextMenuEvent* event)
{
433
    QMenu menu(this);
lm's avatar
lm committed
434 435
    menu.addAction(selectAction);
    menu.addSeparator();
436
    menu.addAction(renameAction);
437
    if (timeout) {
438
        menu.addAction(removeAction);
439
    }
440
    menu.addAction(selectAirframeAction);
441
    menu.addAction(setBatterySpecsAction);
442 443 444
    menu.exec(event->globalPos());
}

445 446
void UASView::setBatterySpecs()
{
447
    if (uas) {
448 449
        bool ok;
        QString newName = QInputDialog::getText(this, tr("Set Battery Specifications for %1").arg(uas->getUASName()),
450
                                                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,
451 452 453 454 455 456
                                                uas->getBatterySpecs(), &ok);

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

457 458
void UASView::rename()
{
459
    if (uas) {
460 461 462 463 464 465
        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);
466 467 468
    }
}

469 470
void UASView::selectAirframe()
{
471
    if (uas) {
472 473 474
        // Get list of airframes from UAS
        QStringList airframes;
        airframes << "Generic"
475 476 477 478 479 480 481 482 483
                << "Multiplex Easystar"
                << "Multiplex Twinstar"
                << "Multiplex Merlin"
                << "Pixhawk Cheetah"
                << "Mikrokopter"
                << "Reaper"
                << "Predator"
                << "Coaxial"
                << "Pteryx";
484 485 486 487

        bool ok;
        QString item = QInputDialog::getItem(this, tr("Select Airframe for %1").arg(uas->getUASName()),
                                             tr("Airframe"), airframes, uas->getAirframe(), false, &ok);
488
        if (ok && !item.isEmpty()) {
489 490 491 492 493 494
            // Set this airframe as UAS airframe
            uas->setAirframe(airframes.indexOf(item));
        }
    }
}

pixhawk's avatar
pixhawk committed
495 496
void UASView::refresh()
{
497
    //setUpdatesEnabled(false);
498 499
    //setUpdatesEnabled(true);
    //repaint();
500 501

    static quint64 lastupdate = 0;
502
    //// qDebug() << "UASVIEW update diff: " << MG::TIME::getGroundTimeNow() - lastupdate;
503 504 505 506 507
    lastupdate = MG::TIME::getGroundTimeNow();

    // FIXME
    static int generalUpdateCount = 0;

508
    if (generalUpdateCount == 4) {
509
#if (QGC_EVENTLOOP_DEBUG)
510
        // qDebug() << "EVENTLOOP:" << __FILE__ << __LINE__;
511
#endif
512
        generalUpdateCount = 0;
513
        //// qDebug() << "UPDATING EVERYTHING";
514 515 516 517 518 519 520 521 522 523 524
        // 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
        QString position;
525
        position = position.sprintf("%05.1f %05.1f %06.1f m", x, y, z);
526 527 528
        m_ui->positionLabel->setText(position);
        QString globalPosition;
        QString latIndicator;
529
        if (lat > 0) {
530
            latIndicator = "N";
531
        } else {
532 533 534
            latIndicator = "S";
        }
        QString lonIndicator;
535
        if (lon > 0) {
536
            lonIndicator = "E";
537
        } else {
538 539
            lonIndicator = "W";
        }
540 541
        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);
pixhawk's avatar
pixhawk committed
542

543
        // Altitude
544
        if (groundDistance == 0 && alt != 0) {
545
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(alt, 6, 'f', 1, '0'));
546
        } else {
547
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(groundDistance, 6, 'f', 1, '0'));
548
        }
549

550
        // Speed
551 552
        QString speed("%1 m/s");
        m_ui->speedLabel->setText(speed.arg(totalSpeed, 4, 'f', 1, '0'));
pixhawk's avatar
pixhawk committed
553

554 555
        // Thrust
        m_ui->thrustBar->setValue(thrust * 100);
pixhawk's avatar
pixhawk committed
556

557
        if(this->timeRemaining > 1 && this->timeRemaining < QGC::MAX_FLIGHT_TIME) {
558 559 560 561 562 563 564 565 566 567
            // Filter output to get a higher stability
            static double filterTime = static_cast<int>(this->timeRemaining);
            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);
568
        } else {
569
            m_ui->timeRemainingLabel->setText(tr("Calc.."));
570 571 572 573 574 575 576
        }

        // 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
577 578 579 580
        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);
581
        m_ui->timeElapsedLabel->setText(timeText);
pixhawk's avatar
pixhawk committed
582
    }
583
    generalUpdateCount++;
pixhawk's avatar
pixhawk committed
584

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

587
    if (timeout) {
588 589
        // CRITICAL CONDITION, NO HEARTBEAT

590
        QString borderColor = "#FFFF00";
591
        if (isActive) {
592 593 594
            borderColor = "#FA4A4F";
        }

595
        if (iconIsRed) {
596 597
            QColor warnColor(Qt::red);
            m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(warnColor.name()));
598
            QString style = QString("QGroupBox { border-radius: 12px; padding: 0px; margin: 0px; border: 2px solid %1; background-color: %2; }").arg(borderColor, warnColor.name());
599
            m_ui->uasViewFrame->setStyleSheet(style);
600
        } else {
601 602
            QColor warnColor(Qt::black);
            m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(warnColor.name()));
603
            QString style = QString("QGroupBox { border-radius: 12px; padding: 0px; margin: 0px; border: 2px solid %1; background-color: %2; }").arg(borderColor, warnColor.name());
604
            m_ui->uasViewFrame->setStyleSheet(style);
LM's avatar
LM committed
605 606

            refreshTimer->setInterval(errorUpdateInterval);
607 608
        }
        iconIsRed = !iconIsRed;
609
    } else {
610 611 612 613
        if (!lowPowerModeEnabled)
        {
            // Fade heartbeat icon
            // Make color darker
LM's avatar
LM committed
614
            heartbeatColor = heartbeatColor.darker(210);
615 616 617

            //m_ui->heartbeatIcon->setAutoFillBackground(true);
            m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
LM's avatar
LM committed
618
            refreshTimer->setInterval(updateInterval);
619
        }
620
    }
621
    //setUpdatesEnabled(true);
622 623

    //setUpdatesEnabled(false);
pixhawk's avatar
pixhawk committed
624 625 626 627 628 629 630 631 632 633 634 635 636
}

void UASView::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}