Example #1
0
int main(int argc, const char* argv[]) {
	sm_set_program_name(argv[0]);

	log2pdf_params p;
	
	lds_set_defaults(&(p.laser));
	ls_set_defaults(&(p.pose_path));
	
	p.laser.rays.draw = 0;
	p.laser.points.draw = 0;
	p.laser.normals.draw = 0;
	p.laser.countour.width = 0.1;
	p.pose_path.width = 0.1;
	p.pose_path.color = "#f00";
	
	options_banner(banner);
	struct option * ops = options_allocate(100);
	options_string(ops, "in", &p.input_filename, "stdin", "input file (Carmen or JSON)");
	options_string(ops, "out", &p.output_filename, "", "output file (if empty, input file + '.pdf')");
	options_double(ops, "padding", &p.padding, 0.2, "padding around bounding box (m)");
	options_double(ops, "dimension", &p.dimension, 500.0, "dimension of the image (points)");
	options_double(ops, "offset_theta_deg", &p.offset_theta_deg, 0.0, " rotate entire map by this angle (deg) ");

	options_string(ops, "use", &p.use, "estimate", "One in 'odometry','estimate','true_pose'");
	options_double(ops, "distance_xy", &p.distance_xy, 5.0, " Minimum distance between scans (m) ");
	options_double(ops, "distance_th_deg", &p.distance_th_deg, 45.0, " Minimum distance between scans (deg) ");
	options_double(ops, "start_pose_width", &p.start_pose_width, 0.4, "First pose | Circle width");
	lds_add_options(&(p.laser), ops, "laser_", "");
	ls_add_options(&(p.pose_path), ops, "path_", "");
	
	if(!options_parse_args(ops, argc, argv)) {
		sm_error("Could not parse arguments.\n");
		options_print_help(ops, stderr);
		return -1;
	}
	
	/* If out not specified */
	if(strlen(p.output_filename)==0) {
		char buf[PATH_MAX];
		sprintf(buf, "%s.pdf", p.input_filename);
		p.output_filename = my_strdup(buf);
/*		sm_info("Writing on file '%s'.\n", p.output_filename);*/
	}
	
	p.use_reference = ld_string_to_reference(p.use);
	if(Invalid == p.use_reference) {
		sm_error("Invalid reference '%s'. " 
			"Use one in 'odometry','estimate','true_pose'.\n", p.use);
		return -1;
	}
/*	sm_info("Using reference: %s.\n", ld_reference_to_string(p.use_reference));*/
	
	return !log2pdf(&p);
}
Example #2
0
int main(int argc, const char * argv[]) {
	sm_set_program_name(argv[0]);
	
    int period; int phase;
	const char*input_filename;
	const char*output_filename;
	
	struct csm_option* ops = csm_options_allocate(3);
	csm_options_int(ops, "period", &period, 1, "Period of objects to extract.");
	csm_options_int(ops, "phase", &phase, 0, "Phase (=0 starts with the first object)");
	csm_options_string(ops, "in", &input_filename, "stdin", "input file (JSON)");
	csm_options_string(ops, "out", &output_filename, "stdout", "output file (JSON)");
	
	if(!csm_options_parse_args(ops, argc, argv)) {
		fprintf(stderr, "%s : decimates a JSON stream."
			"\n\ncsm_options:\n", argv[0]);
		csm_options_print_help(ops, stderr);
		return -1;
	}
	
	if(period < 1) {
		sm_error("Period must be >= 1.\n");
		return 2;
	}
	
	FILE * input_stream = open_file_for_reading(input_filename);
	FILE *output_stream = open_file_for_writing(output_filename);
	
	if(!input_stream || !output_stream) return -1;
	
	
	int count = 0;
	while(1) { 
		JO jo = json_read_stream(input_stream);
		if(!jo) {
			if(feof(input_stream)) break;
			sm_error("Malformed JSON\n");
			return -1;
		}
		
		if( (count - phase) % period == 0) {
			const char * s = json_object_to_json_string(jo);
			fputs(s,output_stream); fputs("\n",output_stream);
		} 
		
		jo_free(jo);
		count++;
	}
	
	return 0;
}
Example #3
0
int bbfind_compute(bbfind*bbf, BB2 bbox) {
	double ul[2], ur[2], ll[2], lr[2];
	
	if(1) {
		if(!getBoundingBox(bbf->buf, bbf->num, ul, ur, ll, lr)) {
			sm_error("Could not compute bounding box.\n");
			return 0;
		}
		bbox->pose[0] = ll[0];
		bbox->pose[1] = ll[1];
		bbox->pose[2] = atan2(lr[1]-ll[1], lr[0]-ll[0]);
		bbox->size[0] = distance_d(lr, ll);
		bbox->size[1] = distance_d(ll, ul);
	} else {
		double bb_min[2] = {bbf->buf[0].x,bbf->buf[0].y}, 
				bb_max[2] = {bbf->buf[0].x,bbf->buf[0].y};
		int i; for(i=0;i<bbf->num; i++) {
			bb_min[0] = GSL_MIN(bb_min[0], bbf->buf[i].x);
			bb_min[1] = GSL_MIN(bb_min[1], bbf->buf[i].y);
			bb_max[0] = GSL_MAX(bb_max[0], bbf->buf[i].x);
			bb_max[1] = GSL_MAX(bb_max[1], bbf->buf[i].y);
		}
		bbox->pose[0] = bb_min[0];
		bbox->pose[1] = bb_min[1];
		bbox->pose[2] = 0;
		bbox->size[0] = bb_max[0] - bb_min[0];
		bbox->size[1] = bb_max[1] - bb_min[1];
	}
	return 1;
}
Example #4
0
int main(int argc, const char * argv[]) {
	sm_set_program_name(argv[0]);
/*	
	struct csm_option* ops = csm_options_allocate(3);
	csm_options_double(ops, "scale_deg", &p.scale_deg, 0.0, "Scale factor (degrees) ");
	csm_options_int(ops, "neighbours", &p.neighbours, 1, "How many neighbours to consider (regardless of scale).");
		
	if(!csm_options_parse_args(ops, argc, argv)) {
		fprintf(stderr, "A simple program for smoothing a sensor scan.\n\nUsage:\n");
		csm_options_print_help(ops, stderr);
		return -1;
	}
*/	
/* jj_set_stream(open_file_for_writing("ld_cluster_curv.txt")); */

	int errors = 0;
	int count = -1;
	LDP ld;
	while( (ld = ld_read_smart(stdin)) ) {
		count++;
		if(!ld_valid_fields(ld))  {
			sm_error("Invalid laser data (#%d in file)\n", count);
			return -1;
		}
		
		ld_cluster_curv(ld);

		ld_write_as_json(ld, stdout);

		ld_free(ld);
	}
	
	return errors;
}
Example #5
0
void cluster_convolve(const int*cluster,const double*original, int n, double*dest, double*filter, int filter_len, int negate_negative) 
{
	int i; /* index on the points */
	int j; /* index on the filter */
	
	for(i=0;i<n;i++) {
		if(cluster[i] == -1) {
			dest[i] = GSL_NAN;
			continue;
		}
		
		dest[i] = 0;
		for(j=-(filter_len-1);j<=(filter_len-1);j++) {
			int i2 = i + j;
			if(i2<0) i2=0; if(i2>=n) i2=n-1;
			if(cluster[i2] != cluster[i]) i2 = i; 
			double coeff = filter[abs(j)];
			if(j<0 && negate_negative) coeff *= -1;
			dest[i] += original[i2] * coeff;

			if(is_nan(dest[i]))  
				sm_error("i: %d; something wrong after processing i2: %d  cluster[i2]=%d original[i2] = %f \n", i, i2, cluster[i2], original[i2]);
			
		}
		
	}
}
Example #6
0
FILE * open_file(const char *filename, const char*mode) {
	FILE*file = fopen(filename, mode);
	if(file==NULL) {
		sm_error("Could not open file '%s': %s.\n", filename, strerror(errno)); 
		return 0;
	}
	return file;
}
Example #7
0
/** Returns 0 on success */
int read_next_double(const char*line, size_t*cur, double*d) {
	int inc;
	int ret = sscanf(line+*cur, " %lf %n", d, &inc);
	if(1 != ret) {
		sm_error("Could not read double at %p + %d '%s'. ret: %d.\n", line, *cur, line+*cur, ret);
		return -1;
	}
	*cur += inc;
	return 0;
}
Example #8
0
bool json2tuple(const JO jo, calib_tuple&tuple) {
	int res = 
		jo_read_double(jo, "T", &tuple.T) &&
		jo_read_double(jo, "phi_l", &tuple.phi_l) &&
		jo_read_double(jo, "phi_r", &tuple.phi_r) &&
		jo_read_double_array (jo, "sm", tuple.sm, 3, GSL_NAN);
		
	if(!res)
		sm_error("Cannot read tuple form JSON.\n");
	return res;
}
Example #9
0
/* Init Opus encoder, return it on success. Print error to stdout, release wave resource and return NULL on error. */
OpusSM* init_opus(WAVE* wave) {
	OpusSM* sm = sm_init(wave->header.SampleRate, wave->header.NumChannels);

	if (sm_error(sm) != SM_OK) {
		fprintf(stderr, "Opus encoder returned error on opus_encoder_create(). Error code: %d\n", sm_error(sm));
		sm = sm_destroy(sm);
		return NULL;
	}

	return sm;
}
Example #10
0
int bbfind_add_point2(bbfind*bbf, double x, double y) {
	if(bbf->num > bbf->buf_size - 2) {
		bbf->buf_size	*= 2;
		if(! (bbf->buf = (BB_Point*) realloc(bbf->buf, sizeof(BB_Point)*bbf->buf_size)) ) {
			sm_error("Cannot allocate (size=%d)\n", bbf->buf_size);
			return 0;
		}
	}
	bbf->buf[bbf->num].x = x;
	bbf->buf[bbf->num].y = y;
	bbf->num++;
	return 1;
}
Example #11
0
int main(int argc, const char * argv[]) {
	sm_set_program_name(argv[0]);
	
	
	options_banner("ld_purify: Makes sure that the file format is valid. \n * Sets valid=0 if reading is outside interval ");
	
	struct ld_purify_params p;
	
	struct option* ops = options_allocate(20);
	options_double(ops, "threshold_min", &p.threshold_min, 0.01, 
		"Sets valid=0 if readings are less than this threshold.");
	options_double(ops, "threshold_max", &p.threshold_max, 79.0, 
		"Sets valid=0 if readings are more than this threshold.");
	
	options_string(ops, "in", &p.file_input, "stdin", "Input file ");
	options_string(ops, "out", &p.file_output, "stdout", "Output file ");
		
		
	if(!options_parse_args(ops, argc, argv)) {
		options_print_help(ops, stderr);
		return -1;
	}

	FILE * in = open_file_for_reading(p.file_input);
	if(!in) return -3;

	FILE * out = open_file_for_writing(p.file_output);
	if(!out) return -2;



	LDP ld; int count = -1;
	while( (ld = ld_from_json_stream(in))) {
		
		purify(ld, p.threshold_min, p.threshold_max);
		
		if(!ld_valid_fields(ld))  {
			sm_error("Wait, we didn't purify enough  (#%d in file)\n", count);
			continue;
		}
		
		ld_write_as_json(ld, out);
		ld_free(ld);
	}
	
	return 0;
}
Example #12
0
/** Write the laser data in CARMEN format */
void ld_write_as_carmen(LDP ld, FILE * stream) {
	int i;
	double timestamp;
	if(!ld_valid_fields(ld)) {
		sm_error("Writing bad data to the stream.\n");
	}
	fprintf(stream, "FLASER %d ", ld->nrays);
	for(i=0; i<ld->nrays; i++){
		fprintf(stream, "%g ", ld->readings[i]);
	}
	fprintf(stream, "%g %g %g ", ld->estimate[0], ld->estimate[1], ld->estimate[2]);
	fprintf(stream, "%g %g %g ", ld->odometry[0], ld->odometry[1], ld->odometry[2]);
	
	timestamp = ld->tv.tv_sec + ((double)ld->tv.tv_sec)/1e6;
	
	fprintf(stream, "%g %s %g", timestamp, ld->hostname, timestamp);
	
	fputs("\n", stream);
}
Example #13
0
int main(int argc, const char * argv[]) {
	sm_set_program_name(argv[0]);
	
	int nth;
	const char*input_filename;
	const char*output_filename;
	
	struct csm_option* ops = csm_options_allocate(3);
	csm_options_int(ops, "nth", &nth, 0, "Index of object to extract.");
	csm_options_string(ops, "in", &input_filename, "stdin", "input file (JSON)");
	csm_options_string(ops, "out", &output_filename, "stdout", "output file (JSON)");
	
	if(!csm_options_parse_args(ops, argc, argv)) {
		fprintf(stderr, "%s : extracts n-th JSON object from stream."
			"\n\ncsm_options:\n", argv[0]);
		csm_options_print_help(ops, stderr);
		return -1;
	}
	
	FILE * input_stream = open_file_for_reading(input_filename);
	FILE *output_stream = open_file_for_writing(output_filename);
	
	if(!input_stream || !output_stream) return -1;
	
	int i; for(i=0;i<nth;i++) {
		if(!json_stream_skip(input_stream)) {
			sm_error("Could not skip %d-th object\n", i);
			return -2;
		}
	}
	
	JO jo = json_read_stream(input_stream);
	if(!jo) {
		fprintf(stderr, "Could not read %d-th object (after skipping %d)\n", 
			nth, i);
		return -2;
	}
	
	fputs(json_object_to_json_string(jo), output_stream);
	fputs("\n", output_stream);
	return 0;
}
Example #14
0
static void nble_security_reply(struct bt_conn *conn,
				struct nble_sm_passkey *par)
{
	struct nble_sm_passkey_reply_req rsp = {
		.conn = conn,
		.conn_handle = conn->handle,
	};

