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 // 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)26 void diversityCheckerInit(
27 struct DiversityChecker* diverse_data,
28 size_t min_num_diverse_vectors,
29 size_t max_num_max_distance,
30 float var_threshold,
31 float max_min_threshold,
32 float local_field,
33 float threshold_tuning_param,
34 float max_distance_tuning_param) {
35 ASSERT_NOT_NULL(diverse_data);
36
37 // Initialize parameters.
38 diverse_data->threshold_tuning_param_sq =
39 (threshold_tuning_param * threshold_tuning_param);
40 diverse_data->max_distance_tuning_param_sq =
41 (max_distance_tuning_param * max_distance_tuning_param);
42
43 // Updating the threshold and max_distance using assumed local field.
44 // Testing for zero and negative local_field.
45 if (local_field <= 0) {
46 local_field = 1;
47 }
48 diversityCheckerLocalFieldUpdate(diverse_data, local_field);
49 diverse_data->min_num_diverse_vectors = min_num_diverse_vectors;
50
51 // Checking for min_num_diverse_vectors = 0.
52 if (min_num_diverse_vectors < 1) {
53 diverse_data->min_num_diverse_vectors = 1;
54 }
55 diverse_data->max_num_max_distance = max_num_max_distance;
56 diverse_data->var_threshold = var_threshold;
57 diverse_data->max_min_threshold = max_min_threshold;
58
59 // Setting the rest to zero.
60 diversityCheckerReset(diverse_data);
61
62 // Debug Messages
63 #ifdef DIVERSE_DEBUG_ENABLE
64 memset(&diverse_data->diversity_dbg, 0, sizeof(diverse_data->diversity_dbg));
65 #endif
66 }
67
68 // Reset
diversityCheckerReset(struct DiversityChecker * diverse_data)69 void diversityCheckerReset(struct DiversityChecker* diverse_data) {
70 ASSERT_NOT_NULL(diverse_data);
71 // Clear data memory.
72 memset(&diverse_data->diverse_data, 0,
73 sizeof(diverse_data->diverse_data));
74
75 // Resetting counters and data full bit.
76 diverse_data->num_points = 0;
77 diverse_data->num_max_dist_violations = 0;
78 diverse_data->data_full = false;
79 }
80
diversityCheckerUpdate(struct DiversityChecker * diverse_data,float x,float y,float z)81 void diversityCheckerUpdate(
82 struct DiversityChecker* diverse_data, float x, float y, float z) {
83 ASSERT_NOT_NULL(diverse_data);
84
85 // Converting three single inputs to a vector.
86 const float vec[3] = {x, y, z};
87
88 // Result vector for vector difference.
89 float vec_diff[3];
90
91 // normSquared result (k)
92 float norm_squared_result;
93
94 // If memory is full, no need to run through the data.
95 if (!diverse_data->data_full) {
96 size_t i;
97 // Running over all existing data points
98 for (i = 0; i < diverse_data->num_points; ++i) {
99 // v = v1 - v2;
100 vecSub(vec_diff,
101 &diverse_data->diverse_data[i * THREE_AXIS_DATA_DIM],
102 vec,
103 THREE_AXIS_DATA_DIM);
104
105 // k = |v|^2
106 norm_squared_result = vecNormSquared(vec_diff, THREE_AXIS_DATA_DIM);
107
108 // if k < Threshold then leave the function.
109 if (norm_squared_result < diverse_data->threshold) {
110 return;
111 }
112
113 // if k > max_distance, count and leave the function.
114 if (norm_squared_result > diverse_data->max_distance) {
115 diverse_data->num_max_dist_violations++;
116 return;
117 }
118 }
119
120 // If none of the above caused to leave the function, data is diverse.
121 // Notice that the first data vector will be stored no matter what.
122 memcpy(&diverse_data->
123 diverse_data[diverse_data->num_points * THREE_AXIS_DATA_DIM],
124 vec,
125 sizeof(float) * THREE_AXIS_DATA_DIM);
126 // Count new data point.
127 diverse_data->num_points++;
128
129 // Setting data_full to 1, if memory is full.
130 if (diverse_data->num_points == NUM_DIVERSE_VECTORS) {
131 diverse_data->data_full = true;
132 }
133 }
134 }
135
diversityCheckerNormQuality(struct DiversityChecker * diverse_data,float x_bias,float y_bias,float z_bias)136 bool diversityCheckerNormQuality(struct DiversityChecker* diverse_data,
137 float x_bias,
138 float y_bias,
139 float z_bias) {
140 ASSERT_NOT_NULL(diverse_data);
141 // If not enough diverse data points or max distance violations return false.
142 if (diverse_data->num_points <= diverse_data->min_num_diverse_vectors ||
143 diverse_data->num_max_dist_violations >=
144 diverse_data->max_num_max_distance) {
145 return false;
146 }
147 float vec_bias[3] = {x_bias, y_bias, z_bias};
148 float vec_bias_removed[3];
149 float norm_results;
150 float acc_norm = 0.0f;
151 float acc_norm_square = 0.0f;
152 float max = 0.0f;
153 float min = 0.0f;
154 size_t i;
155 for (i = 0; i < diverse_data->num_points; ++i) {
156 // v = v1 - v_bias;
157 vecSub(vec_bias_removed,
158 &diverse_data->diverse_data[i * THREE_AXIS_DATA_DIM],
159 vec_bias,
160 THREE_AXIS_DATA_DIM);
161
162 // norm = ||v||
163 norm_results = vecNorm(vec_bias_removed, THREE_AXIS_DATA_DIM);
164
165 // Accumulate for mean and VAR.
166 acc_norm += norm_results;
167 acc_norm_square += norm_results * norm_results ;
168
169 if (i == 0) {
170 min = norm_results;
171 max = norm_results;
172 }
173 // Finding min
174 if (norm_results < min) {
175 min = norm_results;
176 }
177
178 // Finding max.
179 if (norm_results > max) {
180 max = norm_results;
181 }
182 // can leave the function if max-min is violated
183 // no need to continue.
184 if ((max - min) > diverse_data->max_min_threshold) {
185 return false;
186 }
187 }
188 float inv = 1.0f / diverse_data->num_points;
189 float var = (acc_norm_square - (acc_norm * acc_norm) * inv) * inv;
190
191 // Debug Message.
192 #ifdef DIVERSE_DEBUG_ENABLE
193 diverse_data->diversity_dbg.diversity_count++;
194 diverse_data->diversity_dbg.var_log = var;
195 diverse_data->diversity_dbg.mean_log = acc_norm * inv;
196 diverse_data->diversity_dbg.max_log = max;
197 diverse_data->diversity_dbg.min_log = min;
198 memcpy(&diverse_data->diversity_dbg.diverse_data_log,
199 &diverse_data->diverse_data,
200 sizeof(diverse_data->diversity_dbg.diverse_data_log));
201 #endif
202 return (var < diverse_data->var_threshold);
203 }
204
diversityCheckerLocalFieldUpdate(struct DiversityChecker * diverse_data,float local_field)205 void diversityCheckerLocalFieldUpdate(struct DiversityChecker* diverse_data,
206 float local_field) {
207 if (local_field > 0) {
208 // Updating threshold based on the local field information.
209 diverse_data->threshold = diverse_data->threshold_tuning_param_sq *
210 (local_field * local_field);
211
212 // Updating max distance based on the local field information.
213 diverse_data->max_distance = diverse_data->max_distance_tuning_param_sq *
214 (local_field * local_field);
215 }
216 }
217