UASView.cc 21.6 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4 5 6 7 8 9 10 11
/*=====================================================================
PIXHAWK Micro Air Vehicle Flying Robotics Toolkit

(c) 2009, 2010 PIXHAWK PROJECT  <http://pixhawk.ethz.ch>

This file is part of the PIXHAWK project

    PIXHAWK is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
12

pixhawk's avatar
pixhawk committed
13 14 15 16
    PIXHAWK is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
17

pixhawk's avatar
pixhawk committed
18 19
    You should have received a copy of the GNU General Public License
    along with PIXHAWK. If not, see <http://www.gnu.org/licenses/>.
20

pixhawk's avatar
pixhawk committed
21 22 23 24
======================================================================*/

/**
 * @file
pixhawk's avatar
pixhawk committed
25
 *   @brief Implementation of one airstrip
pixhawk's avatar
pixhawk committed
26 27 28 29 30 31 32 33
 *
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *
 */

#include <cmath>
#include <QDateTime>
#include <QDebug>
34
#include <QMenu>
35
#include <QInputDialog>
pixhawk's avatar
pixhawk committed
36

37
#include "QGC.h"
38
#include "MultiVehicleManager.h"
pixhawk's avatar
pixhawk committed
39
#include "UASView.h"
40
#include "UASWaypointManager.h"
41
#include "MainWindow.h"
pixhawk's avatar
pixhawk committed
42
#include "ui_UASView.h"
dogmaphobic's avatar
dogmaphobic committed
43 44

#ifndef __mobile__
45
#include <QGCHilFlightGearConfiguration.h>
dogmaphobic's avatar
dogmaphobic committed
46
#endif
pixhawk's avatar
pixhawk committed
47

48
UASView::UASView(Vehicle* vehicle, QWidget *parent) :
49
    QWidget(parent),
50 51
    vehicle(vehicle),
    uas(vehicle->uas()),
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 80 81 82 83
    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)
84
{
85
    m_ui->setupUi(this);
86
    setToolTip(""); // Make sure the QGroupBox's tooltip doesn't seep through.
87

88 89 90
    // FIXME XXX
    lowPowerModeEnabled = MainWindow::instance()->lowPowerModeEnabled();

lm's avatar
lm committed
91
    hilAction->setCheckable(true);
92

pixhawk's avatar
pixhawk committed
93
    // Setup communication
pixhawk's avatar
pixhawk committed
94
    //connect(uas, SIGNAL(valueChanged(int,QString,double,quint64)), this, SLOT(receiveValue(int,QString,double,quint64)));
dongfang's avatar
dongfang committed
95
    connect(uas, SIGNAL(batteryChanged(UASInterface*, double, double, double, int)), this, SLOT(updateBattery(UASInterface*, double, double, double, int)));
pixhawk's avatar
pixhawk committed
96 97 98
    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)));
99
    connect(uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,double,quint64)), this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,double,quint64)));
100
    connect(uas, SIGNAL(velocityChanged_NED(UASInterface*,double,double,double,quint64)), this, SLOT(updateSpeed(UASInterface*,double,double,double,quint64)));
pixhawk's avatar
pixhawk committed
101
    connect(uas, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(updateState(UASInterface*,QString,QString)));
pixhawk's avatar
pixhawk committed
102
    connect(uas, SIGNAL(modeChanged(int,QString,QString)), this, SLOT(updateMode(int,QString,QString)));
pixhawk's avatar
pixhawk committed
103
    connect(uas, SIGNAL(loadChanged(UASInterface*, double)), this, SLOT(updateLoad(UASInterface*, double)));
104
    connect(uas, SIGNAL(heartbeatTimeout(bool, unsigned int)), this, SLOT(heartbeatTimeout(bool, unsigned int)));
pixhawk's avatar
pixhawk committed
105
    connect(uas, SIGNAL(waypointSelected(int,int)), this, SLOT(selectWaypoint(int,int)));
pixhawk's avatar
pixhawk committed
106
    connect(uas->getWaypointManager(), SIGNAL(currentWaypointChanged(quint16)), this, SLOT(currentWaypointUpdated(quint16)));
