diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2018-04-12 07:21:51 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2018-04-12 07:21:51 +0000 |
commit | 1676bc304518a8851b34a45fd1be5cdfc4f0e202 (patch) | |
tree | 28eec23c20babccce1eae5ee760c177e0ced2b46 | |
parent | a52688e8b93b47a40a8ea70f9abba4feb48b97e6 (diff) | |
parent | 1b3adf02ce3c7d184c77a764b6b56741ede784ea (diff) | |
download | contexthub-1676bc304518a8851b34a45fd1be5cdfc4f0e202.tar.gz |
Snap for 4716599 from 1b3adf02ce3c7d184c77a764b6b56741ede784ea to pi-release
Change-Id: I23b9438a24c9b7f5a974cd2bf39e5c4b3391e171
4 files changed, 0 insertions, 929 deletions
diff --git a/firmware/os/algos/calibration/magnetometer/mag_gyro_cal.c b/firmware/os/algos/calibration/magnetometer/mag_gyro_cal.c deleted file mode 100644 index 29a7ba07..00000000 --- a/firmware/os/algos/calibration/magnetometer/mag_gyro_cal.c +++ /dev/null @@ -1,271 +0,0 @@ -#include "calibration/magnetometer/mag_gyro_cal.h" - -#include <string.h> - -#include "calibration/util/cal_log.h" -#include "common/math/macros.h" - -#define SINGULAR_TOL (1e-4f) - -static bool allDiagonalsLessThan(struct Mat33 *matrix, float threshold) { - return matrix->elem[0][0] < threshold && matrix->elem[1][1] < threshold && - matrix->elem[2][2] < threshold; -} - -static void calculatingAndSettingBias(struct MagGyroCal *mgc, - struct Mat33 *first_sum_inverse, - struct Vec3 *bias) { - // Calculate bias, since we have high trust into this estimates. - mat33Apply(bias, first_sum_inverse, &mgc->mgac.second_sum_average); - - // Setting bias update. - mgc->x_bias = bias->x; - mgc->y_bias = bias->y; - mgc->z_bias = bias->z; -} - -void magGyroCalBatchReset(struct MagGyroBatchCal *mgbc) { - mgbc->first_sample = true; - mgbc->start_time_ns = 0; - mgbc->timestamp_buffer_ns = 0; - initZeroMatrix(&mgbc->first_sum_update); - initVec3(&mgbc->last_mag_sample, 0.0f, 0.0f, 0.0f); - initVec3(&mgbc->second_sum_update, 0.0f, 0.0f, 0.0f); -} - -static void magGyroCalAverageReset(struct MagGyroAverageCal *mgac) { - initZeroMatrix(&mgac->first_sum_average); - initVec3(&mgac->second_sum_average, 0.0f, 0.0f, 0.0f); - initVec3(&mgac->confidence_metric, 0.0f, 0.0f, 0.0f); - mgac->medium_accuracy_bias_update = false; - initVec3(&mgac->bias_running, 0.0f, 0.0f, 0.0f); -} - -void magGyroCalReset(struct MagGyroCal *mgc) { - // Reset Batch Cal. - magGyroCalBatchReset(&mgc->mgbc); - - // Reset Avarge Cal. - magGyroCalAverageReset(&mgc->mgac); - - initVec3(&mgc->mgac.confidence_metric, - mgc->algo_parameters.confidence_threshold_start, - mgc->algo_parameters.confidence_threshold_start, - mgc->algo_parameters.confidence_threshold_start); -} - -void magGyroCalGetBias(struct MagGyroCal *mgc, float *x, float *y, float *z) { - *x = mgc->x_bias; - *y = mgc->y_bias; - *z = mgc->z_bias; -} - -void magGyroCalInit(struct MagGyroCal *mgc, - const struct MagGyroCalParameters *params) { - // Tuning parameters. - memcpy(&mgc->algo_parameters, params, sizeof(mgc->algo_parameters)); - - // Bias Updates set to zero. - mgc->x_bias = 0.0f; - mgc->y_bias = 0.0f; - mgc->z_bias = 0.0f; - - // Reseting Algo. - magGyroCalReset(mgc); -} - -void magGyroCalBatchUpdate(struct MagGyroBatchCal *mgbc, - uint64_t sample_time_ns, float mag_x_ut, - float mag_y_ut, float mag_z_ut, float gyro_x_rps, - float gyro_y_rps, float gyro_z_rps) { - // local variables, only needed for math on single samples. - struct Vec3 mag_data; - struct Vec3 gyro_data; - struct Vec3 mag_data_dot; - struct Vec3 cross_mag_gyro; - struct Vec3 second_sum; - struct Vec3 yi; - struct Mat33 first_sum; - struct Mat33 w; - struct Mat33 w_trans; - float odr_hz_int; - // Creating gyro and mag vector. - initVec3(&mag_data, mag_x_ut, mag_y_ut, mag_z_ut); - initVec3(&gyro_data, gyro_x_rps, gyro_y_rps, gyro_z_rps); - - // Saving first sample in a batch and skipping the rest, this is done in order - // to do the discrete time derivative. x_dot = x(n) - x(n-1). - if (mgbc->first_sample) { - initVec3(&mgbc->last_mag_sample, mag_x_ut, mag_y_ut, mag_z_ut); - mgbc->first_sample = false; - mgbc->start_time_ns = sample_time_ns; - mgbc->timestamp_buffer_ns = sample_time_ns; - return; - } - // checking if delta time can become zero or negative. - if (sample_time_ns <= mgbc->timestamp_buffer_ns) { - // Timestamp is not monotonic, resetting batch. - magGyroCalBatchReset(mgbc); - return; - } - - // Calculating time delta between this sample and the sample before. - float delta_time_ns = (float)(sample_time_ns - mgbc->timestamp_buffer_ns); - - // Calculating 1/deltaT = ODR [Hz], for time derivative. - odr_hz_int = 1 / (delta_time_ns * NANOS_TO_SEC); - mgbc->timestamp_buffer_ns = sample_time_ns; - - // creating mag_dot. - // mag_data_dot = (mag_data - last_mag_sample) * odr. - vec3SubVecs(&mag_data_dot, &mag_data, &mgbc->last_mag_sample); - vec3ScalarMul(&mag_data_dot, odr_hz_int); - - // Cross product (gyro x mag). - vec3Cross(&cross_mag_gyro, &gyro_data, &mag_data); - - // Saving data into memory, for next derivative. - initVec3(&mgbc->last_mag_sample, mag_x_ut, mag_y_ut, mag_z_ut); - - // calculating yi = mag_dot + (gyro x mag). - vec3AddVecs(&yi, &mag_data_dot, &cross_mag_gyro); - - // creating skew-symmetric matrix. - // / 0, -w3, w2 \. - // w = | w3, 0, -w1 |. - // \ -w2, w1, 0 /. - w.elem[0][0] = 0; - w.elem[0][1] = -gyro_z_rps; - w.elem[0][2] = gyro_y_rps; - w.elem[1][0] = gyro_z_rps; - w.elem[1][1] = 0; - w.elem[1][2] = -gyro_x_rps; - w.elem[2][0] = -gyro_y_rps; - w.elem[2][1] = gyro_x_rps; - w.elem[2][2] = 0; - - // calculating second_sum: - // second_sum = w^T * yi. - mat33Transpose(&w_trans, &w); - mat33Apply(&second_sum, &w_trans, &yi); - - // calculating first sum: - // first_sum = w^T * w. - mat33MultiplyTransposed(&first_sum, &w, &w); - - // Updating sums. - mat33Add(&mgbc->first_sum_update, &first_sum); - vec3Add(&mgbc->second_sum_update, &second_sum); -} - -enum MagUpdate magGyroCalBiasUpdate(struct MagGyroCal *mgc, - struct Mat33 *first_sum_inverse) { - struct Vec3 bias; - // Testing for medium accuracy. - if (allDiagonalsLessThan(first_sum_inverse, - mgc->algo_parameters.confidence_threshold_medium)) { - // Testing for high accuracy, will leave the function here if true. - if (allDiagonalsLessThan(first_sum_inverse, - mgc->algo_parameters.confidence_threshold_high)) { - // Calculate bias, since we have high trust into this estimates. - calculatingAndSettingBias(mgc, first_sum_inverse, &bias); - - // Resetting everything since we have found the bias. - magGyroCalReset(mgc); - - // Return high accuracy indicator. - return UPDATE_BIAS_MAGGYRO_HIGH; - } - // Only will reach this point if accuracy is between high and medium, now - // we test for if we already have a medium update. - if (mgc->mgac.medium_accuracy_bias_update == false) { - // Calculate bias, since we have high trust into the estimates. - calculatingAndSettingBias(mgc, first_sum_inverse, &bias); - - // Resetting Batch, since we are not done yet. - magGyroCalBatchReset(&mgc->mgbc); - - // Setting medium_accuracy_bias_update to "true". - mgc->mgac.medium_accuracy_bias_update = true; - - // Return medium accuracy indicator. - return UPDATE_BIAS_MAGGYRO_MEDIUM; - - // already have an medium update, still calculate the actual offset, can - // be used for log files and manual bias extractions. - } else { - // Calculate bias, since we have high trust into the estimates. - mat33Apply(&bias, first_sum_inverse, &mgc->mgac.second_sum_average); - - // Setting bias update. - mgc->mgac.bias_running = bias; - - // Resetting Batch, since we are not done yet. - magGyroCalBatchReset(&mgc->mgbc); - - // Return no update indicator. - return NO_UPDATE; - } - } - // Have not gotten to medium accuracy, reset the batch. - magGyroCalBatchReset(&mgc->mgbc); - - // Return no update indicator. - return NO_UPDATE; -} - -enum MagUpdate magGyroCalRun(struct MagGyroCal *mgc, uint64_t sample_time_ns, - float mag_x_ut, float mag_y_ut, float mag_z_ut, - float gyro_x_rps, float gyro_y_rps, - float gyro_z_rps) { - struct Mat33 first_sum_inverse; - // Running samples into the batch function. - magGyroCalBatchUpdate(&mgc->mgbc, sample_time_ns, mag_x_ut, mag_y_ut, - mag_z_ut, gyro_x_rps, gyro_y_rps, gyro_z_rps); - - // Timeout, reset and start over, return MAGGYRO_TIMEOUT. - if ((sample_time_ns - mgc->mgbc.start_time_ns) >= - mgc->algo_parameters.max_run_time_in_ns) { - magGyroCalReset(mgc); - return MAGGYRO_TIMEOUT; - } - - // Early return if batch not complete. - if ((sample_time_ns - mgc->mgbc.start_time_ns) <= - mgc->algo_parameters.batch_window_in_ns) { - return NO_UPDATE; - } - - // Updating the average matrix. - mat33Add(&mgc->mgac.first_sum_average, &mgc->mgbc.first_sum_update); - - // Testing for singular matrix. - if (fabsf(mat33Determinant(&mgc->mgac.first_sum_average)) > SINGULAR_TOL) { - // Inverse of the average system matrix. - mat33Invert(&first_sum_inverse, &mgc->mgac.first_sum_average); - - // Testing if the confidence metric has been improved. - if (first_sum_inverse.elem[0][0] < mgc->mgac.confidence_metric.x && - first_sum_inverse.elem[1][1] < mgc->mgac.confidence_metric.y && - first_sum_inverse.elem[2][2] < mgc->mgac.confidence_metric.z) { - // Updating the second_sum vector. - vec3Add(&mgc->mgac.second_sum_average, &mgc->mgbc.second_sum_update); - - // Updating the confidence metric. - initVec3(&mgc->mgac.confidence_metric, first_sum_inverse.elem[0][0], - first_sum_inverse.elem[1][1], first_sum_inverse.elem[2][2]); - - // Testing for Bias update and leaving the function. - return magGyroCalBiasUpdate(mgc, &first_sum_inverse); - } - // No improvement, removing the last batch from the average. - mat33Sub(&mgc->mgac.first_sum_average, &mgc->mgbc.first_sum_update); - - // Resetting Batch, since we are not done yet. - magGyroCalBatchReset(&mgc->mgbc); - - // Returning no bias update. - return NO_UPDATE; - } - return NO_UPDATE; -} diff --git a/firmware/os/algos/calibration/magnetometer/mag_gyro_cal.h b/firmware/os/algos/calibration/magnetometer/mag_gyro_cal.h deleted file mode 100644 index edf92e88..00000000 --- a/firmware/os/algos/calibration/magnetometer/mag_gyro_cal.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * This module contains the algorithms for producing a magnetometer offset - * calibration. The algorithm is based on the paper “Adaptive Estimation of - * Measurement Bias in Three-Dimensional Field Sensors with Angular-Rate - * Sensors: Theory and Comparative Experimental Evaluation” by G. Troni and L. - * Whitcomb and uses gyroscope data as well as magnetometer data. We use a batch - * method, resulting in a Linear Least-Squares Fit (Section III B of the paper). - * We define the following mathematical setup: - * - * wi (wx,wy,wx) -> are the gyroscope readings [RAD/s] - * xi -> are the magnetometer readings [uT] - * xi_dot -> is the derivative of xi - * - * Form here we can define: - * - * yi = xi_dot + (wi x xi) (x denotes the cross product) - * - * and - * - * / 0 -wz wy \ - * Wi =| wz 0 -wx | - * \ -wy wx 0 / - * - * which we can use to define, what we call first sum and second sum - * - * firstSum = sum( Wi^2) - * - * and - * - * secondSum = sum(Wi yi) - * - * The bias is calculated the following way - * - * b = inverse(firstSum) * secondSum - * - * Notice that we use the diagonal of the matrix “inverse(firstSum)” as a - * confidence metric, to make a accuracy assessment. - * - * The algorithm expects time synchronized magnetometer and gyro data, any delay - * shift between those two greater than 5-10ms will result in poor accuracy. - * Furthermore, the minimum sample rate of the sensors should be higher than 50 - * Hz. - */ - -#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_GYRO_CAL_H_ -#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_GYRO_CAL_H_ - -#ifdef SPHERE_FIT_ENABLED -#ifndef DIVERSITY_CHECK_ENABLED -#define DIVERSITY_CHECK_ENABLED -#endif -#endif - -#include <stdbool.h> -#include <stdint.h> -#include <sys/types.h> - -#include "calibration/magnetometer/mag_cal.h" -#include "common/math/mat.h" -#include "common/math/vec.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Algo Batch Data Struct. -struct MagGyroBatchCal { - // Batch Start time. - uint64_t start_time_ns; - - // Time Stamp Buffer. Variable used to calculate 1/deltaT = odr_in_hz, where - // 1/deltaT is used to calculate the derivative of the mag signal. - uint64_t timestamp_buffer_ns; - - // First sample in batch indicator. - bool first_sample; - - // Matrix and vector definition. - struct Mat33 first_sum_update; - struct Vec3 last_mag_sample; - struct Vec3 second_sum_update; -}; - -// Algorithm tuning Parameter struct. -struct MagGyroCalParameters { - // Batch window size. - uint64_t batch_window_in_ns; - - // Algo resets after max_run_time. - uint64_t max_run_time_in_ns; - - // Confidence Threshold. - // The confidence metric is explained in go/magcalp design document. - // Furthermore more details are given as well on how to tune it. Confidence - // Threshold high accuracy. - float confidence_threshold_high; - - // Confidence Threshold medium accuracy. - float confidence_threshold_medium; - - // Confidence Threshold start. Don't want to start with a bad matrix. - float confidence_threshold_start; -}; - -// Data Struct for the Batch average function. -struct MagGyroAverageCal { - // Matrix and vector definition. - struct Mat33 first_sum_average; - struct Vec3 second_sum_average; - - // Medium accuracy bias update. - bool medium_accuracy_bias_update; - - // Confidence Metric. - struct Vec3 confidence_metric; - - // Running biases update. - struct Vec3 bias_running; -}; - -// Main algo data Struct. -struct MagGyroCal { - // Algorithm tuning parameters. - struct MagGyroCalParameters algo_parameters; - - // Single batch struct. We use batches, which in turn get again averaged over - // time. The single batch is the amount of data that we do the Linear - // Least-Squares fit on and decide if we will add this to the averaging based - // on the confidence metric. Notice that we do on every batch a matrix - // inversion, hence in order to save power it is beneficial to make the batch - // size reasonably large. This is controlled by the “batch_window_in_ns”. - struct MagGyroBatchCal mgbc; - - // Algo average struct. - struct MagGyroAverageCal mgac; - - // New bias update. - float x_bias; - float y_bias; - float z_bias; -}; - -// Algorithm initialization. -void magGyroCalInit(struct MagGyroCal *mgc, - const struct MagGyroCalParameters *params); - -// Resets the batch struct. -void magGyroCalReset(struct MagGyroCal *mgc); - -// Gets the current MagGyro bias estimate. -void magGyroCalGetBias(struct MagGyroCal *mgc, float *x, float *y, float *z); - -// Main algorithm runner function. -// sample_time_ns in [ns]. -// mag_x_ut, mag_y_ut, mag_z_ut are in [uT]. -// gyro_x_rps, gyro_y_rps, gyro_z_rps are in [RAD/s]. -// odr_hz is in [Hz]. -enum MagUpdate magGyroCalRun(struct MagGyroCal *mgc, uint64_t sample_time_ns, - float mag_x_ut, float mag_y_ut, float mag_z_ut, - float gyro_x_rps, float gyro_y_rps, - float gyro_z_rps); - -//////// Function exposed for testing /////////////////////////////////// -// Updating sensor data into the batch. -// sample_time_ns in [ns]. -// mag_x_ut, mag_y_ut, mag_z_ut are in [uT]. -// gyro_x_rps, gyro_y_rps, gyro_z_rps are in [RAD/s]. -// odr_hz is in [Hz]. -void magGyroCalBatchUpdate(struct MagGyroBatchCal *mgbc, - uint64_t sample_time_ns, float mag_x_ut, - float mag_y_ut, float mag_z_ut, float gyro_x_rps, - float gyro_y_rps, float gyro_z_rps); - -// Checks metrics and classifies bias update into either: -// NO_UPDATE and no bias is updated -// UPDATE_BIAS_MEDIUM bias is update with medium accuracy. -// UPDATE_BIAS_HIGH bias is update with high accuracy. -enum MagUpdate magGyroCalBiasUpdate(struct MagGyroCal *mgc, - struct Mat33 *first_sum_inverse); - -// Resetting the batch struct. -void magGyroCalBatchReset(struct MagGyroBatchCal *mgbc); - -#ifdef __cplusplus -} -#endif - -#endif // LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_MAGNETOMETER_MAG_GYRO_CAL_H_ diff --git a/firmware/os/algos/calibration/synchronizer/synchronizer.cc b/firmware/os/algos/calibration/synchronizer/synchronizer.cc deleted file mode 100644 index a485389b..00000000 --- a/firmware/os/algos/calibration/synchronizer/synchronizer.cc +++ /dev/null @@ -1,370 +0,0 @@ -#include "calibration/synchronizer/synchronizer.h" - -#include "calibration/util/cal_log.h" - -namespace synchronizer { -namespace { - -// Alias to simplify the access to SensorIndex. -using SensorIndex = online_calibration::SensorIndex; - -// Seeks through data_to_interpolate_to and data_to_interpolate queues so that -// first two entries of data_to_interpolate have timestamps that straddle the -// timestamp of the first entry of data_to_interpolate_to. Leading queue items -// are popped and discarded to perform seeking. -// -// Assumes both data_to_interpolate_to and data_to_interpolate sorted by -// strictly increasing timestamp. -// -// Returns True if seeking was achieved. Returns false if seeking could not -// be achieved, such is if either pointer was null or they contain data -// streams which cannot be made to straddle in time. - -bool SeekStraddle( - chre::ArrayQueue<online_calibration::SensorData, - Synchronizer::kInputBufferSize>* data_to_interpolate_to, - chre::ArrayQueue<online_calibration::SensorData, - Synchronizer::kInputBufferSize>* data_to_interpolate) { - // If either is a null pointer, return false - if (data_to_interpolate_to == nullptr || data_to_interpolate == nullptr) { -#ifdef SYNCHRONIZER_DBG_ENABLED - CAL_DEBUG_LOG("[SYNCHRONIZER WARNING]", - "Unexpected null pointer during seek!"); -#endif - return false; - } - - // If data_to_interpolate_to and data_to_interpolate are the same, no seeking. - if (reinterpret_cast<void*>(data_to_interpolate_to) == - reinterpret_cast<void*>(data_to_interpolate)) { - return true; - } - - // Check that queues are not empty and time min/max aren't impossible. - if (data_to_interpolate_to->empty() || data_to_interpolate->empty() || - data_to_interpolate->front().timestamp_nanos > - data_to_interpolate_to->back().timestamp_nanos || - data_to_interpolate->back().timestamp_nanos < - data_to_interpolate_to->front().timestamp_nanos) { - return false; - } - - // Seek in data_to_interpolate_to until first entry of data_to_interpolate - // precedes first of data_to_interpolate_to. - while (!data_to_interpolate_to->empty() && - data_to_interpolate->front().timestamp_nanos > - data_to_interpolate_to->front().timestamp_nanos) { - data_to_interpolate_to->pop(); - } - - // Check that data_to_interpolate_to still has at least one element. - if (data_to_interpolate_to->empty()) { - return false; - } - - // Seek in data_to_interpolate until 1st and 2nd entries straddle first - // data_to_interpolate_to entry. - while (data_to_interpolate->size() > 1 && - !((*data_to_interpolate)[0].timestamp_nanos <= - data_to_interpolate_to->front().timestamp_nanos && - (*data_to_interpolate)[1].timestamp_nanos >= - data_to_interpolate_to->front().timestamp_nanos)) { - data_to_interpolate->pop(); - } - - // data_to_interpolate must either match exactly, or have >=2 elements to - // interpolate - if (data_to_interpolate->front().timestamp_nanos == - data_to_interpolate_to->front().timestamp_nanos) { - return true; - } else if (data_to_interpolate->size() < 2) { - return false; - } - - // Check that data_to_interpolate still has at least two elements and they - // straddle the first entry of data_to_interpolate_to. - if ((*data_to_interpolate)[0].timestamp_nanos > - data_to_interpolate_to->front().timestamp_nanos || - (*data_to_interpolate)[1].timestamp_nanos < - data_to_interpolate_to->front().timestamp_nanos) { - return false; - } - - return true; -} -// Performs linear interpolation for a single axis. -float SingleAxisLinearInterpolation(float tb_minus_ta, float tc_minus_ta, - float va, float vc) { - return va + (vc - va) * (tb_minus_ta / tc_minus_ta); -} - -// Interpolates data_to_interpolate using timestamps in -// data_to_interpolate_to, writing to interpolated the resulting 3-axis -// measurement vector and timestamp that matches a timestamp in -// data_to_interpolate_to. For this to be possible, data_to_interpolate -// must have at least two timestamps which straddle a timestamp in -// data_to_interpolate_to. -// -// The input queues are assumed to have strictly increasing timestamps. -// -// First, this uses SeekStraddle() to pop off entries of each queue until the -// first two entries of data_to_interpolate have timestamps that straddle the -// timestamp of the first entry of data_to_interpolate_to. Then linear -// interpolation proceeds and results are written to interpolated. -// -// Returns true if interpolation was possible. Returns false if any of the -// inputs are nullptr or if interpolation was not possible given the -// timestamps in the data queues. -bool SeekAndInterpolateLinear( - chre::ArrayQueue<online_calibration::SensorData, - Synchronizer::kInputBufferSize>* data_to_interpolate_to, - chre::ArrayQueue<online_calibration::SensorData, - Synchronizer::kInputBufferSize>* data_to_interpolate, - online_calibration::SensorData* interpolated) { - // Seek until first two entries of data_to_interpolate straddle first entry of - // data_to_interpolate_to. Seek function also checks that - // data_to_interpolate_to and data_to_interpolate are not nullptr. - if (!SeekStraddle(data_to_interpolate_to, data_to_interpolate) || - interpolated == nullptr) { - return false; - } - - // Use some local variables to avoid repeated pointer dereferencing. - // data_to_interpolate_to and data_to_interpolate queues guaranteed by seek - // function to be non-empty. - online_calibration::SensorData data_to_interpolate_to_0 = - data_to_interpolate_to->front(); - const online_calibration::SensorData data_to_interpolate_0 = - data_to_interpolate->front(); - online_calibration::SensorData data_to_interpolate_1; - - // Avoid floating point math if possible: check if timestamps match exactly. - if (data_to_interpolate_to_0.timestamp_nanos == - data_to_interpolate_0.timestamp_nanos) { - *interpolated = data_to_interpolate_0; - return true; - } else if (data_to_interpolate->size() > 1) { - data_to_interpolate_1 = (*data_to_interpolate)[1]; - if (data_to_interpolate_to_0.timestamp_nanos == - data_to_interpolate_1.timestamp_nanos) { - *interpolated = data_to_interpolate_1; - return true; - } - } else { -// Size was 1 and first entries didn't match, so interpolation impossible! -#ifdef SYNCHRONIZER_DBG_ENABLED - CAL_DEBUG_LOG("[SYNCHRONIZER WARNING]", - "Unexpected queue state while attempting interpolation!"); -#endif - return false; - } - - // Linearly interpolate data_to_interpolate at data_to_interpolate_to's 0th - // entry timepoint. Interpolate vector vb between va, vc at time tb where - // ta < tb < tc. - const float tb_minus_ta = - static_cast<float>(data_to_interpolate_to_0.timestamp_nanos - - data_to_interpolate_0.timestamp_nanos); - const float tc_minus_ta = - static_cast<float>(data_to_interpolate_1.timestamp_nanos - - data_to_interpolate_0.timestamp_nanos); - - if (data_to_interpolate_0.type == - online_calibration::SensorType::kAccelerometerMps2 || - data_to_interpolate_0.type == - online_calibration::SensorType::kGyroscopeRps || - data_to_interpolate_0.type == - online_calibration::SensorType::kMagnetometerUt) { - // Perform linear interpolation for 3-axis sensor and populate the result - // struct. - interpolated->data[SensorIndex::kXAxis] = SingleAxisLinearInterpolation( - tb_minus_ta, tc_minus_ta, - data_to_interpolate_0.data[SensorIndex::kXAxis], - data_to_interpolate_1.data[SensorIndex::kXAxis]); - interpolated->data[SensorIndex::kYAxis] = SingleAxisLinearInterpolation( - tb_minus_ta, tc_minus_ta, - data_to_interpolate_0.data[SensorIndex::kYAxis], - data_to_interpolate_1.data[SensorIndex::kYAxis]); - interpolated->data[SensorIndex::kZAxis] = SingleAxisLinearInterpolation( - tb_minus_ta, tc_minus_ta, - data_to_interpolate_0.data[SensorIndex::kZAxis], - data_to_interpolate_1.data[SensorIndex::kZAxis]); - interpolated->timestamp_nanos = data_to_interpolate_to_0.timestamp_nanos; - interpolated->type = data_to_interpolate_0.type; - return true; - } else if (data_to_interpolate_0.type == - online_calibration::SensorType::kTemperatureCelsius || - data_to_interpolate_0.type == - online_calibration::SensorType::kBarometerHpa) { - // Perform linear interpolation for 1-axis sensor and populate the result - // struct. - interpolated->data[SensorIndex::kSingleAxis] = - SingleAxisLinearInterpolation( - tb_minus_ta, tc_minus_ta, - data_to_interpolate_0.data[SensorIndex::kSingleAxis], - data_to_interpolate_1.data[SensorIndex::kSingleAxis]); - interpolated->timestamp_nanos = data_to_interpolate_to_0.timestamp_nanos; - interpolated->type = data_to_interpolate_0.type; - return true; - } else { -#ifdef SYNCHRONIZER_DBG_ENABLED - CAL_DEBUG_LOG("[SYNCHRONIZER WARNING]", - "Invalid sensor_type in SeekAndInterpolateLinear"); -#endif - return false; - } -} - -// Attempts to add a SensorData measurement to a deque of them, returning -// whether the new measurement was strictly greater in time than the last -// entry in the queue. If it was not, measurement is not added and false is -// returned. This function is primarily for code compactness: several queues -// of measurements are appended-to in this same manner. -bool AddMeasurementToDeque( - const online_calibration::SensorData& measurement, - chre::ArrayQueue<online_calibration::SensorData, - Synchronizer::kInputBufferSize>* mutable_deque) { - // Push measurement onto the measurement queue if sequential. - if (mutable_deque->empty() || - (!mutable_deque->empty() && - measurement.timestamp_nanos > mutable_deque->back().timestamp_nanos)) { - mutable_deque->push(measurement); - return true; - } else { -#ifdef SYNCHRONIZER_DBG_ENABLED - CAL_DEBUG_LOG( - "[SYNCHRONIZER WARNING]", - "measurement timestamp: %lu was not strictly greater than existing" - "queued timestamps.", - measurement.timestamp_nanos); -#endif - return false; - } -} -} // namespace - -Synchronizer::Synchronizer() - : Synchronizer(online_calibration::SensorType::kGyroscopeRps, - online_calibration::SensorType::kAccelerometerMps2) {} - -Synchronizer::Synchronizer( - const online_calibration::SensorType& sensor_to_interpolate_to, - const online_calibration::SensorType& sensor_to_interpolate) { - if (sensor_to_interpolate_to == sensor_to_interpolate) { -#ifdef SYNCHRONIZER_DBG_ENABLED - CAL_DEBUG_LOG("[SYNCHRONIZER WARNING]", - "Sensor_types are equal! Using default settings!"); -#endif - sensor_to_interpolate_to_ = online_calibration::SensorType::kGyroscopeRps; - sensor_to_interpolate_ = online_calibration::SensorType::kAccelerometerMps2; - } else { - // Setting sensors. - sensor_to_interpolate_to_ = sensor_to_interpolate_to; - sensor_to_interpolate_ = sensor_to_interpolate; - } -} - -bool Synchronizer::SetDataToInterpolateToSensorType( - const online_calibration::SensorType& sensor_type) { - if (sensor_type == sensor_to_interpolate_) { -#ifdef SYNCHRONIZER_DBG_ENABLED - CAL_DEBUG_LOG("[SYNCHRONIZER WARNING]", - "Sensor_type in SetDataToInterpolateToSensorType is " - "already used!"); -#endif - return false; - } - if (sensor_type == online_calibration::SensorType::kUndefined) { -#ifdef SYNCHRONIZER_DBG_ENABLED - CAL_DEBUG_LOG("[SYNCHRONIZER WARNING]", - "Invalid sensor_type in SetDataToInterpolateToSensorType"); -#endif - return false; - } - sensor_to_interpolate_to_ = sensor_type; - return true; -} - -bool Synchronizer::SetDataToInterpolateSensorType( - const online_calibration::SensorType& sensor_type) { - if (sensor_type == sensor_to_interpolate_to_) { -#ifdef SYNCHRONIZER_DBG_ENABLED - CAL_DEBUG_LOG( - "[SYNCHRONIZER WARNING]", - "Sensor_type in SetDataToInterpolateSensorType is already used!"); -#endif - return false; - } - if (sensor_type == online_calibration::SensorType::kUndefined) { -#ifdef SYNCHRONIZER_DBG_ENABLED - CAL_DEBUG_LOG("[SYNCHRONIZER WARNING]", - "Invalid sensor_type in SetDataToInterpolateSensorType"); -#endif - return false; - } - sensor_to_interpolate_ = sensor_type; - return true; -} - -void Synchronizer::AddMeasurement(const online_calibration::SensorData& meas) { - online_calibration::SensorType sensor_type = meas.type; - if (sensor_type == sensor_to_interpolate_to_) { - if (input_sensor_to_interpolate_to_.full()) { - CAL_DEBUG_LOG("[SYNCHRONIZER WARNING]", - "input_sensor_to_interpolate_to queue is full! " - "Removing front element from queue"); - input_sensor_to_interpolate_to_.pop(); - } - if (AddMeasurementToDeque(meas, &input_sensor_to_interpolate_to_)) { - // Add succeeded. Process applicable measurement queue. - ProcessMeasurementQueues(); - } - } - if (sensor_type == sensor_to_interpolate_) { - if (input_sensor_to_interpolate_.full()) { - CAL_DEBUG_LOG("[SYNCHRONIZER WARNING]", - "input_sensor_to_interpolate queue is full !" - "Removing front element from queue"); - input_sensor_to_interpolate_.pop(); - } - if (AddMeasurementToDeque(meas, &input_sensor_to_interpolate_)) { - // Add succeeded. Process applicable measurement queue. - ProcessMeasurementQueues(); - } - } -} - -bool Synchronizer::ConsumeSynchronizedMeasurementQueues( - /*first sensor*/ online_calibration::SensorData* sensor_to_interpolate_to, - /*second sensor*/ online_calibration::SensorData* sensor_to_interpolate) { - if (!synchronized_first_and_second_queues_.empty()) { - *sensor_to_interpolate_to = - synchronized_first_and_second_queues_.front().first; - *sensor_to_interpolate = - synchronized_first_and_second_queues_.front().second; - synchronized_first_and_second_queues_.pop(); - return true; - } - return false; -} - -void Synchronizer::ProcessMeasurementQueues() { - // Results of interpolation written here. - online_calibration::SensorData interpolated; - - // Process the queues, interpolating and queuing up measurements. - while (SeekAndInterpolateLinear(&input_sensor_to_interpolate_to_, - &input_sensor_to_interpolate_, - &interpolated)) { - synchronized_first_and_second_queues_.push( - std::pair<online_calibration::SensorData, - online_calibration::SensorData>( - input_sensor_to_interpolate_to_.front(), interpolated)); - - // Pop off data_to_interpolate_to measurement used to create this sample. - // data_to_interpolate will be cleaned up next seek. - input_sensor_to_interpolate_to_.pop(); - } -} - -} // namespace synchronizer diff --git a/firmware/os/algos/calibration/synchronizer/synchronizer.h b/firmware/os/algos/calibration/synchronizer/synchronizer.h deleted file mode 100644 index 1a0ef4cf..00000000 --- a/firmware/os/algos/calibration/synchronizer/synchronizer.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This is a sensor data synchronizer module that interpolates buffers (queues) - * of streamed measurements with respect to a user-selected input master stream - * to set the timebase. To perform synchronization, a sensor (sensor_data.h) - * is selected to define the resulting synchronized time axis. The second - * selected sensor is interpolated to the first sensor's timescale. This - * produces a synchronized queue of measurement pairs. - */ - -#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SYNCHRONIZER_SYNCHRONIZER_H_ -#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SYNCHRONIZER_SYNCHRONIZER_H_ - -#include "calibration/online_calibration/common_data/sensor_data.h" -#include "chre/util/array_queue.h" - -namespace synchronizer { - -/* - * Buffers measurements and synchronizes them using interpolation. - * - * Processes input streams of sensors and queues up output streams. - */ -class Synchronizer { - public: - // Input buffer size = 400 gives 1 second of buffer for a input sensor data - // rate of 400 Hz. - static constexpr int kInputBufferSize = 400; - // The output buffer size can store 10 sample, hist code has to ensure to - // grab the data before overflow. - static constexpr int kOutputBufferSize = 10; - - Synchronizer(); - - Synchronizer(const online_calibration::SensorType& sensor_to_interpolate_to, - const online_calibration::SensorType& sensor_to_interpolate); - - // Sets the sensor (first) to which the second sensor is interpolated to. - // Hence this sensor timebase is the master of the synchronized data stream. - // Notice that "sensor_to_interpolate_to_" cannot be equal - // "sensor_to_interpolate_", so this function cannot synchronize two accel's - // to each other. - // TODO(b/70861106): Change interface to a master slave approach. - // Sensors available (sensor_data.h). - bool SetDataToInterpolateToSensorType( - const online_calibration::SensorType& sensor_type); - - // Sets the sensor (second) which will be interpolated. Notice that - // "sensor_to_interpolate_to_" cannot be equal "sensor_to_interpolate_". - // Sensors available (sensor_data.h). - bool SetDataToInterpolateSensorType( - const online_calibration::SensorType& sensor_type); - - // Adds measurements. Uses the type in SensorData to identify - // sensor_to_interpolate and sensor_to_interpolate_to sensors. - void AddMeasurement(const online_calibration::SensorData& meas); - - // Processes the synchronization queues in chronological order. Processing - // involves popping off each queue element and passing it to the specified - // function target of corresponding sensor type. - // - // Returns true if at least one element is in the sensor queue, and populates - // the synchronzied sensor data structs. - bool ConsumeSynchronizedMeasurementQueues( - /*sensor_to_interpolate_to*/ - online_calibration::SensorData* sensor_to_interpolate_to, - /*sensor_to_interpolate*/ - online_calibration::SensorData* sensor_to_interpolate); - - private: - // Attempts to pair up "sensor_to_interpolate_to" (first) and - // "sensor_to_interpolate" (second) measurements buffered by the - // AddMeasurement() function, interpolating one using the other as a - // data_to_interpolate_to timescale if necessary. - // - // If interpolated measurements are generated, they are queued in this - // function. - - void ProcessMeasurementQueues(); - - // Queue of synchronized measurements. - chre::ArrayQueue< - std::pair<online_calibration::SensorData, online_calibration::SensorData>, - kOutputBufferSize> - synchronized_first_and_second_queues_; - - // Enums set which measurement defines the data_to_interpolate_to (first) - // timebase, against which sensor_to_interpolate is interpolated (second). - online_calibration::SensorType sensor_to_interpolate_to_; - online_calibration::SensorType sensor_to_interpolate_; - - // Queues of time-ordered measurements for interpolation within this class. - chre::ArrayQueue<online_calibration::SensorData, kInputBufferSize> - input_sensor_to_interpolate_to_; - chre::ArrayQueue<online_calibration::SensorData, kInputBufferSize> - input_sensor_to_interpolate_; -}; - -} // namespace synchronizer - -#endif // LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SYNCHRONIZER_SYNCHRONIZER_H_ |