コード例 #1
0
    def navigate_to_goal(self, game_state, start_pose, end_pose):
        # Look down

        self.update_map(game_state.env)

        start_angle = start_pose[3]
        if start_angle > 180:
            start_angle -= 360
        if start_angle != 45:  # pitch angle
            # Perform initial tilt to get to 45 degrees.
            tilt_pose = [pp for pp in start_pose]
            tilt_pose[3] = 45
            tilt_actions, _ = self.get_shortest_path(start_pose, tilt_pose)
            for action in tilt_actions:
                game_state.step(action)
            start_pose = tuple(tilt_pose)

        actions, path = self.get_shortest_path(start_pose, end_pose)
        while len(actions) > 0:
            for ii, (action, pose) in enumerate(zip(actions, path)):
                game_state.step(action)
                event = game_state.env.last_event
                last_action_success = event.metadata['lastActionSuccess']

                if not last_action_success:
                    # Can't traverse here, make sure the weight is correct.
                    if action['action'].startswith('Look') or action['action'].startswith('Rotate'):
                        raise Exception('Look action failed %s' % event.metadata['errorMessage'])
                    self.add_impossible_spot(path[ii + 1])
                    break
            pose = game_util.get_pose(event)
            actions, path = self.get_shortest_path(pose, end_pose)
コード例 #2
0
    def process_frame(self):
        self.event = self.env.last_event
        self.pose = game_util.get_pose(self.event)

        self.s_t_orig = self.event.frame
        self.s_t = game_util.imresize(self.event.frame,
                                      (constants.SCREEN_HEIGHT, constants.SCREEN_WIDTH), rescale=False)

        self.s_t_depth = game_util.imresize(self.event.depth_frame,
                                            (constants.SCREEN_HEIGHT, constants.SCREEN_WIDTH), rescale=False)
コード例 #3
0
    def state_to_pddl(self, traj_data):
        object_dict = game_util.get_object_dict(self.env.last_event.metadata)
        domain = 'alfred'
        problem_id = traj_data['task_id']
        pddl_params = traj_data['pddl_params']

        points_source = os.path.join(
            alfworld.gen.__path__[0],
            'layouts/%s-openable.json' % traj_data['scene']['floor_plan'])
        with open(points_source, 'r') as f:
            openable_object_to_point = json.load(f)
        self.openable_object_to_point = openable_object_to_point

        receptacle_types = copy.deepcopy(constants.RECEPTACLES) - set(
            constants.MOVABLE_RECEPTACLES)
        objects = copy.deepcopy(constants.OBJECTS_SET) - receptacle_types
        object_str = '\n        '.join([obj + ' # object' for obj in objects])

        self.knife_obj = {'ButterKnife', 'Knife'
                          } if pddl_params['object_sliced'] else {}

        otype_str = '\n        '.join(
            [obj + 'Type # otype' for obj in objects])
        rtype_str = '\n        '.join(
            [obj + 'Type # rtype' for obj in receptacle_types])

        pddl_goal = get_goal_pddl(traj_data)

        pddl_start = '''
(define (problem plan_%s)
(:domain %s)
(:objects
agent1 # agent
%s
%s
%s
''' % (
            problem_id,
            domain,
            object_str,
            otype_str,
            rtype_str,
        )

        pddl_init = '''
(:init
'''

        pddl_start = fix_pddl_str_chars(pddl_start)
        pddl_init = fix_pddl_str_chars(pddl_init)
        pddl_goal = fix_pddl_str_chars(pddl_goal)

        # pddl_mid section
        pose = game_util.get_pose(self.env.last_event)
        agent_location = 'loc|%d|%d|%d|%d' % (pose[0], pose[1], pose[2],
                                              pose[3])
        #agent_location = "Middle of the room."

        agent_location_str = '\n        (atLocation agent1 %s)' % agent_location
        opened_receptacle_str = '\n        '.join(
            ['(opened %s)' % obj for obj in list()])

        movable_recep_cls_with_knife = []
        in_receptacle_strs = []
        was_in_receptacle_strs = []
        for key, val in self.in_receptacle_ids.items():
            if len(val) == 0:
                continue
            key_cls = object_dict[key]['objectType']
            if key_cls in constants.MOVABLE_RECEPTACLES_SET:
                recep_str = 'inReceptacleObject'
            else:
                recep_str = 'inReceptacle'
            for vv in val:
                vv_cls = object_dict[vv]['objectType']
                if (vv_cls == pddl_params['object_target']
                        or (pddl_params['mrecep_target'] is not None
                            and vv_cls == pddl_params['mrecep_target']) or
                    (len(self.knife_obj) > 0 and vv_cls in self.knife_obj)):

                    # if knife is inside a movable receptacle, make sure to add it to the object list
                    if recep_str == 'inReceptacleObject':
                        movable_recep_cls_with_knife.append(key_cls)

                in_receptacle_strs.append('(%s %s %s)' % (recep_str, vv, key))
                # if key_cls not in constants.MOVABLE_RECEPTACLES_SET and vv_cls == pddl_params['object_target']:
                #     was_in_receptacle_strs.append('(wasInReceptacle  %s %s)' % (vv, key))

        in_receptacle_str = '\n        '.join(in_receptacle_strs)
        was_in_receptacle_str = '\n        '.join(was_in_receptacle_strs)

        # Note which openable receptacles we can safely open (precomputed).
        openable_objects = self.openable_object_to_point.keys()

        metadata_objects = self.env.last_event.metadata['objects']
        receptacles = set({
            obj['objectId']
            for obj in metadata_objects
            if obj['objectType'] in constants.RECEPTACLES
            and obj['objectType'] not in constants.MOVABLE_RECEPTACLES_SET
        })

        objects = set({
            obj['objectId']
            for obj in metadata_objects
            if (obj['objectType'] == pddl_params['object_target']
                or obj['objectType'] in constants.MOVABLE_RECEPTACLES_SET or (
                    pddl_params['mrecep_target'] is not None
                    and obj['objectType'] == pddl_params['mrecep_target']) or
                ((pddl_params['toggle_target'] is not None
                  and obj['objectType'] == pddl_params['toggle_target']) or (
                      (len(self.knife_obj) > 0 and
                       (obj['objectType'] in self.knife_obj or
                        obj['objectType'] in movable_recep_cls_with_knife)))))
        })

        objects = set(obj['objectId'] for obj in metadata_objects
                      if obj['objectId'] not in receptacles)
        #from ipdb import set_trace; set_trace()

        if len(self.inventory_ids) > 0:
            objects = objects | self.inventory_ids
        if len(self.placed_items) > 0:
            objects = objects | self.placed_items

        receptacle_str = '\n        '.join(
            sorted(
                [receptacle + ' # receptacle' for receptacle in receptacles]))

        object_str = '\n        '.join(
            sorted([obj + ' # object' for obj in objects]))

        locations = set()
        for key, val in self.receptacle_to_point.items():
            key_cls = object_dict[key]['objectType']
            if key_cls not in constants.MOVABLE_RECEPTACLES_SET:
                locations.add(tuple(val.tolist()))
                # locations.add(key + "|loc")
        for obj, loc in self.object_to_point.items():
            obj_cls = object_dict[obj]['objectType']
            # if (obj_cls == pddl_params['object_target'] or
            #         (pddl_params['toggle_target'] is not None and obj_cls == pddl_params['toggle_target']) or
            #         (len(self.knife_obj) > 0 and obj_cls in self.knife_obj) or
            #         (obj_cls in constants.MOVABLE_RECEPTACLES_SET)):
            if obj_cls in constants.OBJECTS:
                locations.add(tuple(loc))

        location_str = ('\n        '.join(
            ['loc|%d|%d|%d|%d # location' % (*loc, ) for loc in locations]) +
                        '\n        %s # location' % agent_location)
        #location_str = ('\n        '.join(['loc|%d|%d|%d|%d # location' % (*loc,)
        # location_str = ('\n        '.join(['{loc} # location'.format(loc=loc) for loc in locations]) +
        #                 '\n        %s # location' % agent_location)
        # location_str = '\n        %s # location' % agent_location
        if constants.PRUNE_UNREACHABLE_POINTS:
            # don't flag problematic receptacleTypes for the planner.
            receptacle_type_str = '\n        '.join([
                '(receptacleType %s %sType)' %
                (receptacle, object_dict[receptacle]['objectType'])
                for receptacle in receptacles
                if object_dict[receptacle]['objectType'] not in
                constants.OPENABLE_CLASS_SET or receptacle in openable_objects
            ])
        else:
            receptacle_type_str = '\n        '.join([
                '(receptacleType %s %sType)' %
                (receptacle, object_dict[receptacle]['objectType'])
                for receptacle in receptacles
            ])

        object_type_str = '\n        '.join([
            '(objectType %s %sType)' % (obj, object_dict[obj]['objectType'])
            for obj in objects
            if object_dict[obj]['objectType'] in constants.OBJECTS
        ])

        receptacle_objects_str = '\n        '.join([
            '(isReceptacleObject %s)' % (obj) for obj in objects if
            object_dict[obj]['objectType'] in constants.MOVABLE_RECEPTACLES_SET
        ])

        if constants.PRUNE_UNREACHABLE_POINTS:
            openable_str = '\n        '.join([
                '(openable %s)' % receptacle for receptacle in receptacles
                if object_dict[receptacle]['objectType'] in
                constants.OPENABLE_CLASS_SET
            ])
        else:
            # don't flag problematic open objects as openable for the planner.
            openable_str = '\n        '.join([
                '(openable %s)' % receptacle for receptacle in receptacles
                if object_dict[receptacle]['objectType'] in
                constants.OPENABLE_CLASS_SET and receptacle in openable_objects
            ])

        # dists = []
        # dist_points = list(locations | {(pose[0], pose[1], pose[2], pose[3])})
        # for dd, l_start in enumerate(dist_points[:-1]):
        #     for l_end in dist_points[dd + 1:]:
        #         actions, path = self.gt_graph.get_shortest_path_unweighted(l_start, l_end)
        #         # Should cost one more for the trouble of going there at all. Discourages waypoints.
        #         dist = len(actions) + 1
        #         dists.append('(= (distance loc|%d|%d|%d|%d loc|%d|%d|%d|%d) %d)' % (
        #             l_start[0], l_start[1], l_start[2], l_start[3],
        #             l_end[0], l_end[1], l_end[2], l_end[3], dist))
        #         dists.append('(= (distance loc|%d|%d|%d|%d loc|%d|%d|%d|%d) %d)' % (
        #             l_end[0], l_end[1], l_end[2], l_end[3],
        #             l_start[0], l_start[1], l_start[2], l_start[3], dist))
        # location_distance_str = '\n        '.join(dists)
        location_distance_str = ""

        # pickupable objects
        pickupable_str = '\n        '.join([
            '(pickupable %s)' % obj_id for obj_id in objects
            if object_dict[obj_id]["pickupable"]
        ])

        # clean objects
        cleanable_str = '\n        '.join([
            '(cleanable %s)' % obj for obj in objects if object_dict[obj]
            ['objectType'] in constants.VAL_ACTION_OBJECTS['Cleanable']
        ])

        is_clean_str = '\n        '.join(([
            '(isClean %s)' % obj for obj in self.cleaned_object_ids
            if object_dict[obj]['objectType'] == pddl_params['object_target']
        ]))

        # heat objects
        heatable_str = '\n        '.join([
            '(heatable %s)' % obj for obj in objects if object_dict[obj]
            ['objectType'] in constants.VAL_ACTION_OBJECTS['Heatable']
        ])

        is_hot_str = '\n        '.join(([
            '(isHot %s)' % obj for obj in self.hot_object_ids
            if object_dict[obj]['objectType'] == pddl_params['object_target']
        ]))

        # cool objects
        coolable_str = '\n        '.join([
            '(coolable %s)' % obj for obj in objects if object_dict[obj]
            ['objectType'] in constants.VAL_ACTION_OBJECTS['Coolable']
        ])

        # toggleable objects
        toggleable_str = '\n        '.join([
            '(toggleable %s)' % obj for obj in objects if object_dict[obj]
            ['objectType'] in constants.VAL_ACTION_OBJECTS['Toggleable']
        ])

        is_on_str = '\n        '.join([
            '(isOn %s)' % obj for obj in self.on_object_ids
            if (pddl_params['toggle_target'] is not None and object_dict[obj]
                ['objectType'] == pddl_params['toggle_target'])
        ])

        # sliceable objects
        sliceable_str = '\n        '.join([
            '(sliceable %s)' % obj for obj in objects
            if (object_dict[obj]['objectType'] in
                constants.VAL_ACTION_OBJECTS['Sliceable'])
        ])

        # sliced objects
        # TODO cleanup: sliced_object_ids is never added to. Does that matter?
        is_sliced_str = '\n        '.join(([
            '(isSliced %s)' % obj for obj in self.sliced_object_ids
            if object_dict[obj]['objectType'] == pddl_params['object_target']
        ]))

        # look for objects that are already cool
        for (key, val) in self.was_in_receptacle_ids.items():
            if 'Fridge' in key:
                for vv in val:
                    self.cool_object_ids.add(vv)

        is_cool_str = '\n        '.join(([
            '(isCool %s)' % obj for obj in self.cool_object_ids
            if object_dict[obj]['objectType'] == pddl_params['object_target']
        ]))

        # Receptacle Objects
        recep_obj_str = '\n        '.join([
            '(isReceptacleObject %s)' % obj for obj in receptacles
            if (object_dict[obj]['objectType'] in
                constants.MOVABLE_RECEPTACLES_SET and
                (pddl_params['mrecep_target'] is not None and object_dict[obj]
                 ['objectType'] == pddl_params['mrecep_target']))
        ])

        receptacle_nearest_point_strs = sorted(
            # ['(receptacleAtLocation {obj} {loc})'.format(obj=obj_id, loc=obj_id + "|loc")
            [
                '(receptacleAtLocation %s loc|%d|%d|%d|%d)' % (obj_id, *point)
                for obj_id, point in self.receptacle_to_point.items()
                if (object_dict[obj_id]['objectType'] in constants.RECEPTACLES
                    and object_dict[obj_id]['objectType'] not in
                    constants.MOVABLE_RECEPTACLES_SET)
            ])
        receptacle_at_location_str = '\n        '.join(
            receptacle_nearest_point_strs)

        receptacle_can_holds = []
        obj_types_in_scene = [
            obj['objectType'] for obj in object_dict.values()
        ]
        for recep in receptacles:
            recep_type = object_dict[recep]['objectType']
            for obj in constants.VAL_RECEPTACLE_OBJECTS[recep_type]:
                if obj in obj_types_in_scene:
                    can_hold_str = '(canContain %sType %sType)' % (recep_type,
                                                                   obj)
                    receptacle_can_holds.append(can_hold_str)
        receptacle_can_holds_str = '\n        '.join(receptacle_can_holds)

        extra_facts = self.get_extra_facts()

        # salient_mat_str = '\n        '.join(['(salientMaterials %s %s)' % (obj, ','.join(object_dict[obj]['salientMaterials']))
        #                                      for obj in objects if object_dict[obj]['salientMaterials'] is not None])

        # mass_props_str = '\n        '.join(['(mass %s %s)' % (obj, str(object_dict[obj]['mass']))
        #                                     for obj in objects])

        # temp_props_str = '\n        '.join(['(temp %s %s)' % (obj, object_dict[obj]['ObjectTemperature'])
        #                                     for obj in objects])

        pddl_mid_start = '''
        %s
        %s
        %s
        )
    ''' % (
            object_str,
            receptacle_str,
            location_str,
        )
        pddl_mid_init = '''
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        %s
        )
    ''' % (
            receptacle_type_str,
            object_type_str,
            receptacle_can_holds_str,
            # salient_mat_str,
            # mass_props_str,
            # temp_props_str,
            pickupable_str,
            receptacle_objects_str,
            openable_str,
            agent_location_str,
            opened_receptacle_str,
            cleanable_str,
            is_clean_str,
            heatable_str,
            coolable_str,
            is_hot_str,
            is_cool_str,
            toggleable_str,
            is_on_str,
            recep_obj_str,
            sliceable_str,
            is_sliced_str,
            in_receptacle_str,
            was_in_receptacle_str,
            location_distance_str,
            receptacle_at_location_str,
            extra_facts,
        )

        pddl_mid_start = fix_pddl_str_chars(pddl_mid_start)
        pddl_mid_init = fix_pddl_str_chars(pddl_mid_init)

        pddl_str = (pddl_start + '\n' + pddl_mid_start + '\n' + pddl_init +
                    '\n' + pddl_mid_init + '\n' + pddl_goal)

        return pddl_str
コード例 #4
0
        agent_height = env.last_event.metadata['agent']['position']['y']
        action = {'action': 'TeleportFull',
                  'x': start_pose[0] * constants.AGENT_STEP_SIZE,
                  'y': agent_height,
                  'z': start_pose[1] * constants.AGENT_STEP_SIZE,
                  'rotateOnTeleport': True,
                  'rotation': start_pose[2],
                  'horizon': start_pose[3],
                  }
        env.step(action)
        actions, path = graph.get_shortest_path(start_pose, end_pose)
        while len(actions) > 0:
            for ii, (action, pose) in enumerate(zip(actions, path)):
                env.step(action)
                event = env.last_event
                last_action_success = event.metadata['lastActionSuccess']

                if not last_action_success:
                    # Can't traverse here, make sure the weight is correct.
                    if action['action'].startswith('Look') or action['action'].startswith('Rotate'):
                        raise Exception('Look action failed %s' % event.metadata['errorMessage'])
                    graph.add_impossible_spot(path[ii + 1])
                    break
            pose = game_util.get_pose(event)
            actions, path = graph.get_shortest_path(pose, end_pose)
        if end_pose == pose:
            print('made it')
        else:
            print('could not make it :(')

コード例 #5
0
    def reset(self, scene_num=None, use_gt=True, seed=None, max_num_repeats=constants.MAX_NUM_OF_OBJ_INSTANCES,
              remove_prob=None, scene=None, objs=None):
        # Reset should be called only when all information from a scene should be cleared.
        self.current_frame_count = 0
        self.timers = np.zeros((2, 2))
        self.board = None
        self.original_board = None
        self.currently_opened_object_ids = SetWithGet()

        self.cleaned_object_ids = SetWithGet()
        self.hot_object_ids = SetWithGet()
        self.cool_object_ids = SetWithGet()

        self.on_object_ids = set()
        self.toggleable_object_ids = set()
        self.sliced_object_ids = set()

        self.inventory_ids = SetWithGet()
        self.scene_name = None
        self.bounds = None
        self.start_point = None
        self.event = None
        self.s_t = None
        self.s_t_orig = None
        self.s_t_depth = None
        self.pose = None
        self.agent_height = None
        self.camera_height = None

        new_scene = (self.gt_graph is None or self.gt_graph.scene_id is None or self.gt_graph.scene_id == scene_num)
        self.scene_num = scene_num

        if self.scene_num is None:
            self.scene_num = self.local_random.choice(constants.SCENE_NUMBERS)
        self.scene_num = self.scene_num

        if scene is not None:
            self.scene_num = scene['scene_num']
            seed = scene['random_seed']

        self.scene_name = 'FloorPlan%d' % self.scene_num
        self.event = self.env.reset(self.scene_name)
        if max_num_repeats is None:
            self.event = self.env.random_initialize(seed)
        else:
            self.env.step(dict(
                action='Initialize',
                gridSize=constants.AGENT_STEP_SIZE / constants.RECORD_SMOOTHING_FACTOR,
                cameraY=constants.CAMERA_HEIGHT_OFFSET,
                renderImage=constants.RENDER_IMAGE,
                renderDepthImage=constants.RENDER_DEPTH_IMAGE,
                renderClassImage=constants.RENDER_CLASS_IMAGE,
                renderObjectImage=constants.RENDER_OBJECT_IMAGE,
                visibility_distance=constants.VISIBILITY_DISTANCE,
                makeAgentsVisible=False,
            ))

            free_per_receptacle = []
            if objs is not None:
                if 'sparse' in objs:
                    for o, c in objs['sparse']:
                        free_per_receptacle.append({'objectType': o, 'count': c})
                if 'empty' in objs:
                    for o, c in objs['empty']:
                        free_per_receptacle.append({'objectType': o, 'count': c})
            self.env.step(dict(action='InitialRandomSpawn', randomSeed=seed, forceVisible=False,
                               numRepeats=[{'objectType': o, 'count': c}
                                           for o, c in objs['repeat']]
                               if objs is not None and 'repeat' in objs else None,
                               minFreePerReceptacleType=free_per_receptacle if objs is not None else None
                               ))

            # if 'clean' action, make everything dirty and empty out fillable things
            if constants.pddl_goal_type == "pick_clean_then_place_in_recep":
                self.env.step(dict(action='SetStateOfAllObjects',
                                   StateChange="CanBeDirty",
                                   forceAction=True))

                self.env.step(dict(action='SetStateOfAllObjects',
                                   StateChange="CanBeFilled",
                                   forceAction=False))

            if objs is not None and ('seton' in objs and len(objs['seton']) > 0):
                self.env.step(dict(action='SetObjectToggles',
                                   objectToggles=[{'objectType': o, 'isOn': v}
                                                  for o, v in objs['seton']]))

        self.gt_graph = graph_obj.Graph(use_gt=True, construct_graph=True, scene_id=self.scene_num)

        if seed is not None:
            self.local_random.seed(seed)
            print('set seed in game_state_base reset', seed)

        self.bounds = np.array([self.gt_graph.xMin, self.gt_graph.yMin,
                                self.gt_graph.xMax - self.gt_graph.xMin + 1,
                                self.gt_graph.yMax - self.gt_graph.yMin + 1])

        self.agent_height = self.env.last_event.metadata['agent']['position']['y']
        self.camera_height = self.agent_height + constants.CAMERA_HEIGHT_OFFSET
        start_point = self.local_random.randint(0, self.gt_graph.points.shape[0] - 1)
        start_point = self.gt_graph.points[start_point, :].copy()
        self.start_point = (start_point[0], start_point[1], self.local_random.randint(0, 3))

        action = {'action': 'TeleportFull',
                  'x': self.start_point[0] * constants.AGENT_STEP_SIZE,
                  'y': self.agent_height,
                  'z': self.start_point[1] * constants.AGENT_STEP_SIZE,
                  'rotateOnTeleport': True,
                  'horizon': 30,
                  'rotation': self.start_point[2] * 90,
                  }
        self.event = self.env.step(action)

        constants.data_dict['scene']['scene_num'] = self.scene_num
        constants.data_dict['scene']['init_action'] = action
        constants.data_dict['scene']['floor_plan'] = self.scene_name
        constants.data_dict['scene']['random_seed'] = seed

        self.pose = game_util.get_pose(self.event)

        # Manually populate parentReceptacles data based on existing ReceptableObjectIds.
        objects = self.env.last_event.metadata['objects']
        for idx in range(len(objects)):
            if objects[idx]['parentReceptacles'] is None:
                objects[idx]['parentReceptacles'] = []
                for jdx in range(len(objects)):
                    if (objects[jdx]['receptacleObjectIds'] is not None
                            and objects[idx]['objectId'] in objects[jdx]['receptacleObjectIds']):
                        objects[idx]['parentReceptacles'].append(objects[jdx]['objectId'])
コード例 #6
0
    def step(self, action_or_ind, process_frame=True):
        if self.event is None:
            self.event = self.env.last_event
        self.current_frame_count += 1
        self.total_frame_count += 1
        action, should_fail = self.get_action(action_or_ind)
        if should_fail:
            self.env.last_event.metadata['lastActionSuccess'] = False
        else:
            t_start = time.time()
            start_pose = game_util.get_pose(self.event)
            if 'action' not in action or action['action'] is None or action['action'] == 'None':
                self.env.last_event.metadata['lastActionSuccess'] = True
            else:
                if constants.RECORD_VIDEO_IMAGES:
                    im_ind = len(glob.glob(constants.save_path + '/*.png'))
                    if 'Teleport' in action['action']:
                        position = self.env.last_event.metadata['agent']['position']
                        rotation = self.env.last_event.metadata['agent']['rotation']
                        start_horizon = self.env.last_event.metadata['agent']['cameraHorizon']
                        start_rotation = rotation['y']
                        if (np.abs(action['x'] - position['x']) > 0.001 or
                            np.abs(action['z'] - position['z']) > 0.001):
                            # Movement
                            for xx in np.arange(.1, 1, .1):
                                new_action = copy.deepcopy(action)
                                new_action['x'] = np.round(position['x'] * (1 - xx) + action['x'] * xx, 5)
                                new_action['z'] = np.round(position['z'] * (1 - xx) + action['z'] * xx, 5)
                                new_action['rotation'] = start_rotation
                                new_action['horizon'] = start_horizon
                                self.event = self.env.step(new_action)
                                cv2.imwrite(constants.save_path + '/%09d.png' % im_ind,
                                            self.event.frame[:, :, ::-1])
                                # #game_util.store_image_name('%09d.png' % im_ind)  # eww... seriously need to clean this up
                                im_ind += 1
                        if np.abs(action['horizon'] - self.env.last_event.metadata['agent']['cameraHorizon']) > 0.001:
                            end_horizon = action['horizon']
                            for xx in np.arange(.1, 1, .1):
                                new_action = copy.deepcopy(action)
                                new_action['horizon'] = np.round(start_horizon * (1 - xx) + end_horizon * xx, 3)
                                new_action['rotation'] = start_rotation
                                self.event = self.env.step(new_action)
                                cv2.imwrite(constants.save_path + '/%09d.png' % im_ind,
                                            self.event.frame[:, :, ::-1])
                                #game_util.store_image_name('%09d.png' % im_ind)
                                im_ind += 1
                        if np.abs(action['rotation'] - rotation['y']) > 0.001:
                            end_rotation = action['rotation']
                            for xx in np.arange(.1, 1, .1):
                                new_action = copy.deepcopy(action)
                                new_action['rotation'] = np.round(start_rotation * (1 - xx) + end_rotation * xx, 3)
                                self.event = self.env.step(new_action)
                                cv2.imwrite(constants.save_path + '/%09d.png' % im_ind,
                                            self.event.frame[:, :, ::-1])
                                #game_util.store_image_name('%09d.png' % im_ind)
                                im_ind += 1

                        self.event = self.env.step(action)

                    # elif 'MoveAhead' in action['action']:
                    #     # self.store_ll_action(action)
                    #     # self.save_image(1)
                    #     events = self.env.smooth_move_ahead(action)
                    #     # for event in events:
                    #     #     im_ind = len(glob.glob(constants.save_path + '/*.png'))
                    #     #     cv2.imwrite(constants.save_path + '/%09d.png' % im_ind, event.frame[:, :, ::-1])
                    #     #     #game_util.store_image_name('%09d.png' % im_ind)
                    #
                    # elif 'Rotate' in action['action']:
                    #     # self.store_ll_action(action)
                    #     # self.save_image(1)
                    #     events = self.env.smooth_rotate(action)
                    #     # for event in events:
                    #     #     im_ind = len(glob.glob(constants.save_path + '/*.png'))
                    #     #     cv2.imwrite(constants.save_path + '/%09d.png' % im_ind, event.frame[:, :, ::-1])
                    #     #     #game_util.store_image_name('%09d.png' % im_ind)
                    #
                    # elif 'Look' in action['action']:
                    #     # self.store_ll_action(action)
                    #     # self.save_image(1)
                    #     events = self.env.smooth_look(action)
                    #     # for event in events:
                    #     #     im_ind = len(glob.glob(constants.save_path + '/*.png'))
                    #     #     cv2.imwrite(constants.save_path + '/%09d.png' % im_ind, event.frame[:, :, ::-1])
                    #     #     #game_util.store_image_name('%09d.png' % im_ind)

                    elif 'OpenObject' in action['action']:
                        open_action = dict(action=action['action'],
                                           objectId=action['objectId'],
                                           moveMagnitude=1.0)
                        # self.store_ll_action(open_action)
                        # self.save_act_image(open_action, dir=constants.BEFORE)

                        self.event = self.env.step(open_action)

                        # self.save_act_image(open_action, dir=constants.AFTER)
                        self.check_action_success(self.event)

                    elif 'CloseObject' in action['action']:
                        close_action = dict(action=action['action'],
                                            objectId=action['objectId'])
                        # self.store_ll_action(close_action)
                        # self.save_act_image(close_action, dir=constants.BEFORE)

                        self.event = self.env.step(close_action)

                        # self.save_act_image(close_action, dir=constants.AFTER)
                        self.check_action_success(self.event)

                    elif 'PickupObject' in action['action']:
                        # [hack] correct object ids of slices
                        action['objectId'] = self.correct_slice_id(action['objectId'])

                        # open the receptacle if needed
                        parent_recep = self.get_parent_receps(action['objectId'])
                        if parent_recep is not None and parent_recep['objectType'] in constants.OPENABLE_CLASS_SET:
                            self.open_recep(parent_recep)  # stores LL action

                        # close/open the object if needed
                        pickup_obj = game_util.get_object(action['objectId'], self.env.last_event.metadata)
                        if pickup_obj['objectType'] in constants.FORCED_OPEN_STATE_ON_PICKUP:
                            if pickup_obj['isOpen'] != constants.FORCED_OPEN_STATE_ON_PICKUP[pickup_obj['objectType']]:
                                if pickup_obj['isOpen']:
                                    self.close_recep(pickup_obj)  # stores LL action
                                else:
                                    self.open_recep(pickup_obj)  # stores LL action

                        # pick up the object
                        self.check_obj_visibility(action, min_pixels=10)
                        pickup_action = dict(action=action['action'],
                                             objectId=action['objectId'])
                        # self.store_ll_action(pickup_action)
                        # self.save_act_image(pickup_action, dir=constants.BEFORE)

                        self.event = self.env.step(pickup_action)

                        # self.save_act_image(pickup_action, dir=constants.AFTER)
                        self.check_action_success(self.event)

                        # close the receptacle if needed
                        if parent_recep is not None:
                            parent_recep = game_util.get_object(parent_recep['objectId'], self.env.last_event.metadata)
                            self.close_recep(parent_recep)  # stores LL action

                    elif 'PutObject' in action['action']:
                        if len(self.env.last_event.metadata['inventoryObjects']) > 0:
                            inv_obj = self.env.last_event.metadata['inventoryObjects'][0]['objectId']
                        else:
                            raise RuntimeError("Taking 'PutObject' action with no held inventory object")
                        action['objectId'] = inv_obj

                        # open the receptacle if needed
                        parent_recep = game_util.get_object(action['receptacleObjectId'], self.env.last_event.metadata)
                        if parent_recep is not None and parent_recep['objectType'] in constants.OPENABLE_CLASS_SET:
                            self.open_recep(parent_recep)  # stores LL action

                        # Open the parent receptacle of the movable receptacle target.
                        elif parent_recep['objectType'] in constants.MOVABLE_RECEPTACLES_SET:
                            movable_parent_recep_ids = parent_recep['parentReceptacles']
                            if movable_parent_recep_ids is not None and len(movable_parent_recep_ids) > 0:
                                print(parent_recep['objectId'], movable_parent_recep_ids)  # DEBUG
                                movable_parent_recep = game_util.get_object(movable_parent_recep_ids[0],
                                                                            self.env.last_event.metadata)
                                if movable_parent_recep['objectType'] in constants.OPENABLE_CLASS_SET:
                                    self.open_recep(movable_parent_recep)  # stores LL action

                        # put the object
                        put_action = dict(action=action['action'],
                                          objectId=action['objectId'],
                                          receptacleObjectId=action['receptacleObjectId'],
                                          forceAction=True,
                                          placeStationary=True)
                        # self.store_ll_action(put_action)
                        # self.save_act_image(put_action, dir=constants.BEFORE)

                        self.event = self.env.step(put_action)

                        # self.save_act_image(put_action, dir=constants.AFTER)
                        self.check_obj_visibility(action)
                        self.check_action_success(self.event)

                        # close the receptacle if needed
                        if parent_recep is not None:
                            parent_recep = game_util.get_object(parent_recep['objectId'], self.env.last_event.metadata)
                            self.close_recep(parent_recep)  # stores LL action

                    elif 'CleanObject' in action['action']:
                        # put the object in the sink
                        sink_obj_id = self.get_some_visible_obj_of_name('SinkBasin')['objectId']
                        inv_obj = self.env.last_event.metadata['inventoryObjects'][0]
                        put_action = dict(action='PutObject',
                                          objectId=inv_obj['objectId'],
                                          receptacleObjectId=sink_obj_id,
                                          forceAction=True,
                                          placeStationary=True)
                        # self.store_ll_action(put_action)
                        # self.save_act_image(put_action, dir=constants.BEFORE)
                        self.event = self.env.step(put_action)
                        # self.save_act_image(put_action, dir=constants.AFTER)
                        self.check_obj_visibility(put_action)
                        self.check_action_success(self.event)

                        # turn on the tap
                        clean_action = copy.deepcopy(action)
                        clean_action['action'] = 'ToggleObjectOn'
                        clean_action['objectId'] = game_util.get_obj_of_type_closest_to_obj(
                            "Faucet", inv_obj['objectId'], self.env.last_event.metadata)['objectId']
                        # self.store_ll_action(clean_action)
                        # self.save_act_image(clean_action, dir=constants.BEFORE)
                        self.event = self.env.step({k: clean_action[k]
                                                    for k in ['action', 'objectId']})
                        # self.save_act_image(clean_action, dir=constants.AFTER)
                        self.check_action_success(self.event)
                        # Need to delay one frame to let `isDirty` update on stream-affected.
                        self.env.noop()

                        # Call built-in 'CleanObject' THOR action on every object in the SinkBasin.
                        # This means we clean everything in the sink, rather than just the things that happen to touch
                        # the water stream, which is the default simulator behavior but looks weird for our purposes.
                        sink_basin_obj = game_util.get_obj_of_type_closest_to_obj(
                            "SinkBasin", clean_action['objectId'], self.env.last_event.metadata)
                        for in_sink_obj_id in sink_basin_obj['receptacleObjectIds']:
                            if (game_util.get_object(in_sink_obj_id, self.env.last_event.metadata)['dirtyable']
                                    and game_util.get_object(in_sink_obj_id, self.env.last_event.metadata)['isDirty']):
                                self.event = self.env.step({'action': 'CleanObject',
                                                            'objectId': in_sink_obj_id})

                        # turn off the tap
                        close_action = copy.deepcopy(clean_action)
                        close_action['action'] = 'ToggleObjectOff'
                        # self.store_ll_action(close_action)
                        # self.save_act_image(close_action, dir=constants.BEFORE)
                        self.event = self.env.step({k: close_action[k]
                                                    for k in ['action', 'objectId']})
                        # self.save_act_image(action, dir=constants.AFTER)
                        self.check_action_success(self.event)

                        # pick up the object from the sink
                        pickup_action = dict(action='PickupObject',
                                             objectId=inv_obj['objectId'])
                        # self.store_ll_action(pickup_action)
                        # self.save_act_image(pickup_action, dir=constants.BEFORE)
                        self.event = self.env.step(pickup_action)
                        # self.save_act_image(pickup_action, dir=constants.AFTER)
                        self.check_obj_visibility(pickup_action)
                        self.check_action_success(self.event)

                    elif 'HeatObject' in action['action']:
                        # open the microwave
                        microwave_obj_id = self.get_some_visible_obj_of_name('Microwave')['objectId']
                        microwave_obj = game_util.get_object(microwave_obj_id, self.env.last_event.metadata)
                        self.open_recep(microwave_obj)

                        # put the object in the microwave
                        inv_obj = self.env.last_event.metadata['inventoryObjects'][0]
                        put_action = dict(action='PutObject',
                                          objectId=inv_obj['objectId'],
                                          receptacleObjectId=microwave_obj_id,
                                          forceAction=True,
                                          placeStationary=True)
                        # self.store_ll_action(put_action)
                        # self.save_act_image(put_action, dir=constants.BEFORE)
                        self.event = self.env.step(put_action)
                        # self.save_act_image(put_action, dir=constants.AFTER)
                        self.check_obj_visibility(put_action)
                        self.check_action_success(self.event)

                        # close the microwave
                        microwave_obj = game_util.get_object(microwave_obj_id, self.env.last_event.metadata)
                        self.close_recep(microwave_obj)

                        # turn on the microwave
                        heat_action = copy.deepcopy(action)
                        heat_action['action'] = 'ToggleObjectOn'
                        heat_action['objectId'] = microwave_obj_id
                        # self.store_ll_action(heat_action)
                        # self.save_act_image(heat_action, dir=constants.BEFORE)
                        self.event = self.env.step({k: heat_action[k]
                                                    for k in ['action', 'objectId']})
                        # self.save_act_image(heat_action, dir=constants.AFTER)

                        # turn off the microwave
                        stop_action = copy.deepcopy(heat_action)
                        stop_action['action'] = 'ToggleObjectOff'
                        # self.store_ll_action(stop_action)
                        # self.save_act_image(stop_action, dir=constants.BEFORE)
                        self.event = self.env.step({k: stop_action[k]
                                                    for k in ['action', 'objectId']})
                        # self.save_act_image(stop_action, dir=constants.AFTER)

                        # open the microwave
                        microwave_obj = game_util.get_object(microwave_obj_id, self.env.last_event.metadata)
                        self.open_recep(microwave_obj)

                        # pick up the object from the microwave
                        pickup_action = dict(action='PickupObject',
                                             objectId=inv_obj['objectId'])
                        # self.store_ll_action(pickup_action)
                        # self.save_act_image(pickup_action, dir=constants.BEFORE)
                        self.event = self.env.step(pickup_action)
                        # self.save_act_image(pickup_action, dir=constants.AFTER)
                        self.check_obj_visibility(pickup_action)
                        self.check_action_success(self.event)

                        # close the microwave again
                        microwave_obj = game_util.get_object(microwave_obj_id, self.env.last_event.metadata)
                        self.close_recep(microwave_obj)

                    elif 'CoolObject' in action['action']:
                        # open the fridge
                        fridge_obj_id = self.get_some_visible_obj_of_name('Fridge')['objectId']
                        fridge_obj = game_util.get_object(fridge_obj_id, self.env.last_event.metadata)
                        self.open_recep(fridge_obj)

                        # put the object in the fridge
                        inv_obj = self.env.last_event.metadata['inventoryObjects'][0]
                        put_action = dict(action='PutObject',
                                          objectId=inv_obj['objectId'],
                                          receptacleObjectId=fridge_obj_id,
                                          forceAction=True,
                                          placeStationary=True)
                        # self.store_ll_action(put_action)
                        # self.save_act_image(put_action, dir=constants.BEFORE)
                        self.event = self.env.step(put_action)
                        # self.save_act_image(put_action, dir=constants.AFTER)
                        self.check_obj_visibility(put_action)
                        self.check_action_success(self.event)

                        # close and cool the object inside the frige
                        cool_action = dict(action='CloseObject',
                                           objectId=action['objectId'])
                        # self.store_ll_action(cool_action)
                        # self.save_act_image(action, dir=constants.BEFORE)
                        self.event = self.env.step(cool_action)
                        # self.save_act_image(action, dir=constants.MIDDLE)
                        # self.save_act_image(action, dir=constants.AFTER)

                        # open the fridge again
                        fridge_obj = game_util.get_object(fridge_obj_id, self.env.last_event.metadata)
                        self.open_recep(fridge_obj)

                        # pick up the object from the fridge
                        pickup_action = dict(action='PickupObject',
                                             objectId=inv_obj['objectId'])
                        # self.store_ll_action(pickup_action)
                        # self.save_act_image(pickup_action, dir=constants.BEFORE)
                        self.event = self.env.step(pickup_action)
                        # self.save_act_image(pickup_action, dir=constants.AFTER)
                        self.check_obj_visibility(pickup_action)
                        self.check_action_success(self.event)

                        # close the fridge again
                        fridge_obj = game_util.get_object(fridge_obj_id, self.env.last_event.metadata)
                        self.close_recep(fridge_obj)

                    elif 'ToggleObject' in action['action']:
                        on_action = dict(action=action['action'],
                                         objectId=action['objectId'])

                        toggle_obj = game_util.get_object(action['objectId'], self.env.last_event.metadata)
                        on_action['action'] = 'ToggleObjectOff' if toggle_obj['isToggled'] else 'ToggleObjectOn'
                        # self.store_ll_action(on_action)
                        # self.save_act_image(on_action, dir=constants.BEFORE)
                        self.event = self.env.step(on_action)
                        # self.save_act_image(on_action, dir=constants.AFTER)
                        self.check_action_success(self.event)

                    elif 'SliceObject' in action['action']:
                        # open the receptacle if needed
                        parent_recep = self.get_parent_receps(action['objectId'])
                        if parent_recep is not None and parent_recep['objectType'] in constants.OPENABLE_CLASS_SET:
                            self.open_recep(parent_recep)

                        # slice the object
                        slice_action = dict(action=action['action'],
                                            objectId=action['objectId'])
                        # self.store_ll_action(slice_action)
                        # self.save_act_image(slice_action, dir=constants.BEFORE)
                        self.event = self.env.step(slice_action)
                        # self.save_act_image(action, dir=constants.AFTER)
                        self.check_action_success(self.event)

                        # close the receptacle if needed
                        if parent_recep is not None:
                            parent_recep = game_util.get_object(parent_recep['objectId'], self.env.last_event.metadata)
                            self.close_recep(parent_recep)  # stores LL action

                    else:
                        # check that the object to pick is visible in the camera frame
                        if action['action'] == 'PickupObject':
                            self.check_obj_visibility(action)

                        # self.store_ll_action(action)
                        # self.save_act_image(action, dir=constants.BEFORE)

                        self.event = self.env.step(action)

                        # self.save_act_image(action, dir=constants.AFTER)

                        if action['action'] == 'PutObject':
                            self.check_obj_visibility(action)
                else:
                    self.event = self.env.step(action)
                new_pose = game_util.get_pose(self.event)
                point_dists = np.sum(np.abs(self.gt_graph.points - np.array(new_pose)[:2]), axis=1)
                if np.min(point_dists) > 0.0001:
                    # print('Point teleport failure')
                    self.event = self.env.step({
                        'action': 'Teleport',
                        'x': start_pose[0] * constants.AGENT_STEP_SIZE,
                        'y': self.agent_height,
                        'z': start_pose[1] * constants.AGENT_STEP_SIZE,
                        'rotateOnTeleport': True,
                        'rotation': new_pose[2] * 90,
                    })
                    self.env.last_event.metadata['lastActionSuccess'] = False

            self.timers[0, 0] += time.time() - t_start
            self.timers[0, 1] += 1
            if self.timers[0, 1] % 100 == 0:
                # print('env step time %.3f' % (self.timers[0, 0] / self.timers[0, 1]))
                self.timers[0, :] = 0

        if self.env.last_event.metadata['lastActionSuccess']:
            if action['action'] == 'OpenObject':
                self.currently_opened_object_ids.add(action['objectId'])
            elif action['action'] == 'CloseObject':
                self.currently_opened_object_ids.remove(action['objectId'])
            elif action['action'] == 'PickupObject':
                self.inventory_ids.add(action['objectId'])
            elif action['action'] == 'PutObject':
                self.inventory_ids.remove(action['objectId'])

        if self.env.last_event.metadata['lastActionSuccess'] and process_frame:
            self.process_frame()