class PlacingDataset: def __init__(self, episodes, seed=None): self.episodes = episodes self.episodes_place_success_index = list(map(lambda e: e[0], filter(lambda e: e[1]['actions'][1]['reward'] > 0, enumerate(episodes)))) self.episodes_different_objects_ids = { 'wooden': ('2019-12-16-17-01-18-409', '2020-01-22-09-34-02-952'), 'baby': ('2020-01-22-09-34-02-953', '2020-01-29-23-17-15-032'), } # Get indexes of episodes between the ids (from above) which have a positive place action self.episodes_different_objects_index = { k: list(map(lambda e: e[0], filter(lambda e: v[0] <= e[1]['id'] <= v[1] and e[1]['actions'][1]['reward'] > 0, enumerate(episodes)))) for k, v in self.episodes_different_objects_ids.items() } self.size_input = (752, 480) self.size_memory_scale = 4 self.size_cropped = (200, 200) self.size_result = (32, 32) self.size_cropped_area = (self.size_cropped[0] // self.size_memory_scale, self.size_cropped[1] // self.size_memory_scale) self.use_hindsight = True self.use_further_hindsight = False self.use_negative_foresight = True self.use_own_goal = True self.use_different_episodes_as_goals = True self.jittered_hindsight_images = 1 self.jittered_hindsight_x_images = 2 # Only if place reward > 0 self.jittered_goal_images = 1 self.different_episodes_images = 1 self.different_episodes_images_success = 4 # Only if place reward > 0 self.different_object_images = 4 # Only if place reward > 0 self.different_jittered_object_images = 0 # Only if place reward > 0 self.box_distance = 0.281 # [m] self.indexer = GraspIndexer([0.05, 0.07, 0.086]) # [m] # self.indexer = GraspIndexer([0.025, 0.05, 0.07, 0.086]) # [m] self.cameras = ('ed',) # self.cameras = ('ed', 'rd', 'rc') self.seed = seed self.random_gen = np.random.RandomState(seed) @lru_cache(maxsize=None) def load_image(self, collection, episode_id, action_id, suffix): image = Loader.get_image(collection, episode_id, action_id, suffix, as_float=True) draw_around_box(image, box=Config.box) image.mat = cv2.resize(image.mat, (self.size_input[0] // self.size_memory_scale, self.size_input[1] // self.size_memory_scale)) image.pixel_size /= self.size_memory_scale return image def area_of_interest(self, image, pose): area = get_area_of_interest_new( image, RobotPose(all_data=pose), size_cropped=self.size_cropped_area, size_result=self.size_result, border_color=image.value_from_depth(self.box_distance) / (255 * 255), ) if len(area.mat.shape) == 2: return np.expand_dims(area.mat, 2) return area.mat def jitter_pose(self, pose, scale_x=0.05, scale_y=0.05, scale_a=1.5, around=True): new_pose = copy.deepcopy(pose) if around: low = [np.minimum(0.001, scale_x), np.minimum(0.001, scale_y), np.minimum(0.06, scale_a)] mode = [np.minimum(0.006, scale_x), np.minimum(0.006, scale_y), np.minimum(0.32, scale_a)] high = [scale_x + 1e-6, scale_y + 1e-6, scale_a + 1e-6] dx, dy, da = self.random_gen.choice([-1, 1], size=3) * self.random_gen.triangular(low, mode, high, size=3) else: low = [-scale_x - 1e-6, -scale_y - 1e-6, -scale_a - 1e-6] mode = [0.0, 0.0, 0.0] high = [scale_x + 1e-6, scale_y + 1e-6, scale_a + 1e-6] dx, dy, da = self.random_gen.triangular(low, mode, high, size=3) new_pose['x'] += np.cos(pose['a']) * dx - np.sin(pose['a']) * dy new_pose['y'] += np.sin(pose['a']) * dx + np.cos(pose['a']) * dy new_pose['a'] += da return new_pose def generator(self, index): e = self.episodes[index] result = [] collection = e['collection'] episode_id = e['id'] grasp = e['actions'][0] grasp_before = self.load_image(collection, episode_id, 0, 'ed-v') grasp_before_area = self.area_of_interest(grasp_before, grasp['pose']) grasp_index = self.indexer.from_pose(grasp['pose']) # Only single grasp if len(e['actions']) == 1: pass place = e['actions'][1] place_before = self.load_image(collection, episode_id, 1, 'ed-v') place_after = self.load_image(collection, episode_id, 1, 'ed-after') # Generate goal has no action_id def generate_goal(g_collection, g_episode_id, g_suffix, g_pose, g_suffix_before='v', g_reward=0, g_index=None, g_place_weight=1.0, g_merge_weight=1.0, jitter=None): if g_collection == collection and g_episode_id == episode_id and g_suffix == 'v' and g_suffix_before == 'v': place_goal_before = place_before place_goal = place_before elif g_collection == collection and g_episode_id == episode_id and g_suffix == 'v' and g_suffix_before == 'after': place_goal_before = place_after place_goal = place_before elif g_collection == collection and g_episode_id == episode_id and g_suffix == 'after' and g_suffix_before == 'v': place_goal_before = place_before place_goal = place_after elif g_collection == collection and g_episode_id == episode_id and g_suffix == 'after' and g_suffix_before == 'after': place_goal_before = place_after place_goal = place_after else: goal_e = self.episodes[g_index] g_collection = g_collection if g_collection else goal_e['collection'] g_episode_id = g_episode_id if g_episode_id else goal_e['id'] g_pose = g_pose if g_pose else goal_e['actions'][1]['pose'] place_goal_before = self.load_image(g_collection, g_episode_id, 1, 'ed-' + g_suffix_before) place_goal = self.load_image(g_collection, g_episode_id, 1, 'ed-' + g_suffix) if isinstance(jitter, dict): g_pose = self.jitter_pose(g_pose, **jitter) place_before_area = self.area_of_interest(place_goal_before, g_pose) place_goal_area = self.area_of_interest(place_goal, g_pose) reward_grasp = grasp['reward'] reward_place = g_reward * grasp['reward'] * place['reward'] reward_merge = reward_place grasp_weight = g_reward place_weight = (1.0 + 3.0 * reward_place) * reward_grasp * g_place_weight merge_weight = (1.0 + 3.0 * reward_merge) * reward_grasp * g_merge_weight return ( grasp_before_area, place_before_area, place_goal_area, (reward_grasp, grasp_index, grasp_weight), (reward_place, 0, place_weight), (reward_merge, 0, merge_weight), ) if self.use_hindsight: result.append(generate_goal(collection, episode_id, 'after', place['pose'], g_reward=1)) result += [ generate_goal(collection, episode_id, 'after', place['pose'], jitter={}) for _ in range(self.jittered_hindsight_images) ] if place['reward'] > 0: result += [ generate_goal(collection, episode_id, 'after', place['pose'], jitter={'scale_x': 0.02, 'scale_y': 0.01, 'scale_a': 0.2}) for _ in range(self.jittered_hindsight_x_images) ] if self.use_further_hindsight and 'bin_episode' in place: for i in range(index + 1, len(self.episodes)): place_later = self.episodes[i]['actions'][1] if place_later['bin_episode'] != place['bin_episode']: break if place_later['reward'] > 0: result.append(generate_goal(None, None, 'after', place['pose'], g_index=i, g_reward=1)) if self.use_negative_foresight: g_suffix, g_suffix_before = random.choice([('v', 'v'), ('after', 'after'), ('v', 'after')]) result.append(generate_goal(collection, episode_id, g_suffix, place['pose'], g_suffix_before=g_suffix_before, jitter={'around': False})) if self.use_own_goal and 'ed-goal' in place['images']: result.append(generate_goal(collection, episode_id, 'goal', place['pose'], g_place_weight=0.2, g_merge_weight=0.7, g_index=index)) result += [ generate_goal(collection, episode_id, 'goal', place['pose'], g_index=index, jitter={}) for _ in range(self.jittered_goal_images) ] if self.use_different_episodes_as_goals: result += [ generate_goal(None, None, 'after', None, g_index=goal_index, g_place_weight=0.0) for goal_index in self.random_gen.choice(self.episodes_place_success_index, size=self.different_episodes_images) ] if place['reward'] > 0: result += [ generate_goal(None, None, 'after', None, g_index=goal_index, g_place_weight=0.0) for goal_index in self.random_gen.choice(self.episodes_place_success_index, size=self.different_episodes_images_success) ] for k, v in self.episodes_different_objects_ids.items(): if v[0] <= e['id'] <= v[1]: result += [ generate_goal(None, None, 'after', None, g_index=goal_index, g_place_weight=0.0) for goal_index in self.random_gen.choice(self.episodes_different_objects_index[k], size=self.different_object_images) ] # result += [ # generate_goal(None, None, 'after', None, g_index=goal_index, jitter={}) # for goal_index in self.random_gen.choice(self.episodes_different_objects_index[k], size=self.different_jittered_object_images) # ] return [np.array(t, dtype=np.float32) for t in zip(*result)] def tf_generator(self, index): r = tf.py_function( self.generator, [index], (tf.float32,) * 6, ) r[0].set_shape((None, 32, 32, 1)) r[1].set_shape((None, 32, 32, 1)) r[2].set_shape((None, 32, 32, 1)) r[3].set_shape((None, 3)) r[4].set_shape((None, 3)) r[5].set_shape((None, 3)) return (r[0], r[1], r[2]), (r[3], r[4], r[5]) def get_data(self, shuffle=None): data = tf.data.Dataset.range(0, len(self.episodes)) if shuffle: shuffle_number = len(self.episodes) if shuffle == 'all' else int(shuffle) data = data.shuffle(shuffle_number, seed=self.seed) data = data.map(self.tf_generator, num_parallel_calls=tf.data.experimental.AUTOTUNE) # data = data.map(self.tf_generator) return data.interleave(lambda *x: tf.data.Dataset.from_tensor_slices(x), cycle_length=1)
class PlacingDataset: def __init__(self, episodes, seed=None): self.episodes = episodes self.episodes_place_success_index = list( map( lambda e: e[0], filter( lambda e: len(e[1]['actions']) > 1 and e[1]['actions'][1][ 'reward'] > 0, enumerate(episodes)))) # self.episodes_different_objects_index = list(map(lambda e: e[0], filter(lambda e: '2019-12-16-17-01-18-409' <= e[1]['id'] <= '2020-01-16-17-09-47-989' and e[1]['actions'][1]['reward'] > 0, enumerate(episodes)))) self.size_input = (752, 480) self.size_memory_scale = 4 self.size_cropped = (200, 200) self.size_result = (32, 32) self.size_cropped_area = (self.size_cropped[0] // self.size_memory_scale, self.size_cropped[1] // self.size_memory_scale) self.use_hindsight = True self.use_further_hindsight = False self.use_negative_foresight = True self.use_own_goal = True self.use_different_episodes_as_goals = True self.jittered_hindsight_images = 3 self.jittered_hindsight_x_images = 3 self.jittered_goal_images = 2 self.different_episodes_images = 2 self.different_object_images = 5 # self.different_jittered_object_images = 2 self.box_distance = 0.281 # [m] # self.indexer = GraspIndexer([0.05, 0.07, 0.086]) # [m] self.indexer = GraspIndexer([0.025, 0.05, 0.07, 0.086]) # [m] self.cameras = ('ed', 'rd', 'rc') self.random_gen = np.random.RandomState(seed) @lru_cache(maxsize=None) def load_image(self, collection, episode_id, action_id, suffix): image = Loader.get_image(collection, episode_id, action_id, suffix, as_float=True) draw_around_box(image, box=Config.box) image.mat = cv2.resize(image.mat, (self.size_input[0] // self.size_memory_scale, self.size_input[1] // self.size_memory_scale)) image.pixel_size /= self.size_memory_scale return image def area_of_interest(self, image, pose): area = get_area_of_interest_new( image, RobotPose(all_data=pose), size_cropped=self.size_cropped_area, size_result=self.size_result, border_color=image.value_from_depth(self.box_distance) / (255 * 255), ) if len(area.mat.shape) == 2: return np.expand_dims(area.mat, 2) return area.mat def jitter_pose(self, pose, scale_x=0.05, scale_y=0.05, scale_a=1.5): new_pose = copy.deepcopy(pose) low = [ np.minimum(0.002, scale_x), np.minimum(0.002, scale_y), np.minimum(0.05, scale_a) ] high = [scale_x, scale_y, scale_a] dx, dy, da = self.random_gen.choice( [-1, 1], size=3) * self.random_gen.uniform(low, high, size=3) new_pose['x'] += np.cos(pose['a']) * dx - np.sin(pose['a']) * dy new_pose['y'] += np.sin(pose['a']) * dx + np.cos(pose['a']) * dy new_pose['a'] += da return new_pose def generator(self, index): e = self.episodes[index] result = [] collection = e['collection'] episode_id = e['id'] grasp = e['actions'][0] grasp_before = tuple( self.load_image(collection, episode_id, 0, camera + '-v') for camera in self.cameras) grasp_before_area = tuple( self.area_of_interest(image, grasp['pose']) for image in grasp_before) grasp_index = self.indexer.from_pose(grasp['pose']) # Only grasp if len(e['actions']) == 1: zeros = (np.zeros(self.size_result + (1, )), np.zeros(self.size_result + (1, )), np.zeros(self.size_result + (3, ))) result = [ grasp_before_area + zeros + zeros + ( (grasp['reward'], grasp_index, 0.4), (0, 0, 0), (0, 0, 0), ) ] return [np.array(t, dtype=np.float32) for t in zip(*result)] place = e['actions'][1] place_before = tuple( self.load_image(collection, episode_id, 1, camera + '-v') for camera in self.cameras) place_after = tuple( self.load_image(collection, episode_id, 1, camera + '-after') for camera in self.cameras) # Generate goal has no action_id def generate_goal(g_collection, g_episode_id, g_suffix, g_pose, g_reward=0, g_index=None, g_merge_weight=1.0, jitter=None): if g_collection == collection and g_episode_id == episode_id and g_suffix == 'v': place_goal_before = place_before place_goal = place_before elif g_collection == collection and g_episode_id == episode_id and g_suffix == 'after': place_goal_before = place_before place_goal = place_after else: goal_e = self.episodes[g_index] g_collection = g_collection if g_collection else goal_e[ 'collection'] g_episode_id = g_episode_id if g_episode_id else goal_e['id'] g_pose = g_pose if g_pose else goal_e['actions'][1]['pose'] place_goal_before = tuple( self.load_image(g_collection, g_episode_id, 1, camera + '-v') for camera in self.cameras) place_goal = tuple( self.load_image(g_collection, g_episode_id, 1, camera + '-' + g_suffix) for camera in self.cameras) if isinstance(jitter, dict): g_pose = self.jitter_pose(g_pose, **jitter) place_before_area = tuple( self.area_of_interest(image, g_pose) for image in place_goal_before) place_goal_area = tuple( self.area_of_interest(image, g_pose) for image in place_goal) goal_reward = g_reward reward_grasp = grasp['reward'] reward_place = goal_reward * place['reward'] reward_merge = reward_place grasp_weight = g_reward place_weight = (1.0 + 5.0 * reward_place) * reward_grasp merge_weight = (1.0 + 5.0 * reward_merge) * g_merge_weight return grasp_before_area + place_before_area + place_goal_area + ( (reward_grasp, grasp_index, grasp_weight), (reward_place, 0, place_weight), (reward_merge, 0, merge_weight), ) if self.use_hindsight: result.append( generate_goal(collection, episode_id, 'after', place['pose'], g_reward=1)) result += [ generate_goal(collection, episode_id, 'after', place['pose'], jitter={}) for _ in range(self.jittered_hindsight_images) ] result += [ generate_goal(collection, episode_id, 'after', place['pose'], jitter={ 'scale_x': 0.025, 'scale_y': 0, 'scale_a': 0 }) for _ in range(self.jittered_hindsight_x_images) ] if self.use_further_hindsight and 'bin_episode' in place: for i in range(index + 1, len(self.episodes)): place_later = self.episodes[i]['actions'][1] if place_later['bin_episode'] != place['bin_episode']: break if place_later['reward'] > 0: result.append( generate_goal(None, None, 'after', place['pose'], g_index=i, g_reward=1)) if self.use_negative_foresight: result.append( generate_goal(collection, episode_id, 'v', place['pose'])) if self.use_own_goal and 'ed-goal' in place['images']: result.append( generate_goal(collection, episode_id, 'goal', place['pose'], g_index=index)) result += [ generate_goal(collection, episode_id, 'goal', place['pose'], g_index=index, g_merge_weight=0.5, jitter={}) for _ in range(self.jittered_goal_images) ] if self.use_different_episodes_as_goals: result += [ generate_goal(None, None, 'after', None, g_index=goal_index, g_merge_weight=0.3) for goal_index in self.random_gen.choice(self.episodes_place_success_index, size=self.different_episodes_images) ] # result += [ # generate_goal(None, None, 'after', None, g_index=goal_index, g_merge_weight=0.3) # for goal_index in self.random_gen.choice(self.episodes_different_objects_index, size=self.different_object_images) # ] # result += [ # generate_goal(None, None, 'after', None, g_index=goal_index, g_merge_weight=0.3, jitter={}) # for goal_index in self.random_gen.choice(self.episodes_different_objects_index, size=self.different_jittered_object_images) # ] return [np.array(t, dtype=np.float32) for t in zip(*result)] def tf_generator(self, index): r = tf.py_function( self.generator, [index], (tf.float32, ) * (3 * len(self.cameras) + 3), ) r[0].set_shape((None, 32, 32, 1)) r[1].set_shape((None, 32, 32, 1)) r[2].set_shape((None, 32, 32, 3)) r[3].set_shape((None, 32, 32, 1)) r[4].set_shape((None, 32, 32, 1)) r[5].set_shape((None, 32, 32, 3)) r[6].set_shape((None, 32, 32, 1)) r[7].set_shape((None, 32, 32, 1)) r[8].set_shape((None, 32, 32, 3)) r[9].set_shape((None, 3)) r[10].set_shape((None, 3)) r[11].set_shape((None, 3)) return (r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8]), (r[9], r[10], r[11]) def get_data(self, shuffle=None): data = tf.data.Dataset.range(0, len(self.episodes)) if shuffle: shuffle_number = len( self.episodes) if shuffle == 'all' else int(shuffle) data = data.shuffle(shuffle_number) data = data.map(self.tf_generator, num_parallel_calls=tf.data.experimental.AUTOTUNE) return data.interleave( lambda *x: tf.data.Dataset.from_tensor_slices(x), cycle_length=1)