def choose_object_def(self) -> Dict[str, Any]: """Pick one object definition (to be added to the scene) and return a copy of it.""" object_def_list = random.choices([ objects.OBJECTS_PICKUPABLE, objects.OBJECTS_MOVEABLE, objects.OBJECTS_IMMOBILE ], [50, 25, 25])[0] return util.finalize_object_definition(random.choice(object_def_list))
def _create_b(self) -> Dict[str, Any]: a = self._scenes[0]['objects'][0] possible_defs = [] normalized_scale = a['shows'][0]['scale'] # cylinders have "special" scaling: scale.y is half what it is # for other objects (because Unity automatically doubles the # scale.y of cylinders) if a['type'] == 'cylinder': normalized_scale = normalized_scale.copy() normalized_scale['y'] *= 2 for obj_def in objects.OBJECTS_INTPHYS: if obj_def['type'] != a['type']: def_scale = obj_def['scale'] if obj_def['type'] == 'cylinder': def_scale = def_scale.copy() def_scale['y'] *= 2 if def_scale == normalized_scale: possible_defs.append(obj_def) if len(possible_defs) == 0: raise goal.GoalException( f'no valid choices for "b" object. a = {a}') b_def = random.choice(possible_defs) b_def = util.finalize_object_definition(b_def) b = util.instantiate_object(b_def, a['original_location'], a['materials_list']) logging.debug(f'a type: {a["type"]}\tb type: {b["type"]}') return b
def test_can_contain_both(): small1 = {'dimensions': {'x': 0.01, 'y': 0.01, 'z': 0.01}} small2 = {'dimensions': {'x': 0.02, 'y': 0.02, 'z': 0.02}} big = {'dimensions': {'x': 42, 'y': 42, 'z': 42}} container_def = util.finalize_object_definition(DEFAULT_CONTAINER) assert can_contain_both(container_def, small1, small2) is not None assert can_contain_both(container_def, small1, big) is None
def move_to_container(target: Dict[str, Any], all_objects: List[Dict[str, Any]], bounding_rects: List[List[Dict[str, float]]], performer_position: Dict[str, float]) -> bool: """Try to find a random container that target will fit in. If found, set the target's locationParent, and add container to all_objects (and bounding_rects). Return True iff the target was put in a container.""" shuffled_containers = objects.get_enclosed_containers().copy() random.shuffle(shuffled_containers) for container_def in shuffled_containers: container_def = finalize_object_definition(container_def) area_index = geometry.can_contain(container_def, target) if area_index is not None: # try to place the container before we accept it container_location = geometry.calc_obj_pos(performer_position, bounding_rects, container_def) if container_location is not None: found_container = instantiate_object(container_def, container_location) found_area = container_def['enclosed_areas'][area_index] all_objects.append(found_container) target['locationParent'] = found_container['id'] target['shows'][0]['position'] = found_area['position'].copy() if 'rotation' not in target['shows'][0]: target['shows'][0]['rotation'] = geometry.ORIGIN.copy() return True return False
def choose_definition( self, must_be_pickupable: bool = False ) -> Dict[str, Any]: """Choose and return an object definition.""" definition_list = random.choice(retrieve_trained_definition_list( objects.get(objects.ObjectDefinitionList.PICKUPABLES) if must_be_pickupable else objects.get(objects.ObjectDefinitionList.ALL) )) # Same chance to pick each object definition from the list. definition = finalize_object_definition(random.choice(definition_list)) # Finalize the material here in case we need to make a confusor. return random.choice(finalize_object_materials_and_colors(definition))
def choose_target_definition(self, target_number: int) -> Dict[str, Any]: if target_number == 0: return self.choose_definition(must_be_pickupable=True) if target_number != 1: raise exceptions.SceneException( f'Expected target with number 0 or 1 but got {target_number}') definition_list = random.choice(retrieve_trained_definition_list( objects.get(objects.ObjectDefinitionList.STACK_TARGETS) )) # Same chance to pick each object definition from the list. definition = finalize_object_definition(random.choice(definition_list)) # Finalize the material here in case we need to make a confusor. return random.choice(finalize_object_materials_and_colors(definition))
def test_move_to_container(): # find a tiny object so we know it will fit in *something* for obj_def in objects.OBJECTS_PICKUPABLE: obj_def = finalize_object_definition(obj_def) if 'tiny' in obj_def['info']: obj = instantiate_object(obj_def, geometry.ORIGIN_LOCATION) all_objects = [obj] tries = 0 while tries < 100: if move_to_container(obj, all_objects, [], geometry.ORIGIN): break tries += 1 if tries == 100: logging.error('could not put the object in any container') container_id = all_objects[1]['id'] assert obj['locationParent'] == container_id return assert False, 'could not find a tiny object'
def test_finalize_object_definition(): object_type = 'type1' mass = 12.34 material_category = ['plastic'] salient_materials = ['plastic', 'hollow'] object_def = { 'type': 'type2', 'mass': 56.78, 'choose': [{ 'type': object_type, 'mass': mass, 'materialCategory': material_category, 'salientMaterials': salient_materials }] } obj = finalize_object_definition(object_def) assert obj['type'] == object_type assert obj['mass'] == mass assert obj['materialCategory'] == material_category assert obj['salientMaterials'] == salient_materials
def _compute_scenery(self): MIN_VISIBLE_X = -6.5 MAX_VISIBLE_X = 6.5 MIN_Z = 3.25 MAX_Z = 4.95 def random_x(): return random_real(MIN_VISIBLE_X, MAX_VISIBLE_X, MIN_RANDOM_INTERVAL) def random_z(): # Choose values so the scenery is placed between the # moving IntPhys objects and the room's wall. return random_real(MIN_Z, MAX_Z, MIN_RANDOM_INTERVAL) self._scenery_count = random.choices((0, 1, 2, 3, 4, 5), (50, 10, 10, 10, 10, 10))[0] scenery_list = [] scenery_rects = [] scenery_defs = objects.OBJECTS_MOVEABLE + objects.OBJECTS_IMMOBILE for i in range(self._scenery_count): location = None while location is None: scenery_def = finalize_object_definition( random.choice(scenery_defs)) location = geometry.calc_obj_pos(geometry.ORIGIN, scenery_rects, scenery_def, random_x, random_z) if location is not None: # check that the bounds are valid for point in location['bounding_box']: x = point['x'] z = point['z'] if x < MIN_VISIBLE_X or x > MAX_VISIBLE_X or \ z < MIN_Z or z > MAX_Z: # reset location so we try again location = None break scenery_obj = instantiate_object(scenery_def, location) scenery_list.append(scenery_obj) return scenery_list
def test_finalize_object_definition(): dimensions = {'x': 1, 'y': 1, 'z': 1} mass = 12.34 material_category = ['plastic'] salient_materials = ['plastic', 'hollow'] object_def = { 'type': 'type1', 'mass': 56.78, 'chooseMaterial': [{ 'materialCategory': material_category, 'salientMaterials': salient_materials }], 'chooseSize': [{ 'dimensions': dimensions, 'mass': mass }] } obj = finalize_object_definition(object_def) assert obj['dimensions'] == dimensions assert obj['mass'] == mass assert obj['materialCategory'] == material_category assert obj['salientMaterials'] == salient_materials
def _set_target_def(self) -> None: """Chooses a pickupable object since most interaction goals require that.""" pickupable_defs = random.choice(objects.OBJECTS_PICKUPABLE_LISTS) self._target_def = finalize_object_definition( random.choice(pickupable_defs))
from object_data import ObjectData, ReceptacleData, TargetData, \ identify_larger_definition from interactive_plans import ObjectLocationPlan, ObjectPlan import objects import util CAKE = objects._get('CAKE') TROPHY = objects._get('TROPHY') CASE_1_SUITCASE = objects._get('CASE_1_SUITCASE') CASE_1_SUITCASE = util.finalize_object_definition( CASE_1_SUITCASE, choice_size=CASE_1_SUITCASE['chooseSize'][0]) CHEST_1_CUBOID = objects._get('CHEST_1_CUBOID') CHEST_1_CUBOID = util.finalize_object_definition( CHEST_1_CUBOID, choice_size=CHEST_1_CUBOID['chooseSize'][0]) def test_identify_larger_definition(): assert identify_larger_definition(CAKE, TROPHY) == CAKE assert identify_larger_definition(TROPHY, CAKE) == CAKE def test_object_data_init(): data = ObjectData('ROLE', ObjectPlan(ObjectLocationPlan.NONE)) assert data.role == 'ROLE' assert data.location_plan_list == [ObjectLocationPlan.NONE] assert data.untrained_plan_list == [False] assert not data.original_definition assert not data.trained_definition assert not data.untrained_definition
def _get_objects_moving_across(self, room_wall_material_name: str, last_action_end_step: int, earliest_action_start_step: int = EARLIEST_ACTION_START_STEP, valid_positions: Iterable = frozenset(Position), positions = None, valid_defs: List[Dict[str, Any]] = objects.OBJECTS_INTPHYS) \ -> List[Dict[str, Any]]: """Get objects to move across the scene. Returns objects.""" num_objects = self._get_num_objects_moving_across() # The following x positions start outside the camera viewport # and ensure that objects with scale 1 don't collide with each # other. object_positions = { IntPhysGoal.Position.RIGHT_FIRST_NEAR: (4.2, IntPhysGoal.OBJECT_NEAR_Z), IntPhysGoal.Position.RIGHT_LAST_NEAR: (5.3, IntPhysGoal.OBJECT_NEAR_Z), IntPhysGoal.Position.RIGHT_FIRST_FAR: (4.8, IntPhysGoal.OBJECT_FAR_Z), IntPhysGoal.Position.RIGHT_LAST_FAR: (5.9, IntPhysGoal.OBJECT_FAR_Z), IntPhysGoal.Position.LEFT_FIRST_NEAR: (-4.2, IntPhysGoal.OBJECT_NEAR_Z), IntPhysGoal.Position.LEFT_LAST_NEAR: (-5.3, IntPhysGoal.OBJECT_NEAR_Z), IntPhysGoal.Position.LEFT_FIRST_FAR: (-4.8, IntPhysGoal.OBJECT_FAR_Z), IntPhysGoal.Position.LEFT_LAST_FAR: (-5.9, IntPhysGoal.OBJECT_FAR_Z) } exclusions = { IntPhysGoal.Position.RIGHT_FIRST_NEAR: (IntPhysGoal.Position.LEFT_FIRST_NEAR, IntPhysGoal.Position.LEFT_LAST_NEAR), IntPhysGoal.Position.RIGHT_LAST_NEAR: (IntPhysGoal.Position.LEFT_FIRST_NEAR, IntPhysGoal.Position.LEFT_LAST_NEAR), IntPhysGoal.Position.RIGHT_FIRST_FAR: (IntPhysGoal.Position.LEFT_FIRST_FAR, IntPhysGoal.Position.LEFT_LAST_FAR), IntPhysGoal.Position.RIGHT_LAST_FAR: (IntPhysGoal.Position.LEFT_FIRST_FAR, IntPhysGoal.Position.LEFT_LAST_FAR), IntPhysGoal.Position.LEFT_FIRST_NEAR: (IntPhysGoal.Position.RIGHT_FIRST_NEAR, IntPhysGoal.Position.RIGHT_LAST_NEAR), IntPhysGoal.Position.LEFT_LAST_NEAR: (IntPhysGoal.Position.RIGHT_FIRST_NEAR, IntPhysGoal.Position.RIGHT_LAST_NEAR), IntPhysGoal.Position.LEFT_FIRST_FAR: (IntPhysGoal.Position.RIGHT_FIRST_FAR, IntPhysGoal.Position.RIGHT_LAST_FAR), IntPhysGoal.Position.LEFT_LAST_FAR: (IntPhysGoal.Position.RIGHT_FIRST_FAR, IntPhysGoal.Position.RIGHT_LAST_FAR) } # Object in key position must have acceleration <= # acceleration for object in value position (e.g., object in # RIGHT_LAST_NEAR must have acceleration <= acceleration for # object in RIGHT_FIRST_NEAR). acceleration_ordering = { IntPhysGoal.Position.RIGHT_LAST_NEAR: IntPhysGoal.Position.RIGHT_FIRST_NEAR, IntPhysGoal.Position.RIGHT_LAST_FAR: IntPhysGoal.Position.RIGHT_FIRST_FAR, IntPhysGoal.Position.LEFT_LAST_NEAR: IntPhysGoal.Position.LEFT_FIRST_NEAR, IntPhysGoal.Position.LEFT_LAST_FAR: IntPhysGoal.Position.LEFT_FIRST_FAR } available_locations = set(valid_positions) location_assignments = {} new_objects = [] for i in range(num_objects): location = random.choice(list(available_locations)) available_locations.remove(location) for loc in exclusions[location]: available_locations.discard(loc) obj_def = finalize_object_definition(random.choice(valid_defs)) remaining_intphys_options = obj_def['intphys_options'].copy() while len(remaining_intphys_options) > 0: intphys_option = random.choice(remaining_intphys_options) if location in acceleration_ordering and \ acceleration_ordering[location] in location_assignments: # ensure the objects won't collide acceleration = abs(intphys_option['force']['x'] / obj_def['mass']) other_obj = location_assignments[ acceleration_ordering[location]] other_acceleration = abs( other_obj['intphys_option']['force']['x'] / other_obj['mass']) collision = acceleration > other_acceleration if not collision: break elif len(remaining_intphys_options) == 1: # last chance, so just swap the items to make their relative acceleration "ok" location_assignments[location] = other_obj location = acceleration_ordering[location] location_assignments[ location] = None # to be assigned later break else: break remaining_intphys_options.remove(intphys_option) object_location = { 'position': { 'x': object_positions[location][0], 'y': intphys_option['y'] + obj_def['position_y'], 'z': object_positions[location][1] } } obj = instantiate_object(obj_def, object_location) location_assignments[location] = obj position_by_step = copy.deepcopy( intphys_option['position_by_step']) object_position_x = object_positions[location][0] # adjust position_by_step and remove outliers new_positions = [] for position in position_by_step: if location in (IntPhysGoal.Position.RIGHT_FIRST_NEAR, IntPhysGoal.Position.RIGHT_LAST_NEAR, IntPhysGoal.Position.RIGHT_FIRST_FAR, IntPhysGoal.Position.RIGHT_LAST_FAR): position = object_position_x - position else: position = object_position_x + position new_positions.append(position) if location in (IntPhysGoal.Position.RIGHT_FIRST_NEAR, IntPhysGoal.Position.RIGHT_LAST_NEAR, IntPhysGoal.Position.LEFT_FIRST_NEAR, IntPhysGoal.Position.LEFT_LAST_NEAR): max_x = IntPhysGoal.VIEWPORT_LIMIT_NEAR + obj_def['scale'][ 'x'] / 2.0 * IntPhysGoal.VIEWPORT_PERSPECTIVE_FACTOR else: max_x = IntPhysGoal.VIEWPORT_LIMIT_FAR + obj_def['scale'][ 'x'] / 2.0 * IntPhysGoal.VIEWPORT_PERSPECTIVE_FACTOR filtered_position_by_step = [ position for position in new_positions if (abs(position) <= max_x) ] # set shows.stepBegin min_step_begin = earliest_action_start_step if location in acceleration_ordering and acceleration_ordering[ location] in location_assignments: min_step_begin = location_assignments[ acceleration_ordering[location]]['shows'][0]['stepBegin'] max_step_begin = last_action_end_step - len( filtered_position_by_step) if min_step_begin >= max_step_begin: stepBegin = min_step_begin else: stepBegin = random.randint(min_step_begin, max_step_begin) obj['shows'][0]['stepBegin'] = stepBegin obj['forces'] = [{ 'stepBegin': stepBegin, 'stepEnd': last_action_end_step, 'vector': intphys_option['force'] }] if location in (IntPhysGoal.Position.RIGHT_FIRST_NEAR, IntPhysGoal.Position.RIGHT_LAST_NEAR, IntPhysGoal.Position.RIGHT_FIRST_FAR, IntPhysGoal.Position.RIGHT_LAST_FAR): obj['forces'][0]['vector']['x'] *= -1 intphys_option['position_by_step'] = filtered_position_by_step intphys_option['position_y'] = obj_def['position_y'] obj['intphys_option'] = intphys_option new_objects.append(obj) if positions is not None: positions.append(location) return new_objects