UASView.cc 21.6 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
#include "ui_UASView.h"
43
#include <QGCHilFlightGearConfiguration.h>
pixhawk's avatar
pixhawk committed
44 45

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),
    uas(uas),
    startTime(0),
    timeout(false),
    iconIsRed(true),
    disconnected(false),
    timeRemaining(0),
    chargeLevel(0),
    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),
    globalFrameKnown(false),
    removeAction(new QAction(tr("Delete this system"), this)),
    renameAction(new QAction(tr("Rename.."), this)),
    selectAction(new QAction(tr("Control this system"), this)),
    hilAction(new QAction(tr("HIL - Hardware in the Loop"), this)),
    selectAirframeAction(new QAction(tr("Choose Airframe"), this)),
    setBatterySpecsAction(new QAction(tr("Set Battery Options"), this)),
    lowPowerModeEnabled(true),
    generalUpdateCount(0),
    filterTime(0),
    m_ui(new Ui::UASView)
80
{
81
    m_ui->setupUi(this);
82
    setToolTip(""); // Make sure the QGroupBox's tooltip doesn't seep through.
83

84 85 86
    // FIXME XXX
    lowPowerModeEnabled = MainWindow::instance()->lowPowerModeEnabled();

lm's avatar
lm committed
87
    hilAction->setCheckable(true);
88

pixhawk's avatar
pixhawk committed
89
    // Setup communication
pixhawk's avatar
pixhawk committed
90
    //connect(uas, SIGNAL(valueChanged(int,QString,double,quint64)), this, SLOT(receiveValue(int,QString,double,quint64)));
dongfang's avatar
dongfang committed
91
    connect(uas, SIGNAL(batteryChanged(UASInterface*, double, double, double, int)), this, SLOT(updateBattery(UASInterface*, double, double, double, int)));
pixhawk's avatar
pixhawk committed
92 93 94
    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)));
95
    connect(uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,double,quint64)), this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,double,quint64)));
96
    connect(uas, SIGNAL(velocityChanged_NED(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64)));
pixhawk's avatar
pixhawk committed
97
    connect(uas, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*,QString,QString)));
pixhawk's avatar
pixhawk committed
98
    connect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString)));
pixhawk's avatar
pixhawk committed
99
    connect(uas, SIGNAL(loadChanged(UASInterface*, double)), this, SLOT(updateLoad(UASInterface*, double)));
100
    connect(uas, SIGNAL(heartbeatTimeout(bool, unsigned int)), this, SLOT(heartbeatTimeout(bool, unsigned int)));
pixhawk's avatar
pixhawk committed
101
    connect(uas, SIGNAL(waypointSelected(int,int)), this, SLOT(selectWaypoint(int,int)));
pixhawk's avatar
pixhawk committed
102
    connect(uas->getWaypointManager(), SIGNAL(currentWaypointChanged(quint16)), this, SLOT(currentWaypointUpdated(quint16)));
pixhawk's avatar
pixhawk committed
103
    connect(uas, SIGNAL(systemTypeSet(UASInterface*,uint)), this, SLOT(setSystemType(UASInterface*,uint)));
104
    connect(UASManager::instance(), SIGNAL(activeUASStatusChanged(UASInterface*,bool)), this, SLOT(updateActiveUAS(UASInterface*,bool)));
105 106 107
    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
108 109 110 111
    // 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()));
112
    connect(m_ui->landButton, SIGNAL(clicked()), uas, SLOT(land()));
pixhawk's avatar
pixhawk committed
113
    connect(m_ui->abortButton, SIGNAL(clicked()), uas, SLOT(emergencySTOP()));
pixhawk's avatar
pixhawk committed
114 115
    connect(m_ui->killButton, SIGNAL(clicked()), uas, SLOT(emergencyKILL()));
    connect(m_ui->shutdownButton, SIGNAL(clicked()), uas, SLOT(shutdown()));
116

117 118
    // Allow deleting this widget
    connect(removeAction, SIGNAL(triggered()), this, SLOT(triggerUASDeletion()));
