def align_traj(self): """yaw only and position alignment at initial time""" self.gt['rpys'] = SO3.to_rpy(self.gt['Rots'].cuda()).cpu() self.iekf['rpys'] = SO3.to_rpy(self.iekf['Rots'].cuda()).cpu() self.gt['ps'] -= self.gt['ps'][0].clone() self.iekf['ps'] -= self.iekf['ps'][0].clone() rpys = self.gt['rpys'][:2] - self.iekf['rpys'][:2] Rot = SO3.from_rpy(rpys[:, 0], rpys[:, 1], rpys[:, 2]) Rot = Rot[0].repeat(self.iekf['ps'].shape[0], 1, 1) self.iekf['Rots'] = Rot.bmm(self.iekf['Rots']) self.iekf['vs'] = bmv(Rot, self.iekf['vs']) self.iekf['ps'] = bmv(Rot, self.iekf['ps']) self.iekf['rpys'] = SO3.to_rpy(self.iekf['Rots'].cuda()).cpu()
def read_data(self, data_dir): r"""Read the data from the dataset""" # threshold for ZUPT ground truth sm_velocity_max_threshold = 0.004 # m/s f = os.path.join(self.predata_dir, 'urban06.p') if True and os.path.exists(f): return print("Start read_data, be patient please") def set_path(seq): path_imu = os.path.join(data_dir, seq, "sensor_data", "xsens_imu.csv") path_gt = os.path.join(data_dir, seq, "global_pose.csv") # path_odo = os.path.join(data_dir, seq, "encoder.csv") return path_imu, path_gt time_factor = 1e9 # ns -> s def interpolate(x, t, t_int, angle=False): """ Interpolate ground truth with sensors """ x_int = np.zeros((t_int.shape[0], x.shape[1])) for i in range(x.shape[1]): if angle: x[:, i] = np.unwrap(x[:, i]) x_int[:, i] = np.interp(t_int, t, x[:, i]) return x_int sequences = os.listdir(data_dir) # read each sequence for sequence in sequences: print("\nSequence name: " + sequence) path_imu, path_gt = set_path(sequence) imu = np.genfromtxt(path_imu, delimiter=",") # Urban00-05 and campus00 have only quaternion and Euler data if not imu.shape[1] > 10: cprint("No IMU data for dataset " + sequence, 'yellow') continue gt = np.genfromtxt(path_gt, delimiter=",") # time synchronization between IMU and ground truth t0 = np.max([gt[0, 0], imu[0, 0]]) t_end = np.min([gt[-1, 0], imu[-1, 0]]) # start index idx0_imu = np.searchsorted(imu[:, 0], t0) idx0_gt = np.searchsorted(gt[:, 0], t0) # end index idx_end_imu = np.searchsorted(imu[:, 0], t_end, 'right') idx_end_gt = np.searchsorted(gt[:, 0], t_end, 'right') # subsample imu = imu[idx0_imu:idx_end_imu] gt = gt[idx0_gt:idx_end_gt] t = imu[:, 0] # take ground truth position p_gt = gt[:, [4, 8, 12]] p_gt = p_gt - p_gt[0] # take ground matrix pose Rot_gt = torch.Tensor(gt.shape[0], 3, 3) for j in range(3): Rot_gt[:, j] = torch.Tensor(gt[:, 1 + 4 * j:1 + 4 * j + 3]) q_gt = SO3.to_quaternion(Rot_gt) # convert to angle orientation rpys = SO3.to_rpy(Rot_gt) t_gt = gt[:, 0] # interpolate ground-truth p_gt = interpolate(p_gt, t_gt, t) rpys = interpolate(rpys.numpy(), t_gt, t, angle=True) # convert from numpy ts = (t - t0) / time_factor p_gt = torch.Tensor(p_gt) rpys = torch.Tensor(rpys).float() q_gt = SO3.to_quaternion( SO3.from_rpy(rpys[:, 0], rpys[:, 1], rpys[:, 2])) imu = torch.Tensor(imu).float() # take IMU gyro and accelerometer and magnetometer imu = imu[:, 8:17] dt = ts[1:] - ts[:-1] # compute speed ground truth (apply smoothing) v_gt = torch.zeros(p_gt.shape[0], 3) for j in range(3): p_gt_smooth = savgol_filter(p_gt[:, j], 11, 1) v_j = (p_gt_smooth[1:] - p_gt_smooth[:-1]) / dt v_j_smooth = savgol_filter(v_j, 11, 0) v_gt[1:, j] = torch.Tensor(v_j_smooth) # ground truth specific motion measurement (binary) zupts = v_gt.norm(dim=1, keepdim=True) < sm_velocity_max_threshold zupts = zupts.float() # set ground truth consistent with ZUPT v_gt[zupts.squeeze() == 1] = 0 # save for all training mondict = { 'xs': zupts.float(), 'us': imu.float(), } pdump(mondict, self.predata_dir, sequence + ".p") # save ground truth mondict = { 'ts': ts, 'qs': q_gt.float(), 'vs': v_gt.float(), 'ps': p_gt.float(), } pdump(mondict, self.predata_dir, sequence + "_gt.p")