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;
32 
33 typedef struct
34 {
35  uint32_t data_length;
36  float *data;
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  */
65 
66 
67 /**
68  * @brief Free storage of data elements in a float vector
69  *
70  * @param[in] vector Vector to be freed
71  */
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 
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  */
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  */
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  */
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