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

Commit bbfbd090 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou Committed by android-build-merger
Browse files

Merge "Native tests for VelocityTracker::getEstimate" am: c7691e69

am: 7f7cb357

Change-Id: Iab65af4b781a0ef868f37b49a1deaf214804dd2e
parents 39218361 7f7cb357
Loading
Loading
Loading
Loading
+147 −18
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


#define LOG_TAG "VelocityTracker_test"
#define LOG_TAG "VelocityTracker_test"


#include <array>
#include <math.h>
#include <math.h>


#include <android-base/stringprintf.h>
#include <android-base/stringprintf.h>
@@ -32,29 +33,35 @@ constexpr int32_t DEFAULT_POINTER_ID = 0; // pointer ID used for manually define
// here EV = expected value, tol = VELOCITY_TOLERANCE
// here EV = expected value, tol = VELOCITY_TOLERANCE
constexpr float VELOCITY_TOLERANCE = 0.2;
constexpr float VELOCITY_TOLERANCE = 0.2;


// estimate coefficients must be within 0.001% of the target value
constexpr float COEFFICIENT_TOLERANCE = 0.00001;

// --- VelocityTrackerTest ---
// --- VelocityTrackerTest ---
class VelocityTrackerTest : public testing::Test { };
class VelocityTrackerTest : public testing::Test { };


static void checkVelocity(float Vactual, float Vtarget) {
/*
    // Compare directions
 * Similar to EXPECT_NEAR, but ensures that the difference between the two float values
    if ((Vactual > 0 && Vtarget <= 0) || (Vactual < 0 && Vtarget >= 0)) {
 * is at most a certain fraction of the target value.
        FAIL() << StringPrintf("Velocity %f does not have the same direction"
 * If fraction is zero, require exact match.
                " as the target velocity %f", Vactual, Vtarget);
 */
    }
static void EXPECT_NEAR_BY_FRACTION(float actual, float target, float fraction) {
    float tolerance = fabsf(target * fraction);


    // Compare magnitudes
    if (target == 0 && fraction != 0) {
    const float Vlower = fabsf(Vtarget * (1 - VELOCITY_TOLERANCE));
        // If target is zero, this would force actual == target, which is too harsh.
    const float Vupper = fabsf(Vtarget * (1 + VELOCITY_TOLERANCE));
        // Relax this requirement a little. The value is determined empirically from the
    if (fabsf(Vactual) < Vlower) {
        // coefficients computed by the quadratic least squares algorithms.
        FAIL() << StringPrintf("Velocity %f is more than %.0f%% below target velocity %f",
        tolerance = 1E-6;
                Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
    }
    }
    if (fabsf(Vactual) > Vupper) {
    EXPECT_NEAR(actual, target, tolerance);
        FAIL() << StringPrintf("Velocity %f is more than %.0f%% above target velocity %f",
                Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
}
}
    SUCCEED() << StringPrintf("Velocity %f within %.0f%% of target %f)",

            Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
static void checkVelocity(float Vactual, float Vtarget) {
    EXPECT_NEAR_BY_FRACTION(Vactual, Vtarget, VELOCITY_TOLERANCE);
}

static void checkCoefficient(float actual, float target) {
    EXPECT_NEAR_BY_FRACTION(actual, target, COEFFICIENT_TOLERANCE);
}
}


void failWithMessage(std::string message) {
void failWithMessage(std::string message) {
@@ -123,6 +130,19 @@ static void computeAndCheckVelocity(const Position* positions, size_t numSamples
    delete event;
    delete event;
}
}


static void computeAndCheckQuadraticEstimate(const Position* positions, size_t numSamples,
        const std::array<float, 3>& coefficients) {
    VelocityTracker vt("lsq2");
    MotionEvent* event = createSimpleMotionEvent(positions, numSamples);
    vt.addMovement(event);
    VelocityTracker::Estimator estimator;
    EXPECT_TRUE(vt.getEstimator(0, &estimator));
    for (size_t i = 0; i< coefficients.size(); i++) {
        checkCoefficient(estimator.xCoeff[i], coefficients[i]);
        checkCoefficient(estimator.yCoeff[i], coefficients[i]);
    }
}

/*
/*
 * ================== VelocityTracker tests generated manually =====================================
 * ================== VelocityTracker tests generated manually =====================================
 */
 */
@@ -660,5 +680,114 @@ TEST_F(VelocityTrackerTest, SailfishFlingDownFast3) {
    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 28354.796875); // lsq2
    computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 28354.796875); // lsq2
}
}


