| import os |
| from glob import glob |
|
|
| from einops import rearrange |
| import math |
| import matplotlib.pyplot as plt |
| import torch.nn.functional as F |
| import numpy as np |
| import torch |
| from torch.utils.data import Dataset |
| from tqdm import tqdm |
| import pickle |
|
|
| from utils.normalization import normalize_min_max |
| from torch.nn.utils.rnn import pad_sequence |
|
|
|
|
| def rotate_traj(past_rel, future_rel, past_abs, rotate_time_frame=0): |
| """ |
| @params past_rel: [N, A, P, 2] |
| @params future_rel: [N, A, F, 2] |
| @params past_abs: [N, A, P, 2] |
| @params rotate_time_frame: int |
| """ |
|
|
| A = past_rel.size(1) |
| past_rel = rearrange(past_rel, 'b a p d -> (b a) p d') |
| past_abs = rearrange(past_abs, 'b a p d -> (b a) p d') |
| future_rel = rearrange(future_rel, 'b a f d -> (b a) f d') |
|
|
| past_diff = past_rel[:, rotate_time_frame] |
| |
|
|
| past_theta = torch.atan(torch.div(past_diff[:, 1], past_diff[:, 0] + 1e-5)) |
| past_theta = torch.where((past_diff[:, 0] < 0), past_theta + math.pi, past_theta) |
| |
| rotate_matrix = torch.zeros((past_theta.size(0), 2, 2)).to(past_theta.device) |
| rotate_matrix[:, 0, 0] = torch.cos(past_theta) |
| rotate_matrix[:, 0, 1] = torch.sin(past_theta) |
| rotate_matrix[:, 1, 0] = -torch.sin(past_theta) |
| rotate_matrix[:, 1, 1] = torch.cos(past_theta) |
|
|
| past_after = torch.matmul(rotate_matrix, past_rel.transpose(1, 2)).transpose(1, 2) |
| future_after = torch.matmul(rotate_matrix, future_rel.transpose(1, 2)).transpose(1, 2) |
| past_abs_after = torch.matmul(rotate_matrix, past_abs.transpose(1, 2)).transpose(1, 2) |
|
|
| past_after = rearrange(past_after, '(b a) p d -> b a p d', a=A) |
| future_after = rearrange(future_after, '(b a) f d -> b a f d', a=A) |
| past_abs_after = rearrange(past_abs_after, '(b a) p d -> b a p d', a=A) |
|
|
|
|
| return past_after, future_after, past_abs_after |
|
|
|
|
| def seq_collate_sdd(batch): |
| (index, past_traj, fut_traj, past_traj_orig, fut_traj_orig, traj_vel) = zip(*batch) |
| indexes = torch.stack(index, dim=0) |
| pre_motion_3D = torch.stack(past_traj,dim=0) |
| fut_motion_3D = torch.stack(fut_traj,dim=0) |
| pre_motion_3D_orig = torch.stack(past_traj_orig, dim=0) |
| fut_motion_3D_orig = torch.stack(fut_traj_orig, dim=0) |
| fut_traj_vel = torch.stack(traj_vel, dim=0) |
|
|
| batch_size = torch.tensor(pre_motion_3D.shape[0]) |
| data = { |
| 'indexes': indexes, |
| 'batch_size': batch_size, |
| 'past_traj': pre_motion_3D, |
| 'fut_traj': fut_motion_3D, |
| 'past_traj_original_scale': pre_motion_3D_orig, |
| 'fut_traj_original_scale': fut_motion_3D_orig, |
| 'fut_traj_vel': fut_traj_vel, |
| } |
| return data |
|
|
|
|
| def seq_collate_imle_train(batch): |
| (past_traj, fut_traj, past_traj_orig, fut_traj_orig, traj_vel, y_t, y_pred_data) = zip(*batch) |
|
|
| pre_motion_3D = torch.stack(past_traj,dim=0) |
| fut_motion_3D = torch.stack(fut_traj,dim=0) |
| pre_motion_3D_orig = torch.stack(past_traj_orig, dim=0) |
| fut_motion_3D_orig = torch.stack(fut_traj_orig, dim=0) |
| fut_traj_vel = torch.stack(traj_vel, dim=0) |
| y_t = torch.stack(y_t, dim=0) |
| y_pred_data = torch.stack(y_pred_data,dim=0) |
|
|
| batch_size = torch.tensor(pre_motion_3D.shape[0]) |
| data = { |
| 'batch_size': batch_size, |
| 'past_traj': pre_motion_3D, |
| 'fut_traj': fut_motion_3D, |
| 'past_traj_original_scale': pre_motion_3D_orig, |
| 'fut_traj_original_scale': fut_motion_3D_orig, |
| 'fut_traj_vel': fut_traj_vel, |
| 'y_t': y_t, |
| 'y_pred_data': y_pred_data |
| } |
|
|
| return data |
|
|
|
|
| class SDDDataset(Dataset): |
| def __init__(self, cfg, data_dir, |
| training=True, overfit=False, rotate_time_frame=0, imle=False): |
| super(SDDDataset, self).__init__() |
|
|
| """init""" |
| self.cfg = cfg |
| dataset_file = os.path.join(data_dir, 'original/sdd_train.pkl') if training else os.path.join(data_dir, 'original/sdd_test.pkl') |
| if overfit: |
| dataset_file = os.path.join(data_dir, 'original/sdd_train.pkl') |
|
|
| |
| |
| |
| |
| |
|
|
| self.training = training |
| self.overfit = overfit |
|
|
| self.rotate_time_frame = rotate_time_frame |
| self.imle = imle |
|
|
| self.past_frames = cfg.past_frames |
| self.future_frames = cfg.future_frames |
| self.seq_len = self.past_frames + self.future_frames |
| self.max_agents_per_scene = 0 |
| assert self.seq_len == 20 and self.past_frames == 8, "Sanity check on frame length failed!" |
|
|
|
|
| """load the data in the original scale""" |
| all_data = pickle.load(open(dataset_file, 'rb')) |
|
|
| print("Mode: {:s}, {:d} sequences".format('train' if training else 'test', len(all_data))) |
|
|
| """process the data""" |
| |
| cfg.MODEL.CONTEXT_ENCODER.AGENTS = cfg.agents |
| |
| |
| past_traj_abs = torch.from_numpy(np.stack([scene[0] for scene in all_data], axis=0)).unsqueeze(1) |
|
|
| |
| |
| |
|
|
| initial_pos = past_traj_abs[:, :, -1:, :] |
| past_traj_rel = (past_traj_abs - initial_pos).contiguous() |
|
|
| fut_traj_abs = torch.from_numpy(np.stack([scene[1] for scene in all_data], axis=0)).unsqueeze(1) |
|
|
| |
| |
| |
|
|
| fut_traj_rel = (fut_traj_abs - initial_pos).contiguous() |
|
|
| if cfg.rotate: |
| past_traj_rel, fut_traj_rel, past_traj_abs = rotate_traj(past_traj_rel, fut_traj_rel, past_traj_abs, rotate_time_frame) |
|
|
| past_traj_vel = torch.cat((past_traj_rel[:, :, 1:] - past_traj_rel[:, :, :-1], torch.zeros_like(past_traj_rel[:,:, -1:])), dim=2) |
| past_traj = torch.cat((past_traj_abs, past_traj_rel, past_traj_vel), dim=-1) |
| self.fut_traj_vel = torch.cat((fut_traj_rel[:, :, 1:] - fut_traj_rel[:,:, :-1], torch.zeros_like(fut_traj_rel[:, :, -1:])), dim=2) |
|
|
| self.rotate_aug = cfg.rotate_aug and training |
|
|
| if training: |
| cfg.fut_traj_max = fut_traj_rel.max() |
| cfg.fut_traj_min = fut_traj_rel.min() |
| cfg.past_traj_max = past_traj.max() |
| cfg.past_traj_min = past_traj.min() |
|
|
| |
| self.past_traj_original_scale = past_traj |
| self.fut_traj_original_scale = fut_traj_rel |
|
|
| |
| self.past_traj = normalize_min_max(past_traj, cfg.past_traj_min, cfg.past_traj_max, -1, 1).contiguous() |
|
|
| |
| self.fut_traj = normalize_min_max(fut_traj_rel, cfg.fut_traj_min, cfg.fut_traj_max, -1, 1).contiguous() |
|
|
|
|
| """load distillation target""" |
| if imle: |
| os.makedirs(os.path.join(data_dir, 'imle'), exist_ok=True) |
| pkl_ls = sorted(glob(os.path.join(data_dir, f'imle/*train*.pkl'))) |
|
|
| keys_ls = ['past_traj', 'fut_traj', 'past_traj_original_scale', 'fut_traj_original_scale', 'fut_traj_vel', 'y_t', 'y_pred_data'] |
| imle_data_dict = {} |
| total_scenes_loaded_ = 0 |
| for i_pkl, cur_pkl in enumerate(pkl_ls): |
| data = pickle.load(open(cur_pkl, 'rb')) |
|
|
| if i_pkl == 0: |
| self.imle_meta_data = data['meta_data'] |
| |
| for key in keys_ls: |
| if key not in imle_data_dict: |
| imle_data_dict[key] = [] |
| if key == 'y_t': |
| imle_data_dict[key].append(data[key][:, -1]) |
| else: |
| imle_data_dict[key].append(data[key]) |
|
|
| total_scenes_loaded_ += data['past_traj'].shape[0] |
|
|
| if total_scenes_loaded_ >= len(self.past_traj): |
| break |
|
|
| if i_pkl == 0: |
| |
| |
| |
| |
| past_tarj_original_scale_ = torch.from_numpy(data['past_traj_original_scale']) |
| assert torch.sum(torch.abs(past_tarj_original_scale_[:10] - self.past_traj_original_scale[:10])) < 1e-5, 'IMLE data is not consistent' |
|
|
| pass |
|
|
| |
| for key in keys_ls: |
| imle_data_dict[key] = torch.from_numpy(np.concatenate(imle_data_dict[key], axis=0))[:len(self.past_traj)] |
|
|
| self.imle_data_dict = imle_data_dict |
| |
| def __len__(self): |
| return len(self.past_traj) |
|
|
| def __getitem__(self, item): |
| if self.imle: |
| out = [ |
| self.imle_data_dict['past_traj'][item], |
| self.imle_data_dict['fut_traj'][item], |
| self.imle_data_dict['past_traj_original_scale'][item], |
| self.imle_data_dict['fut_traj_original_scale'][item], |
| self.imle_data_dict['fut_traj_vel'][item], |
| self.imle_data_dict['y_t'][item], |
| self.imle_data_dict['y_pred_data'][item] |
| ] |
| else: |
| |
| past_traj_norm_scale = self.past_traj[item] |
| fut_traj_norm_scale = self.fut_traj[item] |
| past_traj_original_scale = self.past_traj_original_scale[item] |
| fut_traj_original_scale = self.fut_traj_original_scale[item] |
| fut_traj_vel = self.fut_traj_vel[item] |
|
|
| |
| out = [ |
| torch.Tensor([item]).to(torch.int32), |
| past_traj_norm_scale, |
| fut_traj_norm_scale, |
| past_traj_original_scale, |
| fut_traj_original_scale, |
| fut_traj_vel, |
| ] |
| return out |
|
|