[PATCH synaptics v2 14/21] Replace the motion estimator
Derek Foreman
derek at collabora.co.uk
Wed Jun 15 09:45:32 PDT 2011
On 06/15/11 05:12, Daniel Kurtz wrote:
> On Wed, Jun 15, 2011 at 1:06 AM, Daniel Stone<daniel at fooishbar.org> wrote:
>> 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>
>> Reviewed-by: Simon Thum<simon.thum at gmx.de>
>> ---
>> src/synaptics.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++---
>> 1 files changed, 52 insertions(+), 4 deletions(-)
>>
>> v2: Split a few hunks out into separate patches.
>>
>> NOTE: I realise 'outlier' is unused; I've already fixed this in my local tree.
>>
>> diff --git a/src/synaptics.c b/src/synaptics.c
>> index 23751f4..cfd1384 100644
>> --- a/src/synaptics.c
>> +++ b/src/synaptics.c
>> @@ -1803,6 +1803,54 @@ get_edge_speed(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
>> }
>> }
>>
>
> First of all, in the Synaptics case, I believe the touchpad firmware
> is generating samples at a very consistent 80 Hz rate.
> The reporting rate is only variable due to the way the firmware does
> multitouch reporting with its "Advanced Gesture Mode".
> Therefore, in the single-touch case, this math mostly just adds in
> jitter from PS/2 bus contention and kernel processing latencies.
> In that respect, the previous fixed-time approach may have actually
> been more accurate.
> There may be simpler ways to compensate for AGM-induced variable
> timing... but, that would be a different patch set.
Do you have reason to believe that PS/2 bus contention and kernel
processing latencies will add up to more than a few microseconds? I'm
not convinced there will be enough timing jitter to cause perceptible
errant motion.
This driver also handles non-synaptics devices, like the USB based ones
in some Apple laptops. I think they report at a different rate (8ms
comes to mind.).
The kernel input layer "defuzz" code also filters events out completely
from time to time, and while I'm currently proposing a slight change to
those semantics on the linux-input list, they're the parameters we have
to work with.
>
> As for the implementation below, I'm a little confused, since it
> appears to have two different behaviors depending on
> count_packet_finger:
> (1) If == 1: Return actual delta for last sample time, using current position.
> (2) If> 1: Return estimated delta for last sample time, ignoring
> current position.
>
> Why do you use the current position in the == 1 case, but ignore it in
> the> 1 case?
That's because during our initial testing you raised the concern that
"really short" interactions with the pad could be lost waiting for the
motion history to fill up. We tried passing up the first delta without
passing it through the regression routine, and it subjectively felt very
responsive, even on a synaptics AGM device in its 40Hz reporting mode.
In the > 1 case we only ever output predicted motion. This is so (when
a subsequent patch adds an "error filter") we can test if the current
hardware input deviates radically from the regression line, and not
generate motion based on that.
> I believe the original estimate_delta did, in fact use the current
> position (hw->x,y). However, I seem to recall that this was a source
> of some error, since I believe this position is pre-scaling (whereas
> the positions stored in the HISTORY buffer are post-scaling), and the
> delta estimate was taken before it was determined that this new
> position was really part of the same gesture.
>
>> +/*
>> + * Fit a line through the three most recent points in the motion
>> + * history and return relative co-ordinates.
>
> Maybe:
> (1) compute the average velocity over the past N positions (for N up
> to 3) [including the current hw position?]
> (2) given this average velocity, return the expected position delta
> over the most recent sample time:
> delta = (HIST(0).millis - hw->millis) * velocity_estimate;
That's another potentially valid approach. It loses the ability to
filter based on a maximum deviation from the predicted line, and I'm not
sure it will track an accelerating finger as accurately as the
linear-regression approach.
It's hard to guess how that would feel without anyone having written it
though. Have you written and tested an estimator based on that code?
>> + */
>> +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;
>
> Not used?
Oops, that should have been moved to a later patch that adds filtering.
>> +
>> + 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++) {
>
> It might help readability to declare:
> int packet_count = MIN(priv->count_packet_finger, 3);
Agreed.
>> + ym += HIST(i).y;
>> + xm += HIST(i).x;
>> + tm += HIST_DELTA(i, 0, millis);
>> + }
>> + ym /= MIN(priv->count_packet_finger, 3);
>> + tm /= MIN(priv->count_packet_finger, 3);
>> + xm /= MIN(priv->count_packet_finger, 3);
>> +
>> + 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 * (HIST(0).millis - hw->millis);
>> + *dy = -yb1 * (HIST(0).millis - hw->millis);
>> + return;
>> +
>> +filtered:
>
> There's no goto...?
An artifact from the same rebase as above, will also be corrected in the
v3 patch set.
Thanks,
Derek
More information about the xorg-devel
mailing list