UASView.cc 23.7 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)));
dongfang's avatar
dongfang committed
89
    connect(uas, SIGNAL(batteryChanged(UASInterface*, double, double, double, int)), this, SLOT(updateBattery(UASInterface*, double, double, double, int)));
pixhawk's avatar
pixhawk committed
90 91 92 93 94 95
    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
}

void UASView::hideEvent(QHideEvent* event)
{
    // React only to internal (pre-display)
    // events
    Q_UNUSED(event);
293
   // 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
    }
}

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

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

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

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

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

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

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

535 536
void UASView::selectAirframe()
{
537 538
    if (uas)
    {
539 540 541
        // Get list of airframes from UAS
        QStringList airframes;
        airframes << "Generic"
542 543 544 545 546 547 548 549
                << "Multiplex Easystar"
                << "Multiplex Twinstar"
                << "Multiplex Merlin"
                << "Pixhawk Cheetah"
                << "Mikrokopter"
                << "Reaper"
                << "Predator"
                << "Coaxial"
550
                << "Pteryx"
Lorenz Meier's avatar
Lorenz Meier committed
551 552 553 554 555
                << "Tricopter"
                << "Asctec Firefly"
                << "X8 Flying Wing"
                << "Viper 2.0 Flying Wing"
                << "Cam Flyer Q Flying Wing";
556 557 558 559

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

568 569 570 571 572
void UASView::showHILUi()
{
     MainWindow::instance()->showHILConfigurationWidget(uas);
}

pixhawk's avatar
pixhawk committed
573 574
void UASView::refresh()
{
575
    //setUpdatesEnabled(false);
576 577
    //setUpdatesEnabled(true);
    //repaint();
578
    //qDebug() << "UPDATING UAS WIDGET!" << uas->getUASName();
579 580


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

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

633
        // Altitude
634 635
        if (groundDistance == 0 && alt != 0)
        {
636
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(alt, 6, 'f', 1, '0'));
637 638 639
        }
        else
        {
640
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(groundDistance, 6, 'f', 1, '0'));
641
        }
642

643
        // Speed
644 645
        QString speed("%1 m/s");
        m_ui->speedLabel->setText(speed.arg(totalSpeed, 4, 'f', 1, '0'));
pixhawk's avatar
pixhawk committed
646

647 648
        // Thrust
        m_ui->thrustBar->setValue(thrust * 100);
pixhawk's avatar
pixhawk committed
649

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

        // 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
673 674 675 676
        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);
677
        m_ui->timeElapsedLabel->setText(timeText);
pixhawk's avatar
pixhawk committed
678
    }
679
    generalUpdateCount++;
pixhawk's avatar
pixhawk committed
680

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

683 684
    if (timeout)
    {
685 686
        // CRITICAL CONDITION, NO HEARTBEAT

687
        QString borderColor = "#FFFF00";
688 689
        if (isActive)
        {
690 691 692
            borderColor = "#FA4A4F";
        }

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

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

            //m_ui->heartbeatIcon->setAutoFillBackground(true);
            m_ui->heartbeatIcon->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
LM's avatar
LM committed
722
            refreshTimer->setInterval(updateInterval);
723
            refreshTimer->start();
724
        }
725
    }
726
    //setUpdatesEnabled(true);
727 728

    //setUpdatesEnabled(false);
pixhawk's avatar
pixhawk committed
729 730 731 732 733
}

void UASView::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
734 735
    switch (e->type())
    {
pixhawk's avatar
pixhawk committed
736 737 738 739 740 741 742
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}