119
    connect(renameAction, SIGNAL(triggered()), this, SLOT(rename()));
120
    connect(selectAction, SIGNAL(triggered()), uas, SLOT(setSelected()));
121
    connect(selectAirframeAction, SIGNAL(triggered()), this, SLOT(selectAirframe()));
122
    connect(setBatterySpecsAction, SIGNAL(triggered()), this, SLOT(setBatterySpecs()));
123 124 125

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

pixhawk's avatar
pixhawk committed
127
    // Set static values
128

pixhawk's avatar
pixhawk committed
129
    // Name
130 131
    if (uas->getUASName() == "")
    {
pixhawk's avatar
pixhawk committed
132
        m_ui->nameLabel->setText(tr("UAS") + QString::number(uas->getUASID()));
133 134 135
    }
    else
    {
pixhawk's avatar
pixhawk committed
136 137
        m_ui->nameLabel->setText(uas->getUASName());
    }
138

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

151 152 153 154 155 156 157
    // Style some elements by default to the UAS' color.
    heartbeatColor = uas->getColor();
    QString colorstyle("QLabel { background-color: %1; }");
    m_ui->typeLabel->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
    updateActiveUAS(uas, false);

    // Hide kill and shutdown buttons by default
158 159 160
    m_ui->killButton->hide();
    m_ui->shutdownButton->hide();

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

UASView::~UASView()
{
    delete m_ui;
}

172
void UASView::heartbeatTimeout(bool timeout, unsigned int ms)
173
{
174 175
    Q_UNUSED(ms);
    this->timeout = timeout;
176
}
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192

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

194
void UASView::setUASasActive(bool active)
pixhawk's avatar
pixhawk committed
195
{
196 197
    if (active)
    {
198 199 200 201 202 203
        UASManager::instance()->setActiveUAS(this->uas);
    }
}

void UASView::updateActiveUAS(UASInterface* uas, bool active)
{
204 205
    if (uas == this->uas)
    {
206
        this->isActive = active;
207 208 209 210 211 212 213 214
        if (active)
        {
            setStyleSheet("UASView { border-width: 3px}");
        }
        else
        {
            setStyleSheet(QString("UASView { border-color: %1}").arg(heartbeatColor.name()));
        }
215
    }
pixhawk's avatar
pixhawk committed
216 217
}

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

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

    m_ui->modeLabel->setText(status);
pixhawk's avatar
pixhawk committed
226 227
}

pixhawk's avatar
pixhawk committed
228 229
void UASView::mouseDoubleClickEvent (QMouseEvent * event)
{
230
    Q_UNUSED(event);
pixhawk's avatar
pixhawk committed
231 232 233 234 235
    UASManager::instance()->setActiveUAS(uas);
}

void UASView::receiveHeartbeat(UASInterface* uas)
{
236 237 238 239 240 241 242 243 244 245
    heartbeatColor = uas->getColor();
    QString colorstyle("QLabel { background-color: %1; }");
    m_ui->heartBeatLabel->setStyleSheet(colorstyle.arg(heartbeatColor.name()));

    // If we're returning from a disconnection, recolor things properly.
    if (disconnected)
    {
        updateActiveUAS(this->uas, this->isActive);
        disconnected = false;
    }
246 247 248 249 250
    timeout = false;
}

void UASView::updateName(const QString& name)
{
251
    if (uas) m_ui->nameLabel->setText(name);
pixhawk's avatar
pixhawk committed
252 253 254 255 256 257 258 259 260 261 262
}

