Skip to content
PrimaryFlightDisplay.cc 47.1 KiB
Newer Older
#include "PrimaryFlightDisplay.h"
#include "UASManager.h"

#include <QDebug>
#include <QRectF>
#include <cmath>
#include <QPen>
#include <QPainter>
#include <QPainterPath>
#include <QResizeEvent>
dongfang's avatar
dongfang committed
#include <QtCore/qmath.h>
static const float LINEWIDTH = 0.0036f;
static const float SMALL_TEXT_SIZE = 0.028f;
static const float MEDIUM_TEXT_SIZE = SMALL_TEXT_SIZE*1.2f;
static const float LARGE_TEXT_SIZE = MEDIUM_TEXT_SIZE*1.2f;
static const bool SHOW_ZERO_ON_SCALES = true;

// all in units of display height
static const float ROLL_SCALE_RADIUS = 0.42f;
static const float ROLL_SCALE_TICKMARKLENGTH = 0.04f;
static const float ROLL_SCALE_MARKERWIDTH = 0.06f;
static const float ROLL_SCALE_MARKERHEIGHT = 0.04f;
// scale max. degrees
static const int ROLL_SCALE_RANGE = 60;

// fraction of height to translate for each degree of pitch.
static const float PITCHTRANSLATION = 65;
// 5 degrees for each line
static const int PITCH_SCALE_RESOLUTION = 5;
static const float PITCH_SCALE_MAJORWIDTH = 0.1f;
Don Gagne's avatar
Don Gagne committed
static const float PITCH_SCALE_MINORWIDTH = 0.066f;

// Beginning from PITCH_SCALE_WIDTHREDUCTION_FROM degrees of +/- pitch, the
// width of the lines is reduced, down to PITCH_SCALE_WIDTHREDUCTION times
// the normal width. This helps keep orientation in extreme attitudes.
static const int PITCH_SCALE_WIDTHREDUCTION_FROM = 30;
static const float PITCH_SCALE_WIDTHREDUCTION = 0.3f;
static const int PITCH_SCALE_HALFRANGE = 15;

// The number of degrees to either side of the heading to draw the compass disk.
// 180 is valid, this will draw a complete disk. If the disk is partly clipped
// away, less will do.

static const int  COMPASS_DISK_MAJORTICK = 10;
static const int  COMPASS_DISK_ARROWTICK = 45;
static const int  COMPASS_DISK_RESOLUTION = 10;
Don Gagne's avatar
Don Gagne committed
static const float COMPASS_DISK_MARKERWIDTH = 0.2f;
static const float COMPASS_DISK_MARKERHEIGHT = 0.133f;
static const int  CROSSTRACK_MAX = 1000;
Don Gagne's avatar
Don Gagne committed
static const float CROSSTRACK_RADIUS = 0.6f;
Don Gagne's avatar
Don Gagne committed
static const float TAPE_GAUGES_TICKWIDTH_MAJOR = 0.25f;
static const float TAPE_GAUGES_TICKWIDTH_MINOR = 0.15f;

// The altitude difference between top and bottom of scale
static const int ALTIMETER_LINEAR_SPAN = 50;
// every 5 meters there is a tick mark
static const int ALTIMETER_LINEAR_RESOLUTION = 5;
// every 10 meters there is a number
static const int ALTIMETER_LINEAR_MAJOR_RESOLUTION = 10;

// min. and max. vertical velocity
static const int ALTIMETER_VVI_SPAN = 5;
static const float ALTIMETER_VVI_WIDTH = 0.2f;

// Now the same thing for airspeed!
static const int AIRSPEED_LINEAR_SPAN = 15;
static const int AIRSPEED_LINEAR_RESOLUTION = 1;
static const int AIRSPEED_LINEAR_MAJOR_RESOLUTION = 5;
dongfang's avatar
dongfang committed
 * global fixed pens (and painters too?)
 * repaint on demand multiple canvases
 * multi implementation with shared model class
 */
dongfang's avatar
dongfang committed
double PrimaryFlightDisplay_round(double value, int digits=0)
    return floor(value * pow(10.0, digits) + 0.5) / pow(10.0, digits);
qreal PrimaryFlightDisplay_constrain(qreal value, qreal min, qreal max) {
    if (value<min) value=min;
    else if(value>max) value=max;
    return value;
}

