ref_app_parking.c
Go to the documentation of this file.
1 // Copyright (c) Acconeer AB, 2024
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 #include <math.h>
8 #include <stdbool.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <string.h>
12
13 #include "acc_algorithm.h"
14 #include "acc_config.h"
15 #include "acc_definitions_a121.h"
16 #include "acc_definitions_common.h"
17 #include "acc_hal_integration_a121.h"
18 #include "acc_integration.h"
19 #include "acc_integration_log.h"
20 #include "acc_processing.h"
21 #include "acc_rss_a121.h"
22 #include "acc_sensor.h"
23 #include "ref_app_parking.h"
24
25 #define CAL_ITERATIONS (3U)
26 #define MAX_AMPLITUDE (46341.0f) // sqrt((2^15)^2 + (2^15)^2)
27
28 typedef struct
29 {
30 float energy;
31 float weighted_distance;
32 } signature_t;
33
34 struct ref_app_parking_handle
35 {
36 // config
37 ref_app_parking_config_t parking_config;
38 acc_config_t *sensor_config;
39
40 // sensor handling
41 acc_sensor_id_t sensor_id;
42 acc_sensor_t *sensor;
43 void *buffer;
44 uint32_t buffer_size;
45 acc_cal_result_t cal_result;
46 uint32_t measure_timeout_ms;
47
48 // noise calibration
49 float *noise_magnitudes;
50 int16_t noise_cal_temp;
51 float noise_level;
52
53 // obstruction calibration and processing
54 float *obstruction_distances;
55 float *obstruction_magnitudes;
56 signature_t obstruction_center;
57 float obstruction_noise_level;
58 signature_t obstruction_lp_signature;
59 float obstruction_lp_const;
60 float obstruction_energy_threshold;
61 float obstruction_weighted_distance_threshold;
62
63 // processing and result
64 float *distances;
65 float *norm_distances;
66 float *magnitudes;
67 signature_t *signature_history;
68 signature_t *signature_history_sorted;
69 acc_processing_t *proc;
70 acc_processing_metadata_t proc_meta;
71 acc_processing_result_t proc_result;
72 };
73
74 /**
75 * @brief Set sensor config using already set parking config
76 *
77 * @param[in] handle The parking handle
78 */
79 static void set_sensor_config(ref_app_parking_handle_t *handle);
80
81 /**
82 * @brief Log config
83 *
84 * @param[in] handle The parking handle
85 */
86 static void log_config(ref_app_parking_handle_t *handle);
87
88 /**
89 * @brief Allocate resources for application
90 *
91 * @param[in] handle The parking handle
92 */
93 static bool allocate_application_resources(ref_app_parking_handle_t *handle);
94
95 /**
96 * @brief Initialize resources for application using already set parking config
97 *
98 * @param[in] handle The parking handle
99 */
100 static void initialize_application_resources(ref_app_parking_handle_t *handle);
101
102 /**
103 * @brief Get timeout value, in ms, for specified update rate
104 *
105 * @param[in] update_rate_hz The update rate, in Hz
106 * @return The timeout value, in ms
107 */
108 static uint32_t get_measure_timeout_ms(float update_rate_hz);
109
110 /**
111 * @brief Calculate noise level from noise data
112 *
113 * @param[in] noise_data The noise data
114 * @param[in] noise_magnitudes Intermediate step in processing will be stored here
115 * @param[in] noise_data_length The length of noise data and magnitudes
116 * @return The noise level
117 */
118 static float noise_process(acc_int16_complex_t *noise_data, float *noise_magnitudes, uint16_t noise_data_length);
119
120 /**
121 * @brief Calculate noise mean from obstruction noise data
122 *
123 * @param[in] obs_noise_data The obstruction noise data
124 * @param[in] obs_noise_data_length The length of obstruction noise data
125 * @return The noise mean
126 */
127 static float obstruction_noise(acc_int16_complex_t *obs_noise_data, uint16_t obs_noise_data_length);
128
129 /**
130 * @brief Calculate obstruction signature from obstruction data
131 *
132 * @param[in] subsweep The obstruction data
133 * @param[in] magnitudes Intermediate step in processing will be stored here
134 * @param[in] distances Corresponding distance for each point in the obstruction data
135 * @param[in] length The length of subsweep, magnitudes, and distances
136 * @param[in] noise_level The current noise level to compensate for
137 * @param[out] signature The calculated signature
138 */
139 static void obstruction_signature(acc_int16_complex_t *subsweep,
140 float *magnitudes,
141 float *distances,
142 uint16_t length,
143 float noise_level,
144 signature_t *signature);
145
146 /**
147 * @brief Calculate car signature from car data
148 *
149 * @param[in] magnitudes The car data
150 * @param[in] distances Corresponding distance for each point in the car data
151 * @param[in] length The length of magnitudes and distances
152 * @param[out] signature The calculated signature
153 */
154 static void car_signature(const float *magnitudes, const float *distances, uint16_t length, signature_t *signature);
155
156 /**
157 * @brief Determine if there are any objects present using signature history and thresholds
158 *
159 * @param[in] handle The parking handle
160 * @return true if objects present, false otherwise
161 */
162 static bool objects_present(const ref_app_parking_handle_t *handle);
163
164 /**
165 * @brief Determine if multiple signatures relates to same object
166 *
167 * @param[in] handle The parking handle
168 * @return true if multiple signatures relates to same object, false otherwise
169 */
170 static bool same_objects(ref_app_parking_handle_t *handle);
171
172 /**
173 * @brief Function used to compare two signatures for use in qsort
174 *
175 * @param[in] a First signature
176 * @param[in] b Second signature
177 * @return -1 if a is closer to sensor than b
178 * 1 if b is closer to sensor than a
179 * 0 if a and b is at same distance from sensor
180 */
181 static int compare_signature(const void *a, const void *b);
182
183 /**
184 * @brief Make sensor enter hibernate
185 *
186 * @param[in] handle The parking handle
187 */
188 static bool enter_hibernate(ref_app_parking_handle_t *handle);
189
190 /**
191 * @brief Make sensor exit hibernate
192 *
193 * @param[in] handle The parking handle
194 */
195 static bool exit_hibernate(ref_app_parking_handle_t *handle);
196
197 //-----------------------------
198 // Public definitions
199 //-----------------------------
200
201 void ref_app_parking_set_config(ref_app_parking_parking_preset_t preset, ref_app_parking_config_t *parking_config)
202 {
203 parking_config->preset = preset;
204
205 switch (parking_config->preset)
206 {
207 case PARKING_PRESET_NONE:
208 break;
209 case PARKING_PRESET_GROUND:
210 parking_config->frame_rate = 0.1f;
211 parking_config->obstruction_detection_enabled = true;
212
213 parking_config->car_config.range_start_m = 0.1f;
214 parking_config->car_config.range_end_m = 0.4f;
215 parking_config->car_config.hwaas = 24;
216 parking_config->car_config.profile = ACC_CONFIG_PROFILE_1;
217 parking_config->car_config.subsweep_index = 0U;
218 parking_config->car_config.queue_length_n = 3U;
219 parking_config->car_config.amplitude_threshold = 8.0f;
220 parking_config->car_config.weighted_distance_threshold_m = 0.1f;
221 parking_config->car_config.signature_similarity_threshold = 0.6f;
222
223 parking_config->obstruction_config.range_start_m = 0.03f;
224 parking_config->obstruction_config.range_end_m = 0.05f;
225 parking_config->obstruction_config.hwaas = 16;
226 parking_config->obstruction_config.profile = ACC_CONFIG_PROFILE_1;
227 parking_config->obstruction_config.subsweep_index = 1U;
228 parking_config->obstruction_config.threshold = 0.06f;
229 parking_config->obstruction_config.time_constant = 0.8f;
230 break;
231 case PARKING_PRESET_POLE:
232 parking_config->frame_rate = 6.0f;
233 parking_config->obstruction_detection_enabled = false;
234
235 parking_config->car_config.range_start_m = 0.2f;
236 parking_config->car_config.range_end_m = 3.0f;
237 parking_config->car_config.hwaas = 24;
238 parking_config->car_config.profile = ACC_CONFIG_PROFILE_2;
239 parking_config->car_config.subsweep_index = 0U;
240 parking_config->car_config.queue_length_n = 20U;
241 parking_config->car_config.amplitude_threshold = 6.0f;
242 parking_config->car_config.weighted_distance_threshold_m = 0.9f;
243 parking_config->car_config.signature_similarity_threshold = 0.6f;
244 break;
245 default:
246 break;
247 }
248
249 parking_config->frame_rate_app_driven = true;
250 }
251
252 ref_app_parking_handle_t *ref_app_parking_handle_create(ref_app_parking_config_t *parking_config, acc_sensor_id_t sensor_id)
253 {
254 ref_app_parking_handle_t *handle = acc_integration_mem_alloc(sizeof(*handle));
255
256 if (handle != NULL)
257 {
258 handle->parking_config = *parking_config;
259 handle->sensor_id = sensor_id;
260
261 handle->sensor_config = acc_config_create();
262 if (handle->sensor_config == NULL)
263 {
264 ref_app_parking_handle_destroy(handle);
265 return NULL;
266 }
267
268 set_sensor_config(handle);
269
270 log_config(handle);
271
272 if (!allocate_application_resources(handle))
273 {
274 ref_app_parking_handle_destroy(handle);
275 return NULL;
276 }
277
278 initialize_application_resources(handle);
279 }
280
281 return handle;
282 }
283
284 void ref_app_parking_handle_destroy(ref_app_parking_handle_t *handle)
285 {
286 if (handle != NULL)
287 {
288 acc_hal_integration_sensor_disable(handle->sensor_id);
289 acc_hal_integration_sensor_supply_off(handle->sensor_id);
290
291 if (handle->sensor != NULL)
292 {
293 acc_sensor_destroy(handle->sensor);
294 }
295
296 if (handle->signature_history_sorted != NULL)
297 {
298 acc_integration_mem_free(handle->signature_history_sorted);
299 }
300
301 if (handle->signature_history != NULL)
302 {
303 acc_integration_mem_free(handle->signature_history);
304 }
305
306 if (handle->magnitudes != NULL)
307 {
308 acc_integration_mem_free(handle->magnitudes);
309 }
310
311 if (handle->norm_distances != NULL)
312 {
313 acc_integration_mem_free(handle->norm_distances);
314 }
315
316 if (handle->distances != NULL)
317 {
318 acc_integration_mem_free(handle->distances);
319 }
320
321 if (handle->obstruction_magnitudes != NULL)
322 {
323 acc_integration_mem_free(handle->obstruction_magnitudes);
324 }
325
326 if (handle->obstruction_distances != NULL)
327 {
328 acc_integration_mem_free(handle->obstruction_distances);
329 }
330
331 if (handle->noise_magnitudes != NULL)
332 {
333 acc_integration_mem_free(handle->noise_magnitudes);
334 }
335
336 if (handle->buffer != NULL)
337 {
338 acc_integration_mem_free(handle->buffer);
339 }
340
341 if (handle->proc != NULL)
342 {
343 acc_processing_destroy(handle->proc);
344 }
345
346 if (handle->sensor_config != NULL)
347 {
348 acc_config_destroy(handle->sensor_config);
349 }
350
351 acc_integration_mem_free(handle);
352 }
353 }
354
355 bool ref_app_parking_sensor_calibration(ref_app_parking_handle_t *handle)
356 {
357 bool status = false;
358 bool cal_complete = false;
359 const uint16_t calibration_retries = 1U;
360 const uint32_t calibration_step_timeout_ms = 500U;
361
362 // Random disturbances may cause the calibration to fail. At failure, retry at least once.
363 for (uint16_t i = 0; !status && (i <= calibration_retries); i++)
364 {
365 // Reset sensor before calibration by disabling/enabling it
366 acc_hal_integration_sensor_disable(handle->sensor_id);
367 acc_hal_integration_sensor_enable(handle->sensor_id);
368
369 do
370 {
371 status = acc_sensor_calibrate(handle->sensor, &cal_complete, &handle->cal_result, handle->buffer, handle->buffer_size);
372
373 if (status && !cal_complete)
374 {
375 status = acc_hal_integration_wait_for_sensor_interrupt(handle->sensor_id, calibration_step_timeout_ms);
376 }
377 } while (status && !cal_complete);
378 }
379
380 if (status)
381 {
382 // Reset sensor after calibration by disabling/enabling it
383 acc_hal_integration_sensor_disable(handle->sensor_id);
384 acc_hal_integration_sensor_enable(handle->sensor_id);
385 }
386
387 return status;
388 }
389
390 bool ref_app_parking_noise_calibration(ref_app_parking_handle_t *handle)
391 {
392 // The config to be used for calibration is the same as the 'car config' but with TX off
393 // and a frame rate corresponding to a total measurement time of ~1s.
394 uint16_t noise_subsweep_index = handle->parking_config.car_config.subsweep_index;
395
396 acc_config_subsweep_enable_tx_set(handle->sensor_config, false, noise_subsweep_index);
397 acc_config_frame_rate_set(handle->sensor_config, (float)CAL_ITERATIONS);
398 handle->measure_timeout_ms = get_measure_timeout_ms((float)CAL_ITERATIONS);
399
400 if (!acc_sensor_prepare(handle->sensor, handle->sensor_config, &handle->cal_result, handle->buffer, handle->buffer_size))
401 {
402 printf("acc_sensor_prepare() failed\n");
403 return false;
404 }
405
406 int16_t noise_cal_temps[CAL_ITERATIONS] = {0};
407 float noise_level_sum = 0.0f;
408
409 uint16_t noise_data_offset = handle->proc_meta.subsweep_data_offset[noise_subsweep_index];
410 uint16_t noise_data_length = handle->proc_meta.subsweep_data_length[noise_subsweep_index];
411
412 for (uint16_t i = 0; i < CAL_ITERATIONS; i++)
413 {
414 if (!ref_app_parking_measure(handle, false))
415 {
416 return false;
417 }
418
419 // Only a few measurements and recently calibrated - assume indications ok
420 noise_cal_temps[i] = handle->proc_result.temperature;
421
422 noise_level_sum += noise_process(&handle->proc_result.frame[noise_data_offset], handle->noise_magnitudes, noise_data_length);
423 }
424
425 handle->noise_cal_temp = acc_algorithm_median_i16(noise_cal_temps, CAL_ITERATIONS);
426 handle->noise_level = noise_level_sum / (float)CAL_ITERATIONS;
427 handle->noise_level = (handle->noise_level == 0.0f) ? 1.0f : handle->noise_level;
428
429 // Restore the 'car config'
430 acc_config_subsweep_enable_tx_set(handle->sensor_config, true, noise_subsweep_index);
431 if (handle->parking_config.frame_rate_app_driven)
432 {
433 acc_config_frame_rate_set(handle->sensor_config, 0.0f);
434 }
435 else
436 {
437 acc_config_frame_rate_set(handle->sensor_config, handle->parking_config.frame_rate);
438 }
439
440 handle->measure_timeout_ms = get_measure_timeout_ms(handle->parking_config.frame_rate);
441
442 return true;
443 }
444
445 bool ref_app_parking_obstruction_calibration(ref_app_parking_handle_t *handle)
446 {
447 acc_config_frame_rate_set(handle->sensor_config, (float)CAL_ITERATIONS);
448 handle->measure_timeout_ms = get_measure_timeout_ms((float)CAL_ITERATIONS);
449
450 uint16_t obs_cal_subsweep_index = handle->parking_config.obstruction_config.subsweep_index;
451 uint16_t obs_cal_data_offset = handle->proc_meta.subsweep_data_offset[obs_cal_subsweep_index];
452 uint16_t obs_cal_data_length = handle->proc_meta.subsweep_data_length[obs_cal_subsweep_index];
453
454 // Noise calibration without TX
455 acc_config_subsweep_enable_tx_set(handle->sensor_config, false, handle->parking_config.obstruction_config.subsweep_index);
456
457 if (!acc_sensor_prepare(handle->sensor, handle->sensor_config, &handle->cal_result, handle->buffer, handle->buffer_size))
458 {
459 printf("acc_sensor_prepare() failed\n");
460 return false;
461 }
462
463 float noise_levels[CAL_ITERATIONS] = {0.0f};
464 float noise_level_sum = 0.0f;
465
466 for (uint16_t i = 0; i < CAL_ITERATIONS; i++)
467 {
468 if (!ref_app_parking_measure(handle, false))
469 {
470 return false;
471 }
472
473 // Only a few measurements and recently calibrated - assume indications ok
474
475 noise_levels[i] = obstruction_noise(&handle->proc_result.frame[obs_cal_data_offset], obs_cal_data_length);
476 noise_level_sum += noise_levels[i];
477 }
478
479 handle->obstruction_noise_level = noise_level_sum / CAL_ITERATIONS;
480
481 // Signature calibration with TX - sensitive to environment.
482 // Must be done with sensor free from obstruction and no car present.
483 acc_config_subsweep_enable_tx_set(handle->sensor_config, true, handle->parking_config.obstruction_config.subsweep_index);
484
485 if (!acc_sensor_prepare(handle->sensor, handle->sensor_config, &handle->cal_result, handle->buffer, handle->buffer_size))
486 {
487 printf("acc_sensor_prepare() failed\n");
488 return false;
489 }
490
491 signature_t signature = {0};
492 float energy_sum = 0.0f;
493 float weighted_distance_sum = 0.0f;
494
495 for (uint16_t i = 0; i < CAL_ITERATIONS; i++)
496 {
497 if (!ref_app_parking_measure(handle, false))
498 {
499 return false;
500 }
501
502 // Only a few measurements and recently calibrated - assume indications ok
503
504 acc_int16_complex_t *subsweep = &handle->proc_result.frame[obs_cal_data_offset];
505
506 obstruction_signature(subsweep,
507 handle->obstruction_magnitudes,
508 handle->obstruction_distances,
509 obs_cal_data_length,
510 noise_levels[i],
511 &signature);
512
513 energy_sum += signature.energy;
514 weighted_distance_sum += signature.weighted_distance;
515 }
516
517 handle->obstruction_center.energy = energy_sum / CAL_ITERATIONS;
518 handle->obstruction_center.weighted_distance = weighted_distance_sum / CAL_ITERATIONS;
519
520 handle->obstruction_lp_signature = handle->obstruction_center;
521
522 // Restore the 'obstruction config'
523 if (handle->parking_config.frame_rate_app_driven)
524 {
525 acc_config_frame_rate_set(handle->sensor_config, 0.0f);
526 }
527 else
528 {
529 acc_config_frame_rate_set(handle->sensor_config, handle->parking_config.frame_rate);
530 }
531
532 handle->measure_timeout_ms = get_measure_timeout_ms(handle->parking_config.frame_rate);
533
534 return true;
535 }
536
537 bool ref_app_parking_sensor_prepare(ref_app_parking_handle_t *handle)
538 {
539 if (!acc_sensor_prepare(handle->sensor, handle->sensor_config, &handle->cal_result, handle->buffer, handle->buffer_size))
540 {
541 printf("acc_sensor_prepare failed\n");
542 return false;
543 }
544
545 if (!enter_hibernate(handle))
546 {
547 printf("enter_hibernate failed\n");
548 return false;
549 }
550
551 return true;
552 }
553
554 bool ref_app_parking_measure(ref_app_parking_handle_t *handle, bool hibernate)
555 {
556 if (hibernate)
557 {
558 if (!exit_hibernate(handle))
559 {
560 printf("exit_hibernate failed\n");
561 return false;
562 }
563 }
564
565 if (!acc_sensor_measure(handle->sensor))
566 {
567 printf("acc_sensor_measure failed\n");
568 return false;
569 }
570
571 if (!acc_hal_integration_wait_for_sensor_interrupt(handle->sensor_id, handle->measure_timeout_ms))
572 {
573 printf("Sensor interrupt timeout\n");
574 return false;
575 }
576
577 if (!acc_sensor_read(handle->sensor, handle->buffer, handle->buffer_size))
578 {
579 printf("acc_sensor_read failed\n");
580 return false;
581 }
582
583 if (hibernate)
584 {
585 if (!enter_hibernate(handle))
586 {
587 printf("enter_hibernate failed\n");
588 return false;
589 }
590 }
591
592 acc_processing_execute(handle->proc, handle->buffer, &handle->proc_result);
593
594 return true;
595 }
596
597 bool ref_app_parking_handle_indications(ref_app_parking_handle_t *handle, bool *data_reliable)
598 {
599 bool status = true;
600
601 *data_reliable = true;
602
603 if (handle->proc_result.data_saturated)
604 {
605 *data_reliable = false;
606
607 printf("Data saturated. Try to reduce the sensor gain.\n");
608 }
609
610 if (handle->proc_result.frame_delayed)
611 {
612 printf("Frame delayed. Could not read data fast enough.\n");
613 printf("Try lowering the frame rate or call 'acc_sensor_read' more frequently.\n");
614 }
615
616 if (handle->proc_result.calibration_needed)
617 {
618 printf("The current calibration is not valid for the current temperature.\n");
619 printf("Re-calibrating sensor...\n");
620
621 if (!exit_hibernate(handle))
622 {
623 printf("exit_hibernate failed\n");
624 status = false;
625 }
626
627 if (status)
628 {
629 if (!ref_app_parking_sensor_calibration(handle))
630 {
631 printf("ref_app_parking_sensor_calibration() failed\n");
632 acc_sensor_status(handle->sensor);
633 status = false;
634 }
635 }
636
637 if (status)
638 {
639 if (!acc_sensor_prepare(handle->sensor, handle->sensor_config, &handle->cal_result, handle->buffer, handle->buffer_size))
640 {
641 printf("acc_sensor_prepare() failed\n");
642 status = false;
643 }
644 }
645
646 if (status)
647 {
648 if (!enter_hibernate(handle))
649 {
650 printf("enter_hibernate failed\n");
651 status = false;
652 }
653 }
654
655 *data_reliable = false;
656
657 printf("The sensor was successfully re-calibrated.\n");
658 }
659
660 return status;
661 }
662
663 void ref_app_parking_obstruction_process(ref_app_parking_handle_t *handle, bool *obstruction_detected)
664 {
665 ref_app_parking_config_t *parking_config = &handle->parking_config;
666 acc_config_t *sensor_config = handle->sensor_config;
667 ref_app_parking_obstruction_config_t *obstruction_config = &parking_config->obstruction_config;
668
669 acc_config_profile_t profile = acc_config_subsweep_profile_get(sensor_config, obstruction_config->subsweep_index);
670
671 float signal_adjust_factor;
672 float deviation_adjust_factor;
673
674 acc_processing_get_temperature_adjustment_factors(handle->noise_cal_temp,
675 handle->proc_result.temperature,
676 profile,
677 &signal_adjust_factor,
678 &deviation_adjust_factor);
679
680 float noise_level_adjusted = handle->obstruction_noise_level * deviation_adjust_factor;
681
682 acc_int16_complex_t *subsweep = &handle->proc_result.frame[handle->proc_meta.subsweep_data_offset[obstruction_config->subsweep_index]];
683 uint16_t num_points = acc_config_subsweep_num_points_get(sensor_config, obstruction_config->subsweep_index);
684 signature_t curr_signature = {0};
685
686 // Adjust for temperature changes
687 for (uint16_t i = 0; i < num_points; i++)
688 {
689 subsweep[i].real = ((float)subsweep[i].real / signal_adjust_factor) + 0.5f;
690 subsweep[i].imag = ((float)subsweep[i].imag / signal_adjust_factor) + 0.5f;
691 }
692
693 // Extract signature
694 obstruction_signature(subsweep, handle->obstruction_magnitudes, handle->obstruction_distances, num_points, noise_level_adjusted, &curr_signature);
695
696 // Low-pass filter of signature
697 signature_t *lp_signature = &handle->obstruction_lp_signature;
698 float lp_const = handle->obstruction_lp_const;
699
700 lp_signature->energy = lp_signature->energy * lp_const + (1.0f - lp_const) * curr_signature.energy;
701 lp_signature->weighted_distance = lp_signature->weighted_distance * lp_const + (1.0f - lp_const) * curr_signature.weighted_distance;
702
703 // Compare against thresholds
704 float energy_diff = fabsf(lp_signature->energy - handle->obstruction_center.energy);
705 float weighted_distance_diff = fabsf(lp_signature->weighted_distance - handle->obstruction_center.weighted_distance);
706
707 *obstruction_detected =
708 (energy_diff > handle->obstruction_energy_threshold) || (weighted_distance_diff > handle->obstruction_weighted_distance_threshold);
709 }
710
711 void ref_app_parking_process(ref_app_parking_handle_t *handle, bool *car_detected)
712 {
713 ref_app_parking_config_t *parking_config = &handle->parking_config;
714 acc_config_t *sensor_config = handle->sensor_config;
715 ref_app_parking_car_config_t *car_config = &parking_config->car_config;
716
717 acc_int16_complex_t *subsweep = &handle->proc_result.frame[handle->proc_meta.subsweep_data_offset[car_config->subsweep_index]];
718
719 uint16_t num_points = acc_config_subsweep_num_points_get(sensor_config, car_config->subsweep_index);
720 acc_config_profile_t profile = acc_config_subsweep_profile_get(sensor_config, car_config->subsweep_index);
721
722 float signal_adjust_factor;
723 float deviation_adjust_factor;
724
725 acc_processing_get_temperature_adjustment_factors(handle->noise_cal_temp,
726 handle->proc_result.temperature,
727 profile,
728 &signal_adjust_factor,
729 &deviation_adjust_factor);
730
731 float noise_level_adjusted = handle->noise_level * deviation_adjust_factor;
732
733 for (uint16_t i = 0; i < num_points; i++)
734 {
735 handle->magnitudes[i] = sqrtf((float)subsweep[i].real * (float)subsweep[i].real + (float)subsweep[i].imag * (float)subsweep[i].imag);
736
737 // Compensate for temperature changes
738 handle->magnitudes[i] /= noise_level_adjusted;
739
740 // Remove noise
741 handle->magnitudes[i] = (handle->magnitudes[i] - 1.0f < 0.0f) ? 0.0f : handle->magnitudes[i] - 1.0f;
742
743 // Scale with normalized distance
744 handle->magnitudes[i] *= handle->norm_distances[i];
745 }
746
747 for (uint16_t i = 1; i < car_config->queue_length_n; i++)
748 {
749 handle->signature_history[i - 1] = handle->signature_history[i];
750 }
751
752 car_signature(handle->magnitudes, handle->distances, num_points, &handle->signature_history[car_config->queue_length_n - 1]);
753
754 bool obj_present = objects_present(handle);
755 bool same_obj = same_objects(handle);
756
757 *car_detected = obj_present && same_obj;
758 }
759
760 //-----------------------------
761 // Private definitions
762 //-----------------------------
763
764 static void set_sensor_config(ref_app_parking_handle_t *handle)
765 {
766 ref_app_parking_config_t *parking_config = &handle->parking_config;
767 acc_config_t *sensor_config = handle->sensor_config;
768
769 // Common settings
770 acc_config_sweeps_per_frame_set(sensor_config, 1U); // This should not be changed
771 if (parking_config->frame_rate_app_driven)
772 {
773 acc_config_frame_rate_set(sensor_config, 0.0f);
774 }
775 else
776 {
777 acc_config_frame_rate_set(sensor_config, parking_config->frame_rate);
778 }
779
780 uint8_t num_subsweeps = parking_config->obstruction_detection_enabled ? 2U : 1U;
781
782 acc_config_num_subsweeps_set(sensor_config, num_subsweeps);
783
784 // Car settings
785 ref_app_parking_car_config_t *car_config = &parking_config->car_config;
786
787 int32_t start_point = (int32_t)roundf(car_config->range_start_m / ACC_APPROX_BASE_STEP_LENGTH_M);
788
789 // Handling of step_length based on profile and constraint in RSS API
790 uint16_t step_length = 0U;
791 float fwhm = acc_algorithm_get_fwhm(car_config->profile);
792 uint16_t step_length_ideal = (uint16_t)roundf(fwhm / ACC_APPROX_BASE_STEP_LENGTH_M);
793
794 if (step_length_ideal >= 24)
795 {
796 step_length = (step_length_ideal / 24U) * 24U;
797 }
798 else
799 {
800 step_length = step_length_ideal;
801 while (24U % step_length != 0U)
802 {
803 step_length--;
804 }
805 }
806
807 uint16_t num_points = (uint16_t)ceilf((car_config->range_end_m - car_config->range_start_m) / (step_length * ACC_APPROX_BASE_STEP_LENGTH_M));
808
809 acc_config_subsweep_start_point_set(sensor_config, start_point, car_config->subsweep_index);
810 acc_config_subsweep_step_length_set(sensor_config, step_length, car_config->subsweep_index);
811 acc_config_subsweep_num_points_set(sensor_config, num_points, car_config->subsweep_index);
812 acc_config_subsweep_hwaas_set(sensor_config, car_config->hwaas, car_config->subsweep_index);
813 acc_config_subsweep_profile_set(sensor_config, car_config->profile, car_config->subsweep_index);
814
815 // Obstruction settings
816 if (parking_config->obstruction_detection_enabled)
817 {
818 ref_app_parking_obstruction_config_t *obstruction_config = &parking_config->obstruction_config;
819
820 start_point = (int32_t)roundf(obstruction_config->range_start_m / ACC_APPROX_BASE_STEP_LENGTH_M);
821 step_length = 2U;
822
823 num_points =
824 (uint16_t)ceilf((obstruction_config->range_end_m - obstruction_config->range_start_m) / (step_length * ACC_APPROX_BASE_STEP_LENGTH_M));
825
826 acc_config_subsweep_start_point_set(sensor_config, start_point, obstruction_config->subsweep_index);
827 acc_config_subsweep_step_length_set(sensor_config, step_length, obstruction_config->subsweep_index);
828 acc_config_subsweep_num_points_set(sensor_config, num_points, obstruction_config->subsweep_index);
829 acc_config_subsweep_hwaas_set(sensor_config, obstruction_config->hwaas, obstruction_config->subsweep_index);
830 acc_config_subsweep_profile_set(sensor_config, obstruction_config->profile, obstruction_config->subsweep_index);
831 }
832 }
833
834 static void log_config(ref_app_parking_handle_t *handle)
835 {
836 ref_app_parking_config_t *parking_config = &handle->parking_config;
837
838 printf("\nParking config:\n");
839
840 char *preset_string = NULL;
841
842 switch (parking_config->preset)
843 {
844 case PARKING_PRESET_NONE:
845 preset_string = "None";
846 break;
847 case PARKING_PRESET_GROUND:
848 preset_string = "Ground";
849 break;
850 case PARKING_PRESET_POLE:
851 preset_string = "Pole";
852 break;
853 default:
854 preset_string = "";
855 break;
856 }
857
858 printf("preset: %s\n", preset_string);
859 printf("frame_rate: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(parking_config->frame_rate));
860 printf("obstruction_detection_enabled: %s\n", parking_config->obstruction_detection_enabled ? "true" : "false");
861
862 printf("\nCar config:\n");
863 printf("range_start_m: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(parking_config->car_config.range_start_m));
864 printf("range_end_m: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(parking_config->car_config.range_end_m));
865 printf("queue_length_n: %" PRIu16 "\n", parking_config->car_config.queue_length_n);
866 printf("amplitude_threshold: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(parking_config->car_config.amplitude_threshold));
867 printf("weighted_distance_threshold_m: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(parking_config->car_config.weighted_distance_threshold_m));
868 printf("signature_similarity_threshold: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(parking_config->car_config.signature_similarity_threshold));
869
870 if (parking_config->obstruction_detection_enabled)
871 {
872 printf("\nObstruction config:\n");
873 printf("range_start_m: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(parking_config->obstruction_config.range_start_m));
874 printf("range_end_m: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(parking_config->obstruction_config.range_end_m));
875 printf("threshold: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(parking_config->obstruction_config.threshold));
876 printf("time_constant: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(parking_config->obstruction_config.time_constant));
877 }
878
879 printf("\nSensor config:\n");
880 acc_config_log(handle->sensor_config);
881 }
882
883 static bool allocate_application_resources(ref_app_parking_handle_t *handle)
884 {
885 ref_app_parking_config_t *parking_config = &handle->parking_config;
886 acc_config_t *sensor_config = handle->sensor_config;
887
888 handle->proc = acc_processing_create(handle->sensor_config, &handle->proc_meta);
889 if (handle->proc == NULL)
890 {
891 return false;
892 }
893
894 if (!acc_rss_get_buffer_size(sensor_config, &handle->buffer_size))
895 {
896 return false;
897 }
898
899 handle->buffer = acc_integration_mem_alloc(handle->buffer_size);
900 if (handle->buffer == NULL)
901 {
902 return false;
903 }
904
905 uint16_t car_num_points = acc_config_subsweep_num_points_get(sensor_config, parking_config->car_config.subsweep_index);
906 uint16_t obs_num_points = acc_config_subsweep_num_points_get(sensor_config, parking_config->obstruction_config.subsweep_index);
907
908 handle->noise_magnitudes = acc_integration_mem_alloc(car_num_points * sizeof(*handle->noise_magnitudes));
909 if (handle->noise_magnitudes == NULL)
910 {
911 return false;
912 }
913
914 handle->obstruction_magnitudes = acc_integration_mem_alloc(obs_num_points * sizeof(*handle->obstruction_magnitudes));
915 if (handle->obstruction_magnitudes == NULL)
916 {
917 return false;
918 }
919
920 handle->obstruction_distances = acc_integration_mem_alloc(obs_num_points * sizeof(*handle->obstruction_distances));
921 if (handle->obstruction_distances == NULL)
922 {
923 return false;
924 }
925
926 handle->distances = acc_integration_mem_alloc(car_num_points * sizeof(*handle->distances));
927 if (handle->distances == NULL)
928 {
929 return false;
930 }
931
932 handle->norm_distances = acc_integration_mem_alloc(car_num_points * sizeof(*handle->norm_distances));
933 if (handle->norm_distances == NULL)
934 {
935 return false;
936 }
937
938 handle->magnitudes = acc_integration_mem_alloc(car_num_points * sizeof(*handle->magnitudes));
939 if (handle->magnitudes == NULL)
940 {
941 return false;
942 }
943
944 uint16_t queue_length_n = parking_config->car_config.queue_length_n;
945
946 handle->signature_history = acc_integration_mem_alloc(queue_length_n * sizeof(*handle->signature_history));
947 if (handle->signature_history == NULL)
948 {
949 return false;
950 }
951
952 handle->signature_history_sorted = acc_integration_mem_alloc(queue_length_n * sizeof(*handle->signature_history_sorted));
953 if (handle->signature_history_sorted == NULL)
954 {
955 return false;
956 }
957
958 acc_hal_integration_sensor_supply_on(handle->sensor_id);
959 acc_hal_integration_sensor_enable(handle->sensor_id);
960
961 handle->sensor = acc_sensor_create(handle->sensor_id);
962 if (handle->sensor == NULL)
963 {
964 return false;
965 }
966
967 return true;
968 }
969
970 static void initialize_application_resources(ref_app_parking_handle_t *handle)
971 {
972 ref_app_parking_config_t *parking_config = &handle->parking_config;
973 acc_config_t *sensor_config = handle->sensor_config;
974 ref_app_parking_obstruction_config_t *obstruction_config = &parking_config->obstruction_config;
975 ref_app_parking_car_config_t *car_config = &parking_config->car_config;
976
977 handle->measure_timeout_ms = get_measure_timeout_ms(parking_config->frame_rate);
978
979 float base_step_length = acc_processing_points_to_meter(1);
980
981 // Obstruction distances
982 uint8_t subsweep_index = obstruction_config->subsweep_index;
983
984 uint16_t num_points = acc_config_subsweep_num_points_get(sensor_config, subsweep_index);
985 int32_t start_point = acc_config_subsweep_start_point_get(sensor_config, subsweep_index);
986 uint16_t step_length = acc_config_subsweep_step_length_get(sensor_config, subsweep_index);
987
988 for (uint16_t i = 0; i < num_points; i++)
989 {
990 handle->obstruction_distances[i] = (float)(start_point + i * step_length) * base_step_length;
991 }
992
993 float actual_distance_range = handle->obstruction_distances[num_points - 1U] - handle->obstruction_distances[0];
994
995 handle->obstruction_lp_const = acc_algorithm_exp_smoothing_coefficient(parking_config->frame_rate, obstruction_config->time_constant);
996
997 handle->obstruction_energy_threshold = MAX_AMPLITUDE * obstruction_config->threshold;
998 handle->obstruction_weighted_distance_threshold = actual_distance_range * obstruction_config->threshold;
999
1000 // Car distances
1001 subsweep_index = car_config->subsweep_index;
1002
1003 num_points = acc_config_subsweep_num_points_get(sensor_config, subsweep_index);
1004 start_point = acc_config_subsweep_start_point_get(sensor_config, subsweep_index);
1005 step_length = acc_config_subsweep_step_length_get(sensor_config, subsweep_index);
1006
1007 for (uint16_t i = 0; i < num_points; i++)
1008 {
1009 handle->distances[i] = (float)(start_point + i * step_length) * base_step_length;
1010 handle->norm_distances[i] = handle->distances[i] / handle->distances[0];
1011 }
1012
1013 memset(handle->signature_history, 0, car_config->queue_length_n * sizeof(*handle->signature_history));
1014 memset(handle->signature_history_sorted, 0, car_config->queue_length_n * sizeof(*handle->signature_history_sorted));
1015 }
1016
1017 static uint32_t get_measure_timeout_ms(float update_rate_hz)
1018 {
1019 return (uint32_t)((1.0f / update_rate_hz) * 1000.0f) + 1000U;
1020 }
1021
1022 static float noise_process(acc_int16_complex_t *noise_data, float *noise_magnitudes, uint16_t noise_data_length)
1023 {
1024 float noise_mean = 0.0f;
1025
1026 for (uint16_t i = 0; i < noise_data_length; i++)
1027 {
1028 noise_magnitudes[i] = sqrtf((float)noise_data[i].real * (float)noise_data[i].real + (float)noise_data[i].imag * (float)noise_data[i].imag);
1029 noise_mean += noise_magnitudes[i];
1030 }
1031
1032 noise_mean /= noise_data_length;
1033
1034 float pow_sum = 0.0f;
1035
1036 for (uint16_t i = 0; i < noise_data_length; i++)
1037 {
1038 pow_sum += (noise_magnitudes[i] - noise_mean) * (noise_magnitudes[i] - noise_mean);
1039 }
1040
1041 float noise_std = sqrtf(pow_sum / noise_data_length);
1042
1043 float noise_level = noise_mean + 2.0f * noise_std;
1044
1045 return noise_level;
1046 }
1047
1048 static float obstruction_noise(acc_int16_complex_t *obs_noise_data, uint16_t obs_noise_data_length)
1049 {
1050 float noise_mean = 0.0f;
1051
1052 for (uint16_t i = 0; i < obs_noise_data_length; i++)
1053 {
1054 noise_mean +=
1055 sqrtf((float)obs_noise_data[i].real * (float)obs_noise_data[i].real + (float)obs_noise_data[i].imag * (float)obs_noise_data[i].imag);
1056 }
1057
1058 noise_mean /= obs_noise_data_length;
1059
1060 return noise_mean;
1061 }
1062
1063 static void obstruction_signature(acc_int16_complex_t *subsweep,
1064 float *magnitudes,
1065 float *distances,
1066 uint16_t length,
1067 float noise_level,
1068 signature_t *signature)
1069 {
1070 float energy_sum = 0.0f;
1071
1072 for (uint16_t j = 0; j < length; j++)
1073 {
1074 magnitudes[j] = sqrtf((float)subsweep[j].real * (float)subsweep[j].real + (float)subsweep[j].imag * (float)subsweep[j].imag);
1075 magnitudes[j] -= noise_level;
1076 energy_sum += magnitudes[j];
1077 }
1078
1079 signature->energy = (energy_sum / length);
1080 signature->weighted_distance = acc_algorithm_weighted_mean(distances, magnitudes, length);
1081 }
1082
1083 static void car_signature(const float *magnitudes, const float *distances, uint16_t length, signature_t *signature)
1084 {
1085 signature->energy = acc_algorithm_max_f32(magnitudes, length);
1086 signature->weighted_distance = acc_algorithm_weighted_mean(distances, magnitudes, length);
1087 }
1088
1089 static bool objects_present(const ref_app_parking_handle_t *handle)
1090 {
1091 uint16_t queue_length_n = handle->parking_config.car_config.queue_length_n;
1092 float amplitude_threshold = handle->parking_config.car_config.amplitude_threshold;
1093 float signature_similarity_threshold = handle->parking_config.car_config.signature_similarity_threshold;
1094
1095 uint16_t trig_count = 0;
1096
1097 for (uint16_t i = 0; i < queue_length_n; i++)
1098 {
1099 if (handle->signature_history[i].energy > amplitude_threshold)
1100 {
1101 trig_count++;
1102 }
1103 }
1104
1105 return (float)trig_count > (queue_length_n * signature_similarity_threshold);
1106 }
1107
1108 static bool same_objects(ref_app_parking_handle_t *handle)
1109 {
1110 uint16_t queue_length_n = handle->parking_config.car_config.queue_length_n;
1111 float amplitude_threshold = handle->parking_config.car_config.amplitude_threshold;
1112 float weighted_distance_threshold_m = handle->parking_config.car_config.weighted_distance_threshold_m;
1113 float signature_similarity_threshold = handle->parking_config.car_config.signature_similarity_threshold;
1114
1115 for (uint16_t i = 0; i < queue_length_n; i++)
1116 {
1117 handle->signature_history_sorted[i] = handle->signature_history[i];
1118 }
1119
1120 qsort(handle->signature_history_sorted, queue_length_n, sizeof(*handle->signature_history_sorted), compare_signature);
1121
1122 uint16_t active_cluster_count = 0;
1123 float active_cluster_ref_dist = 0.0f;
1124 uint16_t largest_cluster_count = 0;
1125
1126 for (uint16_t i = 0; i < queue_length_n; i++)
1127 {
1128 if (handle->signature_history_sorted[i].energy > amplitude_threshold)
1129 {
1130 // Start of active cluster
1131 if (active_cluster_count == 0)
1132 {
1133 active_cluster_count++;
1134 active_cluster_ref_dist = handle->signature_history_sorted[i].weighted_distance;
1135 }
1136 // End of active cluster
1137 else if (handle->signature_history_sorted[i].weighted_distance - active_cluster_ref_dist > weighted_distance_threshold_m)
1138 {
1139 if (active_cluster_count > largest_cluster_count)
1140 {
1141 largest_cluster_count = active_cluster_count;
1142 }
1143
1144 active_cluster_count = 0;
1145 active_cluster_ref_dist = 0.0f;
1146 }
1147 // Continuation of active cluster
1148 else
1149 {
1150 active_cluster_count++;
1151 }
1152 }
1153 }
1154
1155 // End last active cluster
1156 if (active_cluster_count != 0)
1157 {
1158 if (active_cluster_count > largest_cluster_count)
1159 {
1160 largest_cluster_count = active_cluster_count;
1161 }
1162 }
1163
1164 return (float)largest_cluster_count / (float)queue_length_n > signature_similarity_threshold;
1165 }
1166
1167 static int compare_signature(const void *a, const void *b)
1168 {
1169 const signature_t *sig_a = (const signature_t *)a;
1170 const signature_t *sig_b = (const signature_t *)b;
1171
1172 if (sig_a->weighted_distance < sig_b->weighted_distance)
1173 {
1174 return -1;
1175 }
1176 else if (sig_a->weighted_distance > sig_b->weighted_distance)
1177 {
1178 return 1;
1179 }
1180 else
1181 {
1182 return 0;
1183 }
1184 }
1185
1186 static bool enter_hibernate(ref_app_parking_handle_t *handle)
1187 {
1188 bool status = true;
1189
1190 if (!acc_sensor_hibernate_on(handle->sensor))
1191 {
1192 printf("acc_sensor_hibernate_on failed\n");
1193 acc_sensor_status(handle->sensor);
1194 status = false;
1195 }
1196
1197 acc_hal_integration_sensor_disable(handle->sensor_id);
1198 return status;
1199 }
1200
1201 static bool exit_hibernate(ref_app_parking_handle_t *handle)
1202 {
1203 bool status = true;
1204
1205 acc_hal_integration_sensor_enable(handle->sensor_id);
1206 if (!acc_sensor_hibernate_off(handle->sensor))
1207 {
1208 printf("acc_sensor_hibernate_off failed\n");
1209 acc_sensor_status(handle->sensor);
1210 status = false;
1211 }
1212
1213 return status;
1214 }
ref_app_parking_car_config_t
Configuration for car detection.
Definition: ref_app_parking.h:43
ref_app_parking_process
void ref_app_parking_process(ref_app_parking_handle_t *handle, bool *car_detected)
Do parking processing.
Definition: ref_app_parking.c:711
acc_hal_integration_sensor_supply_off
void acc_hal_integration_sensor_supply_off(acc_sensor_id_t sensor_id)
Power off sensor supply.
Definition: acc_hal_integration_stm32cube_xm.c:104
acc_algorithm_exp_smoothing_coefficient
float acc_algorithm_exp_smoothing_coefficient(float fs, float tc)
Calculate exponential smoothing coefficient.
Definition: acc_algorithm.c:694
acc_rss_a121.h
ref_app_parking_handle::obstruction_center
signature_t obstruction_center
Definition: ref_app_parking.c:56
ref_app_parking_handle::obstruction_lp_const
float obstruction_lp_const
Definition: ref_app_parking.c:59
acc_processing_destroy
void acc_processing_destroy(acc_processing_t *handle)
Destroy a processing instance identified with the provided processing handle.
objects_present
static bool objects_present(const ref_app_parking_handle_t *handle)
Determine if there are any objects present using signature history and thresholds.
Definition: ref_app_parking.c:1089
acc_config_subsweep_num_points_get
uint16_t acc_config_subsweep_num_points_get(const acc_config_t *config, uint8_t index)
Get the number of data points to measure.
acc_hal_integration_sensor_supply_on
void acc_hal_integration_sensor_supply_on(acc_sensor_id_t sensor_id)
Power on sensor supply.
Definition: acc_hal_integration_stm32cube_xm.c:99
acc_processing_result_t
Result provided by the processing module.
Definition: acc_processing.h:71
PARKING_PRESET_GROUND
@ PARKING_PRESET_GROUND
Definition: ref_app_parking.h:34
ref_app_parking_handle::obstruction_noise_level
float obstruction_noise_level
Definition: ref_app_parking.c:57
PARKING_PRESET_POLE
@ PARKING_PRESET_POLE
Definition: ref_app_parking.h:36
acc_sensor_read
bool acc_sensor_read(const acc_sensor_t *sensor, void *buffer, uint32_t buffer_size)
Read out radar data.
ref_app_parking_noise_calibration
bool ref_app_parking_noise_calibration(ref_app_parking_handle_t *handle)
Noise calibration.
Definition: ref_app_parking.c:390
ref_app_parking_handle::magnitudes
float * magnitudes
Definition: ref_app_parking.c:66
ref_app_parking_obstruction_config_t::time_constant
float time_constant
Definition: ref_app_parking.h:70
ref_app_parking_handle::proc
acc_processing_t * proc
Definition: ref_app_parking.c:69
acc_rss_get_buffer_size
bool acc_rss_get_buffer_size(const acc_config_t *config, uint32_t *buffer_size)
Get the buffer size needed for the specified config.
ref_app_parking_config_t
Overall configuration for parking application.
Definition: ref_app_parking.h:77
acc_int16_complex_t
Data type for interger-based representation of complex numbers.
Definition: acc_definitions_common.h:40
ref_app_parking_handle::obstruction_lp_signature
signature_t obstruction_lp_signature
Definition: ref_app_parking.c:58
acc_config_sweeps_per_frame_set
void acc_config_sweeps_per_frame_set(acc_config_t *config, uint16_t sweeps)
Set sweeps per frame.
acc_config_destroy
void acc_config_destroy(acc_config_t *config)
Destroy a configuration freeing any resources allocated.
ref_app_parking_handle::obstruction_magnitudes
float * obstruction_magnitudes
Definition: ref_app_parking.c:55
acc_cal_result_t
The result from a completed calibration.
Definition: acc_definitions_a121.h:30
ref_app_parking_car_config_t::signature_similarity_threshold
float signature_similarity_threshold
Definition: ref_app_parking.h:54
ref_app_parking_car_config_t::range_end_m
float range_end_m
Definition: ref_app_parking.h:46
ref_app_parking_obstruction_config_t
Configuration for obstruction detection.
Definition: ref_app_parking.h:61
acc_processing_execute
void acc_processing_execute(acc_processing_t *handle, void *buffer, acc_processing_result_t *result)
Process the data according to the configuration used in create.
ref_app_parking_handle::sensor
acc_sensor_t * sensor
Definition: ref_app_parking.c:42
car_signature
static void car_signature(const float *magnitudes, const float *distances, uint16_t length, signature_t *signature)
Calculate car signature from car data.
Definition: ref_app_parking.c:1083
acc_processing_get_temperature_adjustment_factors
void acc_processing_get_temperature_adjustment_factors(int16_t reference_temperature, int16_t current_temperature, acc_config_profile_t profile, float *signal_adjust_factor, float *deviation_adjust_factor)
Calculate temperature compensation for mean sweep and background noise (tx off) standard deviation.
compare_signature
static int compare_signature(const void *a, const void *b)
Function used to compare two signatures for use in qsort.
Definition: ref_app_parking.c:1167
MAX_AMPLITUDE
#define MAX_AMPLITUDE
Definition: ref_app_parking.c:26
acc_algorithm_weighted_mean
float acc_algorithm_weighted_mean(const float *data, const float *weights, uint16_t length)
Calculate weighted mean.
Definition: acc_algorithm.c:1375
acc_config_create
acc_config_t * acc_config_create(void)
Create a configuration.
signature_t
Definition: ref_app_parking.c:28
ref_app_parking_handle::measure_timeout_ms
uint32_t measure_timeout_ms
Definition: ref_app_parking.c:46
ref_app_parking_obstruction_config_t::profile
acc_config_profile_t profile
Definition: ref_app_parking.h:66
acc_integration.h
ref_app_parking_obstruction_config_t::subsweep_index
uint8_t subsweep_index
Definition: ref_app_parking.h:67
ref_app_parking_config_t::frame_rate_app_driven
bool frame_rate_app_driven
Definition: ref_app_parking.h:81
ACC_CONFIG_PROFILE_2
@ ACC_CONFIG_PROFILE_2
Definition: acc_definitions_a121.h:53
ref_app_parking_obstruction_config_t::threshold
float threshold
Definition: ref_app_parking.h:69
ref_app_parking_config_t::obstruction_detection_enabled
bool obstruction_detection_enabled
Definition: ref_app_parking.h:82
exit_hibernate
static bool exit_hibernate(ref_app_parking_handle_t *handle)
Make sensor exit hibernate.
Definition: ref_app_parking.c:1201
ref_app_parking_car_config_t::amplitude_threshold
float amplitude_threshold
Definition: ref_app_parking.h:52
ref_app_parking_car_config_t::weighted_distance_threshold_m
float weighted_distance_threshold_m
Definition: ref_app_parking.h:53
acc_config_frame_rate_set
void acc_config_frame_rate_set(acc_config_t *config, float frame_rate)
Set the frame rate.
acc_integration_mem_alloc
void * acc_integration_mem_alloc(size_t size)
Allocate dynamic memory.
Definition: acc_integration_stm32.c:592
ref_app_parking_handle_create
ref_app_parking_handle_t * ref_app_parking_handle_create(ref_app_parking_config_t *parking_config, acc_sensor_id_t sensor_id)
Create parking handle.
Definition: ref_app_parking.c:252
acc_processing_metadata_t
Metadata that will be populated by the processing module during creation.
Definition: acc_processing.h:36
ref_app_parking_car_config_t::queue_length_n
uint16_t queue_length_n
Definition: ref_app_parking.h:51
acc_sensor.h
noise_process
static float noise_process(acc_int16_complex_t *noise_data, float *noise_magnitudes, uint16_t noise_data_length)
Calculate noise level from noise data.
Definition: ref_app_parking.c:1022
ref_app_parking_handle::obstruction_energy_threshold
float obstruction_energy_threshold
Definition: ref_app_parking.c:60
ref_app_parking_obstruction_config_t::hwaas
uint16_t hwaas
Definition: ref_app_parking.h:65
ref_app_parking_handle
Definition: ref_app_parking.c:34
ref_app_parking_handle::cal_result
acc_cal_result_t cal_result
Definition: ref_app_parking.c:45
acc_hal_integration_wait_for_sensor_interrupt
bool acc_hal_integration_wait_for_sensor_interrupt(acc_sensor_id_t sensor_id, uint32_t timeout_ms)
Wait for a sensor interrupt.
Definition: acc_hal_integration_stm32cube_xm.c:130
log_config
static void log_config(ref_app_parking_handle_t *handle)
Log config.
Definition: ref_app_parking.c:834
obstruction_noise
static float obstruction_noise(acc_int16_complex_t *obs_noise_data, uint16_t obs_noise_data_length)
Calculate noise mean from obstruction noise data.
Definition: ref_app_parking.c:1048
acc_hal_integration_a121.h
ref_app_parking_obstruction_process
void ref_app_parking_obstruction_process(ref_app_parking_handle_t *handle, bool *obstruction_detected)
Do obstruction processing.
Definition: ref_app_parking.c:663
ref_app_parking_obstruction_config_t::range_start_m
float range_start_m
Definition: ref_app_parking.h:63
handle
cargo_handle_t * handle
Definition: i2c_example_cargo.c:35
obstruction_signature
static void obstruction_signature(acc_int16_complex_t *subsweep, float *magnitudes, float *distances, uint16_t length, float noise_level, signature_t *signature)
Calculate obstruction signature from obstruction data.
Definition: ref_app_parking.c:1063
acc_sensor_hibernate_off
bool acc_sensor_hibernate_off(const acc_sensor_t *sensor)
Restore sensor after exiting hibernation.
acc_int16_complex_t::real
int16_t real
Definition: acc_definitions_common.h:42
acc_config_t
struct acc_config acc_config_t
Definition: acc_config.h:24
printf
#define printf
Definition: printf.h:60
acc_config_subsweep_step_length_get
uint16_t acc_config_subsweep_step_length_get(const acc_config_t *config, uint8_t index)
Get the step length in a sweep.
ref_app_parking_handle::noise_magnitudes
float * noise_magnitudes
Definition: ref_app_parking.c:49
acc_processing_points_to_meter
float acc_processing_points_to_meter(int32_t points)
Convert a distance or step length in points to meter.
ref_app_parking_config_t::obstruction_config
ref_app_parking_obstruction_config_t obstruction_config
Definition: ref_app_parking.h:85
ref_app_parking_handle_indications
bool ref_app_parking_handle_indications(ref_app_parking_handle_t *handle, bool *data_reliable)
Handle indications from a measurement.
Definition: ref_app_parking.c:597
acc_config_num_subsweeps_set
void acc_config_num_subsweeps_set(acc_config_t *config, uint8_t num_subsweeps)
Set the number of subsweeps to use.
acc_hal_integration_sensor_enable
void acc_hal_integration_sensor_enable(acc_sensor_id_t sensor_id)
Enable sensor.
Definition: acc_hal_integration_stm32cube_xm.c:109
ref_app_parking_handle::distances
float * distances
Definition: ref_app_parking.c:64
ref_app_parking_config_t::frame_rate
float frame_rate
Definition: ref_app_parking.h:80
ref_app_parking_obstruction_config_t::range_end_m
float range_end_m
Definition: ref_app_parking.h:64
acc_config_subsweep_start_point_set
void acc_config_subsweep_start_point_set(acc_config_t *config, int32_t start_point, uint8_t index)
Set the starting point of the sweep.
ref_app_parking_handle::parking_config
ref_app_parking_config_t parking_config
Definition: ref_app_parking.c:37
acc_config_subsweep_profile_set
void acc_config_subsweep_profile_set(acc_config_t *config, acc_config_profile_t profile, uint8_t index)
Set a profile.
ref_app_parking_handle::obstruction_distances
float * obstruction_distances
Definition: ref_app_parking.c:54
ref_app_parking_handle::buffer_size
uint32_t buffer_size
Definition: ref_app_parking.c:44
ref_app_parking_sensor_prepare
bool ref_app_parking_sensor_prepare(ref_app_parking_handle_t *handle)
Prepare sensor for measurement.
Definition: ref_app_parking.c:537
ref_app_parking_config_t::car_config
ref_app_parking_car_config_t car_config
Definition: ref_app_parking.h:84
ref_app_parking_handle::sensor_config
acc_config_t * sensor_config
Definition: ref_app_parking.c:38
allocate_application_resources
static bool allocate_application_resources(ref_app_parking_handle_t *handle)
Allocate resources for application.
Definition: ref_app_parking.c:883
CAL_ITERATIONS
#define CAL_ITERATIONS
Definition: ref_app_parking.c:25
ACC_APPROX_BASE_STEP_LENGTH_M
#define ACC_APPROX_BASE_STEP_LENGTH_M
Approximate minimum step length for a sensor measurement in meters.
Definition: acc_algorithm.h:19
PARKING_PRESET_NONE
@ PARKING_PRESET_NONE
Definition: ref_app_parking.h:32
ref_app_parking_car_config_t::subsweep_index
uint8_t subsweep_index
Definition: ref_app_parking.h:49
acc_algorithm_max_f32
float acc_algorithm_max_f32(const float *data, uint16_t length)
Find max value of input data.
Definition: acc_algorithm.c:1360
acc_hal_integration_sensor_disable
void acc_hal_integration_sensor_disable(acc_sensor_id_t sensor_id)
Disable sensor.
Definition: acc_hal_integration_stm32cube_xm.c:119
ref_app_parking_handle::proc_result
acc_processing_result_t proc_result
Definition: ref_app_parking.c:71
ref_app_parking_measure
bool ref_app_parking_measure(ref_app_parking_handle_t *handle, bool hibernate)
Perform a sensor measurement.
Definition: ref_app_parking.c:554
ref_app_parking_handle::proc_meta
acc_processing_metadata_t proc_meta
Definition: ref_app_parking.c:70
ref_app_parking_handle::noise_level
float noise_level
Definition: ref_app_parking.c:51
signature_t::energy
float energy
Definition: ref_app_parking.c:30
acc_sensor_id_t
uint32_t acc_sensor_id_t
Type representing a sensor ID.
Definition: acc_definitions_common.h:13
acc_processing_t
struct acc_processing_handle acc_processing_t
Definition: acc_processing.h:30
acc_integration_log.h
ref_app_parking_car_config_t::profile
acc_config_profile_t profile
Definition: ref_app_parking.h:48
acc_sensor_hibernate_on
bool acc_sensor_hibernate_on(acc_sensor_t *sensor)
Prepare sensor for entering hibernation.
ACC_LOG_FLOAT_TO_INTEGER
#define ACC_LOG_FLOAT_TO_INTEGER(a)
Definition: acc_integration_log.h:26
acc_sensor_status
void acc_sensor_status(const acc_sensor_t *sensor)
Check the status of the sensor.
ref_app_parking_handle::noise_cal_temp
int16_t noise_cal_temp
Definition: ref_app_parking.c:50
acc_algorithm_median_i16
int16_t acc_algorithm_median_i16(int16_t *data, uint16_t length)
Calculate median of input data.
Definition: acc_algorithm.c:1324
ref_app_parking_handle::sensor_id
acc_sensor_id_t sensor_id
Definition: ref_app_parking.c:41
acc_algorithm.h
initialize_application_resources
static void initialize_application_resources(ref_app_parking_handle_t *handle)
Initialize resources for application using already set parking config.
Definition: ref_app_parking.c:970
acc_sensor_prepare
bool acc_sensor_prepare(acc_sensor_t *sensor, const acc_config_t *config, const acc_cal_result_t *cal_result, void *buffer, uint32_t buffer_size)
Prepare a sensor to do a measurement.
acc_algorithm_get_fwhm
float acc_algorithm_get_fwhm(acc_config_profile_t profile)
Get the envelope Full Width Half Maximum in meters given a profile.
Definition: acc_algorithm.c:745
enter_hibernate
static bool enter_hibernate(ref_app_parking_handle_t *handle)
Make sensor enter hibernate.
Definition: ref_app_parking.c:1186
acc_integration_mem_free
void acc_integration_mem_free(void *ptr)
Free dynamic memory.
Definition: acc_integration_stm32.c:602
acc_int16_complex_t::imag
int16_t imag
Definition: acc_definitions_common.h:43
acc_config_profile_t
acc_config_profile_t
Profile.
Definition: acc_definitions_a121.h:49
acc_definitions_common.h
ref_app_parking_parking_preset_t
ref_app_parking_parking_preset_t
Configuration presets - a set of configurations for a specific sensor placement.
Definition: ref_app_parking.h:29
set_sensor_config
static void set_sensor_config(ref_app_parking_handle_t *handle)
Set sensor config using already set parking config.
Definition: ref_app_parking.c:764
ref_app_parking.h
ref_app_parking_obstruction_calibration
bool ref_app_parking_obstruction_calibration(ref_app_parking_handle_t *handle)
Obstruction calibration.
Definition: ref_app_parking.c:445
acc_config_subsweep_hwaas_set
void acc_config_subsweep_hwaas_set(acc_config_t *config, uint16_t hwaas, uint8_t index)
Set the hardware accelerated average samples (HWAAS)
acc_config_log
void acc_config_log(const acc_config_t *config)
Print a configuration to the log.
acc_config_subsweep_step_length_set
void acc_config_subsweep_step_length_set(acc_config_t *config, uint16_t step_length, uint8_t index)
Set the step length in a sweep.
acc_config_subsweep_profile_get
acc_config_profile_t acc_config_subsweep_profile_get(const acc_config_t *config, uint8_t index)
Get the currently used profile.
acc_config.h
ref_app_parking_car_config_t::range_start_m
float range_start_m
Definition: ref_app_parking.h:45
ref_app_parking_config_t::preset
ref_app_parking_parking_preset_t preset
Definition: ref_app_parking.h:79
ref_app_parking_sensor_calibration
bool ref_app_parking_sensor_calibration(ref_app_parking_handle_t *handle)
Sensor calibration.
Definition: ref_app_parking.c:355
ref_app_parking_handle::signature_history
signature_t * signature_history
Definition: ref_app_parking.c:67
acc_sensor_calibrate
bool acc_sensor_calibrate(acc_sensor_t *sensor, bool *cal_complete, acc_cal_result_t *cal_result, void *buffer, uint32_t buffer_size)
Calibrate a sensor.
acc_config_subsweep_num_points_set
void acc_config_subsweep_num_points_set(acc_config_t *config, uint16_t num_points, uint8_t index)
Set the number of data points to measure.
get_measure_timeout_ms
static uint32_t get_measure_timeout_ms(float update_rate_hz)
Get timeout value, in ms, for specified update rate.
Definition: ref_app_parking.c:1017
PRIfloat
#define PRIfloat
Specifier for printing float type using integers.
Definition: acc_integration_log.h:31
ref_app_parking_handle::buffer
void * buffer
Definition: ref_app_parking.c:43
ACC_CONFIG_PROFILE_1
@ ACC_CONFIG_PROFILE_1
Definition: acc_definitions_a121.h:52
ref_app_parking_handle::signature_history_sorted
signature_t * signature_history_sorted
Definition: ref_app_parking.c:68
acc_config_subsweep_enable_tx_set
void acc_config_subsweep_enable_tx_set(acc_config_t *config, bool enable, uint8_t index)
Enable or disable the transmitter.
same_objects
static bool same_objects(ref_app_parking_handle_t *handle)
Determine if multiple signatures relates to same object.
Definition: ref_app_parking.c:1108
ref_app_parking_handle::norm_distances
float * norm_distances
Definition: ref_app_parking.c:65
acc_sensor_measure
bool acc_sensor_measure(acc_sensor_t *sensor)
Start a radar measurement with previously prepared configuration.
acc_processing_create
acc_processing_t * acc_processing_create(const acc_config_t *config, acc_processing_metadata_t *processing_metadata)
Create a processing instance with the provided configuration.
acc_config_subsweep_start_point_get
int32_t acc_config_subsweep_start_point_get(const acc_config_t *config, uint8_t index)
Get the starting point of the sweep.
ref_app_parking_car_config_t::hwaas
uint16_t hwaas
Definition: ref_app_parking.h:47
acc_processing.h
acc_sensor_t
struct acc_sensor acc_sensor_t
Definition: acc_sensor.h:31
ref_app_parking_handle_destroy
void ref_app_parking_handle_destroy(ref_app_parking_handle_t *handle)
Destroy parking handle.
Definition: ref_app_parking.c:284
ref_app_parking_handle::obstruction_weighted_distance_threshold
float obstruction_weighted_distance_threshold
Definition: ref_app_parking.c:61
ref_app_parking_set_config
void ref_app_parking_set_config(ref_app_parking_parking_preset_t preset, ref_app_parking_config_t *parking_config)
Set parking config according to specified preset.
Definition: ref_app_parking.c:201
acc_sensor_destroy
void acc_sensor_destroy(acc_sensor_t *sensor)
Destroy a sensor instance freeing any resources allocated.
acc_definitions_a121.h
signature_t::weighted_distance
float weighted_distance
Definition: ref_app_parking.c:31
acc_sensor_create
acc_sensor_t * acc_sensor_create(acc_sensor_id_t sensor_id)
Create a sensor instance.