PrimaryFlightDisplay.h 9.56 KB
Newer Older
1 2 3 4 5 6 7
#ifndef PRIMARYFLIGHTDISPLAY_H
#define PRIMARYFLIGHTDISPLAY_H

#include <QWidget>
#include <QPen>
#include "UASInterface.h"

8 9
#define SEPARATE_COMPASS_ASPECTRATIO (3.0f/4.0f)

dongfang's avatar
dongfang committed
10
#define LINEWIDTH 0.0036f
dongfang's avatar
dongfang committed
11 12 13 14 15 16 17 18

//#define TAPES_TEXT_SIZE 0.028
//#define AI_TEXT_SIZE 0.040
//#define AI_TEXT_MIN_PIXELS 12
//#define AI_TEXT_MAX_PIXELS 36
//#define PANELS_TEXT_SIZE 0.030
//#define COMPASS_SCALE_TEXT_SIZE 0.16

dongfang's avatar
dongfang committed
19
#define SMALL_TEXT_SIZE 0.03f
dongfang's avatar
dongfang committed
20 21 22 23
#define MEDIUM_TEXT_SIZE (SMALL_TEXT_SIZE*1.2f)
#define LARGE_TEXT_SIZE (MEDIUM_TEXT_SIZE*1.2f)

#define SHOW_ZERO_ON_SCALES true
24 25

// all in units of display height
dongfang's avatar
dongfang committed
26 27 28 29
#define ROLL_SCALE_RADIUS 0.42f
#define ROLL_SCALE_TICKMARKLENGTH 0.04f
#define ROLL_SCALE_MARKERWIDTH 0.06f
#define ROLL_SCALE_MARKERHEIGHT 0.04f
30 31 32 33 34 35 36
// scale max. degrees
#define ROLL_SCALE_RANGE 60

// fraction of height to translate for each degree of pitch.
#define PITCHTRANSLATION 65.0
// 10 degrees for each line
#define PITCH_SCALE_RESOLUTION 5
37 38 39 40 41 42 43
#define PITCH_SCALE_MAJORWIDTH 0.1
#define PITCH_SCALE_MINORWIDTH 0.066

// 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.
#define PITCH_SCALE_WIDTHREDUCTION_FROM 30
dongfang's avatar
dongfang committed
44
#define PITCH_SCALE_WIDTHREDUCTION 0.3
45

dongfang's avatar
dongfang committed
46
#define PITCH_SCALE_HALFRANGE 15
47 48 49 50

// 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.
dongfang's avatar
dongfang committed
51 52 53 54 55

#define COMPASS_DISK_MAJORTICK 10
#define COMPASS_DISK_ARROWTICK 45
#define COMPASS_DISK_MAJORLINEWIDTH 0.006
#define COMPASS_DISK_MINORLINEWIDTH 0.004
dongfang's avatar
dongfang committed
56
#define COMPASS_DISK_RESOLUTION 10
57
#define COMPASS_SEPARATE_DISK_RESOLUTION 5
58 59 60
#define COMPASS_DISK_MARKERWIDTH 0.2
#define COMPASS_DISK_MARKERHEIGHT 0.133

61 62 63
#define CROSSTRACK_MAX 1000
#define CROSSTRACK_RADIUS 0.6

dongfang's avatar
dongfang committed
64 65
#define TAPE_GAUGES_TICKWIDTH_MAJOR 0.25
#define TAPE_GAUGES_TICKWIDTH_MINOR 0.15
66 67

// The altitude difference between top and bottom of scale
dongfang's avatar
dongfang committed
68
#define ALTIMETER_LINEAR_SPAN 50
69 70 71 72 73
// every 5 meters there is a tick mark
#define ALTIMETER_LINEAR_RESOLUTION 5
// every 10 meters there is a number
#define ALTIMETER_LINEAR_MAJOR_RESOLUTION 10

74
// Projected: An experiment. Make tape appear projected from a cylinder, like a French "drum" style gauge.
75 76 77 78 79 80 81 82 83
// The altitude difference between top and bottom of scale
#define ALTIMETER_PROJECTED_SPAN 50
// every 5 meters there is a tick mark
#define ALTIMETER_PROJECTED_RESOLUTION 5
// every 10 meters there is a number
#define ALTIMETER_PROJECTED_MAJOR_RESOLUTION 10
// min. and max. vertical velocity
//#define ALTIMETER_PROJECTED

dongfang's avatar
dongfang committed
84 85 86
// min. and max. vertical velocity
#define ALTIMETER_VVI_SPAN 5
#define ALTIMETER_VVI_WIDTH 0.2
87 88

