Lomiri
Loading...
Searching...
No Matches
AxisVelocityCalculator.cpp
1/*
2 * Copyright (C) 2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, as
6 * published by the Free Software Foundation; either version 2.1 or 3.0
7 * of the License.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranties of
11 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12 * PURPOSE. See the applicable version of the GNU Lesser General Public
13 * License for more details.
14 *
15 * You should have received a copy of both the GNU Lesser General Public
16 * License along with this program. If not, see <http://www.gnu.org/licenses/>
17 *
18 * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
19 */
20
21#include "AxisVelocityCalculator.h"
22#include <QtCore/QElapsedTimer>
23
24UG_USE_NAMESPACE
25
26AxisVelocityCalculator::AxisVelocityCalculator(QObject *parent)
27 : AxisVelocityCalculator(SharedTimeSource(new RealTimeSource), parent)
28{
29}
30
31AxisVelocityCalculator::AxisVelocityCalculator(const SharedTimeSource &timeSource,
32 QObject *parent)
33 : QObject(parent)
34 , m_timeSource(timeSource)
35 , m_trackedPosition(0.0)
36{
37 reset();
38}
39
40AxisVelocityCalculator::~AxisVelocityCalculator()
41{
42}
43
44qreal AxisVelocityCalculator::trackedPosition() const
45{
46 return m_trackedPosition;
47}
48
49void AxisVelocityCalculator::setTrackedPosition(qreal newPosition)
50{
51 processMovement(newPosition - m_trackedPosition);
52
53 if (newPosition != m_trackedPosition) {
54 m_trackedPosition = newPosition;
55 Q_EMIT trackedPositionChanged(newPosition);
56 }
57}
58
59void AxisVelocityCalculator::updateIdleTime()
60{
61 processMovement(0);
62}
63
64void AxisVelocityCalculator::processMovement(qreal movement)
65{
66 if (m_samplesRead == -1) {
67 m_samplesRead = m_samplesWrite;
68 } else if (m_samplesRead == m_samplesWrite) {
69 /* the oldest value is going to be overwritten.
70 so now the oldest will be the next one. */
71 m_samplesRead = (m_samplesRead + 1) % MAX_SAMPLES;
72 }
73
74 m_samples[m_samplesWrite].mov = movement;
75 m_samples[m_samplesWrite].time = m_timeSource->msecsSinceReference();
76 m_samplesWrite = (m_samplesWrite + 1) % MAX_SAMPLES;
77}
78
79qreal AxisVelocityCalculator::calculate()
80{
81 if (numSamples() < MIN_SAMPLES_NEEDED) {
82 return 0.0;
83 }
84 updateIdleTime(); // consider the time elapsed since the last update and now
85
86 int lastIndex;
87 if (m_samplesWrite == 0) {
88 lastIndex = MAX_SAMPLES - 1;
89 } else {
90 lastIndex = m_samplesWrite - 1;
91 }
92
93 qint64 currTime = m_samples[lastIndex].time;
94
95 qreal totalTime = 0;
96 qreal totalDistance = 0;
97
98 int sampleIndex = (m_samplesRead + 1) % MAX_SAMPLES;
99 qint64 previousTime = m_samples[m_samplesRead].time;
100 while (sampleIndex != m_samplesWrite) {
101 // Skip this sample if it's too old
102 if (currTime - m_samples[sampleIndex].time <= AGE_OLDEST_SAMPLE) {
103 int deltaTime = m_samples[sampleIndex].time - previousTime;
104 totalDistance += m_samples[sampleIndex].mov;
105 totalTime += deltaTime;
106 }
107
108 previousTime = m_samples[sampleIndex].time;
109 sampleIndex = (sampleIndex + 1) % MAX_SAMPLES;
110 }
111
112 return totalDistance / totalTime;
113}
114
115void AxisVelocityCalculator::reset()
116{
117 m_samplesRead = -1;
118 m_samplesWrite = 0;
119}
120
121int AxisVelocityCalculator::numSamples() const
122{
123 if (m_samplesRead == -1) {
124 return 0;
125 } else {
126 if (m_samplesWrite == 0) {
127 /* consider only what's to the right of m_samplesRead (including himself) */
128 return MAX_SAMPLES - m_samplesRead;
129 } else if (m_samplesWrite == m_samplesRead) {
130 return MAX_SAMPLES; /* buffer is full */
131 } else if (m_samplesWrite < m_samplesRead) {
132 return (MAX_SAMPLES - m_samplesRead) + m_samplesWrite;
133 } else {
134 return m_samplesWrite - m_samplesRead;
135 }
136 }
137}
138
139void AxisVelocityCalculator::setTimeSource(const SharedTimeSource &timeSource)
140{
141 m_timeSource = timeSource;
142
143 if (numSamples() > 0) {
144 qWarning("AxisVelocityCalculator: changing time source while there are samples present.");
145 // Any existent samples are based on the old time source and are, therefore, incompatible
146 // with this new one.
147 reset();
148 }
149}