00001 #include <gsl/gsl_histogram.h>
00002 #include <gsl/gsl_matrix.h>
00003
00004
00005 #include "../csm_all.h"
00006 #include "gpm.h"
00007
00008 #include <egsl/egsl_macros.h>
00009
00010
00011 void sm_gpm(struct sm_params*params, struct sm_result*res) {
00012 res->valid = 0;
00013
00014 if(!ld_valid_fields(params->laser_ref) ||
00015 !ld_valid_fields(params->laser_sens)) {
00016 return;
00017 }
00018
00019 LDP laser_ref = params->laser_ref;
00020 LDP laser_sens = params->laser_sens;
00021
00022
00023 ld_compute_cartesian(laser_ref);
00024
00025 ld_simple_clustering(laser_ref, params->clustering_threshold);
00026 ld_compute_orientation(laser_ref, params->orientation_neighbourhood, params->sigma);
00027
00028 ld_compute_cartesian(laser_sens);
00029 ld_simple_clustering(laser_sens, params->clustering_threshold);
00030 ld_compute_orientation(laser_sens, params->orientation_neighbourhood, params->sigma);
00031
00032
00033 double theta_bin_size = deg2rad(params->gpm_theta_bin_size_deg);
00034 double hist_min = -M_PI-theta_bin_size;
00035 double hist_max = +M_PI+theta_bin_size;
00036 size_t nbins = (size_t) ceil( (hist_max-hist_min) / theta_bin_size);
00037 gsl_histogram*hist = gsl_histogram_alloc(nbins);
00038 gsl_histogram_set_ranges_uniform(hist, hist_min, hist_max);
00039
00040
00041 double u[3]; copy_d(params->first_guess, 3, u);
00042 sm_debug("gpm 1/2: old u = : %s \n", friendly_pose(u) );
00043
00044 int interval = params->gpm_interval;
00045
00046 int num_correspondences_theta=-1;
00047
00048
00049 ght_find_theta_range(laser_ref, laser_sens,
00050 u, params->max_linear_correction,
00051 params->max_angular_correction_deg, interval, hist, &num_correspondences_theta);
00052
00053 if(num_correspondences_theta < laser_ref->nrays) {
00054 sm_error("sm_gpm(): I found only %d correspondences in the first pass of GPM. I consider it a failure.\n",
00055 num_correspondences_theta);
00056 return;
00057 }
00058
00059
00060 size_t max_bin = gsl_histogram_max_bin(hist);
00061
00062
00063 double min_range, max_range;
00064 gsl_histogram_get_range(hist,max_bin,&min_range,&max_range);
00065
00066
00067 double extend_range = deg2rad(params->gpm_extend_range_deg);
00068 min_range += -extend_range;
00069 max_range += +extend_range;
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 u[2] = 0.5 * (max_range + min_range);
00081 double new_range_deg = rad2deg( 0.5*(max_range - min_range) );
00082
00083 double x_new[3];
00084 int num_correspondences=-1;
00085 ght_one_shot(laser_ref, laser_sens,
00086 u, params->max_linear_correction*2,
00087 new_range_deg, interval, x_new, &num_correspondences) ;
00088
00089 if(num_correspondences < laser_ref->nrays) {
00090 sm_error("sm_gpm(): I found only %d correspondences in the second pass of GPM. I consider it a failure.\n",
00091 num_correspondences);
00092 return;
00093 }
00094
00095
00096
00097 {
00098 sm_debug("gpm : max_correction_lin %f def %f\n", params->max_linear_correction, params->max_angular_correction_deg);
00099 sm_debug("gpm : acceptable range for theta: [%f, %f]\n", min_range,max_range);
00100 sm_debug("gpm : 1) Num correspondences for theta: %d\n", num_correspondences_theta);
00101
00102 sm_debug("gpm 1/2: new u = : %s \n", friendly_pose(u) );
00103 sm_debug("gpm 1/2: New range: %f to %f\n",rad2deg(min_range),rad2deg(max_range));
00104
00105 sm_debug("gpm 2/2: Solution: %s \n", friendly_pose(x_new));
00106
00107
00108 }
00109
00110
00111
00112 res->valid = 1;
00113 copy_d(x_new, 3, res->x);
00114
00115 res->iterations = 0;
00116
00117 gsl_histogram_free(hist);
00118 }
00119
00120 void ght_find_theta_range(LDP laser_ref, LDP laser_sens,
00121 const double*x0, double max_linear_correction,
00122 double max_angular_correction_deg, int interval, gsl_histogram*hist, int*num_correspondences)
00123 {
00125 ld_compute_world_coords(laser_sens, x0);
00126
00127 int count = 0;
00128 int i;
00129 for(i=0;i<laser_sens->nrays;i++) {
00130 if(!laser_sens->alpha_valid[i]) continue;
00131 if(i % interval) continue;
00132
00133 const double * p_i = laser_sens->points[i].p;
00134
00135 const double * p_i_w = laser_sens->points_w[i].p;
00136 int from; int to; int start_cell;
00137 possible_interval(p_i_w, laser_ref, max_angular_correction_deg,
00138 max_linear_correction, &from, &to, &start_cell);
00139
00140
00141 int j;
00142 for(j=from;j<=to;j++) {
00143 if(!laser_ref->alpha_valid[j]) continue;
00144 if(j % interval) continue;
00145
00146 double theta = angleDiff(laser_ref->alpha[j], laser_sens->alpha[i]);
00147 double theta_diff = angleDiff(theta,x0[2]);
00148 if( fabs(theta_diff) > deg2rad(max_angular_correction_deg) )
00149 continue;
00150 theta = x0[2] + theta_diff;
00151
00152 const double * p_j = laser_ref->points[j].p;
00153
00154 double c = cos(theta); double s = sin(theta);
00155 double t_x = p_j[0] - (c*p_i[0]-s*p_i[1]);
00156 double t_y = p_j[1] - (s*p_i[0]+c*p_i[1]);
00157 double t_dist = sqrt( square(t_x-x0[0]) + square(t_y-x0[1]) );
00158
00159 if(t_dist > max_linear_correction)
00160 continue;
00161
00162
00163 double weight = 1;
00164 gsl_histogram_accumulate(hist, theta, weight);
00165 gsl_histogram_accumulate(hist, theta+2*M_PI, weight);
00166 gsl_histogram_accumulate(hist, theta-2*M_PI, weight);
00167 count ++;
00168 }
00169 }
00170 *num_correspondences = count;
00171 sm_debug(" correspondences = %d\n",count);
00172 }
00173
00174 void ght_one_shot(LDP laser_ref, LDP laser_sens,
00175 const double*x0, double max_linear_correction,
00176 double max_angular_correction_deg, int interval, double*x, int*num_correspondences)
00177 {
00179 ld_compute_world_coords(laser_sens, x0);
00180
00181 double L[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
00182 double z[3] = {0,0,0};
00183
00184 int count = 0;
00185 int i;
00186 for(i=0;i<laser_sens->nrays;i++) {
00187 if(!laser_sens->alpha_valid[i]) continue;
00188 if(i % interval) continue;
00189
00190
00191 const double * p_i = laser_sens->points_w[i].p;
00192
00193 const double * p_i_w = laser_sens->points_w[i].p;
00194 int from; int to; int start_cell;
00195 possible_interval(p_i_w, laser_ref, max_angular_correction_deg,
00196 max_linear_correction, &from, &to, &start_cell);
00197
00198
00199
00200 int j;
00201 for(j=from;j<=to;j++) {
00202 if(j % interval) continue;
00203 if(!laser_ref->alpha_valid[j]) continue;
00204
00205 double theta = angleDiff(laser_ref->alpha[j], laser_sens->alpha[i]);
00206 double theta_diff = angleDiff(theta,x0[2]);
00207 if( fabs(theta_diff) > deg2rad(max_angular_correction_deg) )
00208 continue;
00209 theta = x0[2] + theta_diff;
00210
00211 const double * p_j = laser_ref->points[j].p;
00212
00213 double c = cos(theta); double s = sin(theta);
00214 double t_x = p_j[0] - (c*p_i[0]-s*p_i[1]);
00215 double t_y = p_j[1] - (s*p_i[0]+c*p_i[1]);
00216 double t_dist = sqrt( square(t_x-x0[0]) + square(t_y-x0[1]) );
00217
00218 if(t_dist > max_linear_correction)
00219 continue;
00220
00221
00222
00223
00224 double weight = 1;
00225
00226 double alpha = laser_ref->alpha[j];
00227 double ca = cos(alpha); double sa=sin(alpha);
00228
00229
00230
00231
00232
00233
00234 z[0] += weight*(ca*ca*t_x + sa*ca*t_y);
00235 z[1] += weight*(sa*ca*t_x + sa*sa*t_y);
00236 z[2] += weight*theta;
00237 L[0][0] += weight* ca * ca;
00238 L[0][1] += weight* sa * ca;
00239 L[1][0] += weight* sa * ca;
00240 L[1][1] += weight* sa * sa;
00241 L[2][2] += weight;
00242
00243 count += 1;
00244 }
00245 }
00246
00247 *num_correspondences = count;
00248
00249 if(1) {
00250
00251 double weight = 0.5 * count;
00252 z[0] += x0[0] * weight;
00253 z[1] += x0[1] * weight;
00254 L[0][0] += weight;
00255 L[0][1] += 0;
00256 L[1][0] += 0;
00257 L[1][1] += weight;
00258 }
00259
00260
00261 egsl_push();
00262 val eL = egsl_alloc(3,3);
00263 size_t a,b;
00264 for(a=0;a<3;a++)
00265 for(b=0;b<3;b++)
00266 *egsl_atmp(eL,a,b) = L[a][b];
00267
00268
00269 val ez = egsl_vFa(3,z);
00270
00271 val ex = m(inv(eL), ez);
00272
00273 egsl_v2a(ex, x);
00274
00275
00276
00277
00278
00279
00280 egsl_pop();
00281
00282
00283 sm_debug("gpm: second step: found %d correspondences\n",count);
00284
00285 }
00286