Loading libs/input/VelocityTracker.cpp +71 −69 Original line number Diff line number Diff line Loading @@ -18,10 +18,10 @@ //#define LOG_NDEBUG 0 // Log debug messages about velocity tracking. #define DEBUG_VELOCITY 0 static constexpr bool DEBUG_VELOCITY = false; // Log debug messages about the progress of the algorithm itself. #define DEBUG_STRATEGY 0 static constexpr bool DEBUG_STRATEGY = false; #include <array> #include <inttypes.h> Loading @@ -30,7 +30,6 @@ #include <optional> #include <android-base/stringprintf.h> #include <cutils/properties.h> #include <input/VelocityTracker.h> #include <utils/BitSet.h> #include <utils/Timers.h> Loading Loading @@ -64,7 +63,6 @@ static float vectorNorm(const float* a, uint32_t m) { return sqrtf(r); } #if DEBUG_STRATEGY || DEBUG_VELOCITY static std::string vectorToString(const float* a, uint32_t m) { std::string str; str += "["; Loading @@ -77,9 +75,11 @@ static std::string vectorToString(const float* a, uint32_t m) { str += " ]"; return str; } #endif #if DEBUG_STRATEGY static std::string vectorToString(const std::vector<float>& v) { return vectorToString(v.data(), v.size()); } static std::string matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMajor) { std::string str; str = "["; Loading @@ -99,7 +99,6 @@ static std::string matrixToString(const float* a, uint32_t m, uint32_t n, bool r str += " ]"; return str; } #endif // --- VelocityTracker --- Loading Loading @@ -133,12 +132,18 @@ std::unique_ptr<VelocityTrackerStrategy> VelocityTracker::createStrategy( VelocityTracker::Strategy strategy) { switch (strategy) { case VelocityTracker::Strategy::IMPULSE: if (DEBUG_STRATEGY) { ALOGI("Initializing impulse strategy"); } return std::make_unique<ImpulseVelocityTrackerStrategy>(); case VelocityTracker::Strategy::LSQ1: return std::make_unique<LeastSquaresVelocityTrackerStrategy>(1); case VelocityTracker::Strategy::LSQ2: if (DEBUG_STRATEGY) { ALOGI("Initializing lsq2 strategy"); } return std::make_unique<LeastSquaresVelocityTrackerStrategy>(2); case VelocityTracker::Strategy::LSQ3: Loading Loading @@ -204,10 +209,10 @@ void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, if ((mCurrentPointerIdBits.value & idBits.value) && eventTime >= mLastEventTime + ASSUME_POINTER_STOPPED_TIME) { #if DEBUG_VELOCITY if (DEBUG_VELOCITY) { ALOGD("VelocityTracker: stopped for %0.3f ms, clearing state.", (eventTime - mLastEventTime) * 0.000001f); #endif } // We have not received any movements for too long. Assume that all pointers // have stopped. mStrategy->clear(); Loading @@ -221,8 +226,9 @@ void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, mStrategy->addMovement(eventTime, idBits, positions); #if DEBUG_VELOCITY ALOGD("VelocityTracker: addMovement eventTime=%" PRId64 ", idBits=0x%08x, activePointerId=%d", if (DEBUG_VELOCITY) { ALOGD("VelocityTracker: addMovement eventTime=%" PRId64 ", idBits=0x%08x, activePointerId=%d", eventTime, idBits.value, mActivePointerId); for (BitSet32 iterBits(idBits); !iterBits.isEmpty();) { uint32_t id = iterBits.firstMarkedBit(); Loading @@ -232,13 +238,12 @@ void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, getEstimator(id, &estimator); ALOGD(" %d: position (%0.3f, %0.3f), " "estimator (degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f)", id, positions[index].x, positions[index].y, int(estimator.degree), id, positions[index].x, positions[index].y, int(estimator.degree), vectorToString(estimator.xCoeff, estimator.degree + 1).c_str(), vectorToString(estimator.yCoeff, estimator.degree + 1).c_str(), estimator.confidence); } #endif } } void VelocityTracker::addMovement(const MotionEvent* event) { Loading Loading @@ -419,11 +424,10 @@ void LeastSquaresVelocityTrackerStrategy::addMovement( static bool solveLeastSquares(const std::vector<float>& x, const std::vector<float>& y, const std::vector<float>& w, uint32_t n, float* outB, float* outDet) { const size_t m = x.size(); #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s, w=%s", int(m), int(n), vectorToString(x, m).c_str(), vectorToString(y, m).c_str(), vectorToString(w, m).c_str()); #endif vectorToString(x).c_str(), vectorToString(y).c_str(), vectorToString(w).c_str()); } LOG_ALWAYS_FATAL_IF(m != y.size() || m != w.size(), "Mismatched vector sizes"); // Expand the X vector to a matrix A, pre-multiplied by the weights. Loading @@ -434,9 +438,9 @@ static bool solveLeastSquares(const std::vector<float>& x, const std::vector<flo a[i][h] = a[i - 1][h] * x[h]; } } #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD(" - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).c_str()); #endif } // Apply the Gram-Schmidt process to A to obtain its QR decomposition. float q[n][m]; // orthonormal basis, column-major order Loading @@ -455,9 +459,9 @@ static bool solveLeastSquares(const std::vector<float>& x, const std::vector<flo float norm = vectorNorm(&q[j][0], m); if (norm < 0.000001f) { // vectors are linearly dependent or zero so no solution #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD(" - no solution, norm=%f", norm); #endif } return false; } Loading @@ -469,7 +473,7 @@ static bool solveLeastSquares(const std::vector<float>& x, const std::vector<flo r[j][i] = i < j ? 0 : vectorDot(&q[j][0], &a[i][0], m); } } #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD(" - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).c_str()); ALOGD(" - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).c_str()); Loading @@ -484,7 +488,7 @@ static bool solveLeastSquares(const std::vector<float>& x, const std::vector<flo } } ALOGD(" - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).c_str()); #endif } // Solve R B = Qt W Y to find B. This is easy because R is upper triangular. // We just work from bottom-right to top-left calculating B's coefficients. Loading @@ -500,9 +504,9 @@ static bool solveLeastSquares(const std::vector<float>& x, const std::vector<flo } outB[i] /= r[i][i]; } #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD(" - b=%s", vectorToString(outB, n).c_str()); #endif } // Calculate the coefficient of determination as 1 - (SSerr / SStot) where // SSerr is the residual sum of squares (variance of the error), Loading @@ -528,11 +532,11 @@ static bool solveLeastSquares(const std::vector<float>& x, const std::vector<flo sstot += w[h] * w[h] * var * var; } *outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1; #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD(" - sserr=%f", sserr); ALOGD(" - sstot=%f", sstot); ALOGD(" - det=%f", *outDet); #endif } return true; } Loading Loading @@ -655,13 +659,11 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id, outEstimator->time = newestMovement.eventTime; outEstimator->degree = degree; outEstimator->confidence = xdet * ydet; #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD("estimate: degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f", int(outEstimator->degree), vectorToString(outEstimator->xCoeff, n).c_str(), vectorToString(outEstimator->yCoeff, n).c_str(), outEstimator->confidence); #endif int(outEstimator->degree), vectorToString(outEstimator->xCoeff, n).c_str(), vectorToString(outEstimator->yCoeff, n).c_str(), outEstimator->confidence); } return true; } } Loading Loading @@ -1169,9 +1171,9 @@ bool ImpulseVelocityTrackerStrategy::getEstimator(uint32_t id, outEstimator->time = newestMovement.eventTime; outEstimator->degree = 2; // similar results to 2nd degree fit outEstimator->confidence = 1; #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD("velocity: (%f, %f)", outEstimator->xCoeff[1], outEstimator->yCoeff[1]); #endif } return true; } Loading libs/input/tests/VelocityTracker_test.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -343,7 +343,7 @@ TEST_F(VelocityTrackerTest, SailfishFlingUpSlow1) { { 235089162955851ns, {{560.66, 843.82}} }, // ACTION_UP }; computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X, 872.794617); 764.345703); computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X, 951.698181); computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_Y, Loading Loading
libs/input/VelocityTracker.cpp +71 −69 Original line number Diff line number Diff line Loading @@ -18,10 +18,10 @@ //#define LOG_NDEBUG 0 // Log debug messages about velocity tracking. #define DEBUG_VELOCITY 0 static constexpr bool DEBUG_VELOCITY = false; // Log debug messages about the progress of the algorithm itself. #define DEBUG_STRATEGY 0 static constexpr bool DEBUG_STRATEGY = false; #include <array> #include <inttypes.h> Loading @@ -30,7 +30,6 @@ #include <optional> #include <android-base/stringprintf.h> #include <cutils/properties.h> #include <input/VelocityTracker.h> #include <utils/BitSet.h> #include <utils/Timers.h> Loading Loading @@ -64,7 +63,6 @@ static float vectorNorm(const float* a, uint32_t m) { return sqrtf(r); } #if DEBUG_STRATEGY || DEBUG_VELOCITY static std::string vectorToString(const float* a, uint32_t m) { std::string str; str += "["; Loading @@ -77,9 +75,11 @@ static std::string vectorToString(const float* a, uint32_t m) { str += " ]"; return str; } #endif #if DEBUG_STRATEGY static std::string vectorToString(const std::vector<float>& v) { return vectorToString(v.data(), v.size()); } static std::string matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMajor) { std::string str; str = "["; Loading @@ -99,7 +99,6 @@ static std::string matrixToString(const float* a, uint32_t m, uint32_t n, bool r str += " ]"; return str; } #endif // --- VelocityTracker --- Loading Loading @@ -133,12 +132,18 @@ std::unique_ptr<VelocityTrackerStrategy> VelocityTracker::createStrategy( VelocityTracker::Strategy strategy) { switch (strategy) { case VelocityTracker::Strategy::IMPULSE: if (DEBUG_STRATEGY) { ALOGI("Initializing impulse strategy"); } return std::make_unique<ImpulseVelocityTrackerStrategy>(); case VelocityTracker::Strategy::LSQ1: return std::make_unique<LeastSquaresVelocityTrackerStrategy>(1); case VelocityTracker::Strategy::LSQ2: if (DEBUG_STRATEGY) { ALOGI("Initializing lsq2 strategy"); } return std::make_unique<LeastSquaresVelocityTrackerStrategy>(2); case VelocityTracker::Strategy::LSQ3: Loading Loading @@ -204,10 +209,10 @@ void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, if ((mCurrentPointerIdBits.value & idBits.value) && eventTime >= mLastEventTime + ASSUME_POINTER_STOPPED_TIME) { #if DEBUG_VELOCITY if (DEBUG_VELOCITY) { ALOGD("VelocityTracker: stopped for %0.3f ms, clearing state.", (eventTime - mLastEventTime) * 0.000001f); #endif } // We have not received any movements for too long. Assume that all pointers // have stopped. mStrategy->clear(); Loading @@ -221,8 +226,9 @@ void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, mStrategy->addMovement(eventTime, idBits, positions); #if DEBUG_VELOCITY ALOGD("VelocityTracker: addMovement eventTime=%" PRId64 ", idBits=0x%08x, activePointerId=%d", if (DEBUG_VELOCITY) { ALOGD("VelocityTracker: addMovement eventTime=%" PRId64 ", idBits=0x%08x, activePointerId=%d", eventTime, idBits.value, mActivePointerId); for (BitSet32 iterBits(idBits); !iterBits.isEmpty();) { uint32_t id = iterBits.firstMarkedBit(); Loading @@ -232,13 +238,12 @@ void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, getEstimator(id, &estimator); ALOGD(" %d: position (%0.3f, %0.3f), " "estimator (degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f)", id, positions[index].x, positions[index].y, int(estimator.degree), id, positions[index].x, positions[index].y, int(estimator.degree), vectorToString(estimator.xCoeff, estimator.degree + 1).c_str(), vectorToString(estimator.yCoeff, estimator.degree + 1).c_str(), estimator.confidence); } #endif } } void VelocityTracker::addMovement(const MotionEvent* event) { Loading Loading @@ -419,11 +424,10 @@ void LeastSquaresVelocityTrackerStrategy::addMovement( static bool solveLeastSquares(const std::vector<float>& x, const std::vector<float>& y, const std::vector<float>& w, uint32_t n, float* outB, float* outDet) { const size_t m = x.size(); #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s, w=%s", int(m), int(n), vectorToString(x, m).c_str(), vectorToString(y, m).c_str(), vectorToString(w, m).c_str()); #endif vectorToString(x).c_str(), vectorToString(y).c_str(), vectorToString(w).c_str()); } LOG_ALWAYS_FATAL_IF(m != y.size() || m != w.size(), "Mismatched vector sizes"); // Expand the X vector to a matrix A, pre-multiplied by the weights. Loading @@ -434,9 +438,9 @@ static bool solveLeastSquares(const std::vector<float>& x, const std::vector<flo a[i][h] = a[i - 1][h] * x[h]; } } #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD(" - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).c_str()); #endif } // Apply the Gram-Schmidt process to A to obtain its QR decomposition. float q[n][m]; // orthonormal basis, column-major order Loading @@ -455,9 +459,9 @@ static bool solveLeastSquares(const std::vector<float>& x, const std::vector<flo float norm = vectorNorm(&q[j][0], m); if (norm < 0.000001f) { // vectors are linearly dependent or zero so no solution #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD(" - no solution, norm=%f", norm); #endif } return false; } Loading @@ -469,7 +473,7 @@ static bool solveLeastSquares(const std::vector<float>& x, const std::vector<flo r[j][i] = i < j ? 0 : vectorDot(&q[j][0], &a[i][0], m); } } #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD(" - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).c_str()); ALOGD(" - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).c_str()); Loading @@ -484,7 +488,7 @@ static bool solveLeastSquares(const std::vector<float>& x, const std::vector<flo } } ALOGD(" - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).c_str()); #endif } // Solve R B = Qt W Y to find B. This is easy because R is upper triangular. // We just work from bottom-right to top-left calculating B's coefficients. Loading @@ -500,9 +504,9 @@ static bool solveLeastSquares(const std::vector<float>& x, const std::vector<flo } outB[i] /= r[i][i]; } #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD(" - b=%s", vectorToString(outB, n).c_str()); #endif } // Calculate the coefficient of determination as 1 - (SSerr / SStot) where // SSerr is the residual sum of squares (variance of the error), Loading @@ -528,11 +532,11 @@ static bool solveLeastSquares(const std::vector<float>& x, const std::vector<flo sstot += w[h] * w[h] * var * var; } *outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1; #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD(" - sserr=%f", sserr); ALOGD(" - sstot=%f", sstot); ALOGD(" - det=%f", *outDet); #endif } return true; } Loading Loading @@ -655,13 +659,11 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id, outEstimator->time = newestMovement.eventTime; outEstimator->degree = degree; outEstimator->confidence = xdet * ydet; #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD("estimate: degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f", int(outEstimator->degree), vectorToString(outEstimator->xCoeff, n).c_str(), vectorToString(outEstimator->yCoeff, n).c_str(), outEstimator->confidence); #endif int(outEstimator->degree), vectorToString(outEstimator->xCoeff, n).c_str(), vectorToString(outEstimator->yCoeff, n).c_str(), outEstimator->confidence); } return true; } } Loading Loading @@ -1169,9 +1171,9 @@ bool ImpulseVelocityTrackerStrategy::getEstimator(uint32_t id, outEstimator->time = newestMovement.eventTime; outEstimator->degree = 2; // similar results to 2nd degree fit outEstimator->confidence = 1; #if DEBUG_STRATEGY if (DEBUG_STRATEGY) { ALOGD("velocity: (%f, %f)", outEstimator->xCoeff[1], outEstimator->yCoeff[1]); #endif } return true; } Loading
libs/input/tests/VelocityTracker_test.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -343,7 +343,7 @@ TEST_F(VelocityTrackerTest, SailfishFlingUpSlow1) { { 235089162955851ns, {{560.66, 843.82}} }, // ACTION_UP }; computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X, 872.794617); 764.345703); computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X, 951.698181); computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_Y, Loading