summaryrefslogtreecommitdiff
path: root/libs/input/VelocityTracker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/input/VelocityTracker.cpp')
-rw-r--r--libs/input/VelocityTracker.cpp313
1 files changed, 150 insertions, 163 deletions
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 4f91af14ea..76aaf61da7 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -125,39 +125,29 @@ static std::string matrixToString(const float* a, uint32_t m, uint32_t n, bool r
// --- VelocityTracker ---
-const std::set<int32_t> VelocityTracker::SUPPORTED_AXES = {AMOTION_EVENT_AXIS_X,
- AMOTION_EVENT_AXIS_Y};
-
-const std::set<int32_t> VelocityTracker::PLANAR_AXES = {AMOTION_EVENT_AXIS_X, AMOTION_EVENT_AXIS_Y};
-
VelocityTracker::VelocityTracker(const Strategy strategy)
: mLastEventTime(0), mCurrentPointerIdBits(0), mActivePointerId(-1) {
- // Configure the strategy for each axis.
- for (int32_t axis : SUPPORTED_AXES) {
- configureStrategy(axis, strategy);
+ // Configure the strategy.
+ if (!configureStrategy(strategy)) {
+ ALOGE("Unrecognized velocity tracker strategy %" PRId32 ".", strategy);
+ if (!configureStrategy(VelocityTracker::DEFAULT_STRATEGY)) {
+ LOG_ALWAYS_FATAL("Could not create the default velocity tracker strategy '%" PRId32
+ "'!",
+ strategy);
+ }
}
}
VelocityTracker::~VelocityTracker() {
}
-void VelocityTracker::configureStrategy(int32_t axis, const Strategy strategy) {
- std::unique_ptr<VelocityTrackerStrategy> createdStrategy;
-
+bool VelocityTracker::configureStrategy(Strategy strategy) {
if (strategy == VelocityTracker::Strategy::DEFAULT) {
- createdStrategy = createStrategy(VelocityTracker::DEFAULT_STRATEGY);
+ mStrategy = createStrategy(VelocityTracker::DEFAULT_STRATEGY);
} else {
- createdStrategy = createStrategy(strategy);
- }
-
- if (createdStrategy == nullptr) {
- ALOGE("Unrecognized velocity tracker strategy %" PRId32 ".", strategy);
- createdStrategy = createStrategy(VelocityTracker::DEFAULT_STRATEGY);
- LOG_ALWAYS_FATAL_IF(createdStrategy == nullptr,
- "Could not create the default velocity tracker strategy '%" PRId32 "'!",
- strategy);
+ mStrategy = createStrategy(strategy);
}
- mStrategies[axis] = std::move(createdStrategy);
+ return mStrategy != nullptr;
}
std::unique_ptr<VelocityTrackerStrategy> VelocityTracker::createStrategy(
@@ -211,9 +201,8 @@ std::unique_ptr<VelocityTrackerStrategy> VelocityTracker::createStrategy(
void VelocityTracker::clear() {
mCurrentPointerIdBits.clear();
mActivePointerId = -1;
- for (int32_t axis : SUPPORTED_AXES) {
- mStrategies[axis]->clear();
- }
+
+ mStrategy->clear();
}
void VelocityTracker::clearPointers(BitSet32 idBits) {
@@ -224,13 +213,14 @@ void VelocityTracker::clearPointers(BitSet32 idBits) {
mActivePointerId = !remainingIdBits.isEmpty() ? remainingIdBits.firstMarkedBit() : -1;
}
- for (int32_t axis : SUPPORTED_AXES) {
- mStrategies[axis]->clearPointers(idBits);
- }
+ mStrategy->clearPointers(idBits);
}
void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits,
- const std::map<int32_t /*axis*/, std::vector<float>>& positions) {
+ const std::vector<VelocityTracker::Position>& positions) {
+ LOG_ALWAYS_FATAL_IF(idBits.count() != positions.size(),
+ "Mismatching number of pointers, idBits=%" PRIu32 ", positions=%zu",
+ idBits.count(), positions.size());
while (idBits.count() > MAX_POINTERS) {
idBits.clearLastMarkedBit();
}
@@ -242,9 +232,7 @@ void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits,
// We have not received any movements for too long. Assume that all pointers
// have stopped.
- for (const auto& [_, strategy] : mStrategies) {
- strategy->clear();
- }
+ mStrategy->clear();
}
mLastEventTime = eventTime;
@@ -253,37 +241,29 @@ void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits,
mActivePointerId = idBits.isEmpty() ? -1 : idBits.firstMarkedBit();
}
- for (const auto& [axis, positionValues] : positions) {
- LOG_ALWAYS_FATAL_IF(idBits.count() != positionValues.size(),
- "Mismatching number of pointers, idBits=%" PRIu32 ", positions=%zu",
- idBits.count(), positionValues.size());
- mStrategies[axis]->addMovement(eventTime, idBits, positionValues);
- }
+ mStrategy->addMovement(eventTime, idBits, positions);
if (DEBUG_VELOCITY) {
ALOGD("VelocityTracker: addMovement eventTime=%" PRId64
", idBits=0x%08x, activePointerId=%d",
eventTime, idBits.value, mActivePointerId);
- for (const auto& positionsEntry : positions) {
- for (BitSet32 iterBits(idBits); !iterBits.isEmpty();) {
- uint32_t id = iterBits.firstMarkedBit();
- uint32_t index = idBits.getIndexOfBit(id);
- iterBits.clearBit(id);
- Estimator estimator;
- getEstimator(positionsEntry.first, id, &estimator);
- ALOGD(" %d: axis=%d, position=%0.3f, "
- "estimator (degree=%d, coeff=%s, confidence=%f)",
- id, positionsEntry.first, positionsEntry.second[index], int(estimator.degree),
- vectorToString(estimator.coeff, estimator.degree + 1).c_str(),
- estimator.confidence);
- }
+ for (BitSet32 iterBits(idBits); !iterBits.isEmpty();) {
+ uint32_t id = iterBits.firstMarkedBit();
+ uint32_t index = idBits.getIndexOfBit(id);
+ iterBits.clearBit(id);
+ Estimator estimator;
+ 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),
+ vectorToString(estimator.xCoeff, estimator.degree + 1).c_str(),
+ vectorToString(estimator.yCoeff, estimator.degree + 1).c_str(),
+ estimator.confidence);
}
}
}
void VelocityTracker::addMovement(const MotionEvent* event) {
- // Stores data about which axes to process based on the incoming motion event.
- std::set<int32_t> axesToProcess;
int32_t actionMasked = event->getActionMasked();
switch (actionMasked) {
@@ -291,9 +271,6 @@ void VelocityTracker::addMovement(const MotionEvent* event) {
case AMOTION_EVENT_ACTION_HOVER_ENTER:
// Clear all pointers on down before adding the new movement.
clear();
- for (int32_t axis : PLANAR_AXES) {
- axesToProcess.insert(axis);
- }
break;
case AMOTION_EVENT_ACTION_POINTER_DOWN: {
// Start a new movement trace for a pointer that just went down.
@@ -302,16 +279,10 @@ void VelocityTracker::addMovement(const MotionEvent* event) {
BitSet32 downIdBits;
downIdBits.markBit(event->getPointerId(event->getActionIndex()));
clearPointers(downIdBits);
- for (int32_t axis : PLANAR_AXES) {
- axesToProcess.insert(axis);
- }
break;
}
case AMOTION_EVENT_ACTION_MOVE:
case AMOTION_EVENT_ACTION_HOVER_MOVE:
- for (int32_t axis : PLANAR_AXES) {
- axesToProcess.insert(axis);
- }
break;
case AMOTION_EVENT_ACTION_POINTER_UP:
case AMOTION_EVENT_ACTION_UP: {
@@ -322,9 +293,7 @@ void VelocityTracker::addMovement(const MotionEvent* event) {
toString(delaySinceLastEvent).c_str());
// We have not received any movements for too long. Assume that all pointers
// have stopped.
- for (int32_t axis : PLANAR_AXES) {
- mStrategies[axis]->clear();
- }
+ mStrategy->clear();
}
// These actions because they do not convey any new information about
// pointer movement. We also want to preserve the last known velocity of the pointers.
@@ -356,54 +325,37 @@ void VelocityTracker::addMovement(const MotionEvent* event) {
pointerIndex[i] = idBits.getIndexOfBit(event->getPointerId(i));
}
- std::map<int32_t, std::vector<float>> positions;
- for (int32_t axis : axesToProcess) {
- positions[axis].resize(pointerCount);
- }
+ std::vector<Position> positions;
+ positions.resize(pointerCount);
size_t historySize = event->getHistorySize();
for (size_t h = 0; h <= historySize; h++) {
nsecs_t eventTime = event->getHistoricalEventTime(h);
- for (int32_t axis : axesToProcess) {
- for (size_t i = 0; i < pointerCount; i++) {
- positions[axis][pointerIndex[i]] = event->getHistoricalAxisValue(axis, i, h);
- }
+ for (size_t i = 0; i < pointerCount; i++) {
+ uint32_t index = pointerIndex[i];
+ positions[index].x = event->getHistoricalX(i, h);
+ positions[index].y = event->getHistoricalY(i, h);
}
addMovement(eventTime, idBits, positions);
}
}
-std::optional<float> VelocityTracker::getVelocity(int32_t axis, uint32_t id) const {
+bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const {
Estimator estimator;
- bool validVelocity = getEstimator(axis, id, &estimator) && estimator.degree >= 1;
- if (validVelocity) {
- return estimator.coeff[1];
+ if (getEstimator(id, &estimator) && estimator.degree >= 1) {
+ *outVx = estimator.xCoeff[1];
+ *outVy = estimator.yCoeff[1];
+ return true;
}
- return {};
+ *outVx = 0;
+ *outVy = 0;
+ return false;
}
-void VelocityTracker::populateComputedVelocity(ComputedVelocity& computedVelocity, int32_t units,
- float maxVelocity) {
- for (int32_t axis : SUPPORTED_AXES) {
- BitSet32 copyIdBits = BitSet32(mCurrentPointerIdBits);
- while (!copyIdBits.isEmpty()) {
- uint32_t id = copyIdBits.clearFirstMarkedBit();
- std::optional<float> velocity = getVelocity(axis, id);
- if (velocity) {
- float adjustedVelocity =
- std::clamp(*velocity * units / 1000, -maxVelocity, maxVelocity);
- computedVelocity.addVelocity(axis, id, adjustedVelocity);
- }
- }
- }
+bool VelocityTracker::getEstimator(uint32_t id, Estimator* outEstimator) const {
+ return mStrategy->getEstimator(id, outEstimator);
}
-bool VelocityTracker::getEstimator(int32_t axis, uint32_t id, Estimator* outEstimator) const {
- if (SUPPORTED_AXES.find(axis) == SUPPORTED_AXES.end()) {
- return false;
- }
- return mStrategies.at(axis)->getEstimator(id, outEstimator);
-}
// --- LeastSquaresVelocityTrackerStrategy ---
@@ -426,8 +378,9 @@ void LeastSquaresVelocityTrackerStrategy::clearPointers(BitSet32 idBits) {
mMovements[mIndex].idBits = remainingIdBits;
}
-void LeastSquaresVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits,
- const std::vector<float>& positions) {
+void LeastSquaresVelocityTrackerStrategy::addMovement(
+ nsecs_t eventTime, BitSet32 idBits,
+ const std::vector<VelocityTracker::Position>& positions) {
if (mMovements[mIndex].eventTime != eventTime) {
// When ACTION_POINTER_DOWN happens, we will first receive ACTION_MOVE with the coordinates
// of the existing pointers, and then ACTION_POINTER_DOWN with the coordinates that include
@@ -674,7 +627,8 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
outEstimator->clear();
// Iterate over movement samples in reverse time order and collect samples.
- std::vector<float> positions;
+ std::vector<float> x;
+ std::vector<float> y;
std::vector<float> w;
std::vector<float> time;
@@ -691,13 +645,15 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
break;
}
- positions.push_back(movement.getPosition(id));
+ const VelocityTracker::Position& position = movement.getPosition(id);
+ x.push_back(position.x);
+ y.push_back(position.y);
w.push_back(chooseWeight(index));
time.push_back(-age * 0.000000001f);
index = (index == 0 ? HISTORY_SIZE : index) - 1;
- } while (positions.size() < HISTORY_SIZE);
+ } while (x.size() < HISTORY_SIZE);
- const size_t m = positions.size();
+ const size_t m = x.size();
if (m == 0) {
return false; // no data
}
@@ -710,36 +666,39 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
if (degree == 2 && mWeighting == WEIGHTING_NONE) {
// Optimize unweighted, quadratic polynomial fit
- std::optional<std::array<float, 3>> coeff =
- solveUnweightedLeastSquaresDeg2(time, positions);
- if (coeff) {
+ std::optional<std::array<float, 3>> xCoeff = solveUnweightedLeastSquaresDeg2(time, x);
+ std::optional<std::array<float, 3>> yCoeff = solveUnweightedLeastSquaresDeg2(time, y);
+ if (xCoeff && yCoeff) {
outEstimator->time = newestMovement.eventTime;
outEstimator->degree = 2;
outEstimator->confidence = 1;
for (size_t i = 0; i <= outEstimator->degree; i++) {
- outEstimator->coeff[i] = (*coeff)[i];
+ outEstimator->xCoeff[i] = (*xCoeff)[i];
+ outEstimator->yCoeff[i] = (*yCoeff)[i];
}
return true;
}
} else if (degree >= 1) {
// General case for an Nth degree polynomial fit
- float det;
+ float xdet, ydet;
uint32_t n = degree + 1;
- if (solveLeastSquares(time, positions, w, n, outEstimator->coeff, &det)) {
+ if (solveLeastSquares(time, x, w, n, outEstimator->xCoeff, &xdet) &&
+ solveLeastSquares(time, y, w, n, outEstimator->yCoeff, &ydet)) {
outEstimator->time = newestMovement.eventTime;
outEstimator->degree = degree;
- outEstimator->confidence = det;
+ outEstimator->confidence = xdet * ydet;
- ALOGD_IF(DEBUG_STRATEGY, "estimate: degree=%d, coeff=%s, confidence=%f",
- int(outEstimator->degree), vectorToString(outEstimator->coeff, n).c_str(),
- outEstimator->confidence);
+ ALOGD_IF(DEBUG_STRATEGY, "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);
return true;
}
}
// No velocity data available for this pointer, but we do have its current position.
- outEstimator->coeff[0] = positions[0];
+ outEstimator->xCoeff[0] = x[0];
+ outEstimator->yCoeff[0] = y[0];
outEstimator->time = newestMovement.eventTime;
outEstimator->degree = 0;
outEstimator->confidence = 1;
@@ -831,17 +790,18 @@ void IntegratingVelocityTrackerStrategy::clearPointers(BitSet32 idBits) {
mPointerIdBits.value &= ~idBits.value;
}
-void IntegratingVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits,
- const std::vector<float>& positions) {
+void IntegratingVelocityTrackerStrategy::addMovement(
+ nsecs_t eventTime, BitSet32 idBits,
+ const std::vector<VelocityTracker::Position>& positions) {
uint32_t index = 0;
for (BitSet32 iterIdBits(idBits); !iterIdBits.isEmpty();) {
uint32_t id = iterIdBits.clearFirstMarkedBit();
State& state = mPointerState[id];
- const float position = positions[index++];
+ const VelocityTracker::Position& position = positions[index++];
if (mPointerIdBits.hasBit(id)) {
- updateState(state, eventTime, position);
+ updateState(state, eventTime, position.x, position.y);
} else {
- initState(state, eventTime, position);
+ initState(state, eventTime, position.x, position.y);
}
}
@@ -861,18 +821,21 @@ bool IntegratingVelocityTrackerStrategy::getEstimator(uint32_t id,
return false;
}
-void IntegratingVelocityTrackerStrategy::initState(State& state, nsecs_t eventTime,
- float pos) const {
+void IntegratingVelocityTrackerStrategy::initState(State& state,
+ nsecs_t eventTime, float xpos, float ypos) const {
state.updateTime = eventTime;
state.degree = 0;
- state.pos = pos;
- state.accel = 0;
- state.vel = 0;
+ state.xpos = xpos;
+ state.xvel = 0;
+ state.xaccel = 0;
+ state.ypos = ypos;
+ state.yvel = 0;
+ state.yaccel = 0;
}
-void IntegratingVelocityTrackerStrategy::updateState(State& state, nsecs_t eventTime,
- float pos) const {
+void IntegratingVelocityTrackerStrategy::updateState(State& state,
+ nsecs_t eventTime, float xpos, float ypos) const {
const nsecs_t MIN_TIME_DELTA = 2 * NANOS_PER_MS;
const float FILTER_TIME_CONSTANT = 0.010f; // 10 milliseconds
@@ -883,26 +846,34 @@ void IntegratingVelocityTrackerStrategy::updateState(State& state, nsecs_t event
float dt = (eventTime - state.updateTime) * 0.000000001f;
state.updateTime = eventTime;
- float vel = (pos - state.pos) / dt;
+ float xvel = (xpos - state.xpos) / dt;
+ float yvel = (ypos - state.ypos) / dt;
if (state.degree == 0) {
- state.vel = vel;
+ state.xvel = xvel;
+ state.yvel = yvel;
state.degree = 1;
} else {
float alpha = dt / (FILTER_TIME_CONSTANT + dt);
if (mDegree == 1) {
- state.vel += (vel - state.vel) * alpha;
+ state.xvel += (xvel - state.xvel) * alpha;
+ state.yvel += (yvel - state.yvel) * alpha;
} else {
- float accel = (vel - state.vel) / dt;
+ float xaccel = (xvel - state.xvel) / dt;
+ float yaccel = (yvel - state.yvel) / dt;
if (state.degree == 1) {
- state.accel = accel;
+ state.xaccel = xaccel;
+ state.yaccel = yaccel;
state.degree = 2;
} else {
- state.accel += (accel - state.accel) * alpha;
+ state.xaccel += (xaccel - state.xaccel) * alpha;
+ state.yaccel += (yaccel - state.yaccel) * alpha;
}
- state.vel += (state.accel * dt) * alpha;
+ state.xvel += (state.xaccel * dt) * alpha;
+ state.yvel += (state.yaccel * dt) * alpha;
}
}
- state.pos = pos;
+ state.xpos = xpos;
+ state.ypos = ypos;
}
void IntegratingVelocityTrackerStrategy::populateEstimator(const State& state,
@@ -910,9 +881,12 @@ void IntegratingVelocityTrackerStrategy::populateEstimator(const State& state,
outEstimator->time = state.updateTime;
outEstimator->confidence = 1.0f;
outEstimator->degree = state.degree;
- outEstimator->coeff[0] = state.pos;
- outEstimator->coeff[1] = state.vel;
- outEstimator->coeff[2] = state.accel / 2;
+ outEstimator->xCoeff[0] = state.xpos;
+ outEstimator->xCoeff[1] = state.xvel;
+ outEstimator->xCoeff[2] = state.xaccel / 2;
+ outEstimator->yCoeff[0] = state.ypos;
+ outEstimator->yCoeff[1] = state.yvel;
+ outEstimator->yCoeff[2] = state.yaccel / 2;
}
@@ -935,8 +909,9 @@ void LegacyVelocityTrackerStrategy::clearPointers(BitSet32 idBits) {
mMovements[mIndex].idBits = remainingIdBits;
}
-void LegacyVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits,
- const std::vector<float>& positions) {
+void LegacyVelocityTrackerStrategy::addMovement(
+ nsecs_t eventTime, BitSet32 idBits,
+ const std::vector<VelocityTracker::Position>& positions) {
if (++mIndex == HISTORY_SIZE) {
mIndex = 0;
}
@@ -984,11 +959,12 @@ bool LegacyVelocityTrackerStrategy::getEstimator(uint32_t id,
// overestimate the velocity at that time point. Most samples might be measured
// 16ms apart but some consecutive samples could be only 0.5sm apart because
// the hardware or driver reports them irregularly or in bursts.
- float accumV = 0;
+ float accumVx = 0;
+ float accumVy = 0;
uint32_t index = oldestIndex;
uint32_t samplesUsed = 0;
const Movement& oldestMovement = mMovements[oldestIndex];
- float oldestPosition = oldestMovement.getPosition(id);
+ const VelocityTracker::Position& oldestPosition = oldestMovement.getPosition(id);
nsecs_t lastDuration = 0;
while (numTouches-- > 1) {
@@ -1002,22 +978,26 @@ bool LegacyVelocityTrackerStrategy::getEstimator(uint32_t id,
// the velocity. Consequently, we impose a minimum duration constraint on the
// samples that we include in the calculation.
if (duration >= MIN_DURATION) {
- float position = movement.getPosition(id);
+ const VelocityTracker::Position& position = movement.getPosition(id);
float scale = 1000000000.0f / duration; // one over time delta in seconds
- float v = (position - oldestPosition) * scale;
- accumV = (accumV * lastDuration + v * duration) / (duration + lastDuration);
+ float vx = (position.x - oldestPosition.x) * scale;
+ float vy = (position.y - oldestPosition.y) * scale;
+ accumVx = (accumVx * lastDuration + vx * duration) / (duration + lastDuration);
+ accumVy = (accumVy * lastDuration + vy * duration) / (duration + lastDuration);
lastDuration = duration;
samplesUsed += 1;
}
}
// Report velocity.
- float newestPosition = newestMovement.getPosition(id);
+ const VelocityTracker::Position& newestPosition = newestMovement.getPosition(id);
outEstimator->time = newestMovement.eventTime;
outEstimator->confidence = 1;
- outEstimator->coeff[0] = newestPosition;
+ outEstimator->xCoeff[0] = newestPosition.x;
+ outEstimator->yCoeff[0] = newestPosition.y;
if (samplesUsed) {
- outEstimator->coeff[1] = accumV;
+ outEstimator->xCoeff[1] = accumVx;
+ outEstimator->yCoeff[1] = accumVy;
outEstimator->degree = 1;
} else {
outEstimator->degree = 0;
@@ -1044,8 +1024,9 @@ void ImpulseVelocityTrackerStrategy::clearPointers(BitSet32 idBits) {
mMovements[mIndex].idBits = remainingIdBits;
}
-void ImpulseVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits,
- const std::vector<float>& positions) {
+void ImpulseVelocityTrackerStrategy::addMovement(
+ nsecs_t eventTime, BitSet32 idBits,
+ const std::vector<VelocityTracker::Position>& positions) {
if (mMovements[mIndex].eventTime != eventTime) {
// When ACTION_POINTER_DOWN happens, we will first receive ACTION_MOVE with the coordinates
// of the existing pointers, and then ACTION_POINTER_DOWN with the coordinates that include
@@ -1182,7 +1163,8 @@ bool ImpulseVelocityTrackerStrategy::getEstimator(uint32_t id,
outEstimator->clear();
// Iterate over movement samples in reverse time order and collect samples.
- float positions[HISTORY_SIZE];
+ float x[HISTORY_SIZE];
+ float y[HISTORY_SIZE];
nsecs_t time[HISTORY_SIZE];
size_t m = 0; // number of points that will be used for fitting
size_t index = mIndex;
@@ -1198,7 +1180,9 @@ bool ImpulseVelocityTrackerStrategy::getEstimator(uint32_t id,
break;
}
- positions[m] = movement.getPosition(id);
+ const VelocityTracker::Position& position = movement.getPosition(id);
+ x[m] = position.x;
+ y[m] = position.y;
time[m] = movement.eventTime;
index = (index == 0 ? HISTORY_SIZE : index) - 1;
} while (++m < HISTORY_SIZE);
@@ -1206,30 +1190,33 @@ bool ImpulseVelocityTrackerStrategy::getEstimator(uint32_t id,
if (m == 0) {
return false; // no data
}
- outEstimator->coeff[0] = 0;
- outEstimator->coeff[1] = calculateImpulseVelocity(time, positions, m);
- outEstimator->coeff[2] = 0;
-
+ outEstimator->xCoeff[0] = 0;
+ outEstimator->yCoeff[0] = 0;
+ outEstimator->xCoeff[1] = calculateImpulseVelocity(time, x, m);
+ outEstimator->yCoeff[1] = calculateImpulseVelocity(time, y, m);
+ outEstimator->xCoeff[2] = 0;
+ outEstimator->yCoeff[2] = 0;
outEstimator->time = newestMovement.eventTime;
outEstimator->degree = 2; // similar results to 2nd degree fit
outEstimator->confidence = 1;
- ALOGD_IF(DEBUG_STRATEGY, "velocity: %.1f", outEstimator->coeff[1]);
+ ALOGD_IF(DEBUG_STRATEGY, "velocity: (%.1f, %.1f)", outEstimator->xCoeff[1],
+ outEstimator->yCoeff[1]);
if (DEBUG_IMPULSE) {
// TODO(b/134179997): delete this block once the switch to 'impulse' is complete.
- // Calculate the lsq2 velocity for the same inputs to allow runtime comparisons.
- // X axis chosen arbitrarily for velocity comparisons.
+ // Calculate the lsq2 velocity for the same inputs to allow runtime comparisons
VelocityTracker lsq2(VelocityTracker::Strategy::LSQ2);
BitSet32 idBits;
const uint32_t pointerId = 0;
idBits.markBit(pointerId);
for (ssize_t i = m - 1; i >= 0; i--) {
- lsq2.addMovement(time[i], idBits, {{AMOTION_EVENT_AXIS_X, {positions[i]}}});
+ lsq2.addMovement(time[i], idBits, {{x[i], y[i]}});
}
- std::optional<float> v = lsq2.getVelocity(AMOTION_EVENT_AXIS_X, pointerId);
- if (v) {
- ALOGD("lsq2 velocity: %.1f", *v);
+ float outVx = 0, outVy = 0;
+ const bool computed = lsq2.getVelocity(pointerId, &outVx, &outVy);
+ if (computed) {
+ ALOGD("lsq2 velocity: (%.1f, %.1f)", outVx, outVy);
} else {
ALOGD("lsq2 velocity: could not compute velocity");
}