LinechartPlot.h 8.76 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 49
#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_array.h>
#include <qwt_plot.h>
50
#include "ChartPlot.h"
51
#include "MG.h"
pixhawk's avatar
pixhawk committed
52 53 54 55 56

class TimeScaleDraw: public QwtScaleDraw
{
public:

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

};


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

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

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

    QMutex dataMutex;

    QwtScaleMap* scaleMap;

    void updateScaleMap();

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





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

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

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

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

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

    // Functions referring to the currently active plot
    void setVisible(QString id, bool visible);
217 218

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

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

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

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

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

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

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