// Now the same thing for airspeed!
dongfang's avatar
dongfang committed
89
#define AIRSPEED_LINEAR_SPAN 15
90 91 92
#define AIRSPEED_LINEAR_RESOLUTION 1
#define AIRSPEED_LINEAR_MAJOR_RESOLUTION 5

93
#define UNKNOWN_BATTERY -1
94 95 96
#define UNKNOWN_ATTITUDE 0
#define UNKNOWN_ALTITUDE -1000
#define UNKNOWN_SPEED -1
dongfang's avatar
dongfang committed
97 98
#define UNKNOWN_COUNT -1
#define UNKNOWN_GPSFIXTYPE -1
99 100 101 102 103 104 105 106

class PrimaryFlightDisplay : public QWidget
{
    Q_OBJECT
public:
    PrimaryFlightDisplay(int width = 640, int height = 480, QWidget* parent = NULL);
    ~PrimaryFlightDisplay();

107
public slots:
108 109 110 111
    /** @brief Attitude from main autopilot / system state */
    void updateAttitude(UASInterface* uas, double roll, double pitch, double yaw, quint64 timestamp);
    /** @brief Attitude from one specific component / redundant autopilot */
    void updateAttitude(UASInterface* uas, int component, double roll, double pitch, double yaw, quint64 timestamp);
112

113 114 115 116 117 118 119
    void updatePrimarySpeed(UASInterface* uas, double speed, quint64 timstamp);
    void updateGPSSpeed(UASInterface* uas, double speed, quint64 timstamp);
    void updateClimbRate(UASInterface* uas, double altitude, quint64 timestamp);
    void updatePrimaryAltitude(UASInterface* uas, double altitude, quint64 timestamp);
    void updateGPSAltitude(UASInterface* uas, double altitude, quint64 timestamp);
    void updateNavigationControllerErrors(UASInterface* uas, double altitudeError, double speedError, double xtrackError);

120 121
    /** @brief Set the currently monitored UAS */
    virtual void setActiveUAS(UASInterface* uas);
122

123
protected:
dongfang's avatar
dongfang committed
124
    enum Layout {
125
        COMPASS_INTEGRATED,
dongfang's avatar
dongfang committed
126 127 128 129
        COMPASS_SEPARATED               // For a very high container. Feature panels are at bottom.
    };

    enum Style {
130 131 132
        NO_OVERLAYS,                    // Hzon not visible through tapes nor through feature panels. Frames with margins between.
        OVERLAY_HORIZONTAL,             // Hzon visible through tapes and (frameless) feature panels.
        OVERLAY_HSI                     // Hzon visible through everything except bottom feature panels.
dongfang's avatar
dongfang committed
133 134
    };

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
    void paintEvent(QPaintEvent *event);
    void resizeEvent(QResizeEvent *e);

    // from HUD.h:

    /** @brief Preferred Size */
    QSize sizeHint() const;
    /** @brief Start updating widget */
    void showEvent(QShowEvent* event);
    /** @brief Stop updating widget */
    void hideEvent(QHideEvent* event);

    // dongfang: We have no context menu. Viewonly.
    // void contextMenuEvent (QContextMenuEvent* event);

    // dongfang: What is that?
dongfang's avatar
dongfang committed
151
    // dongfang: OK it's for UI interaction. Presently, there is none.
152 153 154 155 156 157
    void createActions();

signals:
    void visibilityChanged(bool visible);

private:
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
    enum AltimeterMode {
        PRIMARY_MAIN_GPS_SUB,   // Show the primary alt. on tape and GPS as extra info
        GPS_MAIN                // Show GPS on tape and no extra info
    };

    enum AltimeterFrame {
        ASL,                    // Show ASL altitudes (plane pilots' normal preference)
        RELATIVE_TO_HOME        // Show relative-to-home altitude (copter pilots)
    };

    enum SpeedMode {
        PRIMARY_MAIN_GROUND_SUB,// Show primary speed (often airspeed) on tape and groundspeed as extra
        GROUND_MAIN             // Show groundspeed on tape and no extra info
    };

    /*
     * There are at least these differences between airplane and copter PDF view:
     * - Airplane show absolute altutude in altimeter, copter shows relative to home
     */
    bool isAirplane();
178
    bool shouldDisplayNavigationData();
179 180 181 182 183 184

