[PATCH 07/15] Replace the motion estimator
Daniel Stone
daniel at fooishbar.org
Thu Jun 9 12:57:28 PDT 2011
From: Derek Foreman <derek.foreman at collabora.co.uk>
Use a smarter motion estimator that attempts to draw a best-fit line
through the history where possible, including taking acceleration into
account.
Signed-off-by: Derek Foreman <derek.foreman at collabora.co.uk>
Reviewed-by: Daniel Stone <daniel at fooishbar.org>
---
src/synaptics.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 68 insertions(+), 8 deletions(-)
diff --git a/src/synaptics.c b/src/synaptics.c
index 8a6d56e..fb37030 100644
--- a/src/synaptics.c
+++ b/src/synaptics.c
@@ -1689,6 +1689,8 @@ store_history(SynapticsPrivate *priv, int x, int y, unsigned int millis)
priv->move_hist[idx].y = y;
priv->move_hist[idx].millis = millis;
priv->hist_index = idx;
+ if (priv->count_packet_finger < SYNAPTICS_MOVE_HISTORY)
+ priv->count_packet_finger++;
}
/*
@@ -1777,6 +1779,63 @@ get_edge_speed(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
}
}
+/*
+ * Fit a line through the three most recent points in the motion
+ * history and return relative co-ordinates.
+ *
+ * Three forms of filtering are present:
+ * Acceleration - pointer accelerating too fast
+ * Jerk - too great a change in pointer acceleration
+ * Error - hw state deviates too much from the predicted position
+ *
+ * Note - The current state is used for filtering, but only its time is used
+ * in the delta calculation
+ */
+
+static void regress(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
+ double *dx, double *dy)
+{
+ const SynapticsParameters *pars = &priv->synpara;
+ int i, j;
+ double ym = 0, xm = 0, tm = 0;
+ double yb1n = 0, xb1n = 0, b1d = 0, xb1, yb1;
+ double dista, distb, distc, vela, velb, velc, acca, accb, jerk;
+
+ if (priv->count_packet_finger == 1) {
+ *dx = hw->x - HIST(0).x;
+ *dy = hw->y - HIST(0).y;
+ return;
+ }
+
+ /* Determine the best fit line through the 3 most recent history entries */
+ for (i = 0; i < MIN(priv->count_packet_finger, 3); i++) {
+ ym += HIST(i).y;
+ xm += HIST(i).x;
+ tm += HIST_DELTA(i, 0, millis);
+ }
+ ym /= priv->count_packet_finger;
+ tm /= priv->count_packet_finger;
+ xm /= priv->count_packet_finger;
+
+ for (i = 0; i < MIN(priv->count_packet_finger, 3); i++) {
+ double t = HIST_DELTA(i, 0, millis);
+ yb1n += (t - tm) * (HIST(i).y - ym);
+ xb1n += (t - tm) * (HIST(i).x - xm);
+ b1d += (t - tm) * (t - tm);
+ }
+ xb1 = xb1n/b1d;
+ yb1 = yb1n/b1d;
+
+ *dx = xb1 * (hw->millis - HIST(0).millis);
+ *dy = yb1 * (hw->millis - HIST(0).millis);
+ return;
+
+filtered:
+ *dx = 0;
+ *dy = 0;
+ priv->count_packet_finger = 0;
+}
+
static void
get_delta(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
edge_type edge, double *dx, double *dy)
@@ -1787,10 +1846,11 @@ get_delta(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
double tmpf;
int x_edge_speed = 0;
int y_edge_speed = 0;
+ Bool outlier = FALSE;
/* HIST is full enough: priv->count_packet_finger > 3 */
- *dx = estimate_delta(hw->x, HIST(0).x, HIST(1).x, HIST(2).x);
- *dy = estimate_delta(hw->y, HIST(0).y, HIST(1).y, HIST(2).y);
+
+ regress(priv, hw, dx, dy);
if ((priv->tap_state == TS_DRAG) || para->edge_motion_use_always)
get_edge_speed(priv, hw, edge, &x_edge_speed, &y_edge_speed);
@@ -1847,19 +1907,19 @@ ComputeDeltas(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
}
/* to create fluid edge motion, call back 'soon'
- * even in the absence of new hardware events */
+ * even in the absence of new hardware events
+ * Note: This should be longer that the device report rate!
+ */
delay = MIN(delay, POLL_MS);
- if (priv->count_packet_finger <= 3) /* min. 3 packets, see get_delta() */
- goto skip; /* skip the lot */
+ if (priv->count_packet_finger < 1) /* min. 1 packet, see regress() */
+ goto out; /* skip the lot */
if (priv->moving_state == MS_TRACKSTICK)
get_delta_for_trackstick(priv, hw, &dx, &dy);
else if (moving_state == MS_TOUCHPAD_RELATIVE)
get_delta(priv, hw, edge, &dx, &dy);
-skip:
- priv->count_packet_finger++;
out:
priv->prevFingers = hw->numFingers;
@@ -2594,7 +2654,7 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now,
priv->lastButtons = buttons;
/* generate a history of the absolute positions */
- if (inside_active_area)
+ if (inside_active_area && actual)
store_history(priv, hw->x, hw->y, hw->millis);
return delay;
--
1.7.5.3
More information about the xorg-devel
mailing list