widget/gonk/libui/VelocityTracker.h

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /*
michael@0 2 * Copyright (C) 2012 The Android Open Source Project
michael@0 3 *
michael@0 4 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 5 * you may not use this file except in compliance with the License.
michael@0 6 * You may obtain a copy of the License at
michael@0 7 *
michael@0 8 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 9 *
michael@0 10 * Unless required by applicable law or agreed to in writing, software
michael@0 11 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 13 * See the License for the specific language governing permissions and
michael@0 14 * limitations under the License.
michael@0 15 */
michael@0 16
michael@0 17 #ifndef _ANDROIDFW_VELOCITY_TRACKER_H
michael@0 18 #define _ANDROIDFW_VELOCITY_TRACKER_H
michael@0 19
michael@0 20 #include "Input.h"
michael@0 21 #include <utils/Timers.h>
michael@0 22 #include <utils/BitSet.h>
michael@0 23
michael@0 24 namespace android {
michael@0 25
michael@0 26 class VelocityTrackerStrategy;
michael@0 27
michael@0 28 /*
michael@0 29 * Calculates the velocity of pointer movements over time.
michael@0 30 */
michael@0 31 class VelocityTracker {
michael@0 32 public:
michael@0 33 struct Position {
michael@0 34 float x, y;
michael@0 35 };
michael@0 36
michael@0 37 struct Estimator {
michael@0 38 static const size_t MAX_DEGREE = 4;
michael@0 39
michael@0 40 // Estimator time base.
michael@0 41 nsecs_t time;
michael@0 42
michael@0 43 // Polynomial coefficients describing motion in X and Y.
michael@0 44 float xCoeff[MAX_DEGREE + 1], yCoeff[MAX_DEGREE + 1];
michael@0 45
michael@0 46 // Polynomial degree (number of coefficients), or zero if no information is
michael@0 47 // available.
michael@0 48 uint32_t degree;
michael@0 49
michael@0 50 // Confidence (coefficient of determination), between 0 (no fit) and 1 (perfect fit).
michael@0 51 float confidence;
michael@0 52
michael@0 53 inline void clear() {
michael@0 54 time = 0;
michael@0 55 degree = 0;
michael@0 56 confidence = 0;
michael@0 57 for (size_t i = 0; i <= MAX_DEGREE; i++) {
michael@0 58 xCoeff[i] = 0;
michael@0 59 yCoeff[i] = 0;
michael@0 60 }
michael@0 61 }
michael@0 62 };
michael@0 63
michael@0 64 // Creates a velocity tracker using the specified strategy.
michael@0 65 // If strategy is NULL, uses the default strategy for the platform.
michael@0 66 VelocityTracker(const char* strategy = NULL);
michael@0 67
michael@0 68 ~VelocityTracker();
michael@0 69
michael@0 70 // Resets the velocity tracker state.
michael@0 71 void clear();
michael@0 72
michael@0 73 // Resets the velocity tracker state for specific pointers.
michael@0 74 // Call this method when some pointers have changed and may be reusing
michael@0 75 // an id that was assigned to a different pointer earlier.
michael@0 76 void clearPointers(BitSet32 idBits);
michael@0 77
michael@0 78 // Adds movement information for a set of pointers.
michael@0 79 // The idBits bitfield specifies the pointer ids of the pointers whose positions
michael@0 80 // are included in the movement.
michael@0 81 // The positions array contains position information for each pointer in order by
michael@0 82 // increasing id. Its size should be equal to the number of one bits in idBits.
michael@0 83 void addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions);
michael@0 84
michael@0 85 // Adds movement information for all pointers in a MotionEvent, including historical samples.
michael@0 86 void addMovement(const MotionEvent* event);
michael@0 87
michael@0 88 // Gets the velocity of the specified pointer id in position units per second.
michael@0 89 // Returns false and sets the velocity components to zero if there is
michael@0 90 // insufficient movement information for the pointer.
michael@0 91 bool getVelocity(uint32_t id, float* outVx, float* outVy) const;
michael@0 92
michael@0 93 // Gets an estimator for the recent movements of the specified pointer id.
michael@0 94 // Returns false and clears the estimator if there is no information available
michael@0 95 // about the pointer.
michael@0 96 bool getEstimator(uint32_t id, Estimator* outEstimator) const;
michael@0 97
michael@0 98 // Gets the active pointer id, or -1 if none.
michael@0 99 inline int32_t getActivePointerId() const { return mActivePointerId; }
michael@0 100
michael@0 101 // Gets a bitset containing all pointer ids from the most recent movement.
michael@0 102 inline BitSet32 getCurrentPointerIdBits() const { return mCurrentPointerIdBits; }
michael@0 103
michael@0 104 private:
michael@0 105 static const char* DEFAULT_STRATEGY;
michael@0 106
michael@0 107 nsecs_t mLastEventTime;
michael@0 108 BitSet32 mCurrentPointerIdBits;
michael@0 109 int32_t mActivePointerId;
michael@0 110 VelocityTrackerStrategy* mStrategy;
michael@0 111
michael@0 112 bool configureStrategy(const char* strategy);
michael@0 113
michael@0 114 static VelocityTrackerStrategy* createStrategy(const char* strategy);
michael@0 115 };
michael@0 116
michael@0 117
michael@0 118 /*
michael@0 119 * Implements a particular velocity tracker algorithm.
michael@0 120 */
michael@0 121 class VelocityTrackerStrategy {
michael@0 122 protected:
michael@0 123 VelocityTrackerStrategy() { }
michael@0 124
michael@0 125 public:
michael@0 126 virtual ~VelocityTrackerStrategy() { }
michael@0 127
michael@0 128 virtual void clear() = 0;
michael@0 129 virtual void clearPointers(BitSet32 idBits) = 0;
michael@0 130 virtual void addMovement(nsecs_t eventTime, BitSet32 idBits,
michael@0 131 const VelocityTracker::Position* positions) = 0;
michael@0 132 virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const = 0;
michael@0 133 };
michael@0 134
michael@0 135
michael@0 136 /*
michael@0 137 * Velocity tracker algorithm based on least-squares linear regression.
michael@0 138 */
michael@0 139 class LeastSquaresVelocityTrackerStrategy : public VelocityTrackerStrategy {
michael@0 140 public:
michael@0 141 enum Weighting {
michael@0 142 // No weights applied. All data points are equally reliable.
michael@0 143 WEIGHTING_NONE,
michael@0 144
michael@0 145 // Weight by time delta. Data points clustered together are weighted less.
michael@0 146 WEIGHTING_DELTA,
michael@0 147
michael@0 148 // Weight such that points within a certain horizon are weighed more than those
michael@0 149 // outside of that horizon.
michael@0 150 WEIGHTING_CENTRAL,
michael@0 151
michael@0 152 // Weight such that points older than a certain amount are weighed less.
michael@0 153 WEIGHTING_RECENT,
michael@0 154 };
michael@0 155
michael@0 156 // Degree must be no greater than Estimator::MAX_DEGREE.
michael@0 157 LeastSquaresVelocityTrackerStrategy(uint32_t degree, Weighting weighting = WEIGHTING_NONE);
michael@0 158 virtual ~LeastSquaresVelocityTrackerStrategy();
michael@0 159
michael@0 160 virtual void clear();
michael@0 161 virtual void clearPointers(BitSet32 idBits);
michael@0 162 virtual void addMovement(nsecs_t eventTime, BitSet32 idBits,
michael@0 163 const VelocityTracker::Position* positions);
michael@0 164 virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const;
michael@0 165
michael@0 166 private:
michael@0 167 // Sample horizon.
michael@0 168 // We don't use too much history by default since we want to react to quick
michael@0 169 // changes in direction.
michael@0 170 static const nsecs_t HORIZON = 100 * 1000000; // 100 ms
michael@0 171
michael@0 172 // Number of samples to keep.
michael@0 173 static const uint32_t HISTORY_SIZE = 20;
michael@0 174
michael@0 175 struct Movement {
michael@0 176 nsecs_t eventTime;
michael@0 177 BitSet32 idBits;
michael@0 178 VelocityTracker::Position positions[MAX_POINTERS];
michael@0 179
michael@0 180 inline const VelocityTracker::Position& getPosition(uint32_t id) const {
michael@0 181 return positions[idBits.getIndexOfBit(id)];
michael@0 182 }
michael@0 183 };
michael@0 184
michael@0 185 float chooseWeight(uint32_t index) const;
michael@0 186
michael@0 187 const uint32_t mDegree;
michael@0 188 const Weighting mWeighting;
michael@0 189 uint32_t mIndex;
michael@0 190 Movement mMovements[HISTORY_SIZE];
michael@0 191 };
michael@0 192
michael@0 193
michael@0 194 /*
michael@0 195 * Velocity tracker algorithm that uses an IIR filter.
michael@0 196 */
michael@0 197 class IntegratingVelocityTrackerStrategy : public VelocityTrackerStrategy {
michael@0 198 public:
michael@0 199 // Degree must be 1 or 2.
michael@0 200 IntegratingVelocityTrackerStrategy(uint32_t degree);
michael@0 201 ~IntegratingVelocityTrackerStrategy();
michael@0 202
michael@0 203 virtual void clear();
michael@0 204 virtual void clearPointers(BitSet32 idBits);
michael@0 205 virtual void addMovement(nsecs_t eventTime, BitSet32 idBits,
michael@0 206 const VelocityTracker::Position* positions);
michael@0 207 virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const;
michael@0 208
michael@0 209 private:
michael@0 210 // Current state estimate for a particular pointer.
michael@0 211 struct State {
michael@0 212 nsecs_t updateTime;
michael@0 213 uint32_t degree;
michael@0 214
michael@0 215 float xpos, xvel, xaccel;
michael@0 216 float ypos, yvel, yaccel;
michael@0 217 };
michael@0 218
michael@0 219 const uint32_t mDegree;
michael@0 220 BitSet32 mPointerIdBits;
michael@0 221 State mPointerState[MAX_POINTER_ID + 1];
michael@0 222
michael@0 223 void initState(State& state, nsecs_t eventTime, float xpos, float ypos) const;
michael@0 224 void updateState(State& state, nsecs_t eventTime, float xpos, float ypos) const;
michael@0 225 void populateEstimator(const State& state, VelocityTracker::Estimator* outEstimator) const;
michael@0 226 };
michael@0 227
michael@0 228
michael@0 229 /*
michael@0 230 * Velocity tracker strategy used prior to ICS.
michael@0 231 */
michael@0 232 class LegacyVelocityTrackerStrategy : public VelocityTrackerStrategy {
michael@0 233 public:
michael@0 234 LegacyVelocityTrackerStrategy();
michael@0 235 virtual ~LegacyVelocityTrackerStrategy();
michael@0 236
michael@0 237 virtual void clear();
michael@0 238 virtual void clearPointers(BitSet32 idBits);
michael@0 239 virtual void addMovement(nsecs_t eventTime, BitSet32 idBits,
michael@0 240 const VelocityTracker::Position* positions);
michael@0 241 virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const;
michael@0 242
michael@0 243 private:
michael@0 244 // Oldest sample to consider when calculating the velocity.
michael@0 245 static const nsecs_t HORIZON = 200 * 1000000; // 100 ms
michael@0 246
michael@0 247 // Number of samples to keep.
michael@0 248 static const uint32_t HISTORY_SIZE = 20;
michael@0 249
michael@0 250 // The minimum duration between samples when estimating velocity.
michael@0 251 static const nsecs_t MIN_DURATION = 10 * 1000000; // 10 ms
michael@0 252
michael@0 253 struct Movement {
michael@0 254 nsecs_t eventTime;
michael@0 255 BitSet32 idBits;
michael@0 256 VelocityTracker::Position positions[MAX_POINTERS];
michael@0 257
michael@0 258 inline const VelocityTracker::Position& getPosition(uint32_t id) const {
michael@0 259 return positions[idBits.getIndexOfBit(id)];
michael@0 260 }
michael@0 261 };
michael@0 262
michael@0 263 uint32_t mIndex;
michael@0 264 Movement mMovements[HISTORY_SIZE];
michael@0 265 };
michael@0 266
michael@0 267 } // namespace android
michael@0 268
michael@0 269 #endif // _ANDROIDFW_VELOCITY_TRACKER_H

mercurial