• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "calibration/common/diversity_checker.h"
18 
19 #include <errno.h>
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include "common/math/vec.h"
24 
25 #define MAX_FIT_MAG 70.0f
26 #define MIN_FIT_MAG 20.0f
27 
28 // Struct initialization.
diversityCheckerInit(struct DiversityChecker * diverse_data,size_t min_num_diverse_vectors,size_t max_num_max_distance,float var_threshold,float max_min_threshold,float local_field,float threshold_tuning_param,float max_distance_tuning_param)29 void diversityCheckerInit(
30     struct DiversityChecker* diverse_data,
31     size_t min_num_diverse_vectors,
32     size_t max_num_max_distance,
33     float var_threshold,
34     float max_min_threshold,
35     float local_field,
36     float threshold_tuning_param,
37     float max_distance_tuning_param) {
38   ASSERT_NOT_NULL(diverse_data);
39 
40   // Initialize parameters.
41   diverse_data->threshold_tuning_param_sq =
42       (threshold_tuning_param * threshold_tuning_param);
43   diverse_data->max_distance_tuning_param_sq =
44       (max_distance_tuning_param * max_distance_tuning_param);
45 
46   // Updating the threshold and max_distance using assumed local field.
47   // Testing for zero and negative local_field.
48   if (local_field <= 0) {
49     local_field = 1;
50   }
51   diversityCheckerLocalFieldUpdate(diverse_data, local_field);
52   diverse_data->min_num_diverse_vectors = min_num_diverse_vectors;
53 
54   // Checking for min_num_diverse_vectors = 0.
55   if (min_num_diverse_vectors < 1) {
56     diverse_data->min_num_diverse_vectors = 1;
57   }
58   diverse_data->max_num_max_distance = max_num_max_distance;
59   diverse_data->var_threshold = var_threshold;
60   diverse_data->max_min_threshold = max_min_threshold;
61 
62   // Setting the rest to zero.
63   diversityCheckerReset(diverse_data);
64 }
65 
66 // Reset
diversityCheckerReset(struct DiversityChecker * diverse_data)67 void diversityCheckerReset(struct DiversityChecker* diverse_data) {
68   ASSERT_NOT_NULL(diverse_data);
69   // Clear data memory.
70   memset(&diverse_data->diverse_data, 0,
71          sizeof(diverse_data->diverse_data));
72 
73   // Resetting counters and data full bit.
74   diverse_data->num_points = 0;
75   diverse_data->num_max_dist_violations = 0;
76   diverse_data->data_full = false;
77 }
78 
diversityCheckerUpdate(struct DiversityChecker * diverse_data,float x,float y,float z)79 void diversityCheckerUpdate(
80     struct DiversityChecker* diverse_data, float x, float y, float z) {
81   ASSERT_NOT_NULL(diverse_data);
82 
83   // Converting three single inputs to a vector.
84   const float vec[3] = {x, y, z};
85 
86   // Result vector for vector difference.
87   float vec_diff[3];
88 
89   // normSquared result (k)
90   float norm_squared_result;
91 
92   // If memory is full, no need to run through the data.
93   if (!diverse_data->data_full) {
94     size_t i;
95     // Running over all existing data points
96     for (i = 0; i < diverse_data->num_points; ++i) {
97       // v = v1 - v2;
98       vecSub(vec_diff,
99              &diverse_data->diverse_data[i * THREE_AXIS_DATA_DIM],
100              vec,
101              THREE_AXIS_DATA_DIM);
102 
103       // k = |v|^2
104       norm_squared_result = vecNormSquared(vec_diff, THREE_AXIS_DATA_DIM);
105 
106       // if k < Threshold then leave the function.
107       if (norm_squared_result < diverse_data->threshold) {
108         return;
109       }
110 
111       // if k > max_distance, count and leave the function.
112       if (norm_squared_result > diverse_data->max_distance) {
113         diverse_data->num_max_dist_violations++;
114         return;
115       }
116     }
117 
118     // If none of the above caused to leave the function, data is diverse.
119     // Notice that the first data vector will be stored no matter what.
120     memcpy(&diverse_data->
121            diverse_data[diverse_data->num_points * THREE_AXIS_DATA_DIM],
122            vec,
123            sizeof(float) * THREE_AXIS_DATA_DIM);
124     // Count new data point.
125     diverse_data->num_points++;
126 
127     // Setting data_full to 1, if memory is full.
128     if (diverse_data->num_points == NUM_DIVERSE_VECTORS) {
129       diverse_data->data_full = true;
130     }
131   }
132 }
133 
diversityCheckerNormQuality(struct DiversityChecker * diverse_data,float x_bias,float y_bias,float z_bias)134 bool diversityCheckerNormQuality(struct DiversityChecker* diverse_data,
135                                  float x_bias,
136                                  float y_bias,
137                                  float z_bias) {
138   ASSERT_NOT_NULL(diverse_data);
139   // If not enough diverse data points or max distance violations return false.
140   if (diverse_data->num_points <= diverse_data->min_num_diverse_vectors ||
141       diverse_data->num_max_dist_violations >=
142       diverse_data->max_num_max_distance) {
143     return false;
144   }
145   float vec_bias[3] = {x_bias, y_bias, z_bias};
146   float vec_bias_removed[3];
147   float norm_results;
148   float acc_norm = 0.0f;
149   float acc_norm_square = 0.0f;
150   float max;
151   float min;
152   size_t i;
153   for (i = 0; i < diverse_data->num_points; ++i) {
154     // v = v1 - v_bias;
155     vecSub(vec_bias_removed,
156            &diverse_data->diverse_data[i * THREE_AXIS_DATA_DIM],
157            vec_bias,
158            THREE_AXIS_DATA_DIM);
159 
160     // norm = ||v||
161     norm_results = vecNorm(vec_bias_removed, THREE_AXIS_DATA_DIM);
162 
163     // Accumulate for mean and VAR.
164     acc_norm += norm_results;
165     acc_norm_square += norm_results * norm_results ;
166 
167     if (i == 0) {
168       min = norm_results;
169       max = norm_results;
170     }
171     // Finding min
172     if (norm_results < min) {
173       min = norm_results;
174     }
175 
176     // Finding max.
177     if (norm_results > max) {
178       max = norm_results;
179     }
180     // can leave the function if max-min is violated
181     // no need to continue.
182     if ((max - min) > diverse_data->max_min_threshold) {
183       return false;
184     }
185   }
186 
187   float inv = 1.0f / diverse_data->num_points;
188   float var = (acc_norm_square - (acc_norm * acc_norm) * inv) * inv;
189   return (var < diverse_data->var_threshold);
190 }
191 
diversityCheckerLocalFieldUpdate(struct DiversityChecker * diverse_data,float local_field)192 void diversityCheckerLocalFieldUpdate(struct DiversityChecker* diverse_data,
193                                       float local_field) {
194   if ((local_field < MAX_FIT_MAG) && (local_field > MIN_FIT_MAG)) {
195     // Updating threshold based on the local field information.
196     diverse_data->threshold = diverse_data->threshold_tuning_param_sq *
197         (local_field * local_field);
198 
199     // Updating max distance based on the local field information.
200     diverse_data->max_distance = diverse_data->max_distance_tuning_param_sq *
201         (local_field * local_field);
202   }
203 }
204