LogReplayLink.h 5.56 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.
 *
 ****************************************************************************/
Don Gagne's avatar
Don Gagne committed
9 10


11
#pragma once
Don Gagne's avatar
Don Gagne committed
12 13 14 15 16 17 18 19 20 21

#include "LinkInterface.h"
#include "LinkConfiguration.h"
#include "MAVLinkProtocol.h"

#include <QTimer>
#include <QFile>

class LogReplayLinkConfiguration : public LinkConfiguration
{
Don Gagne's avatar
Don Gagne committed
22 23
    Q_OBJECT

Don Gagne's avatar
Don Gagne committed
24
public:
25 26 27

    Q_PROPERTY(QString  fileName    READ logFilename    WRITE setLogFilename    NOTIFY fileNameChanged)

Don Gagne's avatar
Don Gagne committed
28 29
    LogReplayLinkConfiguration(const QString& name);
    LogReplayLinkConfiguration(LogReplayLinkConfiguration* copy);
30

Don Gagne's avatar
Don Gagne committed
31
    QString logFilename(void) { return _logFilename; }
32
    void setLogFilename(const QString logFilename) { _logFilename = logFilename; emit fileNameChanged(); }
33

Don Gagne's avatar
Don Gagne committed
34 35 36
    QString logFilenameShort(void);

    // Virtuals from LinkConfiguration
37 38 39 40 41
    LinkType    type                    () { return LinkConfiguration::TypeLogReplay; }
    void        copyFrom                (LinkConfiguration* source);
    void        loadSettings            (QSettings& settings, const QString& root);
    void        saveSettings            (QSettings& settings, const QString& root);
    void        updateSettings          ();
42
    QString     settingsURL             () { return "LogReplaySettings.qml"; }
43
    QString     settingsTitle           () { return tr("Log Replay Link Settings"); }
44 45
signals:
    void fileNameChanged();
Don Gagne's avatar
Don Gagne committed
46 47 48 49 50 51 52 53 54 55 56

private:
    static const char*  _logFilenameKey;
    QString             _logFilename;
};

class LogReplayLink : public LinkInterface
{
    Q_OBJECT

    friend class LinkManager;
57

Don Gagne's avatar
Don Gagne committed
58 59 60
public:
    /// @return true: log is currently playing, false: log playback is paused
    bool isPlaying(void) { return _readTickTimer.isActive(); }
61

Don Gagne's avatar
Don Gagne committed
62 63
    /// Start replay at current position
    void play(void) { emit _playOnThread(); }
64

Don Gagne's avatar
Don Gagne committed
65 66
    /// Pause replay
    void pause(void) { emit _pauseOnThread(); }
67

Don Gagne's avatar
Don Gagne committed
68 69
    /// Move the playhead to the specified percent complete
    void movePlayhead(int percentComplete);
70

Don Gagne's avatar
Don Gagne committed
71 72
    /// Sets the acceleration factor: -100: 0.01X, 0: 1.0X, 100: 100.0X
    void setAccelerationFactor(int factor) { emit _setAccelerationFactorOnThread(factor); }
73

Don Gagne's avatar
Don Gagne committed
74 75 76 77 78 79 80 81 82 83 84 85 86
    // Virtuals from LinkInterface
    virtual QString getName(void) const { return _config->name(); }
    virtual void requestReset(void){ }
    virtual bool isConnected(void) const { return _connected; }
    virtual qint64 getConnectionSpeed(void) const { return 100000000; }
    virtual qint64 bytesAvailable(void) { return 0; }
    virtual bool isLogReplay(void) { return true; }

    // These are left unimplemented in order to cause linker errors which indicate incorrect usage of
    // connect/disconnect on link directly. All connect/disconnect calls should be made through LinkManager.
    bool connect(void);
    bool disconnect(void);

87
private slots:
88
    virtual void _writeBytes(const QByteArray bytes);
89

Don Gagne's avatar
Don Gagne committed
90 91 92 93 94 95 96
signals:
    void logFileStats(bool logTimestamped, int logDurationSecs, int binaryBaudRate);
    void playbackStarted(void);
    void playbackPaused(void);
    void playbackAtEnd(void);
    void playbackError(void);
    void playbackPercentCompleteChanged(int percentComplete);
97
    void currentLogTimeSecs(int secs);
98

Don Gagne's avatar
Don Gagne committed
99 100 101 102 103 104 105 106 107 108 109 110 111
    // Internal signals
    void _playOnThread(void);
    void _pauseOnThread(void);
    void _setAccelerationFactorOnThread(int factor);

private slots:
    void _readNextLogEntry(void);
    void _play(void);
    void _pause(void);
    void _setAccelerationFactor(int factor);

private:
    // Links are only created/destroyed by LinkManager so constructor/destructor is not public
112
    LogReplayLink(SharedLinkConfigurationPointer& config);
Don Gagne's avatar
Don Gagne committed
113
    ~LogReplayLink();
114

Don Gagne's avatar
Don Gagne committed
115 116 117
    void _replayError(const QString& errorMsg);
    quint64 _parseTimestamp(const QByteArray& bytes);
    quint64 _seekToNextMavlinkMessage(mavlink_message_t* nextMsg);
Don Gagne's avatar
Don Gagne committed
118
    quint64 _readNextMavlinkMessage(QByteArray& bytes);
Don Gagne's avatar
Don Gagne committed
119 120 121 122
    bool _loadLogFile(void);
    void _finishPlayback(void);
    void _playbackError(void);
    void _resetPlaybackToBeginning(void);
123

Don Gagne's avatar
Don Gagne committed
124 125
    // Virtuals from LinkInterface
    virtual bool _connect(void);
Don Gagne's avatar
Don Gagne committed
126
    virtual void _disconnect(void);
127

Don Gagne's avatar
Don Gagne committed
128 129
    // Virtuals from QThread
    virtual void run(void);
130

131
    LogReplayLinkConfiguration* _logReplayConfig;
Don Gagne's avatar
Don Gagne committed
132 133

    bool    _connected;
Don Gagne's avatar
Don Gagne committed
134 135
    int     _mavlinkChannel;
    QTimer  _readTickTimer;      ///< Timer which signals a read of next log record
136

137
    QString _errorTitle; ///< Title for communicatorError signals
138

Don Gagne's avatar
Don Gagne committed
139 140 141 142
    quint64 _logCurrentTimeUSecs;   ///< The timestamp of the next message in the log file.
    quint64 _logStartTimeUSecs;     ///< The first timestamp in the current log file.
    quint64 _logEndTimeUSecs;       ///< The last timestamp in the current log file.
    quint64 _logDurationUSecs;
143

Don Gagne's avatar
Don Gagne committed
144 145
    static const int    _defaultBinaryBaudRate = 57600;
    int                 _binaryBaudRate;        ///< Playback rate for binary log format
146

Don Gagne's avatar
Don Gagne committed
147 148
    float   _replayAccelerationFactor;  ///< Factor to apply to playback rate
    quint64 _playbackStartTimeMSecs;    ///< The time when the logfile was first played back. This is used to pace out replaying the messages to fix long-term drift/skew. 0 indicates that the player hasn't initiated playback of this log file.
149

Don Gagne's avatar
Don Gagne committed
150 151 152 153
    MAVLinkProtocol*    _mavlink;
    QFile               _logFile;
    quint64             _logFileSize;
    bool                _logTimestamped;    ///< true: Timestamped log format, false: no timestamps
154

Don Gagne's avatar
Don Gagne committed
155 156 157
    static const int cbTimestamp = sizeof(quint64);
};