example_processing_peak_interpolation.c

example_processing_peak_interpolation.c This program shows how to apply a distance filter and how to interpolate the position of the peak to improve distance accuracy.The distance filter is applied to the IQ data and will reduce noise and smooth out the the amplitude of the radar eacho peaks. The smoothing is important for the next step where we estimate the acctual position of the peak, i.e the position of the peak that we would have gotten if we had used an shorter distance between the measurement steps.

// Copyright (c) Acconeer AB, 2022-2024
// All rights reserved
// This file is subject to the terms and conditions defined in the file
// 'LICENSES/license_acconeer.txt', (BSD 3-Clause License) which is part
// of this source code package.
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "acc_config.h"
#include "acc_definitions_a121.h"
#include "acc_hal_definitions_a121.h"
#include "acc_hal_integration_a121.h"
#include "acc_integration_log.h"
#include "acc_rss_a121.h"
#include "acc_version.h"
#include "acc_control_helper.h"
#include "acc_processing_helpers.h"
#define SENSOR_ID (1U)
static void update_configuration(acc_config_t *config);
/** \example example_processing_peak_interpolation.c
* @brief example_processing_peak_interpolation.c
* This program shows how to apply a distance filter and how to interpolate the
* position of the peak to improve distance accuracy.
*
* The distance filter is applied to the IQ data and will reduce noise and smooth out
* the the amplitude of the radar eacho peaks. The smoothing is important for the
* next step where we estimate the acctual position of the peak, i.e the position
* of the peak that we would have gotten if we had used an shorter distance between
* the measurement steps.
*/
int acconeer_main(int argc, char *argv[]);
int acconeer_main(int argc, char *argv[])
{
(void)argc;
(void)argv;
acc_control_helper_t control_helper_state = {0};
const uint32_t peak_width_points = 104; // Approximate peak width for profile 3
printf("Acconeer software version %s \n", acc_version_get());
const acc_hal_a121_t *hal = acc_hal_rss_integration_get_implementation();
if (!acc_rss_hal_register(hal))
{
return EXIT_FAILURE;
}
bool status_ok = acc_control_helper_create(&control_helper_state, SENSOR_ID);
if (!status_ok)
{
printf("acc_control_helper_create ()failed \n");
return EXIT_FAILURE;
}
update_configuration(control_helper_state.config);
status_ok = acc_control_helper_activate(&control_helper_state);
if (!status_ok)
{
printf("acc_control_helper_activate ()failed\n");
acc_control_helper_destroy(&control_helper_state);
return EXIT_FAILURE;
}
uint32_t sweep_data_length = control_helper_state.proc_meta.sweep_data_length;
uint32_t filter_length = acc_processing_helper_get_filter_length(peak_width_points, acc_config_step_length_get(control_helper_state.config));
acc_vector_iq_t *current_sweep_iq = acc_vector_iq_alloc(sweep_data_length);
acc_vector_iq_t *filtered_sweep_iq = acc_vector_iq_alloc(sweep_data_length);
acc_vector_float_t *filter_vector = acc_vector_float_alloc(filter_length);
acc_vector_float_t *filtered_sweep_amplitude = acc_vector_float_alloc(sweep_data_length);
bool mem_ok = (current_sweep_iq != NULL) && (filtered_sweep_iq != NULL) && (filter_vector != NULL) && (filtered_sweep_amplitude != NULL);
if (!mem_ok)
{
printf("Memory allocation for vectors failed\n");
goto clean_up;
}
acc_vector_float_create_depth_filter_vector(filter_vector);
uint32_t iterations = 50U;
for (uint32_t i = 0U; i < iterations; i++)
{
if (!acc_control_helper_get_next(&control_helper_state))
{
printf("acc_control_helper_get_next() failed\n");
break;
}
acc_get_iq_sweep_vector(&control_helper_state, current_sweep_iq);
// Apply distance filter to smooth out the amplitude of the radar signal and
// reduce noise. Note that phase enhancement should be enabled when applying
// the distance filter on an IQ data vector.
acc_vector_iq_apply_filter(current_sweep_iq, filter_vector, filtered_sweep_iq);
// Find the index of the element with the highest amplitude. We skip the first and last
// element of the vector in the search as we would make an of bounds read in the next step
// if the max value was found in the first or last element.
acc_vector_iq_amplitude(filtered_sweep_iq, filtered_sweep_amplitude);
uint32_t max_peak_index = acc_vector_float_argmax_skip_edges(filtered_sweep_amplitude, 1);
// We know that the distance between steps is constant, so it is enough to
// use only the peak amplitude and the amplitudes before and after the peak to
// estimate the location of the peak relative to the location of the max value.
float peak_offset = acc_processing_helper_interpolate_peak_position(filtered_sweep_amplitude->data[max_peak_index - 1],
filtered_sweep_amplitude->data[max_peak_index],
filtered_sweep_amplitude->data[max_peak_index + 1]);
// Calculate the distance to the start of the measuring range and the distance between
// measurement steps.
float start = acc_processing_points_to_meter(acc_config_start_point_get(control_helper_state.config));
float step_length = acc_processing_points_to_meter(acc_config_step_length_get(control_helper_state.config));
// Make the final calculation of the distance to the reflecting object using the index of the
// value with the higest amplitude and the interpolated peak offset.
float distance = start + (max_peak_index + peak_offset) * step_length;
printf("Interpolated distance: %d mm\n", (int)(distance * 1000 + .5f));
}
clean_up:
acc_control_helper_destroy(&control_helper_state);
acc_vector_iq_free(current_sweep_iq);
acc_vector_iq_free(filtered_sweep_iq);
acc_vector_float_free(filter_vector);
acc_vector_float_free(filtered_sweep_amplitude);
printf("Application finished OK\n");
return EXIT_SUCCESS;
}
static void update_configuration(acc_config_t *config)
{
int32_t start_point = 100; // start at approx 100*2.5 mm ~= 250 mm
uint16_t step_length = 8; // 8 * 2.5 mm ~= 20 mm between each step
uint16_t num_points = 50; // range length ~= 250 mm + 50*20 mm ~= 1250 mm
acc_config_start_point_set(config, start_point);
acc_config_num_points_set(config, num_points);
acc_config_step_length_set(config, step_length);
acc_config_profile_set(config, ACC_CONFIG_PROFILE_3);
acc_config_hwaas_set(config, 200);
// The processing in this example assumes that sweeps_per_frame = 1
acc_config_sweeps_per_frame_set(config, 1);
acc_config_frame_rate_set(config, 5.0f);
acc_config_phase_enhancement_set(config, true);
acc_config_prf_set(config, ACC_CONFIG_PRF_13_0_MHZ);
}
acc_config_start_point_set
void acc_config_start_point_set(acc_config_t *config, int32_t start_point)
Set the starting point of the sweep.
acc_control_helper_create
bool acc_control_helper_create(acc_control_helper_t *radar, acc_sensor_id_t sensor_id)
Create a helper instance.
Definition: acc_control_helper.c:41
acc_rss_a121.h
acc_vector_float_free
void acc_vector_float_free(acc_vector_float_t *vector)
Free storage of data elements in a float vector.
Definition: acc_processing_helpers.c:85
acc_vector_iq_free
void acc_vector_iq_free(acc_vector_iq_t *vector)
Free storage of data elements in an IQ vector.
Definition: acc_processing_helpers.c:73
acc_control_helper_t::config
acc_config_t * config
Definition: acc_control_helper.h:25
acc_version.h
acc_config_profile_set
void acc_config_profile_set(acc_config_t *config, acc_config_profile_t profile)
Set a profile.
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_vector_float_argmax_skip_edges
uint32_t acc_vector_float_argmax_skip_edges(acc_vector_float_t *vector_a, uint32_t elements_to_skip)
Index of element with maximum value in a float vector disregarding edge elements.
Definition: acc_processing_helpers.c:375
acc_vector_float_t::data
float * data
Definition: acc_processing_helpers.h:36
acc_processing_helper_get_filter_length
uint32_t acc_processing_helper_get_filter_length(uint32_t peak_width_points, uint32_t step_length)
Calculate filter vector length.
Definition: acc_processing_helpers.c:166
acc_control_helper_destroy
void acc_control_helper_destroy(acc_control_helper_t *radar)
Destroy a helper instance.
Definition: acc_control_helper.c:50
config
cargo_config_t config
Definition: i2c_example_cargo.c:34
acc_hal_rss_integration_get_implementation
const acc_hal_a121_t * acc_hal_rss_integration_get_implementation(void)
Get hal implementation reference.
Definition: acc_hal_integration_stm32cube_xm.c:152
acc_vector_iq_t
Definition: acc_processing_helpers.h:27
acc_config_frame_rate_set
void acc_config_frame_rate_set(acc_config_t *config, float frame_rate)
Set the frame rate.
acc_config_start_point_get
int32_t acc_config_start_point_get(const acc_config_t *config)
Get the starting point of the sweep.
acc_hal_a121_t
Definition: acc_hal_definitions_a121.h:82
acc_control_helper_t::proc_meta
acc_processing_metadata_t proc_meta
Definition: acc_control_helper.h:32
acc_rss_hal_register
bool acc_rss_hal_register(const acc_hal_a121_t *hal)
Register an integration.
acc_vector_iq_apply_filter
void acc_vector_iq_apply_filter(const acc_vector_iq_t *vector_a, acc_vector_float_t *filter_vector, acc_vector_iq_t *vector_out)
Apply a FIR filter to an IQ vector.
Definition: acc_processing_helpers.c:203
acc_vector_iq_amplitude
void acc_vector_iq_amplitude(const acc_vector_iq_t *vector_a, acc_vector_float_t *vector_out)
Amplitude of an IQ vector.
Definition: acc_processing_helpers.c:305
acc_config_hwaas_set
void acc_config_hwaas_set(acc_config_t *config, uint16_t hwaas)
Set the hardware accelerated average samples (HWAAS)
acc_processing_metadata_t::sweep_data_length
uint16_t sweep_data_length
Definition: acc_processing.h:41
acc_control_helper.h
acc_hal_integration_a121.h
acc_version_get
const char * acc_version_get(void)
Get the version of the Acconeer software.
acc_config_t
struct acc_config acc_config_t
Definition: acc_config.h:24
printf
#define printf
Definition: printf.h:60
acc_config_step_length_get
uint16_t acc_config_step_length_get(const acc_config_t *config)
Get the step length in a sweep.
acc_processing_points_to_meter
float acc_processing_points_to_meter(int32_t points)
Convert a distance or step length in points to meter.
acc_config_step_length_set
void acc_config_step_length_set(acc_config_t *config, uint16_t step_length)
Set the step length in a sweep.
acc_config_num_points_set
void acc_config_num_points_set(acc_config_t *config, uint16_t num_points)
Set the number of data points to measure.
acc_hal_definitions_a121.h
acconeer_main
int acconeer_main(int argc, char *argv[])
Assembly test example.
Definition: example_processing_peak_interpolation.c:41
SENSOR_ID
#define SENSOR_ID
Definition: example_processing_peak_interpolation.c:23
acc_vector_float_create_depth_filter_vector
void acc_vector_float_create_depth_filter_vector(acc_vector_float_t *vector_out)
Create a distance filter vector.
Definition: acc_processing_helpers.c:172
acc_processing_helpers.h
acc_config_phase_enhancement_set
void acc_config_phase_enhancement_set(acc_config_t *config, bool enable)
Enable or disable phase enhancement.
update_configuration
static void update_configuration(acc_config_t *config)
Definition: example_processing_peak_interpolation.c:151
acc_vector_float_t
Definition: acc_processing_helpers.h:33
acc_integration_log.h
acc_vector_iq_alloc
acc_vector_iq_t * acc_vector_iq_alloc(uint32_t data_length)
Allocate storage for an IQ vector.
Definition: acc_processing_helpers.c:27
acc_vector_float_alloc
acc_vector_float_t * acc_vector_float_alloc(uint32_t data_length)
Allocate storage for a float vector.
Definition: acc_processing_helpers.c:50
acc_control_helper_t
Definition: acc_control_helper.h:23
acc_control_helper_activate
bool acc_control_helper_activate(acc_control_helper_t *radar)
Activate the sensor.
Definition: acc_control_helper.c:81
acc_config_prf_set
void acc_config_prf_set(acc_config_t *config, acc_config_prf_t prf)
Set Pulse Repetition Frequency.
ACC_CONFIG_PRF_13_0_MHZ
@ ACC_CONFIG_PRF_13_0_MHZ
Definition: acc_definitions_a121.h:118
acc_config.h
acc_control_helper_get_next
bool acc_control_helper_get_next(acc_control_helper_t *radar)
Perform a radar measurement and wait for the result.
Definition: acc_control_helper.c:157
acc_get_iq_sweep_vector
void acc_get_iq_sweep_vector(const acc_control_helper_t *control_helper_state, acc_vector_iq_t *vector_out)
Converts a newly captured IQ frame with one sweep to an IQ vector.
Definition: acc_processing_helpers.c:138
ACC_CONFIG_PROFILE_3
@ ACC_CONFIG_PROFILE_3
Definition: acc_definitions_a121.h:54
acc_processing_helper_interpolate_peak_position
float acc_processing_helper_interpolate_peak_position(float y1, float y2, float y3)
Interpolate peak position.
Definition: acc_processing_helpers.c:395
acc_definitions_a121.h