    void drawTextCenter(QPainter& painter, QString text, float fontSize, float x, float y);
    void drawTextLeftCenter(QPainter& painter, QString text, float fontSize, float x, float y);
    void drawTextRightCenter(QPainter& painter, QString text, float fontSize, float x, float y);
    void drawTextCenterBottom(QPainter& painter, QString text, float fontSize, float x, float y);
    void drawTextCenterTop(QPainter& painter, QString text, float fontSize, float x, float y);
185
    void drawAIGlobalFeatures(QPainter& painter, QRectF mainArea, QRectF paintArea);
186
    void drawAIAirframeFixedFeatures(QPainter& painter, QRectF area);
dongfang's avatar
dongfang committed
187
    void drawPitchScale(QPainter& painter, QRectF area, float intrusion, bool drawNumbersLeft, bool drawNumbersRight);
188
    void drawRollScale(QPainter& painter, QRectF area, bool drawTicks, bool drawNumbers);
dongfang's avatar
dongfang committed
189 190
    void drawAIAttitudeScales(QPainter& painter, QRectF area, float intrusion);
    void drawAICompassDisk(QPainter& painter, QRectF area, float halfspan);
dongfang's avatar
dongfang committed
191 192
    void drawSeparateCompassDisk(QPainter& painter, QRectF area);

193 194
    void drawAltimeter(QPainter& painter, QRectF area, float altitude, float secondaryAltitude, float vv);
    void drawVelocityMeter(QPainter& painter, QRectF area, float speed, float secondarySpeed);
195
    void fillInstrumentBackground(QPainter& painter, QRectF edge);
dongfang's avatar
dongfang committed
196
    void fillInstrumentOpagueBackground(QPainter& painter, QRectF edge);
197 198
    void drawInstrumentBackground(QPainter& painter, QRectF edge);

dongfang's avatar
dongfang committed
199
    /* This information is not currently included. These headers left in as a memo for restoration later.
200 201 202 203
    void drawLinkStatsPanel(QPainter& painter, QRectF area);
    void drawSysStatsPanel(QPainter& painter, QRectF area);
    void drawMissionStatsPanel(QPainter& painter, QRectF area);
    void drawSensorsStatsPanel(QPainter& painter, QRectF area);
dongfang's avatar
dongfang committed
204
    */
205 206 207

    void doPaint();

208 209
    UASInterface* uas;          ///< The uas currently monitored

210 211 212 213 214 215 216
    AltimeterMode altimeterMode;
    AltimeterFrame altimeterFrame;
    SpeedMode speedMode;

    bool didReceivePrimaryAltitude;
    bool didReceivePrimarySpeed;

217 218 219 220
    float roll;
    float pitch;
    float heading;

221
    float primaryAltitude;
222 223 224 225
    float GPSAltitude;

    // APM: GPS and baro mix above home (GPS) altitude. This value comes from the GLOBAL_POSITION_INT message.
    // Do !!!NOT!!! ever do altitude calculations at the ground station. There are enough pitfalls already.
226
    // If the MP "set home altitude" button is migrated to here, it must set the UAS home altitude, not a GS-local one.
227 228
    float aboveHomeAltitude;

229
    float primarySpeed;
230
    float groundspeed;
dongfang's avatar
dongfang committed
231
    float verticalVelocity;
232

233 234 235 236 237
    float navigationAltitudeError;
    float navigationSpeedError;
    float navigationCrosstrackError;
    float navigationTargetBearing;

dongfang's avatar
dongfang committed
238 239
    Layout layout;      // The display layout.
    Style style;        // The AI style (tapes translusent or opague)
dongfang's avatar
dongfang committed
240

dongfang's avatar
dongfang committed
241 242 243 244 245 246 247 248 249 250 251

    QColor redColor;
    QColor amberColor;
    QColor greenColor;

    qreal lineWidth;
    qreal fineLineWidth;

    qreal smallTestSize;
    qreal mediumTextSize;
    qreal largeTextSize;
252

dongfang's avatar
dongfang committed
253
    // Globally used stuff only.
254 255
    QPen instrumentEdgePen;
    QBrush instrumentBackground;
dongfang's avatar
dongfang committed
256
    QBrush instrumentOpagueBackground;
257 258 259 260 261 262 263 264

    QFont font;

    QTimer* refreshTimer;       ///< The main timer, controls the update rate

    static const int tickValues[];
    static const QString compassWindNames[];

265 266 267
    static const int updateInterval = 40;


268 269 270 271 272 273 274
signals:
    
public slots:
    
};

#endif // PRIMARYFLIGHTDISPLAY_H