LinechartPlot.h 8.74 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
/*=====================================================================

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.

    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.

    You should have received a copy of the GNU General Public License
    along with PIXHAWK. If not, see <http://www.gnu.org/licenses/>.

======================================================================*/

/**
 * @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>
42
#include <QTimer>
pixhawk's avatar
pixhawk committed
43 44 45 46 47 48
#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>
49
#include "ChartPlot.h"
50
#include "MG.h"
pixhawk's avatar
pixhawk committed
51 52 53 54 55

class TimeScaleDraw: public QwtScaleDraw
{
public:

56
    virtual QwtText label(double v) const {
pixhawk's avatar
pixhawk committed
57 58
        QDateTime time = MG::TIME::msecToQDateTime(static_cast<quint64>(v));
        return time.toString("hh:mm:ss"); // was hh:mm:ss:zzz
59 60
        // Show seconds since system startup
        //return QString::number(static_cast<int>(v)/1000000);
pixhawk's avatar
pixhawk committed
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    }

};


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

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

79
    TimeSeriesData(QwtPlot* plot, QString friendlyName = "data", quint64 plotInterval = 10000, quint64 maxInterval = 0, double zeroValue = 0);
pixhawk's avatar
pixhawk committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
    ~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();
104 105
    /** @brief Get the short-term variance */
    double getVariance();
106
    /** @brief Get the current value */
pixhawk's avatar
pixhawk committed
107
    double getCurrentValue();
pixhawk's avatar
pixhawk committed
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
    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
123 124 125 126
    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
127 128 129 130 131 132 133 134 135

    QMutex dataMutex;

    QwtScaleMap* scaleMap;

    void updateScaleMap();

private:
    quint64 count;
136 137
    QVector<double> ms;
    QVector<double> value;
pixhawk's avatar
pixhawk committed
138 139
    double mean;
    double median;
140
    double variance;
pixhawk's avatar
pixhawk committed
141
    unsigned int averageWindow;
142 143
    QVector<double> outputMs;
    QVector<double> outputValue;
pixhawk's avatar
pixhawk committed
144 145 146 147 148 149 150 151 152
};





/**
 * @brief Time series plot
 **/
153
class LinechartPlot : public ChartPlot
pixhawk's avatar
pixhawk committed
154 155 156 157 158 159 160 161 162 163 164
{
    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
165 166
    /** @brief Check if any curve is visible */
    bool anyCurveVisible();
pixhawk's avatar
pixhawk committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181

    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);
182 183
    /** @brief Get the short-term variance of a curve */
    double getVariance(QString id);
184 185
    /** @brief Get the last inserted value */
    double getCurrentValue(QString id);
pixhawk's avatar
pixhawk committed
186 187 188 189 190

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

LM's avatar
LM committed
191
    static const int DEFAULT_REFRESH_RATE = 100; ///< The default refresh rate is 10 Hz / every 100 ms
192 193
    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
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210

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);
211 212
    /** @brief Enable auto-refreshing of plot */
    void setActive(bool active);
pixhawk's avatar
pixhawk committed
213 214

    // Functions referring to the currently active plot
215
    void setVisibleById(QString id, bool visible);
216 217

    /**
218
     * @brief Set the color of a curve and its symbols.
219 220 221 222
     *
     * @param id The id-string of the curve
     * @param color The newly assigned color
     **/
pixhawk's avatar
pixhawk committed
223 224
    void setCurveColor(QString id, QColor color);

225 226
    /** @brief Enforce the use of the receive timestamp */
    void enforceGroundTime(bool enforce);
lm's avatar
lm committed
227 228
    /** @brief Check if the receive timestamp is enforced */
    bool groundTime();
229

pixhawk's avatar
pixhawk committed
230 231 232 233 234 235 236 237 238 239 240 241 242 243
    // 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);
244
    void removeTimedOutCurves();
pixhawk's avatar
pixhawk committed
245 246 247 248

protected:
    QMap<QString, TimeSeriesData*> data;
    QMap<QString, QwtScaleMap*> scaleMaps;
249
    QMap<QString, quint64> lastUpdate;
pixhawk's avatar
pixhawk committed
250 251 252 253 254 255 256

    //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;
    quint64 minTime; ///< The smallest timestamp occured so far
Lorenz Meier's avatar
Lorenz Meier committed
257
    quint64 lastTime; ///< Last added timestamp
pixhawk's avatar
pixhawk committed
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
    quint64 maxTime; ///< The biggest timestamp occured so far
    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;
277
    bool m_active; ///< Decides wether the plot is active or not
278
    bool m_groundTime; ///< Enforce the use of the receive timestamp instead of the data timestamp
279
    QTimer timeoutTimer;
pixhawk's avatar
pixhawk committed
280 281 282

    // Methods
    void addCurve(QString id);
283 284
    void showEvent(QShowEvent* event);
    void hideEvent(QHideEvent* event);
pixhawk's avatar
pixhawk committed
285 286 287 288 289 290 291 292 293 294 295 296

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
         **/
297
    void curveAdded(QString idstring);
pixhawk's avatar
pixhawk committed
298 299 300 301 302
    /**
         * @brief This signal is emitted when a curve is removed
         *
         * @param name The id-string of the curve
         **/
303
    void curveRemoved(QString name);
pixhawk's avatar
pixhawk committed
304 305 306 307 308 309 310 311 312
    /**
         * @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_