/**
 * 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)
{
263 264
    if (uas == this->uas)
    {
pixhawk's avatar
pixhawk committed
265
        // Set matching icon
266 267
        switch (systemType)
        {
268
        case MAV_TYPE_GENERIC:
Don Gagne's avatar
Don Gagne committed
269
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Generic"));
pixhawk's avatar
pixhawk committed
270
            break;
271
        case MAV_TYPE_FIXED_WING:
Don Gagne's avatar
Don Gagne committed
272
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/FixedWing"));
pixhawk's avatar
pixhawk committed
273
            break;
274
        case MAV_TYPE_QUADROTOR:
Don Gagne's avatar
Don Gagne committed
275
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/QuadRotor"));
pixhawk's avatar
pixhawk committed
276
            break;
277
        case MAV_TYPE_COAXIAL:
Don Gagne's avatar
Don Gagne committed
278
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Coaxial"));
pixhawk's avatar
pixhawk committed
279
            break;
280
        case MAV_TYPE_HELICOPTER:
Don Gagne's avatar
Don Gagne committed
281
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Helicopter"));
pixhawk's avatar
pixhawk committed
282
            break;
283
        case MAV_TYPE_ANTENNA_TRACKER:
Don Gagne's avatar
Don Gagne committed
284
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Unknown"));
lm's avatar
lm committed
285
            break;
286
        case MAV_TYPE_GCS: {
287 288
                // A groundstation is a special system type, update widget
                QString result;
lm's avatar
lm committed
289
                m_ui->nameLabel->setText(tr("GCS ") + result.sprintf("%03d", uas->getUASID()));
290 291 292 293 294 295 296 297 298 299 300 301
                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();
Don Gagne's avatar
Don Gagne committed
302
                m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Groundstation"));
303 304
            }
            break;
305
        case MAV_TYPE_AIRSHIP:
Don Gagne's avatar
Don Gagne committed
306
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Airship"));
307 308
            break;
        case MAV_TYPE_FREE_BALLOON:
Don Gagne's avatar
Don Gagne committed
309
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/FreeBalloon"));
310 311
            break;
        case MAV_TYPE_ROCKET:
Don Gagne's avatar
Don Gagne committed
312
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Rocket"));
313 314
            break;
        case MAV_TYPE_GROUND_ROVER:
Don Gagne's avatar
Don Gagne committed
315
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/GroundRover"));
316 317
            break;
        case MAV_TYPE_SURFACE_BOAT:
Don Gagne's avatar
Don Gagne committed
318
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/SurfaceBoat"));
319 320
            break;
        case MAV_TYPE_SUBMARINE:
Don Gagne's avatar
Don Gagne committed
321
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Submarine"));
322 323
            break;
        case MAV_TYPE_HEXAROTOR:
Don Gagne's avatar
Don Gagne committed
324
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/HexaRotor"));
325 326
            break;
        case MAV_TYPE_OCTOROTOR:
Don Gagne's avatar
Don Gagne committed
327
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/OctoRotor"));
328 329
            break;
        case MAV_TYPE_TRICOPTER:
Don Gagne's avatar
Don Gagne committed
330
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/TriCopter"));
331 332
            break;
        case MAV_TYPE_FLAPPING_WING:
Don Gagne's avatar
Don Gagne committed
333
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/FlappingWing"));
334 335
            break;
        case MAV_TYPE_KITE:
Don Gagne's avatar
Don Gagne committed
336
            m_ui->typeLabel->setPixmap(QPixmap(":/res/mavs/Kite"));
337
            break;
pixhawk's avatar
pixhawk committed
338
        default:
Don Gagne's avatar
Don Gagne committed
339
            m_ui->typeLabel->setPixmap(QPixmap("://res/mavs/Unknown"));
pixhawk's avatar
pixhawk committed
340 341 342 343 344 345 346
            break;
        }
    }
}

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

355
void UASView::updateGlobalPosition(UASInterface* uas, double lon, double lat, double altAMSL, double altWGS84, quint64 usec)
pixhawk's avatar
pixhawk committed
356
{
357 358
    Q_UNUSED(uas);
    Q_UNUSED(usec);
359
    Q_UNUSED(altAMSL);
pixhawk's avatar
pixhawk committed
360 361
    this->lon = lon;
    this->lat = lat;
362
    this->alt = altWGS84;
363
    globalFrameKnown = true;
pixhawk's avatar
pixhawk committed
364 365 366 367
}

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

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

pixhawk's avatar
pixhawk committed
377 378
void UASView::setWaypoint(int uasId, int id, double x, double y, double z, double yaw, bool autocontinue, bool current)
{
379 380 381 382 383
    Q_UNUSED(x);
    Q_UNUSED(y);
    Q_UNUSED(z);
    Q_UNUSED(yaw);
    Q_UNUSED(autocontinue);
384 385 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 396
    if (uasId == this->uas->getUASID())
    {
pixhawk's avatar
pixhawk committed
397 398 399 400 401 402
        m_ui->waypointLabel->setText(tr("WP") + QString::number(id));
    }
}

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

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

void UASView::updateState(UASInterface* uas, QString uasState, QString stateDescription)
{
422 423
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
424 425 426 427 428 429 430
        state = uasState;
        stateDesc = stateDescription;
    }
}

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

437 438 439 440
/**
 * Right-clicking on the view provides a custom menu for interacting
 * with the UAS.
 */
