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"
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;
32 } signature_t;
33 
35 {
36  // config
39 
40  // sensor handling
43  void *buffer;
44  uint32_t buffer_size;
47 
48  // noise calibration
50  int16_t noise_cal_temp;
51  float noise_level;
52 
53  // obstruction calibration and processing
62 
63  // processing and result
64  float *distances;
66  float *magnitudes;
72 };
73 
74 /**
75  * @brief Set sensor config using already set parking config
76  *
77  * @param[in] handle The parking handle
78  */
80 
81 /**
82  * @brief Log config
83  *
84  * @param[in] handle The parking handle
85  */
87 
88 /**
89  * @brief Allocate resources for application
90  *
91  * @param[in] handle The parking handle
92  */
94 
95 /**
96  * @brief Initialize resources for application using already set parking config
97  *
98  * @param[in] handle The parking handle
99  */
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  */
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  */
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  */
189 
190 /**
191  * @brief Make sensor exit hibernate
192  *
193  * @param[in] handle The parking handle
194  */
196 
197 //-----------------------------
198 // Public definitions
199 //-----------------------------
200 
202 {
203  parking_config->preset = preset;
204 
205  switch (parking_config->preset)
206  {
207  case PARKING_PRESET_NONE:
208  break;
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;
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 
253 {
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  {
265  return NULL;
266  }
267 
269 
271 
273  {
275  return NULL;
276  }
277 
279  }
280 
281  return handle;
282 }
283 
285 {
286  if (handle != NULL)
287  {
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  {
339  }
340 
341  if (handle->proc != NULL)
342  {
344  }
345 
346  if (handle->sensor_config != NULL)
347  {
348  acc_config_destroy(handle->sensor_config);
349  }
350 
352  }
353 }
354 
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
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
385  }
386 
387  return status;
388 }
389 
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 
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 
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 
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 
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  {
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 
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 
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 
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 
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 
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 
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;
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 
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 
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 
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 
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 
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 
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 
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 
1198  return status;
1199 }
1200 
1202 {
1203  bool status = true;
1204 
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.