function res = merge_logs(raw_sm, raw_odo) % first of all, we try to select the "best" matchings errors = join(collect(raw_sm, 'error')); nvalid = join(collect(raw_sm, 'nvalid')); mean_error = errors ./ nvalid; errors_sorted = sort(mean_error); perc = 0.95; mean_error_threshold = errors_sorted( round(size(errors,2) * perc) ); nvalid_sorted = sort(nvalid); nvalid_threshold = nvalid_sorted( round(size(nvalid,2) * (1-perc)) ); prefix='merge_logs:'; fprintf('%s nvalid_threshold: %d\n', prefix, nvalid_threshold); fprintf('%s mean_error_threshold: %f\n', prefix, mean_error_threshold); discarded_nvalid = 0; discarded_t_k = 0; discarded_time_tol = 0; discarded_left_speed = 0; discarded_no_odo = 0; discarded_no_small=0; res.still_num = 0; % for each entry in raw_sm we seek % the two indices which are immediately before and % after in raw_odo n_sm = size(raw_sm, 2); fprintf('%s Merging laser and odometry..\n', prefix); m = 1; last = 1; for k=1:n_sm if raw_sm{k}.valid == 0 continue end t_delta = 0; % can we compensate for delay? laser_ref_ts = t_delta + tv2sec(raw_sm{k}.laser_ref_timestamp); laser_sens_ts = t_delta + tv2sec(raw_sm{k}.laser_sens_timestamp); jb_ref = find_closest(laser_ref_ts, raw_odo, last); jb_sens = find_closest(laser_sens_ts, raw_odo, last); if (jb_ref == 0) || (jb_sens == 0) discarded_no_odo = discarded_no_odo + 1; fprintf('merge_logs: Could not match timestamp %f %f\n', laser_ref_ts, laser_sens_ts); pause(0.05); continue; end last = jb_ref; time_tol = max([... abs(tv2sec(raw_odo{jb_ref}.timestamp) - laser_ref_ts),... abs(tv2sec(raw_odo{jb_ref+1}.timestamp) - laser_ref_ts),... abs(tv2sec(raw_odo{jb_sens}.timestamp) - laser_sens_ts),... abs(tv2sec(raw_odo{jb_sens+1}.timestamp) - laser_sens_ts)]); ref_alpha = (laser_ref_ts - tv2sec(raw_odo{jb_ref}.timestamp)) / ... (tv2sec(raw_odo{jb_ref+1}.timestamp) - tv2sec(raw_odo{jb_ref}.timestamp)); sens_alpha = (laser_sens_ts - tv2sec(raw_odo{jb_sens}.timestamp)) / ... (tv2sec(raw_odo{jb_sens+1}.timestamp) - tv2sec(raw_odo{jb_sens}.timestamp)); % avg_left_start = mean([ raw_odo{jb_ref }.left raw_odo{jb_ref +1}.left]); % avg_right_start = mean([ raw_odo{jb_ref }.right raw_odo{jb_ref +1}.right]); % avg_left_end = mean([ raw_odo{jb_sens}.left raw_odo{jb_sens+1}.left]); % avg_right_end = mean([ raw_odo{jb_sens}.right raw_odo{jb_sens+1}.right]); avg_left_start = ref_alpha * raw_odo{jb_ref }.left + (1-ref_alpha) * raw_odo{jb_ref +1}.left; avg_right_start = ref_alpha * raw_odo{jb_ref }.right + (1-ref_alpha) * raw_odo{jb_ref +1}.right; avg_left_end = sens_alpha * raw_odo{jb_sens }.left + (1-sens_alpha) * raw_odo{jb_sens +1}.left; avg_right_end = sens_alpha * raw_odo{jb_sens }.right + (1-sens_alpha) * raw_odo{jb_sens+1}.right; left_inc = avg_left_end - avg_left_start; right_inc = avg_right_end - avg_right_start; if (left_inc == 0) && (right_inc == 0) res.still_num = res.still_num + 1; res.still(:,res.still_num ) = raw_sm{k}.x; continue; end if raw_sm{k}.error == 0 continue end if raw_sm{k}.error / raw_sm{k}.nvalid > mean_error_threshold continue end if raw_sm{k}.nvalid < nvalid_threshold discarded_nvalid = discarded_nvalid + 1; continue end if time_tol > 0.05 discarded_time_tol = discarded_time_tol + 1; continue; end t_k = laser_sens_ts - laser_ref_ts; if( t_k > 3) discarded_t_k = discarded_t_k + 1; continue end ticks_to_rad = 2 * pi / ( 691.2 * 4 ); left_speed = (left_inc * ticks_to_rad) / t_k; right_speed = (right_inc * ticks_to_rad) / t_k; res.data(:, m) = [t_k;raw_sm{k}.x;left_speed;right_speed;... left_inc; right_inc]; res.T(m) = t_k; res.phi_l(m) = left_speed; res.phi_r(m) = right_speed; sm = raw_sm{k}.x; % l1 = [1; 1; 0]; % sm = oplus( oplus( ominus(l1) , sm ), l1); res.sm(:,m) = sm; res.time_tol(m) = time_tol; res.error(m) = raw_sm{k}.error; res.mean_error(m) = raw_sm{k}.error / raw_sm{k}.nvalid; res.nvalid(m) = raw_sm{k}.nvalid; res.sens_alpha(m) = sens_alpha; res.ref_alpha(m) = ref_alpha; m = m+1; end fprintf('%s Number of valid data: %d\n', prefix, m); fprintf('%s discarded nvalid: %d\n', prefix, discarded_nvalid); fprintf('%s discarded_t_k: %d\n', prefix, discarded_t_k); fprintf('%s discarded_time_tol: %d\n', prefix, discarded_time_tol); % fprintf('%s discarded_left_speed: %d\n', prefix, discarded_left_speed); fprintf('%s discarded_no_odo: %d\n', prefix, discarded_no_odo); % fprintf('%s discarded_no_small: %d\n', prefix, discarded_no_small); if true figure subplot(4,1,1) plot(res.nvalid) title('SM: number of valid rays') subplot(4,1,2) plot(res.error) title('SM: total error') subplot(4,1,3) plot(res.mean_error) title('SM: mean error') subplot(4,1,4) plot(res.time_tol) title('time tolerance between SM and odometry') end function just_before = find_closest(ts, raw_odo, start_at) % returns the indexes of the closest before % returns 0 if not found for i=start_at:(size(raw_odo,2)-1) ts_i = tv2sec(raw_odo{i}.timestamp); ts_ip = tv2sec(raw_odo{i+1}.timestamp); if (ts_i < ts) && ( ts_ip > ts) just_before = i; return; end if (ts_i > ts) fprintf('Sorry, could not find match for ts = %f\n', ts); just_before = 0; return; end end just_before = 0; return;