49 #define MAX_COUNT_PT 50
51 #define MIN_SAMPLES_FIT 3
53 #define N_PAR_TR_FIT 6
77 float parameters_u[3], parameters_v[3], min_error_u, min_error_v;
110 float *parameters_u,
float *parameters_v,
float *fit_error,
float *min_error_u,
float *min_error_v,
int *n_inliers_u,
120 int sam,
p, i_rand, si, add_si;
131 float _bu_all[count][1];
133 float _bv_all[count][1];
135 for (sam = 0; sam < count; sam++) {
136 AA[sam][0] = (float) vectors[sam].pos.x;
137 AA[sam][1] = (
float) vectors[sam].
pos.
y;
139 bu_all[sam][0] = (float) vectors[sam].flow_x;
140 bv_all[sam][0] = (float) vectors[sam].flow_y;
168 float PU[n_iterations * 3];
169 float PV[n_iterations * 3];
170 float errors_pu[n_iterations];
172 float errors_pv[n_iterations];
174 int n_inliers_pu[n_iterations];
175 int n_inliers_pv[n_iterations];
177 for (it = 0; it < n_iterations; it++) {
186 for (ii = 0; ii < i_rand; ii++) {
187 if (sample_indices[ii] == si) { add_si = 0; }
190 sample_indices[i_rand] = si;
197 A[sam][0] = (float) vectors[sample_indices[sam]].pos.x;
198 A[sam][1] = (
float) vectors[sample_indices[sam]].
pos.
y;
200 bu[sam][0] = (float) vectors[sample_indices[sam]].flow_x;
201 bv[sam][0] = (float) vectors[sample_indices[sam]].flow_y;
212 PU[it * 3] = pu[0][0];
213 PU[it * 3 + 1] = pu[1][0];
214 PU[it * 3 + 2] = pu[2][0];
218 PV[it * 3] = pv[0][0];
219 PV[it * 3 + 1] = pv[1][0];
220 PV[it * 3 + 2] = pv[2][0];
225 n_inliers_pu[it] = 0;
226 n_inliers_pv[it] = 0;
230 MAT_MUL(count, 3, 1, bb, AA, pu);
232 MAT_SUB(count, 1, C, bb, bu_all);
234 for (
p = 0;
p < count;
p++) {
235 C[
p][0] = fabsf(C[
p][0]);
236 if (C[
p][0] < error_threshold) {
237 errors_pu[it] += C[
p][0];
240 errors_pu[it] += error_threshold;
246 MAT_MUL(count, 3, 1, bb, AA, pv);
248 MAT_SUB(count, 1, C, bb, bv_all);
250 for (
p = 0;
p < count;
p++) {
251 C[
p][0] = fabsf(C[
p][0]);
252 if (C[
p][0] < error_threshold) {
253 errors_pv[it] += C[
p][0];
256 errors_pv[it] += error_threshold;
266 *min_error_u = (float)errors_pu[0];
267 for (it = 1; it < n_iterations; it++) {
268 if (errors_pu[it] < *min_error_u) {
269 *min_error_u = (float)errors_pu[it];
273 for (param = 0; param < 3; param++) {
274 parameters_u[param] = PU[min_ind * 3 + param];
276 *n_inliers_u = n_inliers_pu[min_ind];
280 *min_error_v = (float)errors_pv[0];
281 for (it = 0; it < n_iterations; it++) {
282 if (errors_pv[it] < *min_error_v) {
283 *min_error_v = (float)errors_pv[it];
287 for (param = 0; param < 3; param++) {
288 parameters_v[param] = PV[min_ind * 3 + param];
290 *n_inliers_v = n_inliers_pv[min_ind];
294 MAT_MUL(count, 3, 1, bb, AA, pu);
296 MAT_SUB(count, 1, C, bb, bu_all);
298 for (
p = 0;
p < count;
p++) {
299 *min_error_u += fabsf(C[
p][0]);
302 MAT_MUL(count, 3, 1, bb, AA, pv);
304 MAT_SUB(count, 1, C, bb, bv_all);
306 for (
p = 0;
p < count;
p++) {
307 *min_error_v += fabsf(C[
p][0]);
309 *fit_error = (*min_error_u + *min_error_v) / (2 * count);
336 (im_height / 2.0f) * parameters_u[1]);
338 (im_height / 2.0f) * parameters_v[1]);
344 float threshold_slope = 1.0;
347 if (fabsf(parameters_v[1]) < eta && arv_y < threshold_slope && arv_x >= 2 * threshold_slope) {
350 }
else if (arv_y >= 2 * threshold_slope) {
359 if (fabsf(parameters_u[0]) < eta && arv_x < threshold_slope && arv_y >= 2 * threshold_slope) {
362 }
else if (arv_x >= 2 * threshold_slope) {
375 float denominator = parameters_v[0] * parameters_u[1] - parameters_u[0] * parameters_v[1];
376 if (fabsf(denominator) > 1
E-5) {
377 info->
focus_of_expansion_x = ((parameters_u[2] * parameters_v[1] - parameters_v[2] * parameters_u[1]) / denominator);
380 denominator = parameters_u[1];
381 if (fabsf(denominator) > 1
E-5) {
399 bool analyze_flow_field(
struct flow_t *vectors __attribute__((unused)),
int count,
float error_threshold __attribute__((unused)),
int n_iterations __attribute__((unused)),
int n_samples __attribute__((unused)),
400 int im_width __attribute__((unused)),
int im_height __attribute__((unused)),
float focal_length __attribute__((unused)),
struct linear_flow_fit_info *info __attribute__((unused)))
Perform Random Sample Consensus (RANSAC), a robust fitting method.
#define MAKE_MATRIX_PTR(_ptr, _mat, _rows)
Make a pointer to a matrix of _rows lines.
uint32_t y
The y coordinate of the point.
struct point_t pos
The original position the flow comes from in subpixels.
void fit_linear_flow_field(struct flow_t *vectors, int count, float error_threshold, int n_iterations, int n_samples, float *parameters_u, float *parameters_v, float *fit_error, float *min_error_u, float *min_error_v, int *n_inliers_u, int *n_inliers_v)
Analyze a linear flow field, retrieving information such as divergence, surface roughness,...
bool analyze_flow_field(struct flow_t *vectors, int count, float error_threshold, int n_iterations, int n_samples, int im_width, int im_height, float focal_length, struct linear_flow_fit_info *info)
Analyze a flow field, retrieving information on relative velocities and rotations,...
bool analyze_linear_flow_field(struct flow_t *vectors, int count, float error_threshold, int n_iterations, int n_samples, int im_width, int im_height, struct linear_flow_fit_info *info)
Analyze a linear flow field, retrieving information such as divergence, surface roughness,...
void extract_information_from_parameters(float *parameters_u, float *parameters_v, int im_width, int im_height, struct linear_flow_fit_info *info)
Extract information from the parameters that were fit to the optical flow field.
float slope_x
Slope of the surface in x-direction - given sufficient lateral motion.
float divergence
Basically, relative_velocity_z. Actual divergence of a 2D flow field is 2 * relative_velocity_z.
int n_inliers_v
Number of inliers in the vertical flow fit.
float slope_y
Slope of the surface in y-direction - given sufficient lateral motion.
float focus_of_expansion_x
Image x-coordinate of the focus of expansion (contraction)
float time_to_contact
Basically, 1 / relative_velocity_z.
float relative_velocity_x
Relative velocity in x-direction, i.e., vx / z, where z is the depth in direction of the camera's pri...
int n_inliers_u
Number of inliers in the horizontal flow fit.
float relative_velocity_z
Relative velocity in z-direction, i.e., vz / z, where z is the depth in direction of the camera's pri...
float surface_roughness
The error of the linear fit is a measure of surface roughness.
float focus_of_expansion_y
Image y-coordinate of the focus of expansion (contraction)
float relative_velocity_y
Relative velocity in y-direction, i.e., vy / z, where z is the depth in direction of the camera's pri...
float fit_error
Error of the fit (same as surface roughness)
Paparazzi floating point algebra.
void pprz_svd_solve_float(float **x, float **u, float *w, float **v, float **b, int m, int n, int l)
SVD based linear solver.
int pprz_svd_float(float **a, float *w, float **v, int m, int n)
SVD decomposition.
Matrix decompositions in floating point.
Simple matrix helper macros.
#define MAT_MUL(_i, _k, _j, C, A, B)
#define MAT_SUB(_i, _j, C, A, B)