blob: d3bbf7f15b23457d6d28b55eada0bb23dd40f837 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This module contains an algorithm for performing a sphere fit calibration.
* A sphere fit calibration solves the following non-linear least squares
* problem:
*
* arg min || ||M(x - b)|| - exp_norm ||
* M,b
*
* where:
* x is a 3xN matrix containing N 3-dimensional uncalibrated data points,
* M is a 3x3 lower diagonal scaling matrix
* b is a 3x1 offset vector.
* exp_norm is the expected norm of an individual calibration data point.
* M and b are solved such that the norm of the calibrated data (M(x - b)) is
* near exp_norm.
*
* This module uses a Levenberg-Marquardt nonlinear least squares solver to find
* M and b. M is assumed to be a lower diagonal, consisting of 6 parameters.
*
*/
#ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SPHERE_FIT_SPHERE_FIT_CALIBRATION_H_
#define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SPHERE_FIT_SPHERE_FIT_CALIBRATION_H_
#include <stdbool.h>
#include <stdint.h>
#include "calibration/sphere_fit/calibration_data.h"
#include "common/math/levenberg_marquardt.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MIN_NUM_SPHERE_FIT_POINTS (14)
// Enum defining the meaning of the state parameters. The 9-parameter
// sphere fit calibration computes a lower-diagonal scaling matrix (M) and
// an offset such that:
// x_corrected = M * (x_impaired - offset)
enum SphereFitParams {
eParamScaleMatrix11 = 0,
eParamScaleMatrix21,
eParamScaleMatrix22,
eParamScaleMatrix31,
eParamScaleMatrix32,
eParamScaleMatrix33,
eParamOffset1,
eParamOffset2,
eParamOffset3,
SF_STATE_DIM
};
// Structure containing the data to be used for the sphere fit calibration.
struct SphereFitData {
// Data for fit (assumed to be a matrix of size num_fit_points x SF_DATA_DIM)
const float *fit_data;
// Pointer to standard deviations of the fit data, used to weight individual
// data points. Assumed to point to a matrix of dimensions
// num_fit_points x THREE_AXIS_DIM.
// If NULL, data will all be used with equal weighting in the fit.
const float *fit_data_std;
// Number of fit points.
size_t num_fit_points;
// Expected data norm.
float expected_norm;
};
// Structure for a sphere fit calibration, including a non-linear least squares
// solver and the latest state estimate.
struct SphereFitCal {
// Levenberg-Marquardt solver.
struct LmSolver lm_solver;
// Minimum number of points for computing a calibration.
size_t min_points_for_cal;
// State estimate.
float x[SF_STATE_DIM];
uint64_t estimate_time_nanos;
// Initial state for solver.
float x0[SF_STATE_DIM];
};
// Initialize sphere fit calibration structure with solver and fit params.
void sphereFitInit(struct SphereFitCal *sphere_cal,
const struct LmParams *lm_params,
const size_t min_num_points_for_cal);
// Clears state estimate and initial state.
void sphereFitReset(struct SphereFitCal *sphere_cal);
// Sets data pointer for single solve of the Levenberg-Marquardt solver.
// Must be called before calling sphereFitRunCal().
void sphereFitSetSolverData(struct SphereFitCal *sphere_cal,
struct LmData *lm_data);
// Sends in a set of calibration data and attempts to run calibration.
// Returns true if a calibration was successfully triggered with this data.
bool sphereFitRunCal(struct SphereFitCal *sphere_cal,
const struct SphereFitData *data,
uint64_t timestamp_nanos);
// Set an initial condition for the bias state.
void sphereFitSetInitialBias(struct SphereFitCal *sphere_cal,
const float initial_bias[THREE_AXIS_DIM]);
// Returns the latest calibration data in a ThreeAxisCalData structure.
void sphereFitGetLatestCal(const struct SphereFitCal *sphere_cal,
struct ThreeAxisCalData *cal_data);
///////////////// TEST UTILITIES ///////////////////////////////////////////
// The following functions are exposed in the header for testing only.
// The ResidualAndJacobianFunction for sphere calibration in the
// Levenberg-Marquardt solver.
void sphereFitResidAndJacobianFunc(const float *state, const void *f_data,
float *residual, float *jacobian);
#ifdef __cplusplus
}
#endif
#endif // LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_SPHERE_FIT_SPHERE_FIT_CALIBRATION_H_