pixhawk's avatar
pixhawk committed
107
    connect(uas, SIGNAL(systemTypeSet(UASInterface*,uint)), this, SLOT(setSystemType(UASInterface*,uint)));
108 109 110
    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)));

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

122
    // Allow deleting this widget
123
    connect(renameAction, SIGNAL(triggered()), this, SLOT(rename()));
124
    connect(selectAction, &QAction::triggered, this, &UASView::_activateVehicle);
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
    // 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()));
159
    _activeVehicleChanged(vehicle);
160 161

    // 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 177 178 179 180
void UASView::_activateVehicle(void)
{
    MultiVehicleManager::instance()->setActiveVehicle(vehicle);
}

181
void UASView::heartbeatTimeout(bool timeout, unsigned int ms)
182
{
183 184
    Q_UNUSED(ms);
    this->timeout = timeout;
185
}
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201

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

203
void UASView::setUASasActive(bool active)
pixhawk's avatar
pixhawk committed
204
{
205 206
    if (active)
    {
207
        MultiVehicleManager::instance()->setActiveVehicle(vehicle);
208 209 210
    }
}

211
void UASView::_activeVehicleChanged(Vehicle* vehicle)
212
{
213 214 215 216 217 218 219 220
    bool active = false;
    
    if (vehicle) {
        active = vehicle->uas() == this->uas;
    }
    
    this->isActive = active;
    if (isActive)
221
    {
222 223 224 225 226
        setStyleSheet("UASView { border-width: 3px}");
    }
    else
    {
        setStyleSheet(QString("UASView { border-color: %1}").arg(heartbeatColor.name()));
227
    }
pixhawk's avatar
pixhawk committed
228 229
}

pixhawk's avatar
pixhawk committed
230 231
void UASView::updateMode(int sysId, QString status, QString description)
{
232
    Q_UNUSED(description);
233 234

    //int aa=this->uas->getUASID();
pixhawk's avatar
pixhawk committed
235
    if (sysId == this->uas->getUASID()) m_ui->modeLabel->setText(status);
236 237

    m_ui->modeLabel->setText(status);
pixhawk's avatar
pixhawk committed
238 239
}

pixhawk's avatar
pixhawk committed
240 241
void UASView::mouseDoubleClickEvent (QMouseEvent * event)
{
242
    Q_UNUSED(event);
243
    MultiVehicleManager::instance()->setActiveVehicle(vehicle);
pixhawk's avatar
pixhawk committed
244 245 246 247
}

void UASView::receiveHeartbeat(UASInterface* uas)
{
248 249 250 251 252 253 254
    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)
    {
255
        _activeVehicleChanged(vehicle);
256 257
        disconnected = false;
    }
258 259 260 261 262
    timeout = false;
}

void UASView::updateName(const QString& name)
{
263
    if (uas) m_ui->nameLabel->setText(name);
pixhawk's avatar
pixhawk committed
264 265 266 267 268 269 270 271 272 273 274
}

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

void UASView::updateLocalPosition(UASInterface* uas, double x, double y, double z, quint64 usec)
{
359
    Q_UNUSED(usec);
360 361 362 363
    Q_UNUSED(uas);
    this->x = x;
    this->y = y;
    this->z = z;
364
    localFrame = true;
pixhawk's avatar
pixhawk committed
365 366
}

367
void UASView::updateGlobalPosition(UASInterface* uas, double lat, double lon, double altAMSL, double altWGS84, quint64 usec)
pixhawk's avatar
pixhawk committed
368
{
369 370
    Q_UNUSED(uas);
    Q_UNUSED(usec);
371
    Q_UNUSED(altAMSL);
pixhawk's avatar
pixhawk committed
372 373
    this->lon = lon;
    this->lat = lat;
374
    this->alt = altWGS84;
375
    globalFrameKnown = true;
pixhawk's avatar
pixhawk committed
376 377 378 379
}

void UASView::updateSpeed(UASInterface*, double x, double y, double z, quint64 usec)
{
380
    Q_UNUSED(usec);
381
    totalSpeed = sqrt(x*x + y*y + z*z);
pixhawk's avatar
pixhawk committed
382 383
}