/*
 * Special care must be taken when constructing tests for LeastSquaresVelocityTrackerStrategy
 * getEstimator function. In particular:
 * - inside the function, time gets converted from nanoseconds to seconds
 *   before being used in the fit.
 * - any values that are older than 100 ms are being discarded.
 * - the newest time gets subtracted from all of the other times before being used in the fit.
 * So these tests have to be designed with those limitations in mind.
 *
 * General approach for the tests below:
 * We only used timestamps in milliseconds, 0 ms, 1 ms, and 2 ms, to be sure that
 * we are well within the HORIZON range.
 * When specifying the expected values of the coefficients, we treat the x values as if
 * they were in ms. Then, to adjust for the time units, the coefficients get progressively
 * multiplied by powers of 1E3.
 * For example:
 * data: t(ms), x
 *        1 ms, 1
 *        2 ms, 4
 *        3 ms, 9
 * The coefficients are (0, 0, 1).
 * In the test, we would convert these coefficients to (0*(1E3)^0, 0*(1E3)^1, 1*(1E3)^2).
 */
TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Constant) {
    Position values[] = {
        { 0000000, 1, 1 }, // 0 s
        { 1000000, 1, 1 }, // 0.001 s
        { 2000000, 1, 1 }, // 0.002 s
    };
    // The data used for the fit will be as follows:
    // time(s), position
    // -0.002, 1
    // -0.001, 1
    // -0.000, 1
    size_t count = sizeof(values) / sizeof(Position);
    computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({1, 0, 0}));
}

/*
 * Straight line y = x :: the constant and quadratic coefficients are zero.
 */
TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Linear) {
    Position values[] = {
        { 0000000, -2, -2 },
        { 1000000, -1, -1 },
        { 2000000, -0, -0 },
    };
    // The data used for the fit will be as follows:
    // time(s), position
    // -0.002, -2
    // -0.001, -1
    // -0.000,  0
    size_t count = sizeof(values) / sizeof(Position);
    computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({0, 1E3, 0}));
}

/*
 * Parabola
 */
TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic) {
    Position values[] = {
        { 0000000, 1, 1 },
        { 1000000, 4, 4 },
        { 2000000, 8, 8 },
    };
    // The data used for the fit will be as follows:
    // time(s), position
    // -0.002, 1
    // -0.001, 4
    // -0.000, 8
    size_t count = sizeof(values) / sizeof(Position);
    computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({8, 4.5E3, 0.5E6}));
}

/*
 * Parabola
 */
TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic2) {
    Position values[] = {
        { 0000000, 1, 1 },
        { 1000000, 4, 4 },
        { 2000000, 9, 9 },
    };
    // The data used for the fit will be as follows:
    // time(s), position
    // -0.002, 1
    // -0.001, 4
    // -0.000, 9
    size_t count = sizeof(values) / sizeof(Position);
    computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({9, 6E3, 1E6}));
}

/*
 * Parabola :: y = x^2 :: the constant and linear coefficients are zero.
 */
TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic3) {
    Position values[] = {
        { 0000000, 4, 4 },
        { 1000000, 1, 1 },
        { 2000000, 0, 0 },
    };
    // The data used for the fit will be as follows:
    // time(s), position
    // -0.002, 4
    // -0.001, 1
    // -0.000, 0
    size_t count = sizeof(values) / sizeof(Position);
    computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({0, 0E3, 1E6}));
}


} // namespace android
} // namespace android