icp.c
Go to the documentation of this file.
1 #include <math.h>
2 #include <string.h>
3 
4 #include <gsl/gsl_matrix.h>
5 
6 #include <gpc/gpc.h>
7 #include <egsl/egsl_macros.h>
8 
9 #include "../csm_all.h"
10 
11 #include "icp.h"
12 
13 
14 void sm_journal_open(const char* file) {
15  file = 0;
16 /* journal_open(file);*/
17 }
18 
19 void ld_invalid_if_outside(LDP ld, double min_reading, double max_reading) {
20  int i;
21  for(i=0;i<ld->nrays;i++) {
22  if(!ld_valid_ray(ld, i)) continue;
23  double r = ld->readings[i];
24  if( r <= min_reading || r > max_reading)
25  ld->valid[i] = 0;
26  }
27 }
28 
29 void sm_icp(struct sm_params*params, struct sm_result*res) {
30  res->valid = 0;
31 
32  LDP laser_ref = params->laser_ref;
33  LDP laser_sens = params->laser_sens;
34 
35  if(!ld_valid_fields(laser_ref) ||
36  !ld_valid_fields(laser_sens)) {
37  return;
38  }
39 
40  sm_debug("sm_icp: laser_sens has %d/%d; laser_ref has %d/%d rays valid\n",
41  count_equal(laser_sens->valid, laser_sens->nrays, 1), laser_sens->nrays,
42  count_equal(laser_ref->valid, laser_ref->nrays, 1), laser_ref->nrays);
43 
44 
46  ld_invalid_if_outside(laser_ref, params->min_reading, params->max_reading);
47  ld_invalid_if_outside(laser_sens, params->min_reading, params->max_reading);
48 
49  sm_debug("sm_icp: laser_sens has %d/%d; laser_ref has %d/%d rays valid (after removing outside interval [%f, %f])\n",
50  count_equal(laser_sens->valid, laser_sens->nrays, 1), laser_sens->nrays,
51  count_equal(laser_ref->valid, laser_ref->nrays, 1), laser_ref->nrays,
52  params->min_reading, params->max_reading);
53 
54  if(JJ) jj_context_enter("sm_icp");
55 
56  egsl_push_named("sm_icp");
57 
58 
59  if(params->use_corr_tricks || params->debug_verify_tricks)
60  ld_create_jump_tables(laser_ref);
61 
62  ld_compute_cartesian(laser_ref);
63  ld_compute_cartesian(laser_sens);
64 
65  if(params->do_alpha_test) {
66  ld_simple_clustering(laser_ref, params->clustering_threshold);
67  ld_compute_orientation(laser_ref, params->orientation_neighbourhood, params->sigma);
68  ld_simple_clustering(laser_sens, params->clustering_threshold);
69  ld_compute_orientation(laser_sens, params->orientation_neighbourhood, params->sigma);
70  }
71 
72  if(JJ) jj_add("laser_ref", ld_to_json(laser_ref));
73  if(JJ) jj_add("laser_sens", ld_to_json(laser_sens));
74 
75  gsl_vector * x_new = gsl_vector_alloc(3);
76  gsl_vector * x_old = vector_from_array(3, params->first_guess);
77 
78  if(params->do_visibility_test) {
79  sm_debug("laser_ref:\n");
80  visibilityTest(laser_ref, x_old);
81 
82  sm_debug("laser_sens:\n");
83  gsl_vector * minus_x_old = gsl_vector_alloc(3);
84  ominus(x_old,minus_x_old);
85  visibilityTest(laser_sens, minus_x_old);
86  gsl_vector_free(minus_x_old);
87  }
88 
89  double error;
90  int iterations;
91  int nvalid;
92  if(!icp_loop(params, x_old->data, x_new->data, &error, &nvalid, &iterations)) {
93  sm_error("icp: ICP failed for some reason. \n");
94  res->valid = 0;
95  res->iterations = iterations;
96  res->nvalid = 0;
97 
98  } else {
99  /* It was succesfull */
100 
101  int restarted = 0;
102  double best_error = error;
103  gsl_vector * best_x = gsl_vector_alloc(3);
104  gsl_vector_memcpy(best_x, x_new);
105 
106  if(params->restart &&
107  (error/nvalid)>(params->restart_threshold_mean_error) ) {
108  sm_debug("Restarting: %f > %f \n",(error/nvalid),(params->restart_threshold_mean_error));
109  restarted = 1;
110  double dt = params->restart_dt;
111  double dth = params->restart_dtheta;
112  sm_debug("icp_loop: dt = %f dtheta= %f deg\n",dt,rad2deg(dth));
113 
114  double perturb[6][3] = {
115  {dt,0,0}, {-dt,0,0},
116  {0,dt,0}, {0,-dt,0},
117  {0,0,dth}, {0,0,-dth}
118  };
119 
120  int a; for(a=0;a<6;a++){
121  sm_debug("-- Restarting with perturbation #%d\n", a);
122  struct sm_params my_params = *params;
123  gsl_vector * start = gsl_vector_alloc(3);
124  gvs(start, 0, gvg(x_new,0)+perturb[a][0]);
125  gvs(start, 1, gvg(x_new,1)+perturb[a][1]);
126  gvs(start, 2, gvg(x_new,2)+perturb[a][2]);
127  gsl_vector * x_a = gsl_vector_alloc(3);
128  double my_error; int my_valid; int my_iterations;
129  if(!icp_loop(&my_params, start->data, x_a->data, &my_error, &my_valid, &my_iterations)){
130  sm_error("Error during restart #%d/%d. \n", a, 6);
131  break;
132  }
133  iterations+=my_iterations;
134 
135  if(my_error < best_error) {
136  sm_debug("--Perturbation #%d resulted in error %f < %f\n", a,my_error,best_error);
137  gsl_vector_memcpy(best_x, x_a);
138  best_error = my_error;
139  }
140  gsl_vector_free(x_a); gsl_vector_free(start);
141  }
142  }
143 
144 
145  /* At last, we did it. */
146  res->valid = 1;
147  vector_to_array(best_x, res->x);
148  sm_debug("icp: final x = %s \n", gsl_friendly_pose(best_x));
149 
150  if (restarted) { // recompute correspondences in case of restarts
151  ld_compute_world_coords(laser_sens, res->x);
152  if(params->use_corr_tricks)
154  else
155  find_correspondences(params);
156  }
157 
158  if(params->do_compute_covariance) {
159 
160  val cov0_x, dx_dy1, dx_dy2;
162  laser_ref, laser_sens, best_x,
163  &cov0_x, &dx_dy1, &dx_dy2);
164 
165  val cov_x = sc(square(params->sigma), cov0_x);
166 /* egsl_v2da(cov_x, res->cov_x); */
167 
168  res->cov_x_m = egsl_v2gslm(cov_x);
169  res->dx_dy1_m = egsl_v2gslm(dx_dy1);
170  res->dx_dy2_m = egsl_v2gslm(dx_dy2);
171 
172  if(0) {
173  egsl_print("cov0_x", cov0_x);
174  egsl_print_spectrum("cov0_x", cov0_x);
175 
176  val fim = ld_fisher0(laser_ref);
177  val ifim = inv(fim);
178  egsl_print("fim", fim);
179  egsl_print_spectrum("ifim", ifim);
180  }
181  }
182 
183  res->error = best_error;
184  res->iterations = iterations;
185  res->nvalid = nvalid;
186 
187  gsl_vector_free(best_x);
188  }
189  gsl_vector_free(x_new);
190  gsl_vector_free(x_old);
191 
192 
193  egsl_pop_named("sm_icp");
194 
195  if(JJ) jj_context_exit();
196 }
197 
198 void sm_icp_xy(struct sm_params*params, struct sm_result*res)
199 {
200  res->valid = 0;
201 
202  LDP laser_ref = params->laser_ref;
203  LDP laser_sens = params->laser_sens;
204 
205  if(!ld_valid_fields(laser_ref) ||
206  !ld_valid_fields(laser_sens)) {
207  return;
208  }
209 
210 /*
211  sm_debug("sm_icp: laser_sens has %d/%d; laser_ref has %d/%d rays valid\n",
212  count_equal(laser_sens->valid, laser_sens->nrays, 1), laser_sens->nrays,
213  count_equal(laser_ref->valid, laser_ref->nrays, 1), laser_ref->nrays);
214  */
215 
217  ld_invalid_if_outside(laser_ref, params->min_reading, params->max_reading);
218  ld_invalid_if_outside(laser_sens, params->min_reading, params->max_reading);
219 
220 /*
221  sm_debug("sm_icp: laser_sens has %d/%d; laser_ref has %d/%d rays valid (after removing outside interval [%f, %f])\n",
222  count_equal(laser_sens->valid, laser_sens->nrays, 1), laser_sens->nrays,
223  count_equal(laser_ref->valid, laser_ref->nrays, 1), laser_ref->nrays,
224  params->min_reading, params->max_reading);
225 
226  if(JJ) jj_context_enter("sm_icp");
227 
228  egsl_push_named("sm_icp");
229  */
230 
231  if(params->use_corr_tricks || params->debug_verify_tricks)
232  ld_create_jump_tables(laser_ref);
233 /*
234  ld_compute_cartesian(laser_ref);
235  ld_compute_cartesian(laser_sens);
236 */
237 
238  if(params->do_alpha_test) {
239  ld_simple_clustering(laser_ref, params->clustering_threshold);
240  ld_compute_orientation(laser_ref, params->orientation_neighbourhood, params->sigma);
241  ld_simple_clustering(laser_sens, params->clustering_threshold);
242  ld_compute_orientation(laser_sens, params->orientation_neighbourhood, params->sigma);
243  }
244 
245  if(JJ) jj_add("laser_ref", ld_to_json(laser_ref));
246  if(JJ) jj_add("laser_sens", ld_to_json(laser_sens));
247 
248  gsl_vector * x_new = gsl_vector_alloc(3);
249  gsl_vector * x_old = vector_from_array(3, params->first_guess);
250 
251  if(params->do_visibility_test) {
252  sm_debug("laser_ref:\n");
253  visibilityTest(laser_ref, x_old);
254 
255  sm_debug("laser_sens:\n");
256  gsl_vector * minus_x_old = gsl_vector_alloc(3);
257  ominus(x_old,minus_x_old);
258  visibilityTest(laser_sens, minus_x_old);
259  gsl_vector_free(minus_x_old);
260  }
261 
262  double error;
263  int iterations;
264  int nvalid;
265  if(!icp_loop(params, x_old->data, x_new->data, &error, &nvalid, &iterations)) {
266  sm_error("icp: ICP failed for some reason. \n");
267  res->valid = 0;
268  res->iterations = iterations;
269  res->nvalid = 0;
270 
271  } else {
272  /* It was succesfull */
273 
274  double best_error = error;
275  gsl_vector * best_x = gsl_vector_alloc(3);
276  gsl_vector_memcpy(best_x, x_new);
277 
278  if(params->restart &&
279  (error/nvalid)>(params->restart_threshold_mean_error) ) {
280  sm_debug("Restarting: %f > %f \n",(error/nvalid),(params->restart_threshold_mean_error));
281  double dt = params->restart_dt;
282  double dth = params->restart_dtheta;
283  sm_debug("icp_loop: dt = %f dtheta= %f deg\n",dt,rad2deg(dth));
284 
285  double perturb[6][3] = {
286  {dt,0,0}, {-dt,0,0},
287  {0,dt,0}, {0,-dt,0},
288  {0,0,dth}, {0,0,-dth}
289  };
290 
291  int a; for(a=0;a<6;a++){
292  sm_debug("-- Restarting with perturbation #%d\n", a);
293  struct sm_params my_params = *params;
294  gsl_vector * start = gsl_vector_alloc(3);
295  gvs(start, 0, gvg(x_new,0)+perturb[a][0]);
296  gvs(start, 1, gvg(x_new,1)+perturb[a][1]);
297  gvs(start, 2, gvg(x_new,2)+perturb[a][2]);
298  gsl_vector * x_a = gsl_vector_alloc(3);
299  double my_error; int my_valid; int my_iterations;
300  if(!icp_loop(&my_params, start->data, x_a->data, &my_error, &my_valid, &my_iterations)){
301  sm_error("Error during restart #%d/%d. \n", a, 6);
302  break;
303  }
304  iterations+=my_iterations;
305 
306  if(my_error < best_error) {
307  sm_debug("--Perturbation #%d resulted in error %f < %f\n", a,my_error,best_error);
308  gsl_vector_memcpy(best_x, x_a);
309  best_error = my_error;
310  }
311  gsl_vector_free(x_a); gsl_vector_free(start);
312  }
313  }
314 
315 
316  /* At last, we did it. */
317  res->valid = 1;
318  vector_to_array(best_x, res->x);
319  sm_debug("icp: final x = %s \n", gsl_friendly_pose(best_x));
320 
321 
322  if(params->do_compute_covariance) {
323 
324  val cov0_x, dx_dy1, dx_dy2;
326  laser_ref, laser_sens, best_x,
327  &cov0_x, &dx_dy1, &dx_dy2);
328 
329  val cov_x = sc(square(params->sigma), cov0_x);
330 // egsl_v2da(cov_x, res->cov_x);
331 
332  res->cov_x_m = egsl_v2gslm(cov_x);
333  res->dx_dy1_m = egsl_v2gslm(dx_dy1);
334  res->dx_dy2_m = egsl_v2gslm(dx_dy2);
335 
336  if(0) {
337  egsl_print("cov0_x", cov0_x);
338  egsl_print_spectrum("cov0_x", cov0_x);
339 
340  val fim = ld_fisher0(laser_ref);
341  val ifim = inv(fim);
342  egsl_print("fim", fim);
343  egsl_print_spectrum("ifim", ifim);
344  }
345  }
346 
347  res->error = best_error;
348  res->iterations = iterations;
349  res->nvalid = nvalid;
350 
351  gsl_vector_free(x_new);
352  gsl_vector_free(x_old);
353  gsl_vector_free(best_x);
354  }
355 /*
356  egsl_pop_named("sm_icp");
357 
358  if(JJ) jj_context_exit();
359 */
360 }
int do_alpha_test
Definition: algos.h:79
int *restrict valid
Definition: laser_data.h:23
gsl_vector * vector_from_array(unsigned int n, double *x)
int nvalid
Definition: algos.h:148
#define gvg
Definition: math_utils_gsl.h:9
gsl_matrix * egsl_v2gslm(val)
void ominus(const gsl_vector *x, gsl_vector *res)
#define gvs
Definition: egsl.h:12
int iterations
Definition: algos.h:146
int orientation_neighbourhood
Definition: algos.h:77
TSMparams params
Definition: MbICP.c:57
void ld_create_jump_tables(struct laser_data *ld)
void ld_compute_orientation(LDP ld, int size_neighbourhood, double sigma)
Definition: orientation.c:14
INLINE int ld_valid_ray(LDP ld, int i)
double clustering_threshold
Definition: algos.h:75
int ld_valid_fields(LDP ld)
Definition: laser_data.c:179
void sm_journal_open(const char *file)
Definition: icp.c:14
#define JJ
Definition: json_journal.h:21
double error
Definition: algos.h:150
int valid
Definition: algos.h:140
double max_reading
Definition: algos.h:127
int use_corr_tricks
Definition: algos.h:36
double restart_dt
Definition: algos.h:43
double sigma
Definition: algos.h:124
gsl_matrix * dx_dy2_m
Definition: algos.h:156
double restart_threshold_mean_error
Definition: algos.h:41
double *restrict readings
Definition: laser_data.h:24
void find_correspondences(struct sm_params *params)
Definition: icp_corr_dumb.c:30
int count_equal(const int *v, int n, int value)
Definition: math_utils.c:192
void sm_icp(struct sm_params *params, struct sm_result *res)
Definition: icp.c:29
void compute_covariance_exact(LDP laser_ref, LDP laser_sens, const gsl_vector *x, val *cov0_x, val *dx_dy1, val *dx_dy2)
#define sc(d, v)
Definition: egsl_macros.h:24
void jj_context_exit()
Definition: json_journal.c:56
val ld_fisher0(LDP ld)
JO ld_to_json(LDP ld)
LDP laser_ref
Definition: algos.h:14
int do_visibility_test
Definition: algos.h:96
void egsl_print_spectrum(const char *s, val v)
Definition: egsl_misc.c:31
const char * gsl_friendly_pose(gsl_vector *v)
LDP laser_sens
Definition: algos.h:16
void sm_icp_xy(struct sm_params *params, struct sm_result *res)
Definition: icp.c:198
double min_reading
Definition: algos.h:127
void jj_add(const char *name, JO jo)
Definition: json_journal.c:104
int restart
Definition: algos.h:39
double restart_dtheta
Definition: algos.h:45
void egsl_push_named(const char *name)
Definition: egsl.c:91
double first_guess[3]
Definition: algos.h:19
void ld_simple_clustering(LDP ld, double threshold)
Definition: clustering.c:11
#define inv(v)
Definition: egsl_macros.h:27
void ld_compute_world_coords(LDP ld, const double *pose)
Definition: laser_data.c:133
void find_correspondences_tricks(struct sm_params *params)
void sm_debug(const char *msg,...)
Definition: logging.c:88
double x[3]
Definition: algos.h:143
int do_compute_covariance
Definition: algos.h:114
int icp_loop(struct sm_params *params, const double *q0, double *x_new, double *total_error, int *nvalid, int *iterations)
Definition: icp_loop.c:13
gsl_matrix * cov_x_m
Definition: algos.h:154
void ld_compute_cartesian(LDP ld)
Definition: laser_data.c:118
double square(double x)
Definition: math_utils.c:124
void ld_invalid_if_outside(LDP ld, double min_reading, double max_reading)
Definition: icp.c:19
void sm_error(const char *msg,...)
Definition: logging.c:49
void visibilityTest(LDP ld, const gsl_vector *x_old)
Definition: icp_outliers.c:9
double rad2deg(double rad)
Definition: math_utils.c:79
void egsl_pop_named(const char *name)
Definition: egsl.c:117
void egsl_print(const char *str, val v)
Definition: egsl.c:251
gsl_matrix * dx_dy1_m
Definition: algos.h:155
void vector_to_array(const gsl_vector *v, double *x)
int debug_verify_tricks
Definition: algos.h:117
void jj_context_enter(const char *context_name)
Definition: json_journal.c:36


csm
Author(s): Andrea Censi
autogenerated on Tue May 11 2021 02:18:23