Go to the documentation of this file.
33 #define CONFIG_SURFACE_DISTANCE (1.0f)
40 #define CONFIG_SENSOR_ANGLE (45.0f)
47 #define CONFIG_THRESHOLD_SENSITIVITY (0.15f)
56 #define CONFIG_PSD_LP_COEFF (0.75f)
65 #define CONFIG_VELOCITY_LP_COEFF (0.98f)
72 #define CONFIG_SWEEP_RATE (3000U)
79 #define CONFIG_HWAAS (16U)
81 #define SENSOR_ID (1U)
82 #define SENSOR_TIMEOUT_MS (1000U)
84 #define MIN_PEAK_VS 0.1f
220 if (
config.sensor_config == NULL)
222 printf(
"acc_config_create() failed\n");
235 printf(
"Failed to validate config\n");
242 printf(
"Failed to initialize handle\n");
249 printf(
"Failed to initialize sensor resources\n");
262 if (
handle.proc_result.calibration_needed)
264 printf(
"The current calibration is not valid for the current temperature.\n");
265 printf(
"The sensor needs to be re-calibrated.\n");
269 printf(
"do_sensor_calibration_and_prepare() failed\n");
275 printf(
"The sensor was successfully re-calibrated.\n");
291 printf(
"Application finished OK\n");
298 for (uint16_t i = 0U; i <
handle->segment_length; i++)
303 handle->surface_velocity_config.cfar_win,
304 handle->surface_velocity_config.cfar_guard,
305 handle->surface_velocity_config.threshold_sensitivity,
308 if (
handle->psd[i] > threshold)
321 memset(
handle->merged_velocities, 0,
handle->merged_peaks_length *
sizeof(*
handle->merged_velocities));
322 memset(
handle->merged_energies, 0,
handle->merged_peaks_length *
sizeof(*
handle->merged_energies));
329 handle->merged_velocities,
331 handle->merged_peaks_length,
332 &(
handle->num_merged_peaks));
341 handle->bin_vertical_vs[
handle->middle_index +
handle->surface_velocity_config.slow_zone_half_length]);
349 float insonation_angle = asinf(surface_distance / distance);
350 float angle_correction = 1.0f / cosf(insonation_angle);
352 return angle_correction;
360 if (
handle->processing != NULL)
365 if (
config->sensor_config != NULL)
370 if (
handle->buffer != NULL)
375 if (
handle->sensor != NULL)
380 if (
handle->double_buffer_filter_buffer != NULL)
385 if (
handle->frame != NULL)
390 if (
handle->time_series != NULL)
395 if (
handle->time_series_buffer != NULL)
400 if (
handle->bin_rad_vs != NULL)
405 if (
handle->bin_vertical_vs != NULL)
410 if (
handle->lp_psds != NULL)
415 if (
handle->fft_out != NULL)
430 if (
handle->window != NULL)
435 if (
handle->threshold_check != NULL)
440 if (
handle->merged_velocities != NULL)
445 if (
handle->merged_energies != NULL)
450 if (
handle->peak_indexes != NULL)
458 float optimal_distance =
config->surface_distance / cosf(
config->sensor_angle * (((
float)
M_PI) / 180.0f));
490 config->time_series_length = 512U;
491 config->slow_zone_half_length = 3U;
494 config->max_peak_interval_s = 4.0f;
514 if (num_subsweeps != 1U)
516 printf(
"Multiple subsweeps are not supported\n");
520 if (sweep_rate == 0.0f)
522 printf(
"Sweep rate must be set\n");
526 if (start_point * ACC_APPROX_BASE_STEP_LENGTH_M <= config->surface_distance)
528 printf(
"Start point must be > surface distance");
532 if (
config->sensor_angle <= 0 ||
config->sensor_angle >= 90)
534 printf(
"Sensor angle must be between 0 and 90 degrees");
544 bool cal_complete =
false;
546 const uint16_t calibration_retries = 1U;
549 for (uint16_t i = 0; !status && (i <= calibration_retries); i++)
559 if (status && !cal_complete)
563 }
while (status && !cal_complete);
581 if (
handle->processing == NULL)
583 printf(
"acc_processing_create() failed\n");
589 printf(
"acc_rss_get_buffer_size() failed\n");
594 if (
handle->buffer == NULL)
596 printf(
"buffer allocation failed\n");
604 if (
handle->sensor == NULL)
606 printf(
"acc_sensor_create() failed\n");
612 printf(
"do_sensor_calibration_and_prepare() failed\n");
624 handle->update_index = 0U;
625 handle->lp_velocity = 0.0f;
626 handle->vertical_v = 0.0f;
628 handle->surface_velocity_config.cfar_guard =
config->cfar_guard;
629 handle->surface_velocity_config.cfar_win =
config->cfar_win;
630 handle->surface_velocity_config.slow_zone_half_length =
config->slow_zone_half_length;
631 handle->surface_velocity_config.velocity_lp_coeff =
config->velocity_lp_coeff;
632 handle->surface_velocity_config.surface_distance =
config->surface_distance;
633 handle->surface_velocity_config.psd_lp_coeff =
config->psd_lp_coeff;
637 printf(
"Invalid CFAR sensitivity config\n");
650 float estimated_frame_rate;
654 estimated_frame_rate =
handle->sweep_rate /
handle->sweeps_per_frame;
661 handle->max_peak_interval_n =
config->max_peak_interval_s * estimated_frame_rate;
665 handle->surface_velocity_config.time_series_length =
handle->sweeps_per_frame;
669 if (
handle->sweeps_per_frame >
config->time_series_length)
671 printf(
"Too many sweeps per frame to be handled\n");
676 handle->surface_velocity_config.time_series_length =
config->time_series_length;
680 handle->segment_length =
handle->surface_velocity_config.time_series_length / 4U;
682 if (
handle->segment_length % 2U != 0U)
684 handle->segment_length += 1U;
687 handle->padded_segment_length_shift = 0U;
688 handle->padded_segment_length = 1U <<
handle->padded_segment_length_shift;
690 while (
handle->padded_segment_length <
handle->segment_length)
692 handle->padded_segment_length_shift++;
693 handle->padded_segment_length = 1U <<
handle->padded_segment_length_shift;
696 handle->middle_index = rintf((
float)
handle->segment_length / 2.0f);
715 handle->merged_peaks_length =
handle->segment_length / 2U;
718 handle->num_merged_peaks = 0U;
720 handle->peak_indexes_length =
handle->segment_length / 2U;
724 bool alloc_success =
handle->double_buffer_filter_buffer &&
handle->time_series != NULL &&
handle->time_series_buffer != NULL &&
725 handle->frame != NULL &&
handle->bin_rad_vs != NULL &&
handle->bin_vertical_vs != NULL &&
handle->lp_psds != NULL &&
727 handle->merged_velocities != NULL &&
handle->merged_energies != NULL &&
handle->peak_indexes != NULL;
731 printf(
"Failed to allocate resources for the surface velocity handle\n");
735 memset(
handle->time_series, 0,
handle->surface_velocity_config.time_series_length *
handle->num_distances *
sizeof(*
handle->time_series));
738 memset(
handle->merged_velocities, 0,
handle->merged_peaks_length *
sizeof(*
handle->merged_velocities));
739 memset(
handle->merged_energies, 0,
handle->merged_peaks_length *
sizeof(*
handle->merged_energies));
748 for (uint16_t i = 0U; i <
handle->segment_length; i++)
750 handle->bin_rad_vs[i] *= perceived_wavelength;
760 printf(
"acc_sensor_measure failed\n");
767 printf(
"Sensor interrupt timeout\n");
774 printf(
"acc_sensor_read failed\n");
792 for (uint16_t i = 0U; i <
handle->sweeps_per_frame; i++)
794 for (uint16_t j = 0U; j <
handle->num_distances; j++)
796 uint16_t index = i *
handle->num_distances + j;
798 handle->frame[j] = ((float)
handle->proc_result.frame[index].real) + ((float)
handle->proc_result.frame[index].imag) * I;
802 handle->surface_velocity_config.time_series_length,
809 handle->surface_velocity_config.time_series_length,
812 handle->time_series_buffer,
816 handle->padded_segment_length_shift,
821 if (
handle->update_index *
handle->sweeps_per_frame <
handle->surface_velocity_config.time_series_length)
823 for (uint16_t i = 0U; i <
handle->segment_length; i++)
825 for (uint16_t j = 0U; j <
handle->num_distances; j++)
832 for (uint16_t i = 0U; i <
handle->segment_length; i++)
834 for (uint16_t j = 0U; j <
handle->num_distances; j++)
837 handle->lp_psds[i *
handle->num_distances + j] *
handle->surface_velocity_config.psd_lp_coeff +
838 handle->psds[i *
handle->num_distances + j] * (1 -
handle->surface_velocity_config.psd_lp_coeff);
846 handle->surface_velocity_config.slow_zone_half_length);
848 for (uint16_t i = 0U; i <
handle->segment_length; i++)
863 handle->double_buffer_filter_buffer);
869 for (uint16_t i = 0U; i <
handle->segment_length; i++)
871 handle->bin_vertical_vs[i] =
handle->bin_rad_vs[i] * angle_correction;
880 handle->peak_indexes_length,
884 if (
handle->num_peaks > 0U)
886 float max_abs_bin_vertical_v = -INFINITY;
887 for (uint16_t i = 0U; i <
handle->num_peaks; i++)
889 float abs_bin_vertical_v = fabsf(
handle->bin_vertical_vs[
handle->peak_indexes[i]]);
891 max_abs_bin_vertical_v = fmaxf(abs_bin_vertical_v, max_abs_bin_vertical_v);
894 uint16_t velocity_index =
handle->middle_index +
handle->surface_velocity_config.slow_zone_half_length;
896 if (max_abs_bin_vertical_v >
handle->bin_vertical_vs[velocity_index])
902 printf(
"Failed to merge peaks\n");
911 handle->bin_vertical_vs[velocity_index]);
916 if (fabsf(
handle->lp_velocity) > 0.0f &&
handle->vertical_v /
handle->lp_velocity < 0.8f)
939 handle->vertical_v = 0.0f;
947 if (
handle->update_index *
handle->sweeps_per_frame >
handle->surface_velocity_config.time_series_length)
952 handle->update_index += 1U;
955 result->distance_m = distance;
960 printf(
"Failed to detect peaks\n");
975 const float speed_of_light = 299792458.0f;
976 const float radio_frequency = 60.5e9f;
977 const float wavelength = speed_of_light / radio_frequency;
979 return wavelength / 2.0f;
991 return fminf(static_sf, 1.0f - 1.0f / (1.0f + update_count));
void acc_config_start_point_set(acc_config_t *config, int32_t start_point)
Set the starting point of the sweep.
void acc_config_inter_frame_idle_state_set(acc_config_t *config, acc_config_idle_state_t idle_state)
Set inter frame idle state.
static size_t acc_alg_basic_utils_calculate_length_of_bitarray_uint32(size_t number_of_bits)
Calculate length of 32-bit array to contain size number of bits.
void acc_hal_integration_sensor_supply_off(acc_sensor_id_t sensor_id)
Power off sensor supply.
void acc_processing_destroy(acc_processing_t *handle)
Destroy a processing instance identified with the provided processing handle.
void acc_hal_integration_sensor_supply_on(acc_sensor_id_t sensor_id)
Power on sensor supply.
static bool measure(acc_surface_velocity_handle_t *handle)
Result provided by the processing module.
bool acc_config_continuous_sweep_mode_get(const acc_config_t *config)
Get continuous sweep mode.
static float get_angle_correction(float surface_distance, float distance)
bool acc_sensor_read(const acc_sensor_t *sensor, void *buffer, uint32_t buffer_size)
Read out radar data.
acc_processing_result_t proc_result
int32_t * double_buffer_filter_buffer
uint8_t acc_config_num_subsweeps_get(const acc_config_t *config)
Get the number of subsweeps to use.
float acc_algorithm_get_distance_m(uint16_t step_length, uint16_t start_point, float base_step_length_m, uint16_t idx)
Calculate distance for a point at an index.
void acc_config_profile_set(acc_config_t *config, acc_config_profile_t profile)
Set a profile.
float max_peak_interval_s
void acc_algorithm_double_buffering_frame_filter(acc_int16_complex_t *frame, const uint16_t sweeps_per_frame, const uint16_t num_points, int32_t *work_buffer)
Double buffering frame filter.
void acc_config_sweeps_per_frame_set(acc_config_t *config, uint16_t sweeps)
Set sweeps per frame.
void acc_config_destroy(acc_config_t *config)
Destroy a configuration freeing any resources allocated.
static bool process(acc_surface_velocity_handle_t *handle, acc_surface_velocity_result_t *result)
The result from a completed calibration.
#define CONFIG_SENSOR_ANGLE
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.
float acc_algorithm_get_peak_velocity(const float *velocities, const float *energies, const uint16_t *peak_idxs, uint16_t num_peaks, float limit)
Find the velocity of the peak with the largest amplitude, prioritizing peaks with a velocity over the...
acc_config_profile_t acc_algorithm_select_profile(int32_t start_point, float base_step_length)
Select the highest possible profile without interference of direct leakage.
void acc_config_inter_sweep_idle_state_set(acc_config_t *config, acc_config_idle_state_t idle_state)
Set inter sweep idle state.
acc_config_t * acc_config_create(void)
Create a configuration.
uint32_t * threshold_check
Surface velocity application results container.
static void set_profile(acc_surface_velocity_config_t *config)
void acc_algorithm_fftfreq(uint16_t n, float d, float *freqs)
Calculate the Fast Fourier Transform sample frequencies.
uint16_t padded_segment_length_shift
void acc_algorithm_welch_matrix(const float complex *data, uint16_t rows, uint16_t cols, uint16_t segment_length, float complex *data_buffer, float complex *fft_out, float *psds, const float *window, uint16_t length_shift, float fs)
Estimate power spectral density (PSD) using Welch’s method along row dimensions.
uint16_t slow_zone_half_length
const acc_hal_a121_t * acc_hal_rss_integration_get_implementation(void)
Get hal implementation reference.
uint16_t num_merged_peaks
void acc_config_frame_rate_set(acc_config_t *config, float frame_rate)
Set the frame rate.
int32_t acc_config_start_point_get(const acc_config_t *config)
Get the starting point of the sweep.
void * acc_integration_mem_alloc(size_t size)
Allocate dynamic memory.
acc_config_profile_t acc_config_profile_get(const acc_config_t *config)
Get the currently used profile.
static void cleanup(acc_surface_velocity_handle_t *handle, acc_surface_velocity_config_t *config)
void acc_algorithm_fftshift_matrix(float *data, uint16_t rows, uint16_t cols)
Shift the zero-frequency component to the center along row dimensions.
bool acc_algorithm_find_peaks(const float *abs_sweep, const uint16_t data_length, const uint32_t *threshold_check, uint16_t *peak_idxs, uint16_t peak_idxs_length, uint16_t *num_peaks)
Find peaks above threshold.
static bool do_sensor_calibration_and_prepare(acc_surface_velocity_handle_t *handle, acc_surface_velocity_config_t *config)
acc_processing_metadata_t proc_meta
void acc_config_double_buffering_set(acc_config_t *config, bool enable)
Enable or disable double buffering.
Surface velocity application config container.
void acc_config_hwaas_set(acc_config_t *config, uint16_t hwaas)
Set the hardware accelerated average samples (HWAAS)
uint16_t acc_config_sweeps_per_frame_get(const acc_config_t *config)
Get the number of sweeps per frame.
void acc_algorithm_hann(uint16_t n, float *window)
Calculate non-symmetrical hann window for a specified number of points.
float acc_algorithm_calculate_mirrored_one_sided_cfar(const float *data, uint16_t data_length, uint16_t middle_idx, uint16_t window_length, uint16_t half_guard_length, float sensitivity, uint16_t idx)
Calculate mirrored one sided CFAR threshold.
bool acc_hal_integration_wait_for_sensor_interrupt(acc_sensor_id_t sensor_id, uint32_t timeout_ms)
Wait for a sensor interrupt.
#define CONFIG_SURFACE_DISTANCE
uint16_t acc_algorithm_get_distance_idx(const float *data, uint16_t cols, uint16_t rows, uint16_t middle_idx, uint16_t half_slow_zone)
Find the index of the distance column containing the largest amplitude, disregarding amplitudes prese...
@ ACC_CONFIG_IDLE_STATE_READY
const char * acc_version_get(void)
Get the version of the Acconeer software.
struct acc_config acc_config_t
float acc_config_frame_rate_get(const acc_config_t *config)
Get the frame rate.
uint16_t acc_config_step_length_get(const acc_config_t *config)
Get the step length in a sweep.
float acc_processing_points_to_meter(int32_t points)
Convert a distance or step length in points to meter.
#define CONFIG_VELOCITY_LP_COEFF
void acc_hal_integration_sensor_enable(acc_sensor_id_t sensor_id)
Enable sensor.
acc_config_t * sensor_config
void acc_config_step_length_set(acc_config_t *config, uint16_t step_length)
Set the step length in a sweep.
void acc_config_num_points_set(acc_config_t *config, uint16_t num_points)
Set the number of data points to measure.
#define CONFIG_PSD_LP_COEFF
#define CONFIG_THRESHOLD_SENSITIVITY
void acc_config_sweep_rate_set(acc_config_t *config, float sweep_rate)
Set the sweep rate.
#define ACC_APPROX_BASE_STEP_LENGTH_M
Approximate minimum step length for a sensor measurement in meters.
float * merged_velocities
#define SENSOR_TIMEOUT_MS
acc_config_prf_t acc_algorithm_select_prf(int16_t breakpoint, acc_config_profile_t profile, float base_step_length)
Select a suitable PRF given a breakpoint and profile.
static void acc_alg_basic_utils_clear_bit_bitarray_uint32(uint32_t *bitarray, size_t bit_index)
Clear bit in bit array.
void acc_hal_integration_sensor_disable(acc_sensor_id_t sensor_id)
Disable sensor.
static float calc_dynamic_smoothing_factor(float static_sf, uint32_t update_count)
Calculate a dynamic smoothing factor.
float complex * time_series
uint16_t merged_peaks_length
int acconeer_main(int argc, char *argv[])
Assembly test example.
struct acc_processing_handle acc_processing_t
uint16_t peak_indexes_length
#define ACC_LOG_FLOAT_TO_INTEGER(a)
float complex * time_series_buffer
void acc_config_continuous_sweep_mode_set(acc_config_t *config, bool enabled)
Set continuous sweep mode.
void acc_sensor_status(const acc_sensor_t *sensor)
Check the status of the sensor.
#define CONFIG_SWEEP_RATE
float max_peak_interval_n
static bool init_sensor_resources(acc_surface_velocity_handle_t *handle, acc_surface_velocity_config_t *config)
acc_processing_t * processing
static bool get_velocity_estimate(acc_surface_velocity_handle_t *handle)
void acc_algorithm_roll_and_push_matrix_f32_complex(float complex *data, uint16_t rows, uint16_t cols, const float complex *column, bool pos_shift)
Roll row elements and push a new column.
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.
void acc_algorithm_fftshift(float *data, uint16_t data_length)
Shift the zero-frequency component to the center.
void acc_integration_mem_free(void *ptr)
Free dynamic memory.
static bool init_handle(acc_surface_velocity_handle_t *handle, acc_surface_velocity_config_t *config)
acc_config_profile_t
Profile.
static void update_threshold(acc_surface_velocity_handle_t *handle)
void acc_config_prf_set(acc_config_t *config, acc_config_prf_t prf)
Set Pulse Repetition Frequency.
uint16_t time_series_length
float acc_config_sweep_rate_get(const acc_config_t *config)
Get the sweep rate.
acc_surface_velocity_config_t surface_velocity_config
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.
uint16_t acc_config_num_points_get(const acc_config_t *config)
Get the number of data points to measure.
#define PRIfloat
Specifier for printing float type using integers.
Surface velocity application context handle.
static uint16_t calc_power_spectral_density(acc_surface_velocity_handle_t *handle)
Calculate PSD (power spectral density)
static void acc_alg_basic_utils_set_bit_bitarray_uint32(uint32_t *bitarray, size_t bit_index)
Set bit in bit array.
static void set_prf(acc_surface_velocity_config_t *config)
bool acc_sensor_measure(acc_sensor_t *sensor)
Start a radar measurement with previously prepared configuration.
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.
static void print_result(acc_surface_velocity_result_t *result)
struct acc_sensor acc_sensor_t
float threshold_sensitivity
uint16_t padded_segment_length
uint16_t sweeps_per_frame
static float get_perceived_wavelength(void)
void acc_sensor_destroy(acc_sensor_t *sensor)
Destroy a sensor instance freeing any resources allocated.
static void set_config(acc_surface_velocity_config_t *config)
bool acc_algorithm_merge_peaks(float max_peak_separation, const float *velocities, const float *energies, const uint16_t *peak_idxs, uint16_t num_peaks, float *merged_velocities, float *merged_energies, uint16_t merged_peaks_length, uint16_t *num_merged_peaks)
Merges peaks.
float threshold_sensitivity
static bool validate_config(acc_surface_velocity_config_t *config)
acc_sensor_t * acc_sensor_create(acc_sensor_id_t sensor_id)
Create a sensor instance.