384 385 386 387 388
void UASView::currentWaypointUpdated(quint16 waypoint)
{
    m_ui->waypointLabel->setText(tr("WP") + QString::number(waypoint));
}

pixhawk's avatar
pixhawk committed
389 390
void UASView::setWaypoint(int uasId, int id, double x, double y, double z, double yaw, bool autocontinue, bool current)
{
391 392 393 394 395
    Q_UNUSED(x);
    Q_UNUSED(y);
    Q_UNUSED(z);
    Q_UNUSED(yaw);
    Q_UNUSED(autocontinue);
396 397 398 399
    if (uasId == this->uas->getUASID())
    {
        if (current)
        {
pixhawk's avatar
pixhawk committed
400 401 402 403 404 405 406
            m_ui->waypointLabel->setText(tr("WP") + QString::number(id));
        }
    }
}

void UASView::selectWaypoint(int uasId, int id)
{
407 408
    if (uasId == this->uas->getUASID())
    {
pixhawk's avatar
pixhawk committed
409 410 411 412 413 414
        m_ui->waypointLabel->setText(tr("WP") + QString::number(id));
    }
}

void UASView::updateThrust(UASInterface* uas, double thrust)
{
415 416
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
417
        this->thrust = thrust;
pixhawk's avatar
pixhawk committed
418 419 420
    }
}

dongfang's avatar
dongfang committed
421
void UASView::updateBattery(UASInterface* uas, double voltage, double current, double percent, int seconds)
pixhawk's avatar
pixhawk committed
422
{
423
    Q_UNUSED(voltage);
dongfang's avatar
dongfang committed
424
    Q_UNUSED(current);
425 426
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
427 428 429 430 431 432 433
        timeRemaining = seconds;
        chargeLevel = percent;
    }
}

void UASView::updateState(UASInterface* uas, QString uasState, QString stateDescription)
{
434 435
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
436 437 438 439 440 441 442
        state = uasState;
        stateDesc = stateDescription;
    }
}

void UASView::updateLoad(UASInterface* uas, double load)
{
443 444
    if (this->uas == uas)
    {
pixhawk's avatar
pixhawk committed
445 446 447 448
        this->load = load;
    }
}

449 450 451 452
/**
 * Right-clicking on the view provides a custom menu for interacting
 * with the UAS.
 */
453 454
void UASView::contextMenuEvent (QContextMenuEvent* event)
{
455
    QMenu menu(this);
lm's avatar
lm committed
456 457
    menu.addAction(selectAction);
    menu.addSeparator();
458
    menu.addAction(renameAction);
Don Gagne's avatar
Don Gagne committed
459 460 461
/*
    FIXME: The code below is incorrect. removeAction should only be available when link is
            disconnected. fSee Issue #1275
462 463
    if (timeout)
    {
464
        menu.addAction(removeAction);
465
    }
Don Gagne's avatar
Don Gagne committed
466
*/
467
    menu.addAction(hilAction);
468
    menu.addAction(selectAirframeAction);
469
    menu.addAction(setBatterySpecsAction);
470 471 472
    menu.exec(event->globalPos());
}