const int PrimaryFlightDisplay::tickValues[] = {10, 20, 30, 45, 60};
const QString PrimaryFlightDisplay::compassWindNames[] = {
    QString("N"),
    QString("NE"),
    QString("E"),
    QString("SE"),
    QString("S"),
    QString("SW"),
    QString("W"),
    QString("NW")
};

PrimaryFlightDisplay::PrimaryFlightDisplay(QWidget *parent) :
    _valuesChanged(false),
    _valuesLastPainted(QGC::groundTimeMilliseconds()),

Don Gagne's avatar
Don Gagne committed
    altitudeAMSL(std::numeric_limits<double>::quiet_NaN()),
    altitudeWGS84(std::numeric_limits<double>::quiet_NaN()),
Don Gagne's avatar
Don Gagne committed
    altitudeRelative(std::numeric_limits<double>::quiet_NaN()),
Don Gagne's avatar
Don Gagne committed
    groundSpeed(std::numeric_limits<double>::quiet_NaN()),
    airSpeed(std::numeric_limits<double>::quiet_NaN()),
    climbRate(std::numeric_limits<double>::quiet_NaN()),
    navigationCrosstrackError(std::numeric_limits<double>::quiet_NaN()),
Don Gagne's avatar
Don Gagne committed
    navigationTargetBearing(std::numeric_limits<double>::quiet_NaN()),
    layout(COMPASS_INTEGRATED),
    style(OVERLAY_HSI),
dongfang's avatar
dongfang committed
    redColor(QColor::fromHsvF(0, 0.75, 0.9)),
dongfang's avatar
dongfang committed
    amberColor(QColor::fromHsvF(0.12, 0.6, 1.0)),
    greenColor(QColor::fromHsvF(0.25, 0.8, 0.8)),

    lineWidth(2),
    fineLineWidth(1),

    instrumentEdgePen(QColor::fromHsvF(0, 0, 0.65, 0.5)),
dongfang's avatar
dongfang committed
    instrumentBackground(QColor::fromHsvF(0, 0, 0.3, 0.3)),
    instrumentOpagueBackground(QColor::fromHsvF(0, 0, 0.3, 1.0)),

    font("Bitstream Vera Sans"),
    refreshTimer(new QTimer(this))
dongfang's avatar
dongfang committed
{
    setMinimumSize(120, 80);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

Lorenz Meier's avatar
Lorenz Meier committed
    setActiveUAS(UASManager::instance()->getActiveUAS());

    // Connect with UAS signal
    connect(UASManager::instance(), SIGNAL(UASDeleted(UASInterface*)), this, SLOT(forgetUAS(UASInterface*)));
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
    // Refresh timer
    refreshTimer->setInterval(updateInterval);
    connect(refreshTimer, SIGNAL(timeout()), this, SLOT(checkUpdate()));
}

PrimaryFlightDisplay::~PrimaryFlightDisplay()
{
    refreshTimer->stop();
}

QSize PrimaryFlightDisplay::sizeHint() const
{
    return QSize(width(), (int)(width() * 3.0f / 4.0f));
void PrimaryFlightDisplay::showEvent(QShowEvent* event)
{
    // React only to internal (pre-display) events
    QWidget::showEvent(event);
    refreshTimer->start(updateInterval);
    emit visibilityChanged(true);
}

void PrimaryFlightDisplay::hideEvent(QHideEvent* event)
{
    // React only to internal (pre-display) events
    refreshTimer->stop();
    QWidget::hideEvent(event);
    emit visibilityChanged(false);
}

dongfang's avatar
dongfang committed
void PrimaryFlightDisplay::resizeEvent(QResizeEvent *e) {
    QWidget::resizeEvent(e);

    qreal size = e->size().width();

    lineWidth = PrimaryFlightDisplay_constrain(size*LINEWIDTH, 1, 6);
    fineLineWidth = PrimaryFlightDisplay_constrain(size*LINEWIDTH*2/3, 1, 2);
dongfang's avatar
dongfang committed

    instrumentEdgePen.setWidthF(fineLineWidth);

    smallTextSize = size * SMALL_TEXT_SIZE;
dongfang's avatar
dongfang committed
    mediumTextSize = size * MEDIUM_TEXT_SIZE;
    largeTextSize = size * LARGE_TEXT_SIZE;
}
dongfang's avatar
dongfang committed
void PrimaryFlightDisplay::paintEvent(QPaintEvent *event)
Loading
Loading full blame...