getVelocityEstimate method

VelocityEstimate? getVelocityEstimate()

Returns an estimate of the velocity of the object being tracked by the tracker given the current information available to the tracker.

Information is added using addPosition.

Returns null if there is no data on which to base an estimate.

Implementation

VelocityEstimate? getVelocityEstimate() {
  // Has user recently moved since last sample?
  if (_sinceLastSample.elapsedMilliseconds > _assumePointerMoveStoppedMilliseconds) {
    return const VelocityEstimate(
      pixelsPerSecond: Offset.zero,
      confidence: 1.0,
      duration: Duration.zero,
      offset: Offset.zero,
    );
  }

  final List<double> x = <double>[];
  final List<double> y = <double>[];
  final List<double> w = <double>[];
  final List<double> time = <double>[];
  int sampleCount = 0;
  int index = _index;

  final _PointAtTime? newestSample = _samples[index];
  if (newestSample == null) {
    return null;
  }

  _PointAtTime previousSample = newestSample;
  _PointAtTime oldestSample = newestSample;

  // Starting with the most recent PointAtTime sample, iterate backwards while
  // the samples represent continuous motion.
  do {
    final _PointAtTime? sample = _samples[index];
    if (sample == null) {
      break;
    }

    final double age = (newestSample.time - sample.time).inMicroseconds.toDouble() / 1000;
    final double delta = (sample.time - previousSample.time).inMicroseconds.abs().toDouble() / 1000;
    previousSample = sample;
    if (age > _horizonMilliseconds || delta > _assumePointerMoveStoppedMilliseconds) {
      break;
    }

    oldestSample = sample;
    final Offset position = sample.point;
    x.add(position.dx);
    y.add(position.dy);
    w.add(1.0);
    time.add(-age);
    index = (index == 0 ? _historySize : index) - 1;

    sampleCount += 1;
  } while (sampleCount < _historySize);

  if (sampleCount >= _minSampleSize) {
    final LeastSquaresSolver xSolver = LeastSquaresSolver(time, x, w);
    final PolynomialFit? xFit = xSolver.solve(2);
    if (xFit != null) {
      final LeastSquaresSolver ySolver = LeastSquaresSolver(time, y, w);
      final PolynomialFit? yFit = ySolver.solve(2);
      if (yFit != null) {
        return VelocityEstimate( // convert from pixels/ms to pixels/s
          pixelsPerSecond: Offset(xFit.coefficients[1] * 1000, yFit.coefficients[1] * 1000),
          confidence: xFit.confidence * yFit.confidence,
          duration: newestSample.time - oldestSample.time,
          offset: newestSample.point - oldestSample.point,
        );
      }
    }
  }

  // We're unable to make a velocity estimate but we did have at least one
  // valid pointer position.
  return VelocityEstimate(
    pixelsPerSecond: Offset.zero,
    confidence: 1.0,
    duration: newestSample.time - oldestSample.time,
    offset: newestSample.point - oldestSample.point,
  );
}