LinechartPlot.h 8.11 KB
Newer Older
1 2
/****************************************************************************
 *
3
 *   (c) 2009-2018 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/
pixhawk's avatar
pixhawk committed
9 10 11 12 13 14 15 16 17 18


/**
 * @file
 *   @brief Plot of a Linechart
 *
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *
 */

19
#pragma once
pixhawk's avatar
pixhawk committed
20 21 22 23 24 25 26 27

#define QUINT64_MIN Q_UINT64_C(0)
#define QUINT64_MAX Q_UINT64_C(18446744073709551615)

#include <QMap>
#include <QList>
#include <QMutex>
#include <QTime>
28
#include <QTimer>
pixhawk's avatar
pixhawk committed
29 30 31 32 33 34
#include <qwt_plot_panner.h>
#include <qwt_plot_curve.h>
#include <qwt_scale_draw.h>
#include <qwt_scale_widget.h>
#include <qwt_scale_engine.h>
#include <qwt_plot.h>
35
#include "ChartPlot.h"
36
#include "MG.h"
pixhawk's avatar
pixhawk committed
37 38 39 40 41

class TimeScaleDraw: public QwtScaleDraw
{
public:

42
    virtual QwtText label(double v) const {
pixhawk's avatar
pixhawk committed
43 44
        QDateTime time = MG::TIME::msecToQDateTime(static_cast<quint64>(v));
        return time.toString("hh:mm:ss"); // was hh:mm:ss:zzz
45 46
        // Show seconds since system startup
        //return QString::number(static_cast<int>(v)/1000000);
pixhawk's avatar
pixhawk committed
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
    }

};


/**
 * @brief Data container
 */
class QwtPlotCurve;

/**
 * @brief Container class for the time series data
 *
 **/
class TimeSeriesData
{
public:

65
    TimeSeriesData(QwtPlot* plot, QString friendlyName = "data", quint64 plotInterval = 10000, quint64 maxInterval = 0, double zeroValue = 0);
pixhawk's avatar
pixhawk committed
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
    ~TimeSeriesData();

    void append(quint64 ms, double value);

    QwtScaleMap* getScaleMap();

    int getCount() const;
    int size() const;
    const double* getX() const;
    const double* getY() const;

    const double* getPlotX() const;
    const double* getPlotY() const;
    int getPlotCount() const;

    int getID();
    QString getFriendlyName();
    double getMinValue();
    double getMaxValue();
    double getZeroValue();
    /** @brief Get the short-term mean */
    double getMean();
    /** @brief Get the short-term median */
    double getMedian();
90 91
    /** @brief Get the short-term variance */
    double getVariance();
92
    /** @brief Get the current value */
pixhawk's avatar
pixhawk committed
93
    double getCurrentValue();
pixhawk's avatar
pixhawk committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
    void setZeroValue(double zeroValue);
    void setInterval(quint64 ms);
    void setAverageWindowSize(int windowSize);

protected:
    QwtPlot* plot;
    quint64 startTime;
    quint64 stopTime;
    quint64 interval;
    quint64 plotInterval;
    quint64 maxInterval;
    int id;
    quint64 plotCount;
    QString friendlyName;

pixhawk's avatar
pixhawk committed
109 110 111 112
    double lastValue; ///< The last inserted value
    double minValue;  ///< The smallest value in the dataset
    double maxValue;  ///< The largest value in the dataset
    double zeroValue; ///< The expected value in the dataset
pixhawk's avatar
pixhawk committed
113 114 115 116 117 118 119 120 121

    QMutex dataMutex;

    QwtScaleMap* scaleMap;

    void updateScaleMap();

private:
    quint64 count;
122 123
    QVector<double> ms;
    QVector<double> value;
pixhawk's avatar
pixhawk committed
124 125
    double mean;
    double median;
126
    double variance;
pixhawk's avatar
pixhawk committed
127
    unsigned int averageWindow;
128 129
    QVector<double> outputMs;
    QVector<double> outputValue;
pixhawk's avatar
pixhawk committed
130 131 132 133 134 135 136 137 138
};





/**
 * @brief Time series plot
 **/
