UASView.cc 22.8 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 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)));
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
    // Setup UAS selection
109
    connect(this, SIGNAL(clicked(bool)), this, SLOT(setUASasActive(bool)));
110

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

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

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

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

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

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

155 156 157 158 159 160 161
    // 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
162 163 164
    m_ui->killButton->hide();
    m_ui->shutdownButton->hide();

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

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

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

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

198
void UASView::setUASasActive(bool active)
pixhawk's avatar
pixhawk committed
199
{
200 201
    if (active)
    {
202 203 204 205 206 207
        UASManager::instance()->setActiveUAS(this->uas);
    }
}

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

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

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

    m_ui->modeLabel->setText(status);
pixhawk's avatar
pixhawk committed
230 231
}

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

void UASView::enterEvent(QEvent* event)
{
241 242
    if (event->type() == QEvent::MouseMove)
    {
243
        emit uasInFocus(uas);
244 245
        if (uas != UASManager::instance()->getActiveUAS())
        {
246 247 248
            grabMouse(QCursor(Qt::PointingHandCursor));
        }
    }
249

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

void UASView::leaveEvent(QEvent* event)
{
258 259
    if (event->type() == QEvent::MouseMove)
    {
260 261 262 263 264 265 266 267 268
        emit uasOutFocus(uas);
        releaseMouse();
    }
}

void UASView::showEvent(QShowEvent* event)
{
    // React only to internal (pre-display)
    // events
269
    Q_UNUSED(event);
270
    refreshTimer->start(updateInterval*10);
271 272 273 274 275 276 277
}

void UASView::hideEvent(QHideEvent* event)
{
    // React only to internal (pre-display)
    // events
    Q_UNUSED(event);
278
   // refreshTimer->stop();
pixhawk's avatar
pixhawk committed
279 280 281 282
}

void UASView::receiveHeartbeat(UASInterface* uas)
{
283 284 285 286 287 288 289 290 291 292
    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;
    }
293 294 295 296 297
    timeout = false;
}

void UASView::updateName(const QString& name)
{
298
    if (uas) m_ui->nameLabel->setText(name);
pixhawk's avatar
pixhawk committed
299 300 301 302 303 304 305 306 307 308 309
}

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

void UASView::updateLocalPosition(UASInterface* uas, double x, double y, double z, quint64 usec)
{
394
    Q_UNUSED(usec);
395 396 397 398
    Q_UNUSED(uas);
    this->x = x;
    this->y = y;
    this->z = z;
399
    localFrame = true;
pixhawk's avatar
pixhawk committed
400 401
}

402
void UASView::updateGlobalPosition(UASInterface* uas, double lon, double lat, double alt, quint64 usec)
pixhawk's avatar
pixhawk committed
403
{
404 405
    Q_UNUSED(uas);
    Q_UNUSED(usec);
pixhawk's avatar
pixhawk committed
406 407 408
    this->lon = lon;
    this->lat = lat;
    this->alt = alt;
409
    globalFrameKnown = true;
pixhawk's avatar
pixhawk committed
410 411 412 413
}

void UASView::updateSpeed(UASInterface*, double x, double y, double z, quint64 usec)
{
414
    Q_UNUSED(usec);
415
    totalSpeed = sqrt(x*x + y*y + z*z);
pixhawk's avatar
pixhawk committed
416 417
}

418 419 420 421 422
void UASView::currentWaypointUpdated(quint16 waypoint)
{
    m_ui->waypointLabel->setText(tr("WP") + QString::number(waypoint));
}

pixhawk's avatar
pixhawk committed
423 424
void UASView::setWaypoint(int uasId, int id, double x, double y, double z, double yaw, bool autocontinue, bool current)
{
425 426 427 428 429
    Q_UNUSED(x);
    Q_UNUSED(y);
    Q_UNUSED(z);
    Q_UNUSED(yaw);
    Q_UNUSED(autocontinue);
430 431 432 433
    if (uasId == this->uas->getUASID())
    {
        if (current)
        {
pixhawk's avatar
pixhawk committed
434 435 436 437 438 439 440
            m_ui->waypointLabel->setText(tr("WP") + QString::number(id));
        }
    }
}

void UASView::selectWaypoint(int uasId, int id)
{
441 442
    if (uasId == this->uas->getUASID())
    {
pixhawk's avatar
pixhawk committed
443 444 445 446 447 448
        m_ui->waypointLabel->setText(tr("WP") + QString::number(id));
    }
}

void UASView::updateThrust(UASInterface* uas, double thrust)
{
449 450
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
451
        this->thrust = thrust;
pixhawk's avatar
pixhawk committed
452 453 454
    }
}

dongfang's avatar
dongfang committed
455
void UASView::updateBattery(UASInterface* uas, double voltage, double current, double percent, int seconds)
pixhawk's avatar
pixhawk committed
456
{
457
    Q_UNUSED(voltage);
dongfang's avatar
dongfang committed
458
    Q_UNUSED(current);
459 460
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
461 462 463 464 465 466 467
        timeRemaining = seconds;
        chargeLevel = percent;
    }
}

void UASView::updateState(UASInterface* uas, QString uasState, QString stateDescription)
{
468 469
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
470 471 472 473 474 475 476
        state = uasState;
        stateDesc = stateDescription;
    }
}