	memcpy(&rsp.params, par, sizeof(*par));

	nble_sm_passkey_reply_req(&rsp);
}

static int sm_error(struct bt_conn *conn, uint8_t reason)
{
	struct nble_sm_passkey params;

	params.type = NBLE_GAP_SM_REJECT;
	params.reason = reason;

	nble_security_reply(conn, &params);

	return 0;
}

static void legacy_passkey_entry(struct bt_smp *smp, unsigned int passkey)
{
	struct nble_sm_passkey pkey = {
		.type = NBLE_SM_PK_PASSKEY,
		.passkey = passkey,
	};

	nble_security_reply(smp->conn, &pkey);
}

int bt_smp_auth_cancel(struct bt_conn *conn)
{
	BT_DBG("");

	return sm_error(conn, BT_SMP_ERR_PASSKEY_ENTRY_FAILED);
}
Example #15
0
int main(int argc, const char * argv[]) {
	sm_set_program_name(argv[0]);
	
	int errors = 0;
	int count = -1;
	LDP ld;
	while( (ld = ld_read_smart(stdin)) ) {
		count++;
		if(!ld_valid_fields(ld))  {
			sm_error("Invalid laser data (#%d in file)\n", count);
			errors++;
			continue;
		}
		
		ld_linearize(ld);

		ld_write_as_json(ld, stdout);

		ld_free(ld);
	}
	
	return errors;
}
Example #16
0
int compute_next_estimate(struct sm_params*params, 
	const double x_old[3], double x_new[3]) 
{
	LDP laser_ref  = params->laser_ref;
	LDP laser_sens = params->laser_sens;
	
	struct gpc_corr c[laser_sens->nrays];

	int i; int k=0;
	for(i=0;i<laser_sens->nrays;i++) {
		if(!laser_sens->valid[i])
			continue;
			
		if(!ld_valid_corr(laser_sens,i))
			continue;
		
		int j1 = laser_sens->corr[i].j1;
		int j2 = laser_sens->corr[i].j2;

		c[k].valid = 1;
		
		if(laser_sens->corr[i].type == corr_pl) {

			c[k].p[0] = laser_sens->points[i].p[0];
			c[k].p[1] = laser_sens->points[i].p[1];
			c[k].q[0] = laser_ref->points[j1].p[0];
			c[k].q[1] = laser_ref->points[j1].p[1];

			/** TODO: here we could use the estimated alpha */
			double diff[2];
			diff[0] = laser_ref->points[j1].p[0]-laser_ref->points[j2].p[0];
			diff[1] = laser_ref->points[j1].p[1]-laser_ref->points[j2].p[1];
			double one_on_norm = 1 / sqrt(diff[0]*diff[0]+diff[1]*diff[1]);
			double normal[2];
			normal[0] = +diff[1] * one_on_norm;
			normal[1] = -diff[0] * one_on_norm;

			double cos_alpha = normal[0];
			double sin_alpha = normal[1];
						
			c[k].C[0][0] = cos_alpha*cos_alpha;
			c[k].C[1][0] = 
			c[k].C[0][1] = cos_alpha*sin_alpha;
			c[k].C[1][1] = sin_alpha*sin_alpha;
			
/*			sm_debug("k=%d, i=%d sens_phi: %fdeg, j1=%d j2=%d,  alpha_seg=%f, cos=%f sin=%f \n", k,i,
				rad2deg(laser_sens->theta[i]), j1,j2, atan2(sin_alpha,cos_alpha), cos_alpha,sin_alpha);*/
			
#if 0
			/* Note: it seems that because of numerical errors this matrix might be
			   not semidef positive. */
			double det = c[k].C[0][0] * c[k].C[1][1] - c[k].C[0][1] * c[k].C[1][0];
			double trace = c[k].C[0][0] + c[k].C[1][1];
			
			int semidef = (det >= 0) && (trace>0);
			if(!semidef) {
	/*			printf("%d: Adjusting correspondence weights\n",i);*/
				double eps = -det;
				c[k].C[0][0] += 2*sqrt(eps);
				c[k].C[1][1] += 2*sqrt(eps);
			}
#endif			
		} else {
			c[k].p[0] = laser_sens->points[i].p[0];
			c[k].p[1] = laser_sens->points[i].p[1];
			
			projection_on_segment_d(
				laser_ref->points[j1].p,
				laser_ref->points[j2].p,
				laser_sens->points_w[i].p,
				c[k].q);

			/* Identity matrix */
			c[k].C[0][0] = 1;
			c[k].C[1][0] = 0;
			c[k].C[0][1] = 0;
			c[k].C[1][1] = 1;
		}
		
		
		double factor = 1;
		
		/* Scale the correspondence weight by a factor concerning the 
		   information in this reading. */
		if(params->use_ml_weights) {
			int have_alpha = 0;
			double alpha = 0;
			if(!is_nan(laser_ref->true_alpha[j1])) {
				alpha = laser_ref->true_alpha[j1];
				have_alpha = 1;
			} else if(laser_ref->alpha_valid[j1]) {
				alpha = laser_ref->alpha[j1];;
				have_alpha = 1;
			} else have_alpha = 0;
			
			if(have_alpha) {
				double pose_theta = x_old[2];
				/** Incidence of the ray 
					Note that alpha is relative to the first scan (not the world)
					and that pose_theta is the angle of the second scan with 
					respect to the first, hence it's ok. */
				double beta = alpha - (pose_theta + laser_sens->theta[i]);
				factor = 1 / square(cos(beta));
			} else {
				static int warned_before = 0;
				if(!warned_before) {
					sm_error("Param use_ml_weights was active, but not valid alpha[] or true_alpha[]." 
					          "Perhaps, if this is a single ray not having alpha, you should mark it as inactive.\n");						
					sm_error("Writing laser_ref: \n");						
					ld_write_as_json(laser_ref, stderr);
					warned_before = 1;
				}
			}
		} 
		
		/* Weight the points by the sigma in laser_sens */
		if(params->use_sigma_weights) {
			if(!is_nan(laser_sens->readings_sigma[i])) {
				factor *= 1 / square(laser_sens->readings_sigma[i]);
			} else {
				static int warned_before = 0;
				if(!warned_before) {
					sm_error("Param use_sigma_weights was active, but the field readings_sigma[] was not filled in.\n");						
					sm_error("Writing laser_sens: \n");						
					ld_write_as_json(laser_sens, stderr);
				}
			}
		}
		
		c[k].C[0][0] *= factor;
		c[k].C[1][0] *= factor;
		c[k].C[0][1] *= factor;
		c[k].C[1][1] *= factor;
		
		k++;
	}
	
	/* TODO: use prior for odometry */
	double std = 0.11;
	const double inv_cov_x0[9] = 
		{1/(std*std), 0, 0,
		 0, 1/(std*std), 0,
		 0, 0, 0};
	
	
	int ok = gpc_solve(k, c, 0, inv_cov_x0, x_new);
	if(!ok) {
		sm_error("gpc_solve_valid failed\n");
		return 0;
	}

	double old_error = gpc_total_error(c, k, x_old);
	double new_error = gpc_total_error(c, k, x_new);

	sm_debug("\tcompute_next_estimate: old error: %f  x_old= %s \n", old_error, friendly_pose(x_old));
	sm_debug("\tcompute_next_estimate: new error: %f  x_new= %s \n", new_error, friendly_pose(x_new));
	sm_debug("\tcompute_next_estimate: new error - old_error: %g \n", new_error-old_error);

	double epsilon = 0.000001;
	if(new_error > old_error + epsilon) {
		sm_error("\tcompute_next_estimate: something's fishy here! Old error: %lf  new error: %lf  x_old %lf %lf %lf x_new %lf %lf %lf\n",old_error,new_error,x_old[0],x_old[1],x_old[2],x_new[0],x_new[1],x_new[2]);
	}
	
	return 1;
}
Example #17
0
int icp_loop(struct sm_params*params, const double*q0, double*x_new, 
	double*total_error, int*valid, int*iterations) {
	if(any_nan(q0,3)) {
		sm_error("icp_loop: Initial pose contains nan: %s\n", friendly_pose(q0));
		return 0;
	}
		
		
	LDP laser_sens = params->laser_sens;
	double x_old[3], delta[3], delta_old[3] = {0,0,0};
	copy_d(q0, 3, x_old);
	unsigned int hashes[params->max_iterations];
	int iteration;
	
	sm_debug("icp: starting at  q0 =  %s  \n", friendly_pose(x_old));
	
	if(JJ) jj_loop_enter("iterations");
	
	int all_is_okay = 1;
	
	for(iteration=0; iteration<params->max_iterations;iteration++) {
		if(JJ) jj_loop_iteration();
		if(JJ) jj_add_double_array("x_old", x_old, 3);

		egsl_push_named("icp_loop iteration");
		sm_debug("== icp_loop: starting iteration. %d  \n", iteration);

		/** Compute laser_sens's points in laser_ref's coordinates
		    by roto-translating by x_old */
		ld_compute_world_coords(laser_sens, x_old);

		/** Find correspondences (the naif or smart way) */
		if(params->use_corr_tricks)
			find_correspondences_tricks(params);
		else
			find_correspondences(params);

		/** If debug_verify_tricks, make sure that find_correspondences_tricks()
		    and find_correspondences() return the same answer */
			if(params->debug_verify_tricks)
				debug_correspondences(params);

		/* If not many correspondences, bail out */
		int num_corr = ld_num_valid_correspondences(laser_sens);
		double fail_perc = 0.05;
		if(num_corr < fail_perc * laser_sens->nrays) { /* TODO: arbitrary */
			sm_error("	: before trimming, only %d correspondences.\n",num_corr);
			all_is_okay = 0;
			egsl_pop_named("icp_loop iteration"); /* loop context */
			break;
		}

		if(JJ) jj_add("corr0", corr_to_json(laser_sens->corr, laser_sens->nrays));

		/* Kill some correspondences (using dubious algorithm) */
		if(params->outliers_remove_doubles)
			kill_outliers_double(params);
		
		int num_corr2 = ld_num_valid_correspondences(laser_sens);

		if(JJ) jj_add("corr1", corr_to_json(laser_sens->corr, laser_sens->nrays));
		
		double error=0;
		/* Trim correspondences */
		kill_outliers_trim(params, &error);
		int num_corr_after = ld_num_valid_correspondences(laser_sens);
		
		if(JJ) {
			jj_add("corr2", corr_to_json(laser_sens->corr, laser_sens->nrays));
			jj_add_int("num_corr0", num_corr);
			jj_add_int("num_corr1", num_corr2);
			jj_add_int("num_corr2", num_corr_after);
		}

		*total_error = error; 
		*valid = num_corr_after;

		sm_debug("  icp_loop: total error: %f  valid %d   mean = %f\n", *total_error, *valid, *total_error/ *valid);
		
		/* If not many correspondences, bail out */
		if(num_corr_after < fail_perc * laser_sens->nrays){
			sm_error("  icp_loop: failed: after trimming, only %d correspondences.\n",num_corr_after);
			all_is_okay = 0;
			egsl_pop_named("icp_loop iteration"); /* loop context */
			break;
		}

		/* Compute next estimate based on the correspondences */
		if(!compute_next_estimate(params, x_old, x_new)) {
			sm_error("  icp_loop: Cannot compute next estimate.\n");
			all_is_okay = 0;
			egsl_pop_named("icp_loop iteration");
			break;			
		}

		pose_diff_d(x_new, x_old, delta);
		
		{
			sm_debug("  icp_loop: killing. laser_sens has %d/%d rays valid,  %d corr found -> %d after double cut -> %d after adaptive cut \n", count_equal(laser_sens->valid, laser_sens->nrays, 1), laser_sens->nrays, num_corr, num_corr2, num_corr_after);
			if(JJ) {
				jj_add_double_array("x_new", x_new, 3);
				jj_add_double_array("delta", delta, 3);
			}
		}
		/** Checks for oscillations */
		hashes[iteration] = ld_corr_hash(laser_sens);
		
		{
			sm_debug("  icp_loop: it. %d  hash=%d nvalid=%d mean error = %f, x_new= %s\n", 
				iteration, hashes[iteration], *valid, *total_error/ *valid, 
				friendly_pose(x_new));
		}

		
		/** PLICP terminates in a finite number of steps! */
		if(params->use_point_to_line_distance) {
			int loop_detected = 0; /* TODO: make function */
			int a; for(a=iteration-1;a>=0;a--) {
				if(hashes[a]==hashes[iteration]) {
					sm_debug("icpc: oscillation detected (cycle length = %d)\n", iteration-a);
					loop_detected = 1;
					break;
				}
			}
			if(loop_detected) {
				egsl_pop_named("icp_loop iteration");
				break;
			} 
		}
	
		/* This termination criterium is useless when using
		   the point-to-line-distance; however, we put it here because
		   one can choose to use the point-to-point distance. */
		if(termination_criterion(params, delta)) {
			egsl_pop_named("icp_loop iteration");
			break;
		}
		
		copy_d(x_new, 3, x_old);
		copy_d(delta, 3, delta_old);
		
		
		egsl_pop_named("icp_loop iteration");
	}

	if(JJ) jj_loop_exit();
	
	*iterations = iteration+1;
	
	return all_is_okay;
}
Example #18
0
int main(int argc, const char ** argv) {
	sm_set_program_name(argv[0]);
	
	struct ld_exp_tro1_params p;
	
	options_banner(banner);
	
	struct option* ops = options_allocate(10);
	options_double(ops, "max_xy_error", &p.max_xy_error, 10.0, "Maximum error for x,y (m)");
	options_double(ops, "max_theta_error_deg", &p.max_theta_error_deg, 10.0, "Maximum error for orientation (deg)");
	options_int   (ops, "seed", &p.seed, 0, "Seed for random number generator (if 0, use GSL_RNG_SEED env. variable).");

	options_int(ops, "num_per_scan", &p.num_per_scan, 10, "Number of trials for each scan.");

	options_string(ops, "in", &p.file_input, "stdin", "Input file ");
	options_string(ops, "out1", &p.file_output1, "stdout", "Output file for first scan");
	options_string(ops, "out2", &p.file_output2, "stdout", "Output file for second scan");
	
	options_int(ops, "debug", &p.debug, 0, "Shows debug information");
	
	if(!options_parse_args(ops, argc, argv)) {
		options_print_help(ops, stderr);
		return -1;
	}
	
	sm_debug_write(p.debug);

	gsl_rng_env_setup();
	gsl_rng * rng = gsl_rng_alloc (gsl_rng_ranlxs0);
	if(p.seed != 0)
	gsl_rng_set(rng, (unsigned int) p.seed);
	
	/* Open the two output files (possibly the same one) */
	
	FILE * in = open_file_for_reading(p.file_input);
	if(!in) return -3;

	FILE * out1 = open_file_for_writing(p.file_output1);
	if(!out1) return -2;
	
	FILE * out2;
	if(!strcmp(p.file_output1, p.file_output2)) {
		out1 = out2;
	} else {
		out2 = open_file_for_writing(p.file_output2);
		if(!out2) return -2;
	}

	/* Read laser data from input file */
	LDP ld; int count=0;
	while( (ld = ld_read_smart(in))) {
		count++;
		if(!ld_valid_fields(ld))  {
			sm_error("Invalid laser data (#%d in file)\n", count);
			continue;
		}
		
		for(int n=0; n < p.num_per_scan; n++) {					
			ld->true_pose[0] = 0;
			ld->true_pose[1] = 0;
			ld->true_pose[2] = 0;
			
			ld->odometry[0] = 0;
			ld->odometry[1] = 0;
			ld->odometry[2] = 0;
			
			ld_write_as_json(ld, out1);

			ld->odometry[0] = 2*(gsl_rng_uniform(rng)-0.5) * p.max_xy_error;
			ld->odometry[1] = 2*(gsl_rng_uniform(rng)-0.5) * p.max_xy_error;
			ld->odometry[2] = 2*(gsl_rng_uniform(rng)-0.5) * deg2rad(p.max_theta_error_deg);
			
			ld_write_as_json(ld, out2);
		}

		ld_free(ld);
	}
	
	return 0;
}
Example #19
0
int log2pdf(log2pdf_params *p) {

	/** First of all, we read the entire map into memory */
	FILE *input_file = open_file_for_reading(p->input_filename);
	if(!input_file) return 0;
	
	LDP*scans; int nscans;
	
	if(!ld_read_some_scans_distance(input_file,  &scans, &nscans,
		 p->use_reference, p->distance_xy, deg2rad(p->distance_th_deg) ) ){
		sm_error("Could not read map from file '%s'.\n", p->input_filename); 
		return 0;
	}
	
	if(nscans == 0) {
		sm_error("I could not read any scan from file '%s'.\n", p->input_filename);
		return 0;
	}
	
	sm_debug("Read map: %d scans in total.\n", nscans);

	/** Let's find the bounding box for the map */
	double bb_min[2], bb_max[2];
	double offset[3] = {0,0,0};
	lda_get_bounding_box(scans, nscans, bb_min, bb_max, offset, p->use_reference, p->laser.horizon);
	
	bb_min[0] -= p->padding;
	bb_min[1] -= p->padding;
	bb_max[0] += p->padding;
	bb_max[1] += p->padding;
	

	sm_debug("Bounding box: %f %f -- %f %f.\n", bb_min[0], bb_min[1],
		bb_max[0], bb_max[1]);

		
	/* Create PDF surface and setup paper size and transformations */
	int max_width_points = p->dimension;
	int max_height_points = p->dimension;
	cairo_surface_t *surface;
	cairo_t *cr;

	if(!create_pdf_surface(p->output_filename, max_width_points, max_height_points, 
		bb_min, bb_max, &surface, &cr)) return 0;

	/* Draw pose path */
	if(p->pose_path.draw) {
		cairo_save(cr);
		
		cr_set_style(cr, &(p->pose_path));
		cr_lda_draw_pose_path(cr, scans, nscans, p->use_reference);

		if(nscans > 0 && p->laser.pose.draw) {
			cairo_set_source_rgb(cr, 0.3, 0.0, 1.0);
			double *pose0 = ld_get_reference_pose(scans[0], p->use_reference);
			cairo_arc(cr, pose0[0], pose0[1], p->start_pose_width, 0.0, 2*M_PI);
			cairo_fill(cr);
		}

		cairo_restore(cr);
	}

	/* Draw map */
	int k; for(k=0;k<nscans;k++) {
		LDP ld = scans[k];
		double *pose = ld_get_reference_pose(ld, p->use_reference);
		if(!pose) continue;
		
		double offset[3] = {0,0, deg2rad(p->offset_theta_deg) };
		double world_pose[3];
		oplus_d(offset, pose, world_pose);
				
		cairo_save(cr);
		cr_set_reference(cr, world_pose);
		cr_ld_draw(cr, ld, &(p->laser));
		cairo_restore(cr);
	}

	cairo_show_page (cr);

	cairo_destroy (cr);
	cairo_surface_destroy (surface);
	return 1;
}
Example #20
0
LDP ld_from_carmen_string(const char*line) {
	
	if(0 != strncmp(line, carmen_prefix, strlen(carmen_prefix))) {
		sm_error("This is not a Carmen line: \n-> %s\n", line);
		return 0;
	}
	
	size_t cur = strlen(carmen_prefix); 

	
	int nrays=-1;
	if(read_next_integer(line, &cur, &nrays)) {
		sm_error("Could not get number of rays.\n");
		goto error;
	}

	LDP ld = ld_alloc_new(nrays);
	
	
	double fov = M_PI;
	double min_reading = 0;
	double max_reading = 80;
	
	if(nrays == 769) {
		min_reading = 0.001;
		max_reading = 4;
		fov = deg2rad(270.0);

		static int print = 0;
		if(!print) { print = 1;
			sm_info("Assuming that 769 rays is an Hokuyo "
			 "with fov = %f deg, min_reading = %f m, max_reading = %fm\n",
				rad2deg(fov), min_reading, max_reading);
		}
	}
	
	ld->min_theta = -fov/2;
	ld->max_theta = +fov/2;
	
	int on_error = 0;
	int i;
	for(i=0;i<nrays;i++) {
		double reading;
		if(read_next_double(line,&cur,&reading)) {
			sm_error("Could not read ray #%d / %d, \n", i, nrays); 
			on_error = 1;
			break;
		}
			
		ld->valid[i] = (reading > min_reading) && (reading < max_reading);
		ld->readings[i] = ld->valid[i] ? reading : NAN;
		ld->theta[i] = ld->min_theta + i * 
		  (ld->max_theta-ld->min_theta) / (ld->nrays-1);
		
		/* bad hokuyo!! */
		if(nrays == 769) {
			if(i>725 || i<44) { 
				ld->valid[i] = 0; 
				ld->readings[i] = NAN;
			}
		}
		
	}
	
	if(on_error) goto error;
	
	if(read_next_double(line,&cur,ld->estimate+0)) goto error;
	if(read_next_double(line,&cur,ld->estimate+1)) goto error;
	if(read_next_double(line,&cur,ld->estimate+2)) goto error;
	if(read_next_double(line,&cur,ld->odometry+0)) goto error;
	if(read_next_double(line,&cur,ld->odometry+1)) goto error;
	if(read_next_double(line,&cur,ld->odometry+2)) goto error;

	/* Following: ipc_timestamp hostname timestamp */
	/* Two csm_options:
		double string double: 
			the first is timestamp in seconds, the second is discarded
		int string int:
			the first is sec, the second is usec 
	*/
	static int warn_format = 1;

	int inc; int sec=-1, usec=-1;
	int res = sscanf(line + cur, "%d %s %d%n", &sec, ld->hostname, &usec,  &inc);
	if(3 == res) {
		ld->tv.tv_sec = sec;
		ld->tv.tv_usec = usec;
		if(warn_format)
			sm_info("Reading timestamp as 'sec hostname usec'.\n");
	} else {
		double v1=-1, v2=-1;
		res = sscanf(line + cur, "%lf %s %lf%n", &v1, ld->hostname, &v2,  &inc);
		if(3 == res) {
			ld->tv.tv_sec = (int) floor(v1);
			ld->tv.tv_usec = floor( (v1 - floor(v1)) * 1e6 );
			
			if(warn_format)
				sm_info("Reading timestamp as doubles (discarding second one).\n");
			
		} else {
			ld->tv.tv_sec = 0;
			ld->tv.tv_usec = 0;
			if(warn_format)
				sm_info("I could not read timestamp+hostname; ignoring (I will warn only once for this).\n");
		}
	}

	warn_format = 0;

	fprintf(stderr, "l");
	return ld;
	
	error:
		printf("Malformed line: '%s'\nat cur = %d\n\t-> '%s'\n", line,(int)cur,line+cur);
		return 0;
}
Example #21
0
int main(int argc, const char * argv[]) {
	sm_set_program_name(argv[0]);
	
	csm_options_banner("ld_noise: Adds noise to readings in a scan");
	
	struct ld_noise_params p;
	
	struct csm_option* ops = csm_options_allocate(20);
	csm_options_double(ops, "discretization", &p.discretization, 0.0, 
		"Size of discretization (disabled if 0)");
	csm_options_double(ops, "sigma", &p.sigma, 0.0, 
		"Std deviation of gaussian noise (disabled if 0)");
	csm_options_int(ops, "lambertian", &p.lambertian, 0, 
		"Use lambertian model cov = sigma^2 / cos(beta^2) where beta is the incidence. Need have alpha or true_alpha.");
	csm_options_int(ops, "seed", &p.seed, 0, 
		"Seed for random number generator (if 0, use GSL_RNG_SEED env. variable).");
	csm_options_string(ops, "in", &p.file_input, "stdin", "Input file ");
	csm_options_string(ops, "out", &p.file_output, "stdout", "Output file ");
		
		
	if(!csm_options_parse_args(ops, argc, argv)) {
		fprintf(stderr, "A simple program for adding noise to sensor scans.\n\nUsage:\n");
		csm_options_print_help(ops, stderr);
		return -1;
	}

	FILE * in = open_file_for_reading(p.file_input);
	if(!in) return -3;

	FILE * out = open_file_for_writing(p.file_output);
	if(!out) return -2;


	gsl_rng_env_setup();
	gsl_rng * rng = gsl_rng_alloc (gsl_rng_ranlxs0);
	if(p.seed != 0)
	gsl_rng_set(rng, (unsigned int) p.seed);

	LDP ld; int count = 0;
	while( (ld = ld_from_json_stream(in))) {
		if(!ld_valid_fields(ld))  {
			sm_error("Invalid laser data (#%d in file)\n", count);
			continue;
		}
		
		int i;
		for(i=0;i<ld->nrays;i++) {
			if(!ld->valid[i]) continue;
			
			double * reading = ld->readings + i;
			if(p.sigma > 0) {
				double add_sigma = p.sigma;
				
				if(p.lambertian) {

					int have_alpha = 0;
					double alpha = 0;
					if(!is_nan(ld->true_alpha[i])) {
						alpha = ld->true_alpha[i];
						have_alpha = 1;
					} else if(ld->alpha_valid[i]) {
						alpha = ld->alpha[i];;
						have_alpha = 1;
					} else have_alpha = 0;

					if(have_alpha) {
						/* Recall that alpha points outside the surface */
						double beta = (alpha+M_PI) - ld->theta[i];
					    add_sigma = p.sigma / cos(beta);
					} else {
						sm_error("Because lambertian is active, I need either true_alpha[] or alpha[]");
						ld_write_as_json(ld, stderr);
						return -1;
					}
					
				} 
				
			   *reading += gsl_ran_gaussian(rng, add_sigma);
				
				if(is_nan(ld->readings_sigma[i])) {
					ld->readings_sigma[i] = add_sigma;
				} else {
					ld->readings_sigma[i] = sqrt(square(add_sigma) + square(ld->readings_sigma[i]));
				}
			}
			if(p.discretization > 0)
				*reading -= fmod(*reading , p.discretization);
		}
	
		ld_write_as_json(ld, out);
		ld_free(ld);
	}
	
	return 0;
}
Example #22
0
// computes the minimal bounding box for a set of 2d-points
// ul = upper left  point, ll = lower left point, 
// ur = upper right point, ul = upper left point
int getBoundingBox(BB_Point* p, int nOfPoints, 
	double ul[2], double ur[2], double ll[2], double lr[2]) {

  // calculate the center of all points (schwerpunkt)
  // -------------------------------------------------
  double centerx = 0;
  double centery = 0;
  for (int i=0; i < nOfPoints; i++) {
	 centerx += p[i].x;
	 centery += p[i].y;
  }	 
  centerx /= (double) nOfPoints;
  centery /= (double) nOfPoints;


  
  // calcutae the covariance matrix
  // -------------------------------
  // covariance matrix (x1 x2, x3 x4) 
  double x1 = 0.0;
  double x2 = 0.0;
  double x3 = 0.0;
  double x4 = 0.0;

  for (int i=0; i < nOfPoints; i++) {
	 double cix = p[i].x - centerx;
	 double ciy = p[i].y - centery;
	 
	 x1 += cix*cix;
	 x2 += cix*ciy;  
	 x4 += ciy*ciy;
  }
  x1 /= (double) nOfPoints;
  x2 /= (double) nOfPoints;
  x3 = x2;
  x4 /= (double) nOfPoints;
  // covariance & center  done


  // calculate the eigenvectors
  // ---------------------------
  // catch 1/0 or sqrt(<0)
  if ((x3 == 0) || (x2 == 0)|| (x4*x4-2*x1*x4+x1*x1+4*x2*x3 < 0 ))  {
	sm_error("Cyrill: Could not compute bounding box.\n");
	return 0;
}

 // eigenvalues
  double lamda1 = 0.5* (x4 + x1 + sqrt(x4*x4 - 2.0*x1*x4 + x1*x1 + 4.0*x2*x3));
  double lamda2 = 0.5* (x4 + x1 - sqrt(x4*x4 - 2.0*x1*x4 + x1*x1 + 4.0*x2*x3));
  
  // eigenvector 1  with  (x,y)
  double v1x = - (x4-lamda1) * (x4-lamda1) * (x1-lamda1) / (x2 * x3 * x3);
  double v1y = (x4-lamda1) * (x1-lamda1) / (x2 * x3);
  // eigenvector 2 with	 (x,y)
  double v2x = - (x4-lamda2) * (x4-lamda2) * (x1-lamda2) / (x2 * x3 * x3);
  double v2y = (x4-lamda2) * (x1-lamda2) / (x2 * x3);

  // norm the eigenvectors
  double lv1 = sqrt ( (v1x*v1x) + (v1y*v1y) );
  double lv2 = sqrt ( (v2x*v2x) + (v2y*v2y) );
  v1x /= lv1;
  v1y /= lv1;
  v2x /= lv2;
  v2y /= lv2;
  // eigenvectors done

  // get the points with maximal dot-product 
  double x = 0.0;
  double y = 0.0;
  double xmin = 1e20;
  double xmax = -1e20;
  double ymin = 1e20;
  double ymax = -1e20;
  for(int i = 0; i< nOfPoints; i++) {
	 // dot-product of relativ coordinates of every point
	 x = (p[i].x - centerx) * v1x +	(p[i].y - centery) * v1y;
	 y = (p[i].x - centerx) * v2x +	(p[i].y - centery) * v2y;

	 if( x > xmax) xmax = x;
	 if( x < xmin) xmin = x;
	 if( y > ymax) ymax = y;
	 if( y < ymin) ymin = y;
  }

  // now we can compute the corners of the bounding box
	if(ul) {
		ul[0] = centerx + xmin * v1x + ymin * v2x;
		ul[1] = centery + xmin * v1y + ymin * v2y;
	}

	if(ur) {
		ur[0] = centerx + xmax * v1x + ymin * v2x;
		ur[1] = centery + xmax * v1y + ymin * v2y;
	}
	
	if(ll) {
		ll[0] = centerx + xmin * v1x + ymax * v2x;
		ll[1] = centery + xmin * v1y + ymax * v2y;
	}
	
	if(lr) {
		lr[0] = centerx + xmax * v1x + ymax * v2x;
		lr[1] = centery + xmax * v1y + ymax * v2y;
	}
	return 1;
}
Example #23
0
void sm_icp(struct sm_params*params, struct sm_result*res) {
	res->valid = 0;

	LDP laser_ref  = params->laser_ref;
	LDP laser_sens = params->laser_sens;
	
	if(!ld_valid_fields(laser_ref) || 
	   !ld_valid_fields(laser_sens)) {
		return;
	}
	
	sm_debug("sm_icp: laser_sens has %d/%d; laser_ref has %d/%d rays valid\n",
		count_equal(laser_sens->valid, laser_sens->nrays, 1), laser_sens->nrays,
		count_equal(laser_ref->valid, laser_ref->nrays, 1), laser_ref->nrays);
	
	
	/** Mark as invalid the rays outside of (min_reading, max_reading] */
	ld_invalid_if_outside(laser_ref, params->min_reading, params->max_reading);
	ld_invalid_if_outside(laser_sens, params->min_reading, params->max_reading);
	
	sm_debug("sm_icp:  laser_sens has %d/%d; laser_ref has %d/%d rays valid (after removing outside interval [%f, %f])\n",
		count_equal(laser_sens->valid, laser_sens->nrays, 1), laser_sens->nrays,
		count_equal(laser_ref->valid, laser_ref->nrays, 1), laser_ref->nrays,
   	   params->min_reading, params->max_reading);
	
	if(JJ) jj_context_enter("sm_icp");
	
	egsl_push_named("sm_icp");
	
			
	if(params->use_corr_tricks || params->debug_verify_tricks)
		ld_create_jump_tables(laser_ref);
		
	ld_compute_cartesian(laser_ref);
	ld_compute_cartesian(laser_sens);

	if(params->do_alpha_test) {
		ld_simple_clustering(laser_ref, params->clustering_threshold);
		ld_compute_orientation(laser_ref, params->orientation_neighbourhood, params->sigma);
		ld_simple_clustering(laser_sens, params->clustering_threshold);
		ld_compute_orientation(laser_sens, params->orientation_neighbourhood, params->sigma);
	}

	if(JJ) jj_add("laser_ref",  ld_to_json(laser_ref));
	if(JJ) jj_add("laser_sens", ld_to_json(laser_sens));
	
	gsl_vector * x_new = gsl_vector_alloc(3);
	gsl_vector * x_old = vector_from_array(3, params->first_guess);
	
	if(params->do_visibility_test) {
		sm_debug("laser_ref:\n");
		visibilityTest(laser_ref, x_old);

		sm_debug("laser_sens:\n");
		gsl_vector * minus_x_old = gsl_vector_alloc(3);
		ominus(x_old,minus_x_old);
		visibilityTest(laser_sens, minus_x_old);
		gsl_vector_free(minus_x_old);
	}
	
	double error;
	int iterations;
	int nvalid;
	if(!icp_loop(params, x_old->data, x_new->data, &error, &nvalid, &iterations)) {
		sm_error("icp: ICP failed for some reason. \n");
		res->valid = 0;
		res->iterations = iterations;
		res->nvalid = 0;
		
	} else {
		/* It was succesfull */

		int restarted = 0;		
		double best_error = error;
		gsl_vector * best_x = gsl_vector_alloc(3);
		gsl_vector_memcpy(best_x, x_new);

		if(params->restart && 
			(error/nvalid)>(params->restart_threshold_mean_error) ) {
			sm_debug("Restarting: %f > %f \n",(error/nvalid),(params->restart_threshold_mean_error));
			restarted = 1;
			double dt  = params->restart_dt;
			double dth = params->restart_dtheta;
			sm_debug("icp_loop: dt = %f dtheta= %f deg\n",dt,rad2deg(dth));
		
			double perturb[6][3] = {
				{dt,0,0}, {-dt,0,0},
				{0,dt,0}, {0,-dt,0},
				{0,0,dth}, {0,0,-dth}
			};

			int a; for(a=0;a<6;a++){
				sm_debug("-- Restarting with perturbation #%d\n", a);
				struct sm_params my_params = *params;
				gsl_vector * start = gsl_vector_alloc(3);
					gvs(start, 0, gvg(x_new,0)+perturb[a][0]);
					gvs(start, 1, gvg(x_new,1)+perturb[a][1]);
					gvs(start, 2, gvg(x_new,2)+perturb[a][2]);
				gsl_vector * x_a = gsl_vector_alloc(3);
				double my_error; int my_valid; int my_iterations;
				if(!icp_loop(&my_params, start->data, x_a->data, &my_error, &my_valid, &my_iterations)){
					sm_error("Error during restart #%d/%d. \n", a, 6);
					break;
				}
				iterations+=my_iterations;
		
				if(my_error < best_error) {
					sm_debug("--Perturbation #%d resulted in error %f < %f\n", a,my_error,best_error);
					gsl_vector_memcpy(best_x, x_a);
					best_error = my_error;
				}
				gsl_vector_free(x_a); gsl_vector_free(start);
			}
		}
	
	
		/* At last, we did it. */
		res->valid = 1;
		vector_to_array(best_x, res->x);
		sm_debug("icp: final x =  %s  \n", gsl_friendly_pose(best_x));
	
		if (restarted) { // recompute correspondences in case of restarts
			ld_compute_world_coords(laser_sens, res->x);
			if(params->use_corr_tricks)
				find_correspondences_tricks(params);
			else
				find_correspondences(params);
		}

		if(params->do_compute_covariance)  {

			val cov0_x, dx_dy1, dx_dy2;
			compute_covariance_exact(
				laser_ref, laser_sens, best_x,
				&cov0_x, &dx_dy1, &dx_dy2);
		
			val cov_x = sc(square(params->sigma), cov0_x); 
/*			egsl_v2da(cov_x, res->cov_x); */
		
			res->cov_x_m = egsl_v2gslm(cov_x);
			res->dx_dy1_m = egsl_v2gslm(dx_dy1);
			res->dx_dy2_m = egsl_v2gslm(dx_dy2);
		
			if(0) {
				egsl_print("cov0_x", cov0_x);
				egsl_print_spectrum("cov0_x", cov0_x);
		
				val fim = ld_fisher0(laser_ref);
				val ifim = inv(fim);
				egsl_print("fim", fim);
				egsl_print_spectrum("ifim", ifim);
			}
		}
	
		res->error = best_error;
		res->iterations = iterations;
		res->nvalid = nvalid;

		gsl_vector_free(best_x);
	}
	gsl_vector_free(x_new);
	gsl_vector_free(x_old);


	egsl_pop_named("sm_icp");

	if(JJ) jj_context_exit();
}
Example #24
0
int main(int argc, const char*argv[]) {
	sm_set_program_name(argv[0]);
	
	struct sm_params params;
	struct sm_result result;
	
	struct option* ops = options_allocate(100);
	options_string(ops, "in", &p.file_in, "stdin", "Input file ");
	options_string(ops, "out", &p.file_out, "stdout", "Output file ");
	options_string(ops, "out_stats", &p.file_out_stats, "", "Output file (stats) ");
	options_string(ops, "file_jj", &p.file_jj, "",
		"File for journaling -- if left empty, journal not open.");
	options_int(ops, "algo", &p.algo, 0, "Which algorithm to use (0:(pl)ICP 1:gpm-stripped 2:HSM) ");
	
	options_int(ops, "debug", &p.debug, 0, "Shows debug information");
	options_int(ops, "recover_from_error", &p.recover_from_error, 0, "If true, tries to recover from an ICP matching error");
	
	
	p.format = 0;
/*	options_int(ops, "format", &p.format, 0,
		"Output format (0: log in JSON format, 1: log in Carmen format (not implemented))");*/
	
	sm_options(&params, ops);
	if(!options_parse_args(ops, argc, argv)) {
		fprintf(stderr, "\n\nUsage:\n");
		options_print_help(ops, stderr);
		return -1;
	}

	sm_debug_write(p.debug);

	/* Open input and output files */
	
	FILE * file_in = open_file_for_reading(p.file_in);
	if(!file_in) return -1;
	FILE * file_out = open_file_for_writing(p.file_out);
	if(!file_out) return -1;
	
	if(strcmp(p.file_jj, "")) {
		FILE * jj = open_file_for_writing(p.file_jj);
		if(!jj) return -1;
		jj_set_stream(jj);
	}
	
	FILE * file_out_stats = 0;
	if(strcmp(p.file_out_stats, "")) {
		file_out_stats = open_file_for_writing(p.file_out_stats);
		if(!file_out_stats) return -1;
	}
	
	/* Read first scan */
	LDP laser_ref;
	if(!(laser_ref = ld_read_smart(file_in))) {
		sm_error("Could not read first scan.\n");
		return -1;
	}
	if(!ld_valid_fields(laser_ref))  {
		sm_error("Invalid laser data in first scan.\n");
		return -2;
	}
	
	
	/* For the first scan, set estimate = odometry */
	copy_d(laser_ref->odometry, 3, laser_ref->estimate);
	
	spit(laser_ref, file_out);
	int count=-1;
	LDP laser_sens;
	while( (laser_sens = ld_read_smart(file_in)) ) {
		
		count++;
		if(!ld_valid_fields(laser_sens))  {
			sm_error("Invalid laser data in (#%d in file).\n", count);
			return -(count+2);
		}
		
		params.laser_ref  = laser_ref;
		params.laser_sens = laser_sens;

		/* Set first guess as the difference in odometry */
		
		if(	any_nan(params.laser_ref->odometry,3) ||  
			any_nan(params.laser_sens->odometry,3) ) {
				sm_error("The 'odometry' field is set to NaN so I don't know how to get an initial guess. I usually use the difference in the odometry fields to obtain the initial guess.\n");
				sm_error("  laser_ref->odometry = %s \n",  friendly_pose(params.laser_ref->odometry) );
				sm_error("  laser_sens->odometry = %s \n", friendly_pose(params.laser_sens->odometry) );
				sm_error(" I will quit it here. \n");
				return -3;
		}
		
		double odometry[3];
		pose_diff_d(laser_sens->odometry, laser_ref->odometry, odometry);
		double ominus_laser[3], temp[3];
		ominus_d(params.laser, ominus_laser);
		oplus_d(ominus_laser, odometry, temp);
		oplus_d(temp, params.laser, params.first_guess);
		
		/* Do the actual work */
		switch(p.algo) {
			case(0):
				sm_icp(&params, &result); break;
			case(1):
				sm_gpm(&params, &result); break;
			case(2):
				sm_hsm(&params, &result); break;
			default:
				sm_error("Unknown algorithm to run: %d.\n",p.algo);
				return -1;
		}
		
		if(!result.valid){
			if(p.recover_from_error) {
				sm_info("One ICP matching failed. Because you passed  -recover_from_error, I will try to recover."
				" Note, however, that this might not be good in some cases. \n");
				sm_info("The recover is that the displacement is set to 0. No result stats is output. \n");
				
				/* For the first scan, set estimate = odometry */
				copy_d(laser_ref->estimate, 3, laser_sens->estimate);
				
				ld_free(laser_ref); laser_ref = laser_sens;
				
			} else {
				sm_error("One ICP matching failed. Because I process recursively, I will stop here.\n");
				sm_error("Use the option -recover_from_error if you want to try to recover.\n");
				ld_free(laser_ref);
				return 2;
			}
		} else {
		
			/* Add the result to the previous estimate */
			oplus_d(laser_ref->estimate, result.x, laser_sens->estimate);

			/* Write the corrected log */
			spit(laser_sens, file_out);

			/* Write the statistics (if required) */
			if(file_out_stats) {
				JO jo = result_to_json(&params, &result);
				fputs(jo_to_string(jo), file_out_stats);
				fputs("\n", file_out_stats);
				jo_free(jo);
			}

			ld_free(laser_ref); laser_ref = laser_sens;
		}
	}
	ld_free(laser_ref);
	
	return 0;
}
Example #25
0
int main(int argc, const char * argv[]) {
	sm_set_program_name(argv[0]);

	const char *in_filename;
	const char *ref_filename;
	const char *out_filename;
	const char *ref_field_string; ld_reference ref_field;
	const char *out_field_string; ld_reference out_field;

	struct option* ops = options_allocate(15);
	options_string(ops, "in", &in_filename, "stdin", "scan matching log");
	options_string(ops, "ref", &ref_filename, "ref.log", "slam log");
	options_string(ops, "out", &out_filename, "stdout", "output file");

	options_string(ops, "ref_field", &ref_field_string, "estimate", "What field to find in ref.");
	options_string(ops, "out_field", &out_field_string, "true_pose", "What field to copy to.");
		
	if(!options_parse_args(ops, argc, argv)) {
		fprintf(stderr, " This program works on two logs: A and B. "
		"For each scan in A, the program searches for the scan in B having the same timestamp. "
		"Then, the true_pose field in B is copied to the scan form A, and it is written to the output.\n");
		options_print_help(ops, stderr);
		return -1;
	}
	
	ref_field = ld_string_to_reference(ref_field_string);
	out_field = ld_string_to_reference(out_field_string);
	
	
	FILE * in_stream  = open_file_for_reading(in_filename);
	FILE * ref_stream = open_file_for_reading(ref_filename);
	FILE * out_stream = open_file_for_writing(out_filename);
	
	if(!in_stream || !ref_stream || !out_stream) return -1;

	LDP ld_in;
	while((ld_in = ld_read_smart(in_stream))) {
		int matched = 0;
		while(1) {
			LDP ld_ref = ld_read_smart(ref_stream);
			if(!ld_ref) break;
			if(same_scan(ld_in, ld_ref)) {
				matched = 1;
				const double *ref_pose = ld_get_reference_pose(ld_ref, ref_field);
				double *out_pose = ld_get_reference_pose_silent(ld_in, out_field);
				copy_d(ref_pose, 3, out_pose);
				ld_write_as_json(ld_in, out_stream);
				fputs("\n", out_stream);
				break;
			}
			ld_free(ld_ref);
		}

		if(!matched) {
			sm_error("Could not match %s. \n", short_desc(ld_in));
			if(feof(ref_stream)) {
				sm_error("..because ref stream has ended.\n");
				break;
			}
			continue;
		}
	
		ld_free(ld_in);
	}
	
	return 0;
}
Example #26
0
File: hsm.c Project: abachrach/csm
void hsm_match(struct hsm_params*p, hsm_buffer b1, hsm_buffer b2) {
	sm_log_push("hsm_match");
	/* Let's measure the time */
	clock_t hsm_match_start = clock();
	
	assert(b1->num_angular_cells == b2->num_angular_cells);
	assert(p->max_translation > 0);
	assert(b1->linear_cell_size > 0);

	b1->num_valid_results = 0;

	/* Compute cross-correlation of spectra */
	hsm_circular_cross_corr_stupid(b1->num_angular_cells, b2->hs, b1->hs, b1->hs_cross_corr);

	/* Find peaks in cross-correlation */
	int peaks[p->num_angular_hypotheses], npeaks;
	hsm_find_peaks_circ(b1->num_angular_cells, b1->hs_cross_corr, p->angular_hyp_min_distance_deg, 0, p->num_angular_hypotheses, peaks, &npeaks);

	sm_debug("Found %d peaks (max %d) in cross correlation.\n", npeaks, p->num_angular_hypotheses);

	if(npeaks == 0) {
		sm_error("Cross correlation of spectra has 0 peaks.\n");
		sm_log_pop();
		return;
	}

	sm_log_push("loop on theta hypotheses");
	/* lag e' quanto 2 si sposta a destra rispetto a 1 */
	for(int np=0;np<npeaks;np++) {
		int lag = peaks[np];
		double theta_hypothesis = lag * (2*M_PI/b1->num_angular_cells);

		sm_debug("Theta hyp#%d: lag %d, angle %fdeg\n", np, lag, rad2deg(theta_hypothesis));

		/* Superimpose the two spectra */
		double mult[b1->num_angular_cells];
		for(int r=0;r<b1->num_angular_cells;r++)
			mult[r] = b1->hs[r] * b2->hs[pos_mod(r-lag, b1->num_angular_cells)];

		/* Find directions where both are intense */
		int directions[p->xc_ndirections], ndirections;
		hsm_find_peaks_circ(b1->num_angular_cells, b1->hs_cross_corr, p->xc_directions_min_distance_deg, 1, p->xc_ndirections, directions, &ndirections);

		if(ndirections<2) {
			sm_error("Too few directions.\n");
		}
		
		struct {
			/* Direction of cross correlation */
			double angle;
			int nhypotheses;
			struct {
				double delta;
				double value;
			} hypotheses[p->linear_xc_max_npeaks];
		} dirs[ndirections];


		sm_debug("Using %d (max %d) correlations directions.\n", ndirections, p->xc_ndirections);

		int max_lag = (int) ceil(p->max_translation / b1->linear_cell_size);
		int min_lag = -max_lag;
		sm_debug("Max lag: %d cells (max t: %f, cell size: %f)\n",
			max_lag, p->max_translation, b1->linear_cell_size);

		sm_log_push("loop on xc direction");
		/* For each correlation direction */
		for(int cd=0;cd<ndirections;cd++) {

 			dirs[cd].angle =  theta_hypothesis + (directions[cd]) * (2*M_PI/b1->num_angular_cells);

			printf(" cd %d angle = %d deg\n", cd, (int) rad2deg(dirs[cd].angle));

			/* Do correlation */
			int    lags  [2*max_lag + 1];
			double xcorr [2*max_lag + 1];

			int i1 = pos_mod(directions[cd]        , b1->num_angular_cells);
			int i2 = pos_mod(directions[cd] + lag  , b1->num_angular_cells);
			double *f1 = b1->ht[i1];
			double *f2 = b2->ht[i2];

			hsm_linear_cross_corr_stupid(
				b2->num_linear_cells,f2,
				b1->num_linear_cells,f1,
				xcorr, lags, min_lag, max_lag);

			/* Find peaks of cross-correlation */
			int linear_peaks[p->linear_xc_max_npeaks], linear_npeaks;

			hsm_find_peaks_linear(
				2*max_lag + 1, xcorr, p->linear_xc_peaks_min_distance/b1->linear_cell_size,
				p->linear_xc_max_npeaks, linear_peaks, &linear_npeaks);

			sm_debug("theta hyp #%d: Found %d (max %d) peaks for correlation.\n",
				cd, linear_npeaks, p->linear_xc_max_npeaks);

			dirs[cd].nhypotheses = linear_npeaks;
			sm_log_push("Considering each peak of linear xc");
			for(int lp=0;lp<linear_npeaks;lp++) {
				int linear_xc_lag = lags[linear_peaks[lp]];
				double value = xcorr[linear_peaks[lp]];
				double linear_xc_lag_m = linear_xc_lag * b1->linear_cell_size;
				sm_debug("lag: %d  delta: %f  value: %f \n", linear_xc_lag, linear_xc_lag_m, value);
				dirs[cd].hypotheses[lp].delta = linear_xc_lag_m;
				dirs[cd].hypotheses[lp].value = value;
			}
			sm_log_pop();
			
			if(p->debug_true_x_valid) {
				double true_delta = cos(dirs[cd].angle) * p->debug_true_x[0] + 
					sin(dirs[cd].angle) * p->debug_true_x[1];
				sm_debug("true_x    delta = %f \n", true_delta );
			}

		} /* xc direction */
		sm_log_pop();

		sm_debug("Now doing all combinations. How many are there?\n");
		int possible_choices[ndirections];
		int num_combinations = 1;
		for(int cd=0;cd<ndirections;cd++) {
			possible_choices[cd] = dirs[cd].nhypotheses;
			num_combinations *= dirs[cd].nhypotheses;
		}
		sm_debug("Total: %d combinations\n", num_combinations);
		sm_log_push("For each combination..");
		for(int comb=0;comb<num_combinations;comb++) {
			int choices[ndirections];
			hsm_generate_combinations(ndirections, possible_choices, comb, choices);

			/* Linear least squares */
			double M[2][2]={{0,0},{0,0}}; double Z[2]={0,0};
			/* heuristic quality value */
			double sum_values = 0;
			for(int cd=0;cd<ndirections;cd++) {
				double angle = dirs[cd].angle;
				double c = cos(angle), s = sin(angle);
				double w = dirs[cd].hypotheses[choices[cd]].value;
				double y = dirs[cd].hypotheses[choices[cd]].delta;

				M[0][0] += c * c * w;
				M[1][0] += c * s * w;
				M[0][1] += c * s * w;
				M[1][1] += s * s * w;
				Z[0] += w * c * y;
				Z[1] += w * s * y;

				sum_values += w;
			}

			double det = M[0][0]*M[1][1]-M[0][1]*M[1][0];
			double Minv[2][2];
			Minv[0][0] = M[1][1] * (1/det);
			Minv[1][1] = M[0][0] * (1/det);
			Minv[0][1] = -M[0][1] * (1/det);
			Minv[1][0] = -M[1][0] * (1/det);

			double t[2] = {
				Minv[0][0]*Z[0] + Minv[0][1]*Z[1],
				Minv[1][0]*Z[0] + Minv[1][1]*Z[1]};

			/* copy result in results slot */

			int k = b1->num_valid_results;
			b1->results[k][0] = t[0];
			b1->results[k][1] = t[1];
			b1->results[k][2] = theta_hypothesis;
			b1->results_quality[k] = sum_values;
			b1->num_valid_results++;
		}
		sm_log_pop();

	} /* theta hypothesis */
	sm_log_pop();

/*	for(int i=0;i<b1->num_valid_results;i++) {
		printf("#%d %.0fdeg %.1fm %.1fm  quality %f \n",i,
			rad2deg(b1->results[i][2]),
			b1->results[i][0],
			b1->results[i][1],
			b1->results_quality[i]);
	}*/


	/* Sorting based on values */
	int indexes[b1->num_valid_results];
	for(int i=0;i<b1->num_valid_results;i++)
		indexes[i] = i;

	qsort_descending(indexes, (size_t) b1->num_valid_results, b1->results_quality);

	/* copy in the correct order*/
	double*results_tmp[b1->num_valid_results];
	double results_quality_tmp[b1->num_valid_results];
	for(int i=0;i<b1->num_valid_results;i++) {
		results_tmp[i] = b1->results[i];
		results_quality_tmp[i] = b1->results_quality[i];
	}

	for(int i=0;i<b1->num_valid_results;i++) {
		b1->results[i] = results_tmp[indexes[i]];
		b1->results_quality[i] = results_quality_tmp[indexes[i]];
	}

	for(int i=0;i<b1->num_valid_results;i++) {
		char near[256]="";
		double *x = b1->results[i];
		if(p->debug_true_x_valid) {
			double err_th = rad2deg(fabs(angleDiff(p->debug_true_x[2],x[2])));
			double err_m = hypot(p->debug_true_x[0]-x[0],
				p->debug_true_x[1]-x[1]);
			const char * ast = (i == 0) && (err_th > 2) ? "   ***** " : "";
			sprintf(near, "th err %4d  err_m  %5f %s",(int)err_th ,err_m,ast);
		}
		if(i<10)
		printf("after #%d %3.1fm %.1fm %3.0fdeg quality %5.0f \t%s\n",i,
			x[0],
			x[1], rad2deg(x[2]), b1->results_quality[i], near);
	}
	
	
	/* How long did it take? */
	clock_t hsm_match_stop = clock();
	int ticks = hsm_match_stop-hsm_match_start;
	double ctime = ((double)ticks) / CLOCKS_PER_SEC;
	sm_debug("Time: %f sec (%d ticks)\n", ctime, ticks);
	
	sm_log_pop();
}