UASView.cc 22.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 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(hilAction, SIGNAL(triggered(bool)), this, SLOT(showHILUi()));
122
    connect(selectAirframeAction, SIGNAL(triggered()), this, SLOT(selectAirframe()));
123
    connect(setBatterySpecsAction, SIGNAL(triggered()), this, SLOT(setBatterySpecs()));
124 125 126

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

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

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

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

152 153 154 155 156 157 158
    // 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
159 160 161
    m_ui->killButton->hide();
    m_ui->shutdownButton->hide();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

treymarc's avatar
treymarc committed
638 639 640 641 642 643 644 645 646 647 648
        // 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);

649 650
        if(this->timeRemaining > 1 && this->timeRemaining < QGC::MAX_FLIGHT_TIME)
        {
651
            // Filter output to get a higher stability
652
            filterTime = static_cast<int>(this->timeRemaining);
treymarc's avatar
treymarc committed
653 654 655 656
            // 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);
657 658 659

            timeText = timeText.sprintf("%02d:%02d:%02d", hours, min, sec);
            m_ui->timeRemainingLabel->setText(timeText);
660 661 662
        }
        else
        {
663
            m_ui->timeRemainingLabel->setText(tr("Calc.."));
664 665 666
        }


pixhawk's avatar
pixhawk committed
667
    }
668
    generalUpdateCount++;
pixhawk's avatar
pixhawk committed
669

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

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

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

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