Merge "Make velocity tracker strategy configurable." into jb-dev
This commit is contained in:
@@ -35,7 +35,7 @@ public final class VelocityTracker implements Poolable<VelocityTracker> {
|
||||
private static final Pool<VelocityTracker> sPool = Pools.synchronizedPool(
|
||||
Pools.finitePool(new PoolableManager<VelocityTracker>() {
|
||||
public VelocityTracker newInstance() {
|
||||
return new VelocityTracker();
|
||||
return new VelocityTracker(null);
|
||||
}
|
||||
|
||||
public void onAcquired(VelocityTracker element) {
|
||||
@@ -50,10 +50,12 @@ public final class VelocityTracker implements Poolable<VelocityTracker> {
|
||||
private static final int ACTIVE_POINTER_ID = -1;
|
||||
|
||||
private int mPtr;
|
||||
private final String mStrategy;
|
||||
|
||||
private VelocityTracker mNext;
|
||||
private boolean mIsPooled;
|
||||
|
||||
private static native int nativeInitialize();
|
||||
private static native int nativeInitialize(String strategy);
|
||||
private static native void nativeDispose(int ptr);
|
||||
private static native void nativeClear(int ptr);
|
||||
private static native void nativeAddMovement(int ptr, MotionEvent event);
|
||||
@@ -74,12 +76,30 @@ public final class VelocityTracker implements Poolable<VelocityTracker> {
|
||||
return sPool.acquire();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a velocity tracker with the specified strategy.
|
||||
* For testing and comparison purposes only.
|
||||
*
|
||||
* @param strategy The strategy, or null to use the default.
|
||||
* @return The velocity tracker.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static VelocityTracker obtain(String strategy) {
|
||||
if (strategy == null) {
|
||||
return obtain();
|
||||
}
|
||||
return new VelocityTracker(strategy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a VelocityTracker object back to be re-used by others. You must
|
||||
* not touch the object after calling this function.
|
||||
*/
|
||||
public void recycle() {
|
||||
sPool.release(this);
|
||||
if (mStrategy == null) {
|
||||
sPool.release(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,8 +130,9 @@ public final class VelocityTracker implements Poolable<VelocityTracker> {
|
||||
mIsPooled = isPooled;
|
||||
}
|
||||
|
||||
private VelocityTracker() {
|
||||
mPtr = nativeInitialize();
|
||||
private VelocityTracker(String strategy) {
|
||||
mPtr = nativeInitialize(strategy);
|
||||
mStrategy = strategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -253,7 +274,7 @@ public final class VelocityTracker implements Poolable<VelocityTracker> {
|
||||
*/
|
||||
public static final class Estimator {
|
||||
// Must match VelocityTracker::Estimator::MAX_DEGREE
|
||||
private static final int MAX_DEGREE = 2;
|
||||
private static final int MAX_DEGREE = 4;
|
||||
|
||||
/**
|
||||
* Polynomial coefficients describing motion in X.
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.graphics.RectF;
|
||||
import android.graphics.Paint.FontMetricsInt;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.hardware.input.InputManager.InputDeviceListener;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
@@ -36,7 +37,11 @@ import java.util.ArrayList;
|
||||
|
||||
public class PointerLocationView extends View implements InputDeviceListener {
|
||||
private static final String TAG = "Pointer";
|
||||
|
||||
|
||||
// The system property key used to specify an alternate velocity tracker strategy
|
||||
// to plot alongside the default one. Useful for testing and comparison purposes.
|
||||
private static final String ALT_STRATEGY_PROPERY_KEY = "debug.velocitytracker.alt";
|
||||
|
||||
public static class PointerState {
|
||||
// Trace of previous points.
|
||||
private float[] mTraceX = new float[32];
|
||||
@@ -53,9 +58,12 @@ public class PointerLocationView extends View implements InputDeviceListener {
|
||||
// Most recent velocity.
|
||||
private float mXVelocity;
|
||||
private float mYVelocity;
|
||||
private float mAltXVelocity;
|
||||
private float mAltYVelocity;
|
||||
|
||||
// Position estimator.
|
||||
private VelocityTracker.Estimator mEstimator = new VelocityTracker.Estimator();
|
||||
private VelocityTracker.Estimator mAltEstimator = new VelocityTracker.Estimator();
|
||||
|
||||
public void clearTrace() {
|
||||
mTraceCount = 0;
|
||||
@@ -103,7 +111,8 @@ public class PointerLocationView extends View implements InputDeviceListener {
|
||||
private final PointerCoords mTempCoords = new PointerCoords();
|
||||
|
||||
private final VelocityTracker mVelocity;
|
||||
|
||||
private final VelocityTracker mAltVelocity;
|
||||
|
||||
private final FasterStringBuilder mText = new FasterStringBuilder();
|
||||
|
||||
private boolean mPrintCoords = true;
|
||||
@@ -145,6 +154,14 @@ public class PointerLocationView extends View implements InputDeviceListener {
|
||||
mActivePointerId = 0;
|
||||
|
||||
mVelocity = VelocityTracker.obtain();
|
||||
|
||||
String altStrategy = SystemProperties.get(ALT_STRATEGY_PROPERY_KEY);
|
||||
if (altStrategy.length() != 0) {
|
||||
Log.d(TAG, "Comparing default velocity tracker strategy with " + altStrategy);
|
||||
mAltVelocity = VelocityTracker.obtain(altStrategy);
|
||||
} else {
|
||||
mAltVelocity = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setPrintCoords(boolean state) {
|
||||
@@ -296,6 +313,25 @@ public class PointerLocationView extends View implements InputDeviceListener {
|
||||
float xVel = ps.mXVelocity * (1000 / 60);
|
||||
float yVel = ps.mYVelocity * (1000 / 60);
|
||||
canvas.drawLine(lastX, lastY, lastX + xVel, lastY + yVel, mPaint);
|
||||
|
||||
// Draw alternate estimate.
|
||||
if (mAltVelocity != null) {
|
||||
mPaint.setARGB(128, 0, 128, 128);
|
||||
lx = ps.mAltEstimator.estimateX(-ESTIMATE_PAST_POINTS * ESTIMATE_INTERVAL);
|
||||
ly = ps.mAltEstimator.estimateY(-ESTIMATE_PAST_POINTS * ESTIMATE_INTERVAL);
|
||||
for (int i = -ESTIMATE_PAST_POINTS + 1; i <= ESTIMATE_FUTURE_POINTS; i++) {
|
||||
float x = ps.mAltEstimator.estimateX(i * ESTIMATE_INTERVAL);
|
||||
float y = ps.mAltEstimator.estimateY(i * ESTIMATE_INTERVAL);
|
||||
canvas.drawLine(lx, ly, x, y, mPaint);
|
||||
lx = x;
|
||||
ly = y;
|
||||
}
|
||||
|
||||
mPaint.setARGB(255, 64, 255, 128);
|
||||
xVel = ps.mAltXVelocity * (1000 / 60);
|
||||
yVel = ps.mAltYVelocity * (1000 / 60);
|
||||
canvas.drawLine(lastX, lastY, lastX + xVel, lastY + yVel, mPaint);
|
||||
}
|
||||
}
|
||||
|
||||
if (mCurDown && ps.mCurDown) {
|
||||
@@ -470,6 +506,9 @@ public class PointerLocationView extends View implements InputDeviceListener {
|
||||
mCurNumPointers = 0;
|
||||
mMaxNumPointers = 0;
|
||||
mVelocity.clear();
|
||||
if (mAltVelocity != null) {
|
||||
mAltVelocity.clear();
|
||||
}
|
||||
}
|
||||
|
||||
mCurNumPointers += 1;
|
||||
@@ -497,6 +536,10 @@ public class PointerLocationView extends View implements InputDeviceListener {
|
||||
|
||||
mVelocity.addMovement(event);
|
||||
mVelocity.computeCurrentVelocity(1);
|
||||
if (mAltVelocity != null) {
|
||||
mAltVelocity.addMovement(event);
|
||||
mAltVelocity.computeCurrentVelocity(1);
|
||||
}
|
||||
|
||||
final int N = event.getHistorySize();
|
||||
for (int historyPos = 0; historyPos < N; historyPos++) {
|
||||
@@ -528,6 +571,11 @@ public class PointerLocationView extends View implements InputDeviceListener {
|
||||
ps.mXVelocity = mVelocity.getXVelocity(id);
|
||||
ps.mYVelocity = mVelocity.getYVelocity(id);
|
||||
mVelocity.getEstimator(id, ps.mEstimator);
|
||||
if (mAltVelocity != null) {
|
||||
ps.mAltXVelocity = mAltVelocity.getXVelocity(id);
|
||||
ps.mAltYVelocity = mAltVelocity.getYVelocity(id);
|
||||
mAltVelocity.getEstimator(id, ps.mAltEstimator);
|
||||
}
|
||||
ps.mToolType = event.getToolType(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <androidfw/VelocityTracker.h>
|
||||
#include "android_view_MotionEvent.h"
|
||||
|
||||
#include <ScopedUtfChars.h>
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
@@ -42,7 +44,7 @@ static struct {
|
||||
|
||||
class VelocityTrackerState {
|
||||
public:
|
||||
VelocityTrackerState();
|
||||
VelocityTrackerState(const char* strategy);
|
||||
|
||||
void clear();
|
||||
void addMovement(const MotionEvent* event);
|
||||
@@ -61,7 +63,8 @@ private:
|
||||
Velocity mCalculatedVelocity[MAX_POINTERS];
|
||||
};
|
||||
|
||||
VelocityTrackerState::VelocityTrackerState() : mActivePointerId(-1) {
|
||||
VelocityTrackerState::VelocityTrackerState(const char* strategy) :
|
||||
mVelocityTracker(strategy), mActivePointerId(-1) {
|
||||
}
|
||||
|
||||
void VelocityTrackerState::clear() {
|
||||
@@ -135,8 +138,13 @@ bool VelocityTrackerState::getEstimator(int32_t id, VelocityTracker::Estimator*
|
||||
|
||||
// --- JNI Methods ---
|
||||
|
||||
static jint android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz) {
|
||||
return reinterpret_cast<jint>(new VelocityTrackerState());
|
||||
static jint android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz,
|
||||
jstring strategyStr) {
|
||||
if (strategyStr) {
|
||||
ScopedUtfChars strategy(env, strategyStr);
|
||||
return reinterpret_cast<jint>(new VelocityTrackerState(strategy.c_str()));
|
||||
}
|
||||
return reinterpret_cast<jint>(new VelocityTrackerState(NULL));
|
||||
}
|
||||
|
||||
static void android_view_VelocityTracker_nativeDispose(JNIEnv* env, jclass clazz, jint ptr) {
|
||||
@@ -209,7 +217,7 @@ static jboolean android_view_VelocityTracker_nativeGetEstimator(JNIEnv* env, jcl
|
||||
static JNINativeMethod gVelocityTrackerMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{ "nativeInitialize",
|
||||
"()I",
|
||||
"(Ljava/lang/String;)I",
|
||||
(void*)android_view_VelocityTracker_nativeInitialize },
|
||||
{ "nativeDispose",
|
||||
"(I)V",
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
};
|
||||
|
||||
struct Estimator {
|
||||
static const size_t MAX_DEGREE = 2;
|
||||
static const size_t MAX_DEGREE = 4;
|
||||
|
||||
// Estimator time base.
|
||||
nsecs_t time;
|
||||
@@ -61,7 +61,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
VelocityTracker();
|
||||
// Creates a velocity tracker using the specified strategy.
|
||||
// If strategy is NULL, uses the default strategy for the platform.
|
||||
VelocityTracker(const char* strategy = NULL);
|
||||
|
||||
~VelocityTracker();
|
||||
|
||||
// Resets the velocity tracker state.
|
||||
@@ -99,10 +102,16 @@ public:
|
||||
inline BitSet32 getCurrentPointerIdBits() const { return mCurrentPointerIdBits; }
|
||||
|
||||
private:
|
||||
static const char* DEFAULT_STRATEGY;
|
||||
|
||||
nsecs_t mLastEventTime;
|
||||
BitSet32 mCurrentPointerIdBits;
|
||||
int32_t mActivePointerId;
|
||||
VelocityTrackerStrategy* mStrategy;
|
||||
|
||||
bool configureStrategy(const char* strategy);
|
||||
|
||||
static VelocityTrackerStrategy* createStrategy(const char* strategy);
|
||||
};
|
||||
|
||||
|
||||
@@ -129,7 +138,8 @@ public:
|
||||
*/
|
||||
class LeastSquaresVelocityTrackerStrategy : public VelocityTrackerStrategy {
|
||||
public:
|
||||
LeastSquaresVelocityTrackerStrategy();
|
||||
// Degree must be no greater than Estimator::MAX_DEGREE.
|
||||
LeastSquaresVelocityTrackerStrategy(uint32_t degree);
|
||||
virtual ~LeastSquaresVelocityTrackerStrategy();
|
||||
|
||||
virtual void clear();
|
||||
@@ -139,9 +149,6 @@ public:
|
||||
virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const;
|
||||
|
||||
private:
|
||||
// Polynomial degree. Must be less than or equal to Estimator::MAX_DEGREE.
|
||||
static const uint32_t DEGREE = 2;
|
||||
|
||||
// Sample horizon.
|
||||
// We don't use too much history by default since we want to react to quick
|
||||
// changes in direction.
|
||||
@@ -160,6 +167,7 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
const uint32_t mDegree;
|
||||
uint32_t mIndex;
|
||||
Movement mMovements[HISTORY_SIZE];
|
||||
};
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
// Log debug messages about velocity tracking.
|
||||
#define DEBUG_VELOCITY 0
|
||||
|
||||
// Log debug messages about least squares fitting.
|
||||
#define DEBUG_LEAST_SQUARES 0
|
||||
// Log debug messages about the progress of the algorithm itself.
|
||||
#define DEBUG_STRATEGY 0
|
||||
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
@@ -31,6 +31,8 @@
|
||||
#include <utils/String8.h>
|
||||
#include <utils/Timers.h>
|
||||
|
||||
#include <cutils/properties.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// Nanoseconds per milliseconds.
|
||||
@@ -60,7 +62,7 @@ static float vectorNorm(const float* a, uint32_t m) {
|
||||
return sqrtf(r);
|
||||
}
|
||||
|
||||
#if DEBUG_LEAST_SQUARES || DEBUG_VELOCITY
|
||||
#if DEBUG_STRATEGY || DEBUG_VELOCITY
|
||||
static String8 vectorToString(const float* a, uint32_t m) {
|
||||
String8 str;
|
||||
str.append("[");
|
||||
@@ -98,15 +100,70 @@ static String8 matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMa
|
||||
|
||||
// --- VelocityTracker ---
|
||||
|
||||
VelocityTracker::VelocityTracker() :
|
||||
mLastEventTime(0), mCurrentPointerIdBits(0), mActivePointerId(-1),
|
||||
mStrategy(new LeastSquaresVelocityTrackerStrategy()) {
|
||||
// The default velocity tracker strategy.
|
||||
// Although other strategies are available for testing and comparison purposes,
|
||||
// this is the strategy that applications will actually use. Be very careful
|
||||
// when adjusting the default strategy because it can dramatically affect
|
||||
// (often in a bad way) the user experience.
|
||||
const char* VelocityTracker::DEFAULT_STRATEGY = "lsq2";
|
||||
|
||||
VelocityTracker::VelocityTracker(const char* strategy) :
|
||||
mLastEventTime(0), mCurrentPointerIdBits(0), mActivePointerId(-1) {
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
|
||||
// Allow the default strategy to be overridden using a system property for debugging.
|
||||
if (!strategy) {
|
||||
int length = property_get("debug.velocitytracker.strategy", value, NULL);
|
||||
if (length > 0) {
|
||||
strategy = value;
|
||||
} else {
|
||||
strategy = DEFAULT_STRATEGY;
|
||||
}
|
||||
}
|
||||
|
||||
// Configure the strategy.
|
||||
if (!configureStrategy(strategy)) {
|
||||
ALOGD("Unrecognized velocity tracker strategy name '%s'.", strategy);
|
||||
if (!configureStrategy(DEFAULT_STRATEGY)) {
|
||||
LOG_ALWAYS_FATAL("Could not create the default velocity tracker strategy '%s'!",
|
||||
strategy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VelocityTracker::~VelocityTracker() {
|
||||
delete mStrategy;
|
||||
}
|
||||
|
||||
bool VelocityTracker::configureStrategy(const char* strategy) {
|
||||
mStrategy = createStrategy(strategy);
|
||||
return mStrategy != NULL;
|
||||
}
|
||||
|
||||
VelocityTrackerStrategy* VelocityTracker::createStrategy(const char* strategy) {
|
||||
if (!strcmp("lsq1", strategy)) {
|
||||
// 1st order least squares. Quality: POOR.
|
||||
// Frequently underfits the touch data especially when the finger accelerates
|
||||
// or changes direction. Often underestimates velocity. The direction
|
||||
// is overly influenced by historical touch points.
|
||||
return new LeastSquaresVelocityTrackerStrategy(1);
|
||||
}
|
||||
if (!strcmp("lsq2", strategy)) {
|
||||
// 2nd order least squares. Quality: VERY GOOD.
|
||||
// Pretty much ideal, but can be confused by certain kinds of touch data,
|
||||
// particularly if the panel has a tendency to generate delayed,
|
||||
// duplicate or jittery touch coordinates when the finger is released.
|
||||
return new LeastSquaresVelocityTrackerStrategy(2);
|
||||
}
|
||||
if (!strcmp("lsq3", strategy)) {
|
||||
// 3rd order least squares. Quality: UNUSABLE.
|
||||
// Frequently overfits the touch data yielding wildly divergent estimates
|
||||
// of the velocity when the finger is released.
|
||||
return new LeastSquaresVelocityTrackerStrategy(3);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void VelocityTracker::clear() {
|
||||
mCurrentPointerIdBits.clear();
|
||||
mActivePointerId = -1;
|
||||
@@ -259,11 +316,11 @@ bool VelocityTracker::getEstimator(uint32_t id, Estimator* outEstimator) const {
|
||||
|
||||
// --- LeastSquaresVelocityTrackerStrategy ---
|
||||
|
||||
const uint32_t LeastSquaresVelocityTrackerStrategy::DEGREE;
|
||||
const nsecs_t LeastSquaresVelocityTrackerStrategy::HORIZON;
|
||||
const uint32_t LeastSquaresVelocityTrackerStrategy::HISTORY_SIZE;
|
||||
|
||||
LeastSquaresVelocityTrackerStrategy::LeastSquaresVelocityTrackerStrategy() {
|
||||
LeastSquaresVelocityTrackerStrategy::LeastSquaresVelocityTrackerStrategy(uint32_t degree) :
|
||||
mDegree(degree) {
|
||||
clear();
|
||||
}
|
||||
|
||||
@@ -302,7 +359,7 @@ void LeastSquaresVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet3
|
||||
* Returns true if a solution is found, false otherwise.
|
||||
*
|
||||
* The input consists of two vectors of data points X and Y with indices 0..m-1.
|
||||
* The output is a vector B with indices 0..n-1 that describes a polynomial
|
||||
* The output is a vector B with indices 0..n that describes a polynomial
|
||||
* that fits the data, such the sum of abs(Y[i] - (B[0] + B[1] X[i] + B[2] X[i]^2 ... B[n] X[i]^n))
|
||||
* for all i between 0 and m-1 is minimized.
|
||||
*
|
||||
@@ -332,7 +389,7 @@ void LeastSquaresVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet3
|
||||
*/
|
||||
static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32_t n,
|
||||
float* outB, float* outDet) {
|
||||
#if DEBUG_LEAST_SQUARES
|
||||
#if DEBUG_STRATEGY
|
||||
ALOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s", int(m), int(n),
|
||||
vectorToString(x, m).string(), vectorToString(y, m).string());
|
||||
#endif
|
||||
@@ -345,7 +402,7 @@ static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32
|
||||
a[i][h] = a[i - 1][h] * x[h];
|
||||
}
|
||||
}
|
||||
#if DEBUG_LEAST_SQUARES
|
||||
#if DEBUG_STRATEGY
|
||||
ALOGD(" - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).string());
|
||||
#endif
|
||||
|
||||
@@ -366,7 +423,7 @@ static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32
|
||||
float norm = vectorNorm(&q[j][0], m);
|
||||
if (norm < 0.000001f) {
|
||||
// vectors are linearly dependent or zero so no solution
|
||||
#if DEBUG_LEAST_SQUARES
|
||||
#if DEBUG_STRATEGY
|
||||
ALOGD(" - no solution, norm=%f", norm);
|
||||
#endif
|
||||
return false;
|
||||
@@ -380,7 +437,7 @@ static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32
|
||||
r[j][i] = i < j ? 0 : vectorDot(&q[j][0], &a[i][0], m);
|
||||
}
|
||||
}
|
||||
#if DEBUG_LEAST_SQUARES
|
||||
#if DEBUG_STRATEGY
|
||||
ALOGD(" - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).string());
|
||||
ALOGD(" - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).string());
|
||||
|
||||
@@ -406,7 +463,7 @@ static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32
|
||||
}
|
||||
outB[i] /= r[i][i];
|
||||
}
|
||||
#if DEBUG_LEAST_SQUARES
|
||||
#if DEBUG_STRATEGY
|
||||
ALOGD(" - b=%s", vectorToString(outB, n).string());
|
||||
#endif
|
||||
|
||||
@@ -433,7 +490,7 @@ static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32
|
||||
sstot += var * var;
|
||||
}
|
||||
*outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1;
|
||||
#if DEBUG_LEAST_SQUARES
|
||||
#if DEBUG_STRATEGY
|
||||
ALOGD(" - sserr=%f", sserr);
|
||||
ALOGD(" - sstot=%f", sstot);
|
||||
ALOGD(" - det=%f", *outDet);
|
||||
@@ -475,7 +532,7 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
|
||||
}
|
||||
|
||||
// Calculate a least squares polynomial fit.
|
||||
uint32_t degree = DEGREE;
|
||||
uint32_t degree = mDegree;
|
||||
if (degree > m - 1) {
|
||||
degree = m - 1;
|
||||
}
|
||||
@@ -487,7 +544,7 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
|
||||
outEstimator->time = newestMovement.eventTime;
|
||||
outEstimator->degree = degree;
|
||||
outEstimator->confidence = xdet * ydet;
|
||||
#if DEBUG_LEAST_SQUARES
|
||||
#if DEBUG_STRATEGY
|
||||
ALOGD("estimate: degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f",
|
||||
int(outEstimator->degree),
|
||||
vectorToString(outEstimator->xCoeff, n).string(),
|
||||
|
||||
Reference in New Issue
Block a user