139
class LinechartPlot : public ChartPlot
pixhawk's avatar
pixhawk committed
140 141 142 143 144 145 146 147 148 149 150
{
    Q_OBJECT
public:
    LinechartPlot(QWidget *parent = NULL, int plotid=0, quint64 interval = LinechartPlot::DEFAULT_PLOT_INTERVAL);
    virtual ~LinechartPlot();

    void setZeroValue(QString id, double zeroValue);
    void removeAllData();

    QList<QwtPlotCurve*> getCurves();
    bool isVisible(QString id);
lm's avatar
lm committed
151 152
    /** @brief Check if any curve is visible */
    bool anyCurveVisible();
pixhawk's avatar
pixhawk committed
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167

    int getPlotId();
    /** @brief Get the number of values to average over */
    int getAverageWindow();

    quint64 getMinTime();
    quint64 getMaxTime();
    quint64 getPlotInterval();
    quint64 getDataInterval();
    quint64 getWindowPosition();

    /** @brief Get the short-term mean of a curve */
    double getMean(QString id);
    /** @brief Get the short-term median of a curve */
    double getMedian(QString id);
168 169
    /** @brief Get the short-term variance of a curve */
    double getVariance(QString id);
170 171
    /** @brief Get the last inserted value */
    double getCurrentValue(QString id);
pixhawk's avatar
pixhawk committed
172 173 174 175 176

    static const int SCALE_ABSOLUTE = 0;
    static const int SCALE_BEST_FIT = 1;
    static const int SCALE_LOGARITHMIC = 2;

LM's avatar
LM committed
177
    static const int DEFAULT_REFRESH_RATE = 100; ///< The default refresh rate is 10 Hz / every 100 ms
178 179
    static const int DEFAULT_PLOT_INTERVAL = 1000 * 8; ///< The default plot interval is 15 seconds
    static const int DEFAULT_SCALE_INTERVAL = 1000 * 8;
pixhawk's avatar
pixhawk committed
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

public slots:
    void setRefreshRate(int ms);
    /**
     * @brief Append data to the plot
     *
     * The new data point is appended to the curve with the id-String id. If the curve
     * doesn't yet exist it is created and added to the plot.
     *
     * @param uasId id of originating UAS
     * @param dataname unique string (also used to label the data)
     * @param ms time measure of the data point, in milliseconds
     * @param value value of the data point
     */
    void appendData(QString dataname, quint64 ms, double value);
    void hideCurve(QString id);
    void showCurve(QString id);
197 198
    /** @brief Enable auto-refreshing of plot */
    void setActive(bool active);
pixhawk's avatar
pixhawk committed
199 200

    // Functions referring to the currently active plot
201
    void setVisibleById(QString id, bool visible);
202 203

    /**
204
     * @brief Set the color of a curve and its symbols.
205 206 207 208
     *
     * @param id The id-string of the curve
     * @param color The newly assigned color
     **/
pixhawk's avatar
pixhawk committed
209 210
    void setCurveColor(QString id, QColor color);

211 212
    /** @brief Enforce the use of the receive timestamp */
    void enforceGroundTime(bool enforce);
lm's avatar
lm committed
213 214
    /** @brief Check if the receive timestamp is enforced */
    bool groundTime();
215

pixhawk's avatar
pixhawk committed
216 217 218 219 220 221 222 223 224 225 226 227 228 229
    // General interaction
    void setWindowPosition(quint64 end);
    void setPlotInterval(int interval);
    void setScaling(int scaling);
    void setAutoScroll(bool active);
    void paintRealtime();

    /** @brief Set logarithmic plot y-axis scaling */
    void setLogarithmicScaling();
    /** @brief Set linear plot y-axis scaling */
    void setLinearScaling();

    /** @brief Set the number of values to average over */
    void setAverageWindow(int windowSize);
230
    void removeTimedOutCurves();
pixhawk's avatar
pixhawk committed
231 232 233 234

protected:
    QMap<QString, TimeSeriesData*> data;
    QMap<QString, QwtScaleMap*> scaleMaps;
235
    QMap<QString, quint64> lastUpdate;
pixhawk's avatar
pixhawk committed
236 237 238 239 240 241

    //static const quint64 MAX_STORAGE_INTERVAL = Q_UINT64_C(300000);
    static const quint64 MAX_STORAGE_INTERVAL = Q_UINT64_C(0);  ///< The maximum interval which is stored
    // TODO CHECK THIS!!!
    int scaling;
    QwtScaleEngine* yScaleEngine;
Ricardo de Almeida Gonzaga's avatar
Ricardo de Almeida Gonzaga committed
242
    quint64 minTime; ///< The smallest timestamp occurred so far
Lorenz Meier's avatar
Lorenz Meier committed
243
    quint64 lastTime; ///< Last added timestamp
Ricardo de Almeida Gonzaga's avatar
Ricardo de Almeida Gonzaga committed
244
    quint64 maxTime; ///< The biggest timestamp occurred so far
pixhawk's avatar
pixhawk committed
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
    quint64 maxInterval;
    quint64 storageInterval;

    double maxValue;
    double minValue;
    double valueInterval;

    int averageWindowSize; ///< Size of sliding average / sliding median

    quint64 plotInterval;
    quint64 plotPosition;
    QTimer* updateTimer;
    QMutex datalock;
    QMutex windowLock;
    quint64 timeScaleStep;
    bool automaticScrollActive;
    QTime lastMaxTimeAdded;
    int plotid;
263
    bool m_active; ///< Decides wether the plot is active or not
264
    bool m_groundTime; ///< Enforce the use of the receive timestamp instead of the data timestamp
265
    QTimer timeoutTimer;
pixhawk's avatar
pixhawk committed
266 267 268

    // Methods
    void addCurve(QString id);
269 270
    void showEvent(QShowEvent* event);
    void hideEvent(QHideEvent* event);
pixhawk's avatar
pixhawk committed
271 272 273 274 275 276 277 278 279 280 281 282

private:
    TimeSeriesData* d_data;
    QwtPlotCurve* d_curve;

signals:

    /**
         * @brief This signal is emitted when a new curve is added
         *
         * @param color The curve color in the diagram
         **/
283
    void curveAdded(QString idstring);
pixhawk's avatar
pixhawk committed
284 285 286 287 288
    /**
         * @brief This signal is emitted when a curve is removed
         *
         * @param name The id-string of the curve
         **/
289
    void curveRemoved(QString name);
pixhawk's avatar
pixhawk committed
290 291 292 293 294 295 296 297
    /**
         * @brief This signal is emitted when the plot window position changes
         *
         * @param position The position of the right edge of the window, in milliseconds
         **/
    void windowPositionChanged(quint64 position);
};