acc_processing_helpers.h
Go to the documentation of this file.
1 // Copyright (c) Acconeer AB, 2022
2 // All rights reserved
3 // This file is subject to the terms and conditions defined in the file
4 // 'LICENSES/license_acconeer.txt', (BSD 3-Clause License) which is part
5 // of this source code package.
6
7 #ifndef ACC_PROCESSING_HELPERS_H_
8 #define ACC_PROCESSING_HELPERS_H_
9
10 #include <complex.h>
11 #include <stdbool.h>
12 #include <stdint.h>
13
14 #include "acc_control_helper.h"
15
16 /** \example acc_processing_helpers.c
17 * @brief This is a collection of helper functions for processing of
18 * the sparse IQ data that is generated by Acconeer's A121 radar sensor.
19 * The functions are used by Acconeer's processing examples to show
20 * common processing steps when working on sparse IQ data.
21 * The purpose of the helper functions is to increase the readability
22 * of the example programs. The helper functions do not provide optimized
23 * implementations of the processing steps.
24 */
25
26
27 typedef struct
28 {
29 uint32_t data_length;
30 float complex *data;
31 } acc_vector_iq_t;
32
33 typedef struct
34 {
35 uint32_t data_length;
36 float *data;
37 } acc_vector_float_t;
38
39
40 /**
41 * @brief Allocate storage for an IQ vector
42 *
43 * @param[in] data_length Length of the vector
44 * @return Pointer to vector or NULL if allocation failed
45 */
46
47 acc_vector_iq_t *acc_vector_iq_alloc(uint32_t data_length);
48
49
50 /**
51 * @brief Allocate storage for a float vector
52 *
53 * @param[in] data_length Length of the vector
54 * @return Pointer to vector or NULL if allocation failed
55 */
56 acc_vector_float_t *acc_vector_float_alloc(uint32_t data_length);
57
58
59 /**
60 * @brief Free storage of data elements in an IQ vector
61 *
62 * @param[in] vector Vector to be freed
63 */
64 void acc_vector_iq_free(acc_vector_iq_t *vector);
65
66
67 /**
68 * @brief Free storage of data elements in a float vector
69 *
70 * @param[in] vector Vector to be freed
71 */
72 void acc_vector_float_free(acc_vector_float_t *vector);
73
74
75 /**
76 * @brief Convert time constant to smoothing factor
77 *
78 * @param[in] time_constant_s Time constant
79 * @param[in] update_rate_hz Update rate
80 * @return Smoothing factor
81 */
82 float acc_processing_helper_tc_to_sf(float time_constant_s, float update_rate_hz);
83
84
85 /**
86 * @brief Calculate a dynamic smoothing factor
87 *
88 * Calculate a smoothing factor that are lower for the
89 * first sweeps. For the first n sweeps the exponential average will
90 * be equal to the arithmetic mean of the first n sweeps.
91 *
92 * @param[in] static_sf The target smoothing factor that will be used after the first sweeps
93 * @param[in] update_count The update count should be 0 for the first sweep and increased by one for each update
94 * @return Dynamic smoothing factor
95 */
96 float acc_processing_helper_dynamic_sf(float static_sf, uint32_t update_count);
97
98
99 /**
100 * @brief Update the exponential average of an IQ vector
101 *
102 * @param[in] current The new IQ vector that will be included in the updated exponential average
103 * @param[in, out] averaged_data The filtered data or exponential average that should be updated
104 * @param[in] sf Smoothing factor that determines how much of the old data that should be kept
105 */
106
107 void acc_vector_iq_update_exponential_average(const acc_vector_iq_t *current, acc_vector_iq_t *averaged_data, float sf);
108
109
110 /**
111 * @brief Update the exponential average of a float vector
112 *
113 * @param[in] current The new IQ float that will be included in the updated exponential average
114 * @param[in, out] averaged_data The filtered data or exponential average that should be updated
115 * @param[in] sf Smoothing factor that determines how much of the old data that should be kept
116 */
117
118 void acc_vector_float_update_exponential_average(const acc_vector_float_t *current, acc_vector_float_t *averaged_data, float sf);
119
120
121 /**
122 * @brief Converts a newly captured IQ frame with one sweep to an IQ vector
123 *
124 * The resulting vector can be used with the processing functions in this file.
125 *
126 * @param[in] control_helper_state Pointer to control helper radar state struct
127 * @param[out] vector_out IQ vector
128 */
129 void acc_get_iq_sweep_vector(const acc_control_helper_t *control_helper_state, acc_vector_iq_t *vector_out);
130
131
132 /**
133 * @brief Extract an IQ vector with sweep data for a specific point from a newly captured IQ frame with multiple sweeps
134 *
135 * The resulting vector can be used with the processing functions in this file.
136 *
137 * @param[in] control_helper_state Pointer to control helper radar state struct
138 * @param[in] point The point to get the IQ vector for
139 * @param[out] vector_out IQ vector
140 */
141 void acc_get_iq_point_vector(const acc_control_helper_t *control_helper_state, uint32_t point, acc_vector_iq_t *vector_out);
142
143
144 /**
145 * @brief Calculate filter vector length
146 *
147 * Calculate filter vector length given peak width and step size. The peak width
148 * varies depending on profile.
149 *
150 * @param[in] peak_width_points Peak width in base points
151 * @param[in] step_length Step length in base points
152 * @return Filter vector length
153 */
154 uint32_t acc_processing_helper_get_filter_length(uint32_t peak_width_points, uint32_t step_length);
155
156
157 /**
158 * @brief Create a distance filter vector
159 *
160 * Create a triangle shaped distance filter vector. Use the function
161 * acc_processing_helper_get_filter_length when allocating memory for the
162 * output vector to get the right length of the filter for a given peak width
163 * and step size.
164 *
165 * @param[out] vector_out Filter vector
166 */
167
168 void acc_vector_float_create_depth_filter_vector(acc_vector_float_t *vector_out);
169
170
171 /**
172 * @brief Apply a FIR filter to an IQ vector
173 *
174 * Performs coherent filtering of the input vector.
175 *
176 * @param[in] vector_a IQ vector
177 * @param[in] filter_vector Filter vector
178 * @param[out] vector_out Filtered result
179 *
180 */
181 void acc_vector_iq_apply_filter(const acc_vector_iq_t *vector_a, acc_vector_float_t *filter_vector, acc_vector_iq_t *vector_out);
182
183
184 /**
185 * @brief Copy an IQ vector
186 *
187 * Copy the contents of one IQ vector to another IQ vector.
188 *
189 * @param[in] vector_a Source IQ vector
190 * @param[out] vector_out Destination IQ vector
191 *
192 */
193 void acc_vector_iq_copy(const acc_vector_iq_t *vector_a, acc_vector_iq_t *vector_out);
194
195
196 /**
197 * @brief Add two IQ vectors
198 *
199 * @param[in] vector_a First input vector
200 * @param[in] vector_b Second input vector
201 * @param[out] vector_out The result a + b
202 */
203 void acc_vector_iq_add(const acc_vector_iq_t *vector_a, const acc_vector_iq_t *vector_b, acc_vector_iq_t *vector_out);
204
205
206 /**
207 * @brief Subtract two IQ vectors
208 *
209 * @param[in] vector_a First input vector
210 * @param[in] vector_b Second input vector
211 * @param[out] vector_out The result a - b
212 */
213 void acc_vector_iq_subtract(const acc_vector_iq_t *vector_a, const acc_vector_iq_t *vector_b, acc_vector_iq_t *vector_out);
214
215
216 /**
217 * @brief Multiply two IQ vectors
218 *
219 * Perform element wise multiplication of two IQ vectors.
220 *
221 * @param[in] vector_a First input vector
222 * @param[in] vector_b Second input vector
223 * @param[out] vector_out The result a * b
224 */
225 void acc_vector_iq_mult(const acc_vector_iq_t *vector_a, const acc_vector_iq_t *vector_b, acc_vector_iq_t *vector_out);
226
227
228 /**
229 * @brief Multiply first IQ vector with conjugate of second IQ vector
230 *
231 * Make element wise multiplication of an IQ vector with the conjugate
232 * of another IQ vector. The amplitudes of the result will be the product of the amplitudes
233 * of the input vectors. The phases of the result will be the phase differences of the two
234 * input vectors.
235 *
236 * The function can be used when calculating the phase difference between two consecutive
237 * sweeps.
238 *
239 * @param[in] vector_a First input vector
240 * @param[in] vector_b Second input vector
241 * @param[out] vector_out The result: a * conj(b)
242 */
243 void acc_vector_iq_mult_conj(const acc_vector_iq_t *vector_a, const acc_vector_iq_t *vector_b, acc_vector_iq_t *vector_out);
244
245
246 /**
247 * @brief Rotate the phase of elements in an IQ vector
248 *
249 * @param[in, out] vector_a The IQ vector to be modified
250 * @param[in] radians The angle in radians to rotate the phase
251 */
252 void acc_vector_iq_rotate_phase_inline(acc_vector_iq_t *vector_a, float radians);
253
254
255 /**
256 * @brief Update an IQ vector with its conjugate
257 *
258 * Replace the elements in an IQ vector with the conjugate of the elements.
259 *
260 * @param[in, out] vector_a The IQ vector to be modified
261 */
262 void acc_vector_iq_conj_inline(acc_vector_iq_t *vector_a);
263
264
265 /**
266 * @brief Amplitude of an IQ vector
267 *
268 * Calculate the amplitude of the elements in an IQ vector.
269 *
270 * @param[in] vector_a Input IQ vector
271 * @param[out] vector_out The amplitude of the elements in the input vector
272 */
273 void acc_vector_iq_amplitude(const acc_vector_iq_t *vector_a, acc_vector_float_t *vector_out);
274
275
276 /**
277 * @brief Coherent mean amplitude of IQ vector
278 *
279 * Calculate the coherent mean amplitude of the elements in an IQ vector.
280 *
281 * @param[in] vector_a Input IQ vector
282 * @return The coherent mean amplitude of the elements in vector_a
283 */
284 float acc_vector_iq_coherent_mean_amplitude(const acc_vector_iq_t *vector_a);
285
286
287 /**
288 * @brief Non-coherent mean amplitude of IQ vector
289 *
290 * Calculate the non-coherent mean amplitude of the elements in an IQ vector.
291 *
292 * @param[in] vector_a Input IQ vector
293 * @return The non-coherent mean amplitude of the elements in vector_a
294 */
295 float acc_vector_iq_noncoherent_mean_amplitude(const acc_vector_iq_t *vector_a);
296
297
298 /**
299 * @brief Phase of an IQ vector
300 *
301 * Calculate the phase of the elements in an IQ vector.
302 *
303 * @param[in] vector_a Input IQ vector
304 * @param[out] vector_out The phase of the elements in the input vector
305 */
306 void acc_vector_iq_phase(const acc_vector_iq_t *vector_a, acc_vector_float_t *vector_out);
307
308
309 /**
310 * @brief Index of element with maximum value in a float vector
311 *
312 * @param[in] vector_a Input vector
313 * @return The index of the element with the highest value
314 */
315 uint32_t acc_vector_float_argmax(acc_vector_float_t *vector_a);
316
317
318 /**
319 * @brief Index of element with maximum value in a float vector disregarding edge elements
320 *
321 * Find the index of the maximum element in a float vector disregarding
322 * the first and last elements in the vector.
323 *
324 * @param[in] vector_a Input vector
325 * @param[in] elements_to_skip The number of elements to skip
326 * @return The index of the element with the highest value
327 */
328 uint32_t acc_vector_float_argmax_skip_edges(acc_vector_float_t *vector_a, uint32_t elements_to_skip);
329
330
331 /**
332 * @brief Interpolate peak position
333 *
334 * The function fits a second degree polynomial to three consecutive amplitude
335 * values where second element is expected to contain the maximum measured amplitude.
336 * The function then finds the position of the maximum amplitude of the polynomial.
337 * The position is normalized and a return value of 0 means that the peak is at the
338 * position of the second amplitude. A value of -1 and 1 means that the peak is at
339 * the position of the first or third input amplitude respectively.
340 *
341 * @param[in] y1 The first amplitude value
342 * @param[in] y2 The second amplitude value
343 * @param[in] y3 The third amplitude value
344 * @return Interpolated peak position
345 */
346 float acc_processing_helper_interpolate_peak_position(float y1, float y2, float y3);
347
348
349 /**
350 * @brief Print float vector
351 *
352 * Print a float vector to stdout.
353 *
354 * @param[in] label A string description of the vector
355 * @param[in] vector_a The float vector to print
356 */
357 void acc_vector_float_print(const char *label, acc_vector_float_t *vector_a);
358
359
360 /**
361 * @brief Print IQ vector
362 *
363 * Print an IQ vector to stdout.
364 *
365 * @param[in] label A string description of the vector
366 * @param[in] vector_a The IQ vector to print
367 */
368 void acc_vector_iq_print(const char *label, acc_vector_iq_t *vector_a);
369
370
371 #endif
acc_vector_float_update_exponential_average
void acc_vector_float_update_exponential_average(const acc_vector_float_t *current, acc_vector_float_t *averaged_data, float sf)
Update the exponential average of a float vector.
Definition: acc_processing_helpers.c:127
acc_vector_iq_add
void acc_vector_iq_add(const acc_vector_iq_t *vector_a, const acc_vector_iq_t *vector_b, acc_vector_iq_t *vector_out)
Add two IQ vectors.
Definition: acc_processing_helpers.c:237
acc_vector_iq_phase
void acc_vector_iq_phase(const acc_vector_iq_t *vector_a, acc_vector_float_t *vector_out)
Phase of an IQ vector.
Definition: acc_processing_helpers.c:346
acc_vector_iq_coherent_mean_amplitude
float acc_vector_iq_coherent_mean_amplitude(const acc_vector_iq_t *vector_a)
Coherent mean amplitude of IQ vector.
Definition: acc_processing_helpers.c:316
acc_get_iq_point_vector
void acc_get_iq_point_vector(const acc_control_helper_t *control_helper_state, uint32_t point, acc_vector_iq_t *vector_out)
Extract an IQ vector with sweep data for a specific point from a newly captured IQ frame with multipl...
Definition: acc_processing_helpers.c:152
acc_vector_float_free
void acc_vector_float_free(acc_vector_float_t *vector)
Free storage of data elements in a float vector.
Definition: acc_processing_helpers.c:85
acc_vector_iq_free
void acc_vector_iq_free(acc_vector_iq_t *vector)
Free storage of data elements in an IQ vector.
Definition: acc_processing_helpers.c:73
acc_vector_iq_mult_conj
void acc_vector_iq_mult_conj(const acc_vector_iq_t *vector_a, const acc_vector_iq_t *vector_b, acc_vector_iq_t *vector_out)
Multiply first IQ vector with conjugate of second IQ vector.
Definition: acc_processing_helpers.c:273
acc_vector_iq_conj_inline
void acc_vector_iq_conj_inline(acc_vector_iq_t *vector_a)
Update an IQ vector with its conjugate.
Definition: acc_processing_helpers.c:296
acc_vector_float_argmax_skip_edges
uint32_t acc_vector_float_argmax_skip_edges(acc_vector_float_t *vector_a, uint32_t elements_to_skip)
Index of element with maximum value in a float vector disregarding edge elements.
Definition: acc_processing_helpers.c:375
acc_processing_helper_dynamic_sf
float acc_processing_helper_dynamic_sf(float static_sf, uint32_t update_count)
Calculate a dynamic smoothing factor.
Definition: acc_processing_helpers.c:110
acc_vector_iq_print
void acc_vector_iq_print(const char *label, acc_vector_iq_t *vector_a)
Print IQ vector.
Definition: acc_processing_helpers.c:423
acc_vector_iq_t::data
float complex * data
Definition: acc_processing_helpers.h:30
acc_vector_iq_subtract
void acc_vector_iq_subtract(const acc_vector_iq_t *vector_a, const acc_vector_iq_t *vector_b, acc_vector_iq_t *vector_out)
Subtract two IQ vectors.
Definition: acc_processing_helpers.c:249
acc_vector_float_t::data
float * data
Definition: acc_processing_helpers.h:36
acc_processing_helper_get_filter_length
uint32_t acc_processing_helper_get_filter_length(uint32_t peak_width_points, uint32_t step_length)
Calculate filter vector length.
Definition: acc_processing_helpers.c:166
acc_vector_iq_mult
void acc_vector_iq_mult(const acc_vector_iq_t *vector_a, const acc_vector_iq_t *vector_b, acc_vector_iq_t *vector_out)
Multiply two IQ vectors.
Definition: acc_processing_helpers.c:261
acc_vector_iq_t
Definition: acc_processing_helpers.h:27
acc_vector_iq_apply_filter
void acc_vector_iq_apply_filter(const acc_vector_iq_t *vector_a, acc_vector_float_t *filter_vector, acc_vector_iq_t *vector_out)
Apply a FIR filter to an IQ vector.
Definition: acc_processing_helpers.c:203
acc_vector_iq_amplitude
void acc_vector_iq_amplitude(const acc_vector_iq_t *vector_a, acc_vector_float_t *vector_out)
Amplitude of an IQ vector.
Definition: acc_processing_helpers.c:305
acc_vector_iq_copy
void acc_vector_iq_copy(const acc_vector_iq_t *vector_a, acc_vector_iq_t *vector_out)
Copy an IQ vector.
Definition: acc_processing_helpers.c:226
acc_control_helper.h
acc_vector_float_create_depth_filter_vector
void acc_vector_float_create_depth_filter_vector(acc_vector_float_t *vector_out)
Create a distance filter vector.
Definition: acc_processing_helpers.c:172
acc_vector_float_t
Definition: acc_processing_helpers.h:33
acc_vector_iq_alloc
acc_vector_iq_t * acc_vector_iq_alloc(uint32_t data_length)
Allocate storage for an IQ vector.
Definition: acc_processing_helpers.c:27
acc_vector_float_alloc
acc_vector_float_t * acc_vector_float_alloc(uint32_t data_length)
Allocate storage for a float vector.
Definition: acc_processing_helpers.c:50
acc_vector_float_t::data_length
uint32_t data_length
Definition: acc_processing_helpers.h:35
acc_vector_float_print
void acc_vector_float_print(const char *label, acc_vector_float_t *vector_a)
Print float vector.
Definition: acc_processing_helpers.c:401
acc_control_helper_t
Definition: acc_control_helper.h:23
acc_vector_iq_t::data_length
uint32_t data_length
Definition: acc_processing_helpers.h:29
acc_vector_iq_noncoherent_mean_amplitude
float acc_vector_iq_noncoherent_mean_amplitude(const acc_vector_iq_t *vector_a)
Non-coherent mean amplitude of IQ vector.
Definition: acc_processing_helpers.c:331
acc_get_iq_sweep_vector
void acc_get_iq_sweep_vector(const acc_control_helper_t *control_helper_state, acc_vector_iq_t *vector_out)
Converts a newly captured IQ frame with one sweep to an IQ vector.
Definition: acc_processing_helpers.c:138
acc_processing_helper_interpolate_peak_position
float acc_processing_helper_interpolate_peak_position(float y1, float y2, float y3)
Interpolate peak position.
Definition: acc_processing_helpers.c:395
acc_vector_float_argmax
uint32_t acc_vector_float_argmax(acc_vector_float_t *vector_a)
Index of element with maximum value in a float vector.
Definition: acc_processing_helpers.c:357
acc_vector_iq_rotate_phase_inline
void acc_vector_iq_rotate_phase_inline(acc_vector_iq_t *vector_a, float radians)
Rotate the phase of elements in an IQ vector.
Definition: acc_processing_helpers.c:285
acc_vector_iq_update_exponential_average
void acc_vector_iq_update_exponential_average(const acc_vector_iq_t *current, acc_vector_iq_t *averaged_data, float sf)
Update the exponential average of an IQ vector.
Definition: acc_processing_helpers.c:116
acc_processing_helper_tc_to_sf
float acc_processing_helper_tc_to_sf(float time_constant_s, float update_rate_hz)
Convert time constant to smoothing factor.
Definition: acc_processing_helpers.c:97