473 474
void UASView::setBatterySpecs()
{
475 476
    if (uas)
    {
477 478
        bool ok;
        QString newName = QInputDialog::getText(this, tr("Set Battery Specifications for %1").arg(uas->getUASName()),
479
                                                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,
480 481 482 483 484 485
                                                uas->getBatterySpecs(), &ok);

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

486 487
void UASView::rename()
{
488 489
    if (uas)
    {
490 491 492 493 494 495
        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);
496 497 498
    }
}

499 500
void UASView::selectAirframe()
{
501 502
    if (uas)
    {
503 504 505
        // Get list of airframes from UAS
        QStringList airframes;
        airframes << "Generic"
506 507 508 509 510 511 512 513
                << "Multiplex Easystar"
                << "Multiplex Twinstar"
                << "Multiplex Merlin"
                << "Pixhawk Cheetah"
                << "Mikrokopter"
                << "Reaper"
                << "Predator"
                << "Coaxial"
514
                << "Pteryx"
Lorenz Meier's avatar
Lorenz Meier committed
515 516 517 518 519
                << "Tricopter"
                << "Asctec Firefly"
                << "X8 Flying Wing"
                << "Viper 2.0 Flying Wing"
                << "Cam Flyer Q Flying Wing";
520 521 522 523

        bool ok;
        QString item = QInputDialog::getItem(this, tr("Select Airframe for %1").arg(uas->getUASName()),
                                             tr("Airframe"), airframes, uas->getAirframe(), false, &ok);
524 525
        if (ok && !item.isEmpty())
        {
526 527 528 529 530 531
            // Set this airframe as UAS airframe
            uas->setAirframe(airframes.indexOf(item));
        }
    }
}

pixhawk's avatar
pixhawk committed
532 533
void UASView::refresh()
{
534 535
    if (generalUpdateCount == 4)
    {
536
#if (QGC_EVENTLOOP_DEBUG)
537
        // qDebug() << "EVENTLOOP:" << __FILE__ << __LINE__;
538
#endif
539
        generalUpdateCount = 0;
540
        //// qDebug() << "UPDATING EVERYTHING";
541 542 543 544 545 546 547 548 549 550
        // 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
551 552 553 554 555 556 557
        // 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);
558
        }
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581

        if (globalFrameKnown)
        {
            QString globalPosition;
            QString latIndicator;
            if (lat > 0)
            {
                latIndicator = "N";
            }
            else
            {
                latIndicator = "S";
            }
            QString lonIndicator;
            if (lon > 0)
            {
                lonIndicator = "E";
            }
            else
            {
                lonIndicator = "W";
            }

582
            globalPosition = globalPosition.sprintf("%6.2f%s %6.2f%s %6.1f m", fabs(lon), lonIndicator.toStdString().c_str(), fabs(lat), latIndicator.toStdString().c_str(), alt);
583
            m_ui->positionLabel->setText(globalPosition);
584
        }
pixhawk's avatar
pixhawk committed
585

586
        // Altitude
587 588
        if (groundDistance == 0 && alt != 0)
        {
589
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(alt, 6, 'f', 1, '0'));
590 591 592
        }
        else
        {
593
            m_ui->groundDistanceLabel->setText(QString("%1 m").arg(groundDistance, 6, 'f', 1, '0'));
594
        }
595

596
        // Speed
597 598
        QString speed("%1 m/s");
        m_ui->speedLabel->setText(speed.arg(totalSpeed, 4, 'f', 1, '0'));
pixhawk's avatar
pixhawk committed
599

600 601
        // Thrust
        m_ui->thrustBar->setValue(thrust * 100);
pixhawk's avatar
pixhawk committed
602

treymarc's avatar
treymarc committed
603 604 605 606 607 608 609 610 611 612 613
        // 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);

614 615
        if(this->timeRemaining > 1 && this->timeRemaining < QGC::MAX_FLIGHT_TIME)
        {
616
            // Filter output to get a higher stability
617
            filterTime = static_cast<int>(this->timeRemaining);
treymarc's avatar
treymarc committed
618 619 620 621
            // 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);
622 623 624

            timeText = timeText.sprintf("%02d:%02d:%02d", hours, min, sec);
            m_ui->timeRemainingLabel->setText(timeText);
625 626 627
        }
        else
        {
628
            m_ui->timeRemainingLabel->setText(tr("Calc.."));
629 630 631
        }


pixhawk's avatar
pixhawk committed
632
    }
633
    generalUpdateCount++;
pixhawk's avatar
pixhawk committed
634

635 636
    if (timeout)
    {
637
        // CRITICAL CONDITION, NO HEARTBEAT
638
        disconnected = true;
639

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

void UASView::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
673 674
    switch (e->type())
    {
pixhawk's avatar
pixhawk committed
675 676 677 678 679 680 681
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}
682

683
void UASView::paintEvent(QPaintEvent *event)
684
{
685
    Q_UNUSED(event);
686 687 688 689 690
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}