summaryrefslogtreecommitdiff
path: root/common/newton_fit.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/newton_fit.c')
-rw-r--r--common/newton_fit.c186
1 files changed, 0 insertions, 186 deletions
diff --git a/common/newton_fit.c b/common/newton_fit.c
deleted file mode 100644
index ae81a45f07..0000000000
--- a/common/newton_fit.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "common.h"
-#include "console.h"
-#include "newton_fit.h"
-#include "math.h"
-#include "math_util.h"
-#include <string.h>
-
-#define CPRINTS(fmt, args...) cprints(CC_MOTION_SENSE, fmt, ##args)
-
-static fp_t distance_squared(fpv3_t a, fpv3_t b)
-{
- fpv3_t delta;
-
- fpv3_init(delta, a[X] - b[X], a[Y] - b[Y], a[Z] - b[Z]);
- return fpv3_dot(delta, delta);
-}
-
-static fp_t compute_error(struct newton_fit *fit, fpv3_t center)
-{
- fp_t error = FLOAT_TO_FP(0.0f);
- struct queue_iterator it;
- struct newton_fit_orientation *_it;
-
- for (queue_begin(fit->orientations, &it); it.ptr != NULL;
- queue_next(fit->orientations, &it)) {
- fp_t e;
-
- _it = (struct newton_fit_orientation *)it.ptr;
- e = FLOAT_TO_FP(1.0f) -
- distance_squared(_it->orientation, center);
- error += fp_mul(e, e);
- }
-
- return error;
-}
-
-static bool is_ready_to_compute(struct newton_fit *fit, bool prune)
-{
- bool has_min_samples = true;
- struct queue_iterator it;
- struct newton_fit_orientation *_it;
-
- /* Not full, not ready to compute. */
- if (!queue_is_full(fit->orientations))
- return false;
-
- /* Inspect all the orientations. */
- for (queue_begin(fit->orientations, &it); it.ptr != NULL;
- queue_next(fit->orientations, &it)) {
- _it = (struct newton_fit_orientation *)it.ptr;
- /* If an orientation has too few samples, flag that. */
- CPRINTS(" orientation %u/%u", _it->nsamples,
- fit->min_orientation_samples);
- if (_it->nsamples < fit->min_orientation_samples) {
- has_min_samples = false;
- break;
- }
- }
-
- /* If all orientations have the minimum samples, we're done and can
- * compute the bias.
- */
- if (has_min_samples)
- return true;
-
- /* If we got here and prune is true, then we need to remove the oldest
- * entry to make room for new orientations.
- */
- if (prune)
- queue_advance_head(fit->orientations, 1);
-
- return false;
-}
-
-void newton_fit_reset(struct newton_fit *fit)
-{
- queue_init(fit->orientations);
-}
-
-bool newton_fit_accumulate(struct newton_fit *fit, fp_t x, fp_t y, fp_t z)
-{
- struct queue_iterator it;
- struct newton_fit_orientation *_it;
- fpv3_t v, delta;
-
- fpv3_init(v, x, y, z);
-
- /* Check if we can merge this new data point with an existing
- * orientation.
- */
- for (queue_begin(fit->orientations, &it); it.ptr != NULL;
- queue_next(fit->orientations, &it)) {
- _it = (struct newton_fit_orientation *)it.ptr;
-
- fpv3_sub(delta, v, _it->orientation);
- /* Skip entries that are too far away. */
- if (fpv3_dot(delta, delta) >= fit->nearness_threshold)
- continue;
-
- /* Merge new data point with this orientation. */
- fpv3_scalar_mul(_it->orientation,
- FLOAT_TO_FP(1.0f) - fit->new_pt_weight);
- fpv3_scalar_mul(v, fit->new_pt_weight);
- fpv3_add(_it->orientation, _it->orientation, v);
- if (_it->nsamples < 0xff)
- _it->nsamples++;
- return is_ready_to_compute(fit, false);
- }
-
- /* If queue isn't full. */
- if (!queue_is_full(fit->orientations)) {
- struct newton_fit_orientation entry;
-
- entry.nsamples = 1;
- fpv3_init(entry.orientation, x, y, z);
- queue_add_unit(fit->orientations, &entry);
-
- return is_ready_to_compute(fit, false);
- }
-
- return is_ready_to_compute(fit, true);
-}
-
-void newton_fit_compute(struct newton_fit *fit, fpv3_t bias, fp_t *radius)
-{
- struct queue_iterator it;
- struct newton_fit_orientation *_it;
- fpv3_t new_bias, offset, delta;
- fp_t error, new_error;
- uint32_t iteration = 0;
- fp_t inv_orient_count;
-
- if (queue_is_empty(fit->orientations))
- return;
-
- inv_orient_count = fp_div(FLOAT_TO_FP(1.0f),
- queue_count(fit->orientations));
-
- memcpy(new_bias, bias, sizeof(fpv3_t));
- new_error = compute_error(fit, new_bias);
-
- do {
- memcpy(bias, new_bias, sizeof(fpv3_t));
- error = new_error;
- fpv3_zero(offset);
-
- for (queue_begin(fit->orientations, &it); it.ptr != NULL;
- queue_next(fit->orientations, &it)) {
- fp_t mag;
-
- _it = (struct newton_fit_orientation *)it.ptr;
-
- fpv3_sub(delta, _it->orientation, bias);
- mag = fpv3_norm(delta);
- fpv3_scalar_mul(delta,
- fp_div(mag - FLOAT_TO_FP(1.0f), mag));
- fpv3_add(offset, offset, delta);
- }
-
- fpv3_scalar_mul(offset, inv_orient_count);
- fpv3_add(new_bias, bias, offset);
- new_error = compute_error(fit, new_bias);
- if (new_error > error)
- memcpy(new_bias, bias, sizeof(fpv3_t));
- ++iteration;
- } while (iteration < fit->max_iterations && new_error < error &&
- new_error > fit->error_threshold);
-
- memcpy(bias, new_bias, sizeof(fpv3_t));
-
- if (radius) {
- *radius = FLOAT_TO_FP(0.0f);
- for (queue_begin(fit->orientations, &it); it.ptr != NULL;
- queue_next(fit->orientations, &it)) {
- _it = (struct newton_fit_orientation *)it.ptr;
- fpv3_sub(delta, _it->orientation, bias);
- *radius += fpv3_norm(delta);
- }
- *radius *= inv_orient_count;
- }
-}