Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e37bcece authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Use constexpr in VelocityTracker

Previously, defining DEBUG_STRATEGY as 1 would fail to compile.

In this patch, the defines are changed to bools, in order to fix this
going forward.

Also, when I was porting the velocitytracker algorithm to python, I
realized that one of the velocities was wrong. I updated the value. I
didn't check other values, though. It was previously passing likely
because the tolerance for velocity is quite large.

Bug: 192439431
Test: atest libinput_tests
Change-Id: I70b44af6cd5567ee8321b29e509c628fa0b4950e
parent a4cce653
Loading
Loading
Loading
Loading
+71 −69
Original line number Diff line number Diff line
@@ -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>
@@ -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>
@@ -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 += "[";
@@ -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 = "[";
@@ -99,7 +99,6 @@ static std::string matrixToString(const float* a, uint32_t m, uint32_t n, bool r
    str += " ]";
    return str;
}
#endif


// --- VelocityTracker ---
@@ -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:
@@ -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();
@@ -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();
@@ -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) {
@@ -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.
@@ -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
@@ -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;
        }

@@ -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());

@@ -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.
@@ -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),
@@ -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;
}

@@ -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;
        }
    }
@@ -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;
}

+1 −1
Original line number Diff line number Diff line
@@ -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,