LinechartPlot.h 8.18 KB
Newer Older
1 2 3 4 5 6 7 8
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * 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 19 20 21 22 23 24 25 26 27 28


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

#ifndef _LINECHARTPLOT_H_
#define _LINECHARTPLOT_H_

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

#include <QMap>
#include <QList>
#include <QMutex>
#include <QTime>
29
#include <QTimer>
pixhawk's avatar
pixhawk committed
30 31 32 33 34 35
#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>
36
#include "ChartPlot.h"
37
#include "MG.h"
pixhawk's avatar
pixhawk committed
38 39 40 41 42

class TimeScaleDraw: public QwtScaleDraw
{
public:

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

};


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

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

66
    TimeSeriesData(QwtPlot* plot, QString friendlyName = "data", quint64 plotInterval = 10000, quint64 maxInterval = 0, double zeroValue = 0);
pixhawk's avatar
pixhawk committed
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
    ~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();
91 92
    /** @brief Get the short-term variance */
    double getVariance();
93
    /** @brief Get the current value */
pixhawk's avatar
pixhawk committed
94
    double getCurrentValue();
pixhawk's avatar
pixhawk committed
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
    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
110 111 112 113
    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
114 115 116 117 118 119 120 121 122

    QMutex dataMutex;

    QwtScaleMap* scaleMap;

    void updateScaleMap();

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





/**
 * @brief Time series plot
 **/
140
class LinechartPlot : public ChartPlot
pixhawk's avatar
pixhawk committed
141 142 143 144 145 146 147 148 149 150 151
{
    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
152 153
    /** @brief Check if any curve is visible */
    bool anyCurveVisible();
pixhawk's avatar
pixhawk committed
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168

    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);
169 170
    /** @brief Get the short-term variance of a curve */
    double getVariance(QString id);
171 172
    /** @brief Get the last inserted value */
    double getCurrentValue(QString id);
pixhawk's avatar
pixhawk committed
173 174 175 176 177

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

LM's avatar
LM committed
178
    static const int DEFAULT_REFRESH_RATE = 100; ///< The default refresh rate is 10 Hz / every 100 ms
179 180
    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
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197

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);
198 199
    /** @brief Enable auto-refreshing of plot */
    void setActive(bool active);
pixhawk's avatar
pixhawk committed
200 201

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

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

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

pixhawk's avatar
pixhawk committed
217 218 219 220 221 222 223 224 225 226 227 228 229 230
    // 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);
231
    void removeTimedOutCurves();
pixhawk's avatar
pixhawk committed
232 233 234 235

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

    //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
243
    quint64 minTime; ///< The smallest timestamp occurred so far
Lorenz Meier's avatar
Lorenz Meier committed
244
    quint64 lastTime; ///< Last added timestamp
Ricardo de Almeida Gonzaga's avatar
Ricardo de Almeida Gonzaga committed
245
    quint64 maxTime; ///< The biggest timestamp occurred so far
pixhawk's avatar
pixhawk committed
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
    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;
264
    bool m_active; ///< Decides wether the plot is active or not
265
    bool m_groundTime; ///< Enforce the use of the receive timestamp instead of the data timestamp
266
    QTimer timeoutTimer;
pixhawk's avatar
pixhawk committed
267 268 269

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

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
         **/
284
    void curveAdded(QString idstring);
pixhawk's avatar
pixhawk committed
285 286 287 288 289
    /**
         * @brief This signal is emitted when a curve is removed
         *
         * @param name The id-string of the curve
         **/
290
    void curveRemoved(QString name);
pixhawk's avatar
pixhawk committed
291 292 293 294 295 296 297 298 299
    /**
         * @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);
};

#endif // _LINECHARTPLOT_H_