void UASView::updateLoad(UASInterface* uas, double load)
{
477 478
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
479 480 481 482
        this->load = load;
    }
}

483 484
void UASView::contextMenuEvent (QContextMenuEvent* event)
{
485
    QMenu menu(this);
lm's avatar
lm committed
486 487
    menu.addAction(selectAction);
    menu.addSeparator();
488
    menu.addAction(renameAction);
489 490
    if (timeout)
    {
491
        menu.addAction(removeAction);
492
    }
493
    menu.addAction(hilAction);
494
    menu.addAction(selectAirframeAction);
495
    menu.addAction(setBatterySpecsAction);
496 497 498
    menu.exec(event->globalPos());
}

499 500
void UASView::setBatterySpecs()
{
501 502
    if (uas)
    {
503 504
        bool ok;
        QString newName = QInputDialog::getText(this, tr("Set Battery Specifications for %1").arg(uas->getUASName()),
505
                                                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,
506 507 508 509 510 511
                                                uas->getBatterySpecs(), &ok);

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

512 513
void UASView::rename()
{
514 515
    if (uas)
    {
516 517 518 519 520 521
        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);
522 523 524
    }
}

525 526
void UASView::selectAirframe()
{
527 528
    if (uas)
    {
529 530 531
        // Get list of airframes from UAS
        QStringList airframes;
        airframes << "Generic"
532 533 534 535 536 537 538 539
                << "Multiplex Easystar"
                << "Multiplex Twinstar"
                << "Multiplex Merlin"
                << "Pixhawk Cheetah"
                << "Mikrokopter"
                << "Reaper"
                << "Predator"
                << "Coaxial"
540
                << "Pteryx"
Lorenz Meier's avatar
Lorenz Meier committed
541 542 543 544 545
                << "Tricopter"
                << "Asctec Firefly"
                << "X8 Flying Wing"
                << "Viper 2.0 Flying Wing"
                << "Cam Flyer Q Flying Wing";
546 547 548 549

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

558 559 560 561 562
void UASView::showHILUi()
{
     MainWindow::instance()->showHILConfigurationWidget(uas);
}

563
void UASView::triggerUASDeletion()
564 565 566 567 568
{
    refreshTimer->stop();
    UASManager::instance()->removeUAS(uas);
}

pixhawk's avatar
pixhawk committed
569 570
void UASView::refresh()
{
571 572
    if (generalUpdateCount == 4)
    {
573
#if (QGC_EVENTLOOP_DEBUG)
574
        // qDebug() << "EVENTLOOP:" << __FILE__ << __LINE__;
575
#endif
576
        generalUpdateCount = 0;
577
        //// qDebug() << "UPDATING EVERYTHING";
578 579 580 581 582 583 584 585 586 587
        // 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
588 589 590 591 592 593 594
        // 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);
595
        }
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620

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

623
        // Altitude
624 625
        if (groundDistance == 0 && alt != 0)
        {
626
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(alt, 6, 'f', 1, '0'));
627 628 629
        }
        else
        {
630
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(groundDistance, 6, 'f', 1, '0'));
631
        }
632

633
        // Speed
634 635
        QString speed("%1 m/s");
        m_ui->speedLabel->setText(speed.arg(totalSpeed, 4, 'f', 1, '0'));
pixhawk's avatar
pixhawk committed
636

637 638
        // Thrust
        m_ui->thrustBar->setValue(thrust * 100);
pixhawk's avatar
pixhawk committed
639

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

        // 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
663 664 665 666
        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);
667
        m_ui->timeElapsedLabel->setText(timeText);
pixhawk's avatar
pixhawk committed
668
    }
669
    generalUpdateCount++;
pixhawk's avatar
pixhawk committed
670

671 672
    if (timeout)
    {
673
        // CRITICAL CONDITION, NO HEARTBEAT
674
        disconnected = true;
675

676
        QColor warnColor;
677 678
        if (iconIsRed)
        {
679
            warnColor = Qt::red;
680 681 682
        }
        else
        {
683
            warnColor = Qt::darkRed;
LM's avatar
LM committed
684
            refreshTimer->setInterval(errorUpdateInterval);
685
            refreshTimer->start();
686
        }
687 688
        QString style = QString("UASView {background-color: %1;}").arg(warnColor.name());
        this->setStyleSheet(style);
689
        iconIsRed = !iconIsRed;
690 691 692
    }
    else
    {
693 694
        // If we're not in low power mode, add the additional visual effect of
        // fading out the color of the heartbeat for this UAS.
695 696
        if (!lowPowerModeEnabled)
        {
697 698 699
            heartbeatColor = heartbeatColor.darker(110);
            QString colorstyle("QLabel {background-color: %1;}");
            m_ui->heartBeatLabel->setStyleSheet(colorstyle.arg(heartbeatColor.name()));
LM's avatar
LM committed
700
            refreshTimer->setInterval(updateInterval);
701
            refreshTimer->start();
702
        }
703
    }
pixhawk's avatar
pixhawk committed
704 705 706 707 708
}

void UASView::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
709 710
    switch (e->type())
    {
pixhawk's avatar
pixhawk committed
711 712 713 714 715 716 717
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}
718 719 720 721 722

/**
 * Implement paintEvent() so that stylesheets work for our custom widget.
 */
void UASView::paintEvent(QPaintEvent *)
723 724 725 726 727 728
{
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}