gpm.c
Go to the documentation of this file.
1 #include <gsl/gsl_histogram.h>
2 #include <gsl/gsl_matrix.h>
3 
4 
5 #include "../csm_all.h"
6 #include "gpm.h"
7 
8 #include <egsl/egsl_macros.h>
9 
10 
11 void sm_gpm(struct sm_params*params, struct sm_result*res) {
12  res->valid = 0;
13  /* Check for well-formedness of the input data */
14  if(!ld_valid_fields(params->laser_ref) ||
15  !ld_valid_fields(params->laser_sens)) {
16  return;
17  }
18 
19  LDP laser_ref = params->laser_ref;
20  LDP laser_sens = params->laser_sens;
21 
22  /* We need to compute cartesian points */
23  ld_compute_cartesian(laser_ref);
24  /* ... and orientation */
25  ld_simple_clustering(laser_ref, params->clustering_threshold);
26  ld_compute_orientation(laser_ref, params->orientation_neighbourhood, params->sigma);
27  /* ... for both scans. */
28  ld_compute_cartesian(laser_sens);
29  ld_simple_clustering(laser_sens, params->clustering_threshold);
30  ld_compute_orientation(laser_sens, params->orientation_neighbourhood, params->sigma);
31 
32  /* Create an histogram whose bin is large `theta_bin_size` */
33  double theta_bin_size = deg2rad(params->gpm_theta_bin_size_deg);
34  double hist_min = -M_PI-theta_bin_size; /* be robust */
35  double hist_max = +M_PI+theta_bin_size;
36  size_t nbins = (size_t) ceil( (hist_max-hist_min) / theta_bin_size);
37  gsl_histogram*hist = gsl_histogram_alloc(nbins);
38  gsl_histogram_set_ranges_uniform(hist, hist_min, hist_max);
39 
40  /* Fill the histogram with samples */
41  double u[3]; copy_d(params->first_guess, 3, u);
42  sm_debug("gpm 1/2: old u = : %s \n", friendly_pose(u) );
43 
44  int interval = params->gpm_interval;
45 
46  int num_correspondences_theta=-1;
47 
48 
49  ght_find_theta_range(laser_ref, laser_sens,
50  u, params->max_linear_correction,
51  params->max_angular_correction_deg, interval, hist, &num_correspondences_theta);
52 
53  if(num_correspondences_theta < laser_ref->nrays) {
54  sm_error("sm_gpm(): I found only %d correspondences in the first pass of GPM. I consider it a failure.\n",
55  num_correspondences_theta);
56  return;
57  }
58 
59  /* Find the bin with most samples */
60  size_t max_bin = gsl_histogram_max_bin(hist);
61 
62  /* Around that value will be the range admissible for theta */
63  double min_range, max_range;
64  gsl_histogram_get_range(hist,max_bin,&min_range,&max_range);
65 
66  /* Extend the range of the search */
67  double extend_range = deg2rad(params->gpm_extend_range_deg);
68  min_range += -extend_range;
69  max_range += +extend_range;
70 
71  /* if(jf()) fprintf(jf(), "iteration 0\n");
72  journal_pose("x_old", u);*/
73 
74 
75  /* if(jf()) fprintf(jf(), "iteration 1\n");
76  journal_pose("x_old", u);*/
77 
78 
79  /* Now repeat the samples generation with a smaller domain */
80  u[2] = 0.5 * (max_range + min_range);
81  double new_range_deg = rad2deg( 0.5*(max_range - min_range) );
82 
83  double x_new[3];
84  int num_correspondences=-1;
85  ght_one_shot(laser_ref, laser_sens,
86  u, params->max_linear_correction*2,
87  new_range_deg, interval, x_new, &num_correspondences) ;
88 
89  if(num_correspondences < laser_ref->nrays) {
90  sm_error("sm_gpm(): I found only %d correspondences in the second pass of GPM. I consider it a failure.\n",
91  num_correspondences);
92  return;
93  }
94 
95  /* Et voila, in x_new we have the answer */
96 
97  {
98  sm_debug("gpm : max_correction_lin %f def %f\n", params->max_linear_correction, params->max_angular_correction_deg);
99  sm_debug("gpm : acceptable range for theta: [%f, %f]\n", min_range,max_range);
100  sm_debug("gpm : 1) Num correspondences for theta: %d\n", num_correspondences_theta);
101 
102  sm_debug("gpm 1/2: new u = : %s \n", friendly_pose(u) );
103  sm_debug("gpm 1/2: New range: %f to %f\n",rad2deg(min_range),rad2deg(max_range));
104 
105  sm_debug("gpm 2/2: Solution: %s \n", friendly_pose(x_new));
106  /* if(jf()) fprintf(jf(), "iteration 2\n");
107  journal_pose("x_old", x_new); */
108  }
109 
110  /* Administrivia */
111 
112  res->valid = 1;
113  copy_d(x_new, 3, res->x);
114 
115  res->iterations = 0;
116 
117  gsl_histogram_free(hist);
118 }
119 
120 void ght_find_theta_range(LDP laser_ref, LDP laser_sens,
121  const double*x0, double max_linear_correction,
122  double max_angular_correction_deg, int interval, gsl_histogram*hist, int*num_correspondences)
123 {
125  ld_compute_world_coords(laser_sens, x0);
126 
127  int count = 0;
128  int i;
129  for(i=0;i<laser_sens->nrays;i++) {
130  if(!laser_sens->alpha_valid[i]) continue;
131  if(i % interval) continue;
132 
133  const double * p_i = laser_sens->points[i].p;
134 
135  const double * p_i_w = laser_sens->points_w[i].p;
136  int from; int to; int start_cell;
137  possible_interval(p_i_w, laser_ref, max_angular_correction_deg,
138  max_linear_correction, &from, &to, &start_cell);
139 
140 // printf("\n i=%d interval = [%d,%d] ", i, from, to);
141  int j;
142  for(j=from;j<=to;j++) {
143  if(!laser_ref->alpha_valid[j]) continue;
144  if(j % interval) continue;
145 
146  double theta = angleDiff(laser_ref->alpha[j], laser_sens->alpha[i]);
147  double theta_diff = angleDiff(theta,x0[2]);
148  if( fabs(theta_diff) > deg2rad(max_angular_correction_deg) )
149  continue;
150  theta = x0[2] + theta_diff; // otherwise problems near +- PI
151 
152  const double * p_j = laser_ref->points[j].p;
153 
154  double c = cos(theta); double s = sin(theta);
155  double t_x = p_j[0] - (c*p_i[0]-s*p_i[1]);
156  double t_y = p_j[1] - (s*p_i[0]+c*p_i[1]);
157  double t_dist = sqrt( square(t_x-x0[0]) + square(t_y-x0[1]) );
158 
159  if(t_dist > max_linear_correction)
160  continue;
161 
162  /*double weight = 1/(laser_sens->cov_alpha[i]+laser_ref->cov_alpha[j]);*/
163  double weight = 1;
164  gsl_histogram_accumulate(hist, theta, weight);
165  gsl_histogram_accumulate(hist, theta+2*M_PI, weight); /* be robust */
166  gsl_histogram_accumulate(hist, theta-2*M_PI, weight);
167  count ++;
168  }
169  }
170  *num_correspondences = count;
171  sm_debug(" correspondences = %d\n",count);
172 }
173 
174 void ght_one_shot(LDP laser_ref, LDP laser_sens,
175  const double*x0, double max_linear_correction,
176  double max_angular_correction_deg, int interval, double*x, int*num_correspondences)
177 {
179  ld_compute_world_coords(laser_sens, x0);
180 
181  double L[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
182  double z[3] = {0,0,0};
183 
184  int count = 0;
185  int i;
186  for(i=0;i<laser_sens->nrays;i++) {
187  if(!laser_sens->alpha_valid[i]) continue;
188  if(i % interval) continue;
189 
190 
191  const double * p_i = laser_sens->points_w[i].p;
192 
193  const double * p_i_w = laser_sens->points_w[i].p;
194  int from; int to; int start_cell;
195  possible_interval(p_i_w, laser_ref, max_angular_correction_deg,
196  max_linear_correction, &from, &to, &start_cell);
197 // from = 0; to = laser_ref->nrays-1;
198 
199 
200  int j;
201  for(j=from;j<=to;j++) {
202  if(j % interval) continue;
203  if(!laser_ref->alpha_valid[j]) continue;
204 
205  double theta = angleDiff(laser_ref->alpha[j], laser_sens->alpha[i]);
206  double theta_diff = angleDiff(theta,x0[2]);
207  if( fabs(theta_diff) > deg2rad(max_angular_correction_deg) )
208  continue;
209  theta = x0[2] + theta_diff; // otherwise problems near +- PI
210 
211  const double * p_j = laser_ref->points[j].p;
212 
213  double c = cos(theta); double s = sin(theta);
214  double t_x = p_j[0] - (c*p_i[0]-s*p_i[1]);
215  double t_y = p_j[1] - (s*p_i[0]+c*p_i[1]);
216  double t_dist = sqrt( square(t_x-x0[0]) + square(t_y-x0[1]) );
217 
218  if(t_dist > max_linear_correction)
219  continue;
220 
221  /*double weight = 1/(laser_sens->cov_alpha[i]+laser_ref->cov_alpha[j]);
222  double weight = exp( -square(t_dist) - 5 * square(theta-x0[2]) );*/
223 
224  double weight = 1;
225 
226  double alpha = laser_ref->alpha[j];
227  double ca = cos(alpha); double sa=sin(alpha);
228 
229 // printf("%d ", (int) rad2deg(theta));
230 
231 /* printf("valid %d alpha %f weight %f t_x %f t_y %f\n",
232  laser_ref->alpha_valid[j],alpha,weight,
233  t_x, t_y); */
234  z[0] += weight*(ca*ca*t_x + sa*ca*t_y);
235  z[1] += weight*(sa*ca*t_x + sa*sa*t_y);
236  z[2] += weight*theta;
237  L[0][0] += weight* ca * ca;
238  L[0][1] += weight* sa * ca;
239  L[1][0] += weight* sa * ca;
240  L[1][1] += weight* sa * sa;
241  L[2][2] += weight;
242 
243  count += 1;
244  }
245  }
246 
247  *num_correspondences = count;
248 
249  if(1) {
250 
251  double weight = 0.5 * count;
252  z[0] += x0[0] * weight;
253  z[1] += x0[1] * weight;
254  L[0][0] += weight;
255  L[0][1] += 0;
256  L[1][0] += 0;
257  L[1][1] += weight;
258  }
259 
260 
261  egsl_push();
262  val eL = egsl_alloc(3,3);
263  size_t a,b;
264  for(a=0;a<3;a++)
265  for(b=0;b<3;b++)
266  *egsl_atmp(eL,a,b) = L[a][b];
267 
268 /* egsl_print("eL", eL);*/
269  val ez = egsl_vFa(3,z);
270 
271  val ex = m(inv(eL), ez);
272 
273  egsl_v2a(ex, x);
274 
275 
276 /* egsl_print("eL", eL);
277  egsl_print("ez", ez);
278  egsl_print("ex", ex); */
279 
280  egsl_pop();
281 
282 // sm_debug("gpm: second step: theta = %f %f / %d = %f \n", rad2deg(x[2]), rad2deg(z[2]), count, rad2deg(z[2]) / count);
283  sm_debug("gpm: second step: found %d correspondences\n",count);
284 
285 }
286 
#define deg2rad(x)
Definition: gpc_test.c:22
point2d *restrict points
Definition: laser_data.h:44
void sm_gpm(struct sm_params *params, struct sm_result *res)
Definition: gpm.c:11
void copy_d(const double *from, int n, double *to)
Definition: math_utils.c:83
double angleDiff(double a, double b)
Definition: math_utils.c:128
void egsl_pop()
Definition: egsl.c:89
Definition: egsl.h:12
int iterations
Definition: algos.h:146
double max_angular_correction_deg
Definition: algos.h:22
const char * friendly_pose(const double *pose)
Definition: math_utils.c:266
int orientation_neighbourhood
Definition: algos.h:77
void ld_compute_orientation(LDP ld, int size_neighbourhood, double sigma)
Definition: orientation.c:14
double clustering_threshold
Definition: algos.h:75
int ld_valid_fields(LDP ld)
Definition: laser_data.c:179
double max_linear_correction
Definition: algos.h:24
void ght_find_theta_range(LDP laser_ref, LDP laser_sens, const double *x0, double max_linear_correction, double max_angular_correction_deg, int interval, gsl_histogram *hist, int *num_correspondences)
Definition: gpm.c:120
void egsl_push()
Definition: egsl.c:88
int valid
Definition: algos.h:140
#define M_PI
Definition: math_utils.h:7
void possible_interval(const double *p_i_w, LDP laser_sens, double max_angular_correction_deg, double max_linear_correction, int *from, int *to, int *start_cell)
Definition: math_utils.c:10
val egsl_alloc(size_t rows, size_t columns)
Definition: egsl.c:159
double sigma
Definition: algos.h:124
#define m(v1, v2)
Definition: egsl_macros.h:13
void ght_one_shot(LDP laser_ref, LDP laser_sens, const double *x0, double max_linear_correction, double max_angular_correction_deg, int interval, double *x, int *num_correspondences)
Definition: gpm.c:174
int *restrict alpha_valid
Definition: laser_data.h:30
LDP laser_ref
Definition: algos.h:14
point2d *restrict points_w
Definition: laser_data.h:47
LDP laser_sens
Definition: algos.h:16
val egsl_vFa(size_t rows, const double *)
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
double * egsl_atmp(val v, size_t i, size_t j)
Definition: egsl.c:276
int gpm_interval
Definition: algos.h:132
double gpm_theta_bin_size_deg
Definition: algos.h:130
void sm_debug(const char *msg,...)
Definition: logging.c:88
double x[3]
Definition: algos.h:143
double gpm_extend_range_deg
Definition: algos.h:131
void ld_compute_cartesian(LDP ld)
Definition: laser_data.c:118
double square(double x)
Definition: math_utils.c:124
double *restrict alpha
Definition: laser_data.h:28
void sm_error(const char *msg,...)
Definition: logging.c:49
double interval
Definition: ld_resample.c:12
double rad2deg(double rad)
Definition: math_utils.c:79
double p[2]
Definition: laser_data.h:12
void egsl_v2a(val, double *)


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