441 442
void UASView::contextMenuEvent (QContextMenuEvent* event)
{
443
    QMenu menu(this);
lm's avatar
lm committed
444 445
    menu.addAction(selectAction);
    menu.addSeparator();
446
    menu.addAction(renameAction);
Don Gagne's avatar
Don Gagne committed
447 448 449
/*
    FIXME: The code below is incorrect. removeAction should only be available when link is
            disconnected. fSee Issue #1275
450 451
    if (timeout)
    {
452
        menu.addAction(removeAction);
453
    }
Don Gagne's avatar
Don Gagne committed
454
*/
455
    menu.addAction(hilAction);
456
    menu.addAction(selectAirframeAction);
457
    menu.addAction(setBatterySpecsAction);
458 459 460
    menu.exec(event->globalPos());
}

461 462
void UASView::setBatterySpecs()
{
463 464
    if (uas)
    {
465 466
        bool ok;
        QString newName = QInputDialog::getText(this, tr("Set Battery Specifications for %1").arg(uas->getUASName()),
467
                                                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,
468 469 470 471 472 473
                                                uas->getBatterySpecs(), &ok);

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

474 475
void UASView::rename()
{
476 477
    if (uas)
    {
478 479 480 481 482 483
        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);
484 485 486
    }
}

487 488
void UASView::selectAirframe()
{
489 490
    if (uas)
    {
491 492 493
        // Get list of airframes from UAS
        QStringList airframes;
        airframes << "Generic"
494 495 496 497 498 499 500 501
                << "Multiplex Easystar"
                << "Multiplex Twinstar"
                << "Multiplex Merlin"
                << "Pixhawk Cheetah"
                << "Mikrokopter"
                << "Reaper"
                << "Predator"
                << "Coaxial"
502
                << "Pteryx"
Lorenz Meier's avatar
Lorenz Meier committed
503 504 505 506 507
                << "Tricopter"
                << "Asctec Firefly"
                << "X8 Flying Wing"
                << "Viper 2.0 Flying Wing"
                << "Cam Flyer Q Flying Wing";
508 509 510 511

        bool ok;
        QString item = QInputDialog::getItem(this, tr("Select Airframe for %1").arg(uas->getUASName()),
                                             tr("Airframe"), airframes, uas->getAirframe(), false, &ok);
512 513
        if (ok && !item.isEmpty())
        {
514 515 516 517 518 519
            // Set this airframe as UAS airframe
            uas->setAirframe(airframes.indexOf(item));
        }
    }
}

520
void UASView::triggerUASDeletion()
521 522 523 524 525
{
    refreshTimer->stop();
    UASManager::instance()->removeUAS(uas);
}

pixhawk's avatar
pixhawk committed
526 527
void UASView::refresh()
{
528 529
    if (generalUpdateCount == 4)
    {
530
#if (QGC_EVENTLOOP_DEBUG)
531
        // qDebug() << "EVENTLOOP:" << __FILE__ << __LINE__;
532
#endif
533
        generalUpdateCount = 0;
534
        //// qDebug() << "UPDATING EVERYTHING";
535 536 537 538 539 540 541 542 543 544
        // 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
545 546 547 548 549 550 551
        // 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);
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

        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);
578
        }
pixhawk's avatar
pixhawk committed
579

580
        // Altitude
581 582
        if (groundDistance == 0 && alt != 0)
        {
583
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(alt, 6, 'f', 1, '0'));
584 585 586
        }
        else
        {
587
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(groundDistance, 6, 'f', 1, '0'));
588
        }
589

590
        // Speed
591 592
        QString speed("%1 m/s");
        m_ui->speedLabel->setText(speed.arg(totalSpeed, 4, 'f', 1, '0'));
pixhawk's avatar
pixhawk committed
593

594 595
        // Thrust
        m_ui->thrustBar->setValue(thrust * 100);
pixhawk's avatar
pixhawk committed
596

treymarc's avatar
treymarc committed
597 598 599 600 601 602 603 604 605 606 607
        // Time Elapsed
        //QDateTime time = MG::TIME::msecToQDateTime(uas->getUptime());

       quint64 filterTime = uas->getUptime() / 1000;
       int hours = static_cast<int>(filterTime / 3600);
       int min = static_cast<int>((filterTime - 3600 * hours) / 60);
       int sec = static_cast<int>(filterTime - 60 * min - 3600 * hours);
       QString timeText;
       timeText = timeText.sprintf("%02d:%02d:%02d", hours, min, sec);
       m_ui->timeElapsedLabel->setText(timeText);

608 609
        if(this->timeRemaining > 1 && this->timeRemaining < QGC::MAX_FLIGHT_TIME)
        {
610
            // Filter output to get a higher stability
611
            filterTime = static_cast<int>(this->timeRemaining);
treymarc's avatar
treymarc committed
612 613 614 615
            // filterTime = 0.8 * filterTime + 0.2 * static_cast<int>(this->timeRemaining);
            hours = static_cast<int>(filterTime / 3600);
            min = static_cast<int>((filterTime - 3600 * hours) / 60);
            sec = static_cast<int>(filterTime - 60 * min - 3600 * hours);
616 617 618

            timeText = timeText.sprintf("%02d:%02d:%02d", hours, min, sec);
            m_ui->timeRemainingLabel->setText(timeText);
619 620 621
        }
        else
        {
622
            m_ui->timeRemainingLabel->setText(tr("Calc.."));
623 624 625
        }


pixhawk's avatar
pixhawk committed
626
    }
627
    generalUpdateCount++;
pixhawk's avatar
pixhawk committed
628

629 630
    if (timeout)
    {
631
        // CRITICAL CONDITION, NO HEARTBEAT
632
        disconnected = true;
633

634
        QColor warnColor;
635 636
        if (iconIsRed)
        {
637
            warnColor = Qt::red;
638 639 640
        }
        else
        {
641
            warnColor = Qt::darkRed;
LM's avatar
LM committed
642
            refreshTimer->setInterval(errorUpdateInterval);
643
            refreshTimer->start();
644
        }
645 646
        QString style = QString("UASView {background-color: %1;}").arg(warnColor.name());
        this->setStyleSheet(style);
647
        iconIsRed = !iconIsRed;
648 649 650
    }
    else
    {
651 652
        // If we're not in low power mode, add the additional visual effect of
        // fading out the color of the heartbeat for this UAS.
653 654
        if (!lowPowerModeEnabled)
        {
655 656 657
            heartbeatColor = heartbeatColor.darker(110);
            QString colorstyle("QLabel {background-color: %1;}");
            m_ui->heartBeatLabel->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
LM's avatar
LM committed
658
            refreshTimer->setInterval(updateInterval);
659
            refreshTimer->start();
660
        }
661
    }
pixhawk's avatar
pixhawk committed
662 663 664 665 666
}

void UASView::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
667 668
    switch (e->type())
    {
pixhawk's avatar
pixhawk committed
669 670 671 672 673 674 675
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}
676

677
void UASView::paintEvent(QPaintEvent *event)
678
{
679
    Q_UNUSED(event);
680 681 682 683 684
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}