def update_states(self, action): ''' extra updates to metadata after step ''' # add 'cleaned' to all object that were washed in the sink event = self.last_event if event.metadata['lastActionSuccess']: # clean if action['action'] == 'ToggleObjectOn' and "Faucet" in action[ 'objectId']: sink_basin = get_obj_of_type_closest_to_obj( 'SinkBasin', action['objectId'], event.metadata) cleaned_object_ids = sink_basin['receptacleObjectIds'] self.cleaned_objects = self.cleaned_objects | set( cleaned_object_ids ) if cleaned_object_ids is not None else set() # heat if action['action'] == 'ToggleObjectOn' and "Microwave" in action[ 'objectId']: microwave = get_objects_of_type('Microwave', event.metadata)[0] heated_object_ids = microwave['receptacleObjectIds'] self.heated_objects = self.heated_objects | set( heated_object_ids ) if heated_object_ids is not None else set() # cool if action['action'] == 'CloseObject' and "Fridge" in action[ 'objectId']: fridge = get_objects_of_type('Fridge', event.metadata)[0] cooled_object_ids = fridge['receptacleObjectIds'] self.cooled_objects = self.cooled_objects | set( cooled_object_ids ) if cooled_object_ids is not None else set() return event
def setup_problem(self, seed=None, info=None, scene=None, objs=None): ''' setup goal with sampled objects or with the objects specified note: must be used with `initialize_random_scene` ''' self.terminal = False print( 'setup random goal ----------------------------------------------') print('seed', seed) print('info', info) print( '--------------------------------------------------------------------\n\n' ) super(TaskGameState, self).setup_problem(seed) info, max_num_repeats, remove_prob = self.get_random_task_vals( scene=scene) dataset_type, task_row = info print('Type:', dataset_type, 'Row: ', task_row, 'Scene', self.scene_name, 'seed', self.scene_seed) perform_sanity_check = True # pickupable, receptacle, toggleable candidates pickupable_objects = [ o for o in self.env.last_event.metadata['objects'] if (o['pickupable'] and o['objectType'] in constants.OBJECTS) ] receptacle_objects = [ o for o in self.env.last_event.metadata['objects'] if (o['receptacle'] and o['objectType'] in constants.RECEPTACLES and o['objectType'] not in constants.MOVABLE_RECEPTACLES_SET) ] toggle_objects = [ o for o in self.env.last_event.metadata['objects'] if o['toggleable'] and not o['isToggled'] # must be one we can turn on. and o['objectType'] in constants.VAL_ACTION_OBJECTS["Toggleable"] ] if len(pickupable_objects) == 0: print("Task Failed - %s" % constants.pddl_goal_type) raise Exception("No pickupable objects in the scene") # filter based on crit obj_crit, _ = self.get_filter_crit(constants.pddl_goal_type) pickupable_objects = list(filter(obj_crit, pickupable_objects)) if len(pickupable_objects) == 0: print("Task Failed - %s" % constants.pddl_goal_type) raise Exception("No pickupable objects related to the goal '%s'" % constants.pddl_goal_type) # choose a pickupable object if constants.FORCED_SAMPLING or objs is None: self.rand_chosen_object = random.choice(pickupable_objects) else: chosen_class_available = [ obj for obj in pickupable_objects if obj['objectType'] == constants.OBJ_PARENTS[objs['pickup']] ] if len(chosen_class_available) == 0: print("Task Failed - %s" % constants.pddl_goal_type) raise Exception( "Couldn't find a valid parent '%s' for pickup object with class '%s'" % (constants.OBJ_PARENTS[objs['pickup']], objs['pickup'])) self.rand_chosen_object = random.choice(chosen_class_available) self.rand_chosen_object_class = self.rand_chosen_object['objectType'] self.object_target = constants.OBJECTS.index( self.rand_chosen_object_class) # for now, any obj differing from its parent is obtained via slicing, but that may change in the future. if constants.OBJ_PARENTS[objs['pickup']] != objs['pickup']: requires_slicing = True else: requires_slicing = False # choose a movable receptacle if "movable_recep" in constants.pddl_goal_type: val_movable_receps = [ o for o in self.env.last_event.metadata['objects'] if (o['objectType'] in constants.MOVABLE_RECEPTACLES_SET) and ( self.rand_chosen_object_class in constants.VAL_RECEPTACLE_OBJECTS[o['objectType']]) ] if len(val_movable_receps) == 0: print("Task Failed - %s" % constants.pddl_goal_type) raise Exception( "Couldn't find a valid moveable receptacle for the chosen object class" ) if objs is not None: val_movable_receps = [ o for o in val_movable_receps if o['objectType'] == objs['mrecep'] ] self.rand_chosen_val_moveable_recep_class = random.choice( val_movable_receps)['objectType'] self.mrecep_target = constants.OBJECTS.index( self.rand_chosen_val_moveable_recep_class) else: self.mrecep_target = None # if slicing is required, make sure a knife is available in the scene if requires_slicing: knife_objs = [ o for o in self.env.last_event.metadata['objects'] if ("Knife" in o['objectType']) ] if len(knife_objs) == 0: print("Task Failed - %s" % constants.pddl_goal_type) raise Exception("Couldn't find knife in the scene to cut with") if constants.pddl_goal_type == "look_at_obj_in_light": # choose a toggleable object self.parent_target = None if constants.FORCED_SAMPLING or objs is None: rand_chosen_toggle_object = random.choice(toggle_objects) else: toggle_class_available = [ obj for obj in toggle_objects if obj['objectType'] == objs['toggle'] ] if len(toggle_class_available) == 0: print("Task Failed - %s" % constants.pddl_goal_type) raise Exception( "Couldn't find a valid toggle object of class '%s'" % objs['toggle']) rand_chosen_toggle_object = random.choice( toggle_class_available) rand_chosen_toggle_class = rand_chosen_toggle_object['objectType'] self.toggle_target = constants.OBJECTS.index( rand_chosen_toggle_class) else: self.toggle_target = None # find all valid receptacles in which rand_chosen object or rand chosen moveable receptacle can be placed val_receptacle_objects_orig = [ r for r in receptacle_objects if (self.rand_chosen_val_moveable_recep_class if self. mrecep_target != None else self.rand_chosen_object_class ) in constants.VAL_RECEPTACLE_OBJECTS[r['objectType']] ] _, recep_crit = self.get_filter_crit(constants.pddl_goal_type) val_receptacle_objects = list( filter(recep_crit, val_receptacle_objects_orig)) if len(val_receptacle_objects) == 0: print("Task Failed - %s" % constants.pddl_goal_type) raise Exception( "Couldn't find a valid receptacle object according to constraints specified" ) # choose a receptacle object if constants.FORCED_SAMPLING or objs is None: rand_chosen_receptacle_object = random.choice( val_receptacle_objects) else: receptacle_class_available = [ obj for obj in val_receptacle_objects if obj['objectType'] == objs['receptacle'] ] if len(receptacle_class_available) == 0: print("Task Failed - %s" % constants.pddl_goal_type) raise Exception( "Couldn't find a valid receptacle object of class '%s'" % objs['receptacle']) rand_chosen_receptacle_object = random.choice( receptacle_class_available) rand_chosen_receptacle_object_class = rand_chosen_receptacle_object[ 'objectType'] self.parent_target = constants.OBJECTS.index( rand_chosen_receptacle_object_class) # pddl_param dict constants.data_dict['pddl_params'][ 'object_target'] = constants.OBJECTS[ self.object_target] if self.object_target is not None else "" constants.data_dict['pddl_params']['object_sliced'] = requires_slicing constants.data_dict['pddl_params'][ 'parent_target'] = constants.OBJECTS[ self.parent_target] if self.parent_target is not None else "" constants.data_dict['pddl_params'][ 'toggle_target'] = constants.OBJECTS[ self.toggle_target] if self.toggle_target is not None else "" constants.data_dict['pddl_params'][ 'mrecep_target'] = constants.OBJECTS[ self.mrecep_target] if self.mrecep_target is not None else "" self.task_target = (self.object_target, self.parent_target, self.toggle_target, self.mrecep_target) if self.parent_target is None: validity_check = True else: objs = game_util.get_objects_of_type( constants.OBJECTS[self.object_target], self.env.last_event.metadata) available_receptacles = game_util.get_objects_of_type( constants.OBJECTS[self.parent_target], self.env.last_event.metadata) validity_check = (len(objs) > 0 and len([obj for obj in available_receptacles])) if perform_sanity_check: try: assert validity_check, 'Task does not seem valid according to scene metadata' except AssertionError: raise Exception( str(('Row: ', task_row, 'Scene', self.scene_name, 'seed', self.scene_seed))) templated_task_desc = self.get_task_str() print('problem id', self.problem_id) print('Task:', templated_task_desc) constants.data_dict['template']['task_desc'] = templated_task_desc
def does_have_atleast_n_duplicates(x, n): num_instances = len( game_util.get_objects_of_type(x['objectType'], self.env.last_event.metadata)) return num_instances >= n