UASView.cc 23.5 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
        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),
68
        globalFrameKnown(false),
69 70 71
        removeAction(new QAction("Delete this system", this)),
        renameAction(new QAction("Rename..", this)),
        selectAction(new QAction("Control this system", this )),
72
        hilAction(new QAction("HIL - Hardware in the Loop", 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

pixhawk's avatar
pixhawk committed
85
    m_ui->setupUi(this);
86

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

pixhawk's avatar
pixhawk committed
109 110 111 112
    // 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()));
113
    connect(m_ui->landButton, SIGNAL(clicked()), uas, SLOT(land()));
pixhawk's avatar
pixhawk committed
114
    connect(m_ui->abortButton, SIGNAL(clicked()), uas, SLOT(emergencySTOP()));
pixhawk's avatar
pixhawk committed
115 116
    connect(m_ui->killButton, SIGNAL(clicked()), uas, SLOT(emergencyKILL()));
    connect(m_ui->shutdownButton, SIGNAL(clicked()), uas, SLOT(shutdown()));
117 118 119

    // Allow to delete this widget
    connect(removeAction, SIGNAL(triggered()), this, SLOT(deleteLater()));
120
    connect(renameAction, SIGNAL(triggered()), this, SLOT(rename()));
121
    connect(selectAction, SIGNAL(triggered()), uas, SLOT(setSelected()));
122
    connect(hilAction, SIGNAL(triggered(bool)), this, SLOT(showHILUi()));
123
    connect(selectAirframeAction, SIGNAL(triggered()), this, SLOT(selectAirframe()));
124
    connect(setBatterySpecsAction, SIGNAL(triggered()), this, SLOT(setBatterySpecs()));
125
    connect(uas, SIGNAL(systemRemoved()), this, SLOT(deleteLater()));
126 127 128

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

pixhawk's avatar
pixhawk committed
130
    // Set static values
131

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

142
    setBackgroundColor();
143

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

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

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

UASView::~UASView()
{
    delete m_ui;
169 170 171
    delete removeAction;
    delete renameAction;
    delete selectAction;
pixhawk's avatar
pixhawk committed
172 173
}

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

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

196 197 198 199 200 201 202 203 204 205
/**
 * 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";
206 207
    if (isActive)
    {
208 209
        borderColor = "#FA4A4F";
        uasColor = uasColor.darker(475);
210 211 212
    }
    else
    {
213 214
        uasColor = uasColor.darker(675);
    }
215
    colorstyle = colorstyle.sprintf("QGroupBox { border-radius: 12px; padding: 0px; margin: 0px; background-color: #%02X%02X%02X; border: 2px solid %s; }",
216 217 218 219 220
                                    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
221
{
222 223
    if (active)
    {
224 225 226 227 228 229
        UASManager::instance()->setActiveUAS(this->uas);
    }
}

void UASView::updateActiveUAS(UASInterface* uas, bool active)
{
230 231
    if (uas == this->uas)
    {
232 233 234
        this->isActive = active;
        setBackgroundColor();
    }
pixhawk's avatar
pixhawk committed
235 236
}

pixhawk's avatar
pixhawk committed
237 238
void UASView::updateMode(int sysId, QString status, QString description)
{
239
    Q_UNUSED(description);
240 241

    //int aa=this->uas->getUASID();
pixhawk's avatar
pixhawk committed
242
    if (sysId == this->uas->getUASID()) m_ui->modeLabel->setText(status);
243 244

    m_ui->modeLabel->setText(status);
pixhawk's avatar
pixhawk committed
245 246
}

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

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

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

void UASView::leaveEvent(QEvent* event)
{
273 274
    if (event->type() == QEvent::MouseMove)
    {
275 276 277 278 279 280 281 282 283
        emit uasOutFocus(uas);
        releaseMouse();
    }
}

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

void UASView::hideEvent(QHideEvent* event)
{
    // React only to internal (pre-display)
    // events
    Q_UNUSED(event);
    refreshTimer->stop();
pixhawk's avatar
pixhawk committed
294 295 296 297
}

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

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

/**
 * 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)
{
320 321
    if (uas == this->uas)
    {
pixhawk's avatar
pixhawk committed
322
        // Set matching icon
323 324
        switch (systemType)
        {
325
        case MAV_TYPE_GENERIC:
326
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/generic.svg"));
pixhawk's avatar
pixhawk committed
327
            break;
328
        case MAV_TYPE_FIXED_WING:
329
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/fixed-wing.svg"));
pixhawk's avatar
pixhawk committed
330
            break;
331
        case MAV_TYPE_QUADROTOR:
332
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/quadrotor.svg"));
pixhawk's avatar
pixhawk committed
333
            break;
334
        case MAV_TYPE_COAXIAL:
335
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/coaxial.svg"));
pixhawk's avatar
pixhawk committed
336
            break;
337
        case MAV_TYPE_HELICOPTER:
338
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/helicopter.svg"));
pixhawk's avatar
pixhawk committed
339
            break;
340
        case MAV_TYPE_ANTENNA_TRACKER:
341
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/unknown.svg"));
lm's avatar
lm committed
342
            break;
343
        case MAV_TYPE_GCS: {
344 345
                // A groundstation is a special system type, update widget
                QString result;
lm's avatar
lm committed
346
                m_ui->nameLabel->setText(tr("GCS ") + result.sprintf("%03d", uas->getUASID()));
347 348 349 350 351 352 353 354 355 356 357 358
                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();
359
                m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/groundstation.svg"));
360 361
            }
            break;
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
        case MAV_TYPE_AIRSHIP:
            m_ui->typeButton->setIcon(QIcon(":files/images/mavs/airship.svg"));
            break;
        case MAV_TYPE_FREE_BALLOON:
            m_ui->typeButton->setIcon(QIcon(":files/images/mavs/free-balloon.svg"));
            break;
        case MAV_TYPE_ROCKET:
            m_ui->typeButton->setIcon(QIcon(":files/images/mavs/rocket.svg"));
            break;
        case MAV_TYPE_GROUND_ROVER:
            m_ui->typeButton->setIcon(QIcon(":files/images/mavs/ground-rover.svg"));
            break;
        case MAV_TYPE_SURFACE_BOAT:
            m_ui->typeButton->setIcon(QIcon(":files/images/mavs/surface-boat.svg"));
            break;
        case MAV_TYPE_SUBMARINE:
            m_ui->typeButton->setIcon(QIcon(":files/images/mavs/submarine.svg"));
            break;
        case MAV_TYPE_HEXAROTOR:
            m_ui->typeButton->setIcon(QIcon(":files/images/mavs/hexarotor.svg"));
            break;
        case MAV_TYPE_OCTOROTOR:
            m_ui->typeButton->setIcon(QIcon(":files/images/mavs/octorotor.svg"));
            break;
        case MAV_TYPE_TRICOPTER:
            m_ui->typeButton->setIcon(QIcon(":files/images/mavs/tricopter.svg"));
            break;
        case MAV_TYPE_FLAPPING_WING:
            m_ui->typeButton->setIcon(QIcon(":files/images/mavs/flapping-wing.svg"));
            break;
        case MAV_TYPE_KITE:
            m_ui->typeButton->setIcon(QIcon(":files/images/mavs/kite.svg"));
            break;
pixhawk's avatar
pixhawk committed
395
        default:
396
            m_ui->typeButton->setIcon(QIcon(":/files/images/mavs/unknown.svg"));
pixhawk's avatar
pixhawk committed
397 398 399 400 401 402 403
            break;
        }
    }
}

void UASView::updateLocalPosition(UASInterface* uas, double x, double y, double z, quint64 usec)
{
404
    Q_UNUSED(usec);
405 406 407 408
    Q_UNUSED(uas);
    this->x = x;
    this->y = y;
    this->z = z;
409
    localFrame = true;
pixhawk's avatar
pixhawk committed
410 411
}

412
void UASView::updateGlobalPosition(UASInterface* uas, double lon, double lat, double alt, quint64 usec)
pixhawk's avatar
pixhawk committed
413
{
414 415
    Q_UNUSED(uas);
    Q_UNUSED(usec);
pixhawk's avatar
pixhawk committed
416 417 418
    this->lon = lon;
    this->lat = lat;
    this->alt = alt;
419
    globalFrameKnown = true;
pixhawk's avatar
pixhawk committed
420 421 422 423
}

void UASView::updateSpeed(UASInterface*, double x, double y, double z, quint64 usec)
{
424
    Q_UNUSED(usec);
425
    totalSpeed = sqrt(x*x + y*y + z*z);
pixhawk's avatar
pixhawk committed
426 427
}

428 429 430 431 432
void UASView::currentWaypointUpdated(quint16 waypoint)
{
    m_ui->waypointLabel->setText(tr("WP") + QString::number(waypoint));
}

pixhawk's avatar
pixhawk committed
433 434
void UASView::setWaypoint(int uasId, int id, double x, double y, double z, double yaw, bool autocontinue, bool current)
{
435 436 437 438 439
    Q_UNUSED(x);
    Q_UNUSED(y);
    Q_UNUSED(z);
    Q_UNUSED(yaw);
    Q_UNUSED(autocontinue);
440 441 442 443
    if (uasId == this->uas->getUASID())
    {
        if (current)
        {
pixhawk's avatar
pixhawk committed
444 445 446 447 448 449 450
            m_ui->waypointLabel->setText(tr("WP") + QString::number(id));
        }
    }
}

void UASView::selectWaypoint(int uasId, int id)
{
451 452
    if (uasId == this->uas->getUASID())
    {
pixhawk's avatar
pixhawk committed
453 454 455 456 457 458
        m_ui->waypointLabel->setText(tr("WP") + QString::number(id));
    }
}

void UASView::updateThrust(UASInterface* uas, double thrust)
{
459 460
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
461
        this->thrust = thrust;
pixhawk's avatar
pixhawk committed
462 463 464 465 466
    }
}

void UASView::updateBattery(UASInterface* uas, double voltage, double percent, int seconds)
{
467
    Q_UNUSED(voltage);
468 469
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
470 471 472 473 474 475 476
        timeRemaining = seconds;
        chargeLevel = percent;
    }
}

void UASView::updateState(UASInterface* uas, QString uasState, QString stateDescription)
{
477 478
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
479 480 481 482 483 484 485
        state = uasState;
        stateDesc = stateDescription;
    }
}

void UASView::updateLoad(UASInterface* uas, double load)
{
486 487
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
488 489 490 491
        this->load = load;
    }
}

492 493
void UASView::contextMenuEvent (QContextMenuEvent* event)
{
494
    QMenu menu(this);
lm's avatar
lm committed
495 496
    menu.addAction(selectAction);
    menu.addSeparator();
497
    menu.addAction(renameAction);
498 499
    if (timeout)
    {
500
        menu.addAction(removeAction);
501
    }
502
    menu.addAction(hilAction);
503
    menu.addAction(selectAirframeAction);
504
    menu.addAction(setBatterySpecsAction);
505 506 507
    menu.exec(event->globalPos());
}

508 509
void UASView::setBatterySpecs()
{
510 511
    if (uas)
    {
512 513
        bool ok;
        QString newName = QInputDialog::getText(this, tr("Set Battery Specifications for %1").arg(uas->getUASName()),
514
                                                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,
515 516 517 518 519 520
                                                uas->getBatterySpecs(), &ok);

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

521 522
void UASView::rename()
{
523 524
    if (uas)
    {
525 526 527 528 529 530
        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);
531 532 533
    }
}

534 535
void UASView::selectAirframe()
{
536 537
    if (uas)
    {
538 539 540
        // Get list of airframes from UAS
        QStringList airframes;
        airframes << "Generic"
541 542 543 544 545 546 547 548
                << "Multiplex Easystar"
                << "Multiplex Twinstar"
                << "Multiplex Merlin"
                << "Pixhawk Cheetah"
                << "Mikrokopter"
                << "Reaper"
                << "Predator"
                << "Coaxial"
549 550
                << "Pteryx"
                << "Asctec Firefly";
551 552 553 554

        bool ok;
        QString item = QInputDialog::getItem(this, tr("Select Airframe for %1").arg(uas->getUASName()),
                                             tr("Airframe"), airframes, uas->getAirframe(), false, &ok);
555 556
        if (ok && !item.isEmpty())
        {
557 558 559 560 561 562
            // Set this airframe as UAS airframe
            uas->setAirframe(airframes.indexOf(item));
        }
    }
}

563 564 565 566 567
void UASView::showHILUi()
{
     MainWindow::instance()->showHILConfigurationWidget(uas);
}

pixhawk's avatar
pixhawk committed
568 569
void UASView::refresh()
{
570
    //setUpdatesEnabled(false);
571 572
    //setUpdatesEnabled(true);
    //repaint();
573
    //qDebug() << "UPDATING UAS WIDGET!" << uas->getUASName();
574 575


576 577
    if (generalUpdateCount == 4)
    {
578
#if (QGC_EVENTLOOP_DEBUG)
579
        // qDebug() << "EVENTLOOP:" << __FILE__ << __LINE__;
580
#endif
581
        generalUpdateCount = 0;
582
        //// qDebug() << "UPDATING EVERYTHING";
583 584 585 586 587 588 589 590 591 592
        // 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
593 594 595 596 597 598 599
        // 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);
600
        }
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625

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

628
        // Altitude
629 630
        if (groundDistance == 0 && alt != 0)
        {
631
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(alt, 6, 'f', 1, '0'));
632 633 634
        }
        else
        {
635
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(groundDistance, 6, 'f', 1, '0'));
636
        }
637

638
        // Speed
639 640
        QString speed("%1 m/s");
        m_ui->speedLabel->setText(speed.arg(totalSpeed, 4, 'f', 1, '0'));
pixhawk's avatar
pixhawk committed
641

642 643
        // Thrust
        m_ui->thrustBar->setValue(thrust * 100);
pixhawk's avatar
pixhawk committed
644

645 646
        if(this->timeRemaining > 1 && this->timeRemaining < QGC::MAX_FLIGHT_TIME)
        {
647
            // Filter output to get a higher stability
648
            filterTime = static_cast<int>(this->timeRemaining);
649 650 651 652 653 654 655 656
            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);
657 658 659
        }
        else
        {
660
            m_ui->timeRemainingLabel->setText(tr("Calc.."));
661 662 663 664 665 666 667
        }

        // 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
668 669 670 671
        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);
672
        m_ui->timeElapsedLabel->setText(timeText);
pixhawk's avatar
pixhawk committed
673
    }
674
    generalUpdateCount++;
pixhawk's avatar
pixhawk committed
675

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

678 679
    if (timeout)
    {
680 681
        // CRITICAL CONDITION, NO HEARTBEAT

682
        QString borderColor = "#FFFF00";
683 684
        if (isActive)
        {
685 686 687
            borderColor = "#FA4A4F";
        }

688 689
        if (iconIsRed)
        {
690 691
            QColor warnColor(Qt::red);
            m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(warnColor.name()));
692
            QString style = QString("QGroupBox { border-radius: 12px; padding: 0px; margin: 0px; border: 2px solid %1; background-color: %2; }").arg(borderColor, warnColor.name());
693
            m_ui->uasViewFrame->setStyleSheet(style);
694 695 696
        }
        else
        {
697 698
            QColor warnColor(Qt::black);
            m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(warnColor.name()));
699
            QString style = QString("QGroupBox { border-radius: 12px; padding: 0px; margin: 0px; border: 2px solid %1; background-color: %2; }").arg(borderColor, warnColor.name());
700
            m_ui->uasViewFrame->setStyleSheet(style);
LM's avatar
LM committed
701 702

            refreshTimer->setInterval(errorUpdateInterval);
703
            refreshTimer->start();
704 705
        }
        iconIsRed = !iconIsRed;
706 707 708
    }
    else
    {
709 710 711 712
        if (!lowPowerModeEnabled)
        {
            // Fade heartbeat icon
            // Make color darker
LM's avatar
LM committed
713
            heartbeatColor = heartbeatColor.darker(210);
714 715 716

            //m_ui->heartbeatIcon->setAutoFillBackground(true);
            m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
LM's avatar
LM committed
717
            refreshTimer->setInterval(updateInterval);
718
            refreshTimer->start();
719
        }
720
    }
721
    //setUpdatesEnabled(true);
722 723

    //setUpdatesEnabled(false);
pixhawk's avatar
pixhawk committed
724 725 726 727 728
}

void UASView::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
729 730
    switch (e->type())
    {
pixhawk's avatar
pixhawk committed
731 732 733 734 735 736 737
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}