def test_vector_to_string(self): self.assertEqual(MCS_Util.vector_to_string(None), 'None') self.assertEqual(MCS_Util.vector_to_string({ 'x': 1, 'y': 2, 'z': 3 }), '(1,2,3)')
def test_generate_pretty_object_output(self): object_list = [ MCS_Object( uuid='id1', held=True, visible=True, distance=0, direction=None ), MCS_Object( uuid='really_long_id2', held=False, visible=False, distance=1234.5678, direction={ 'x': 10, 'y': 20, 'z': 30 } ) ] self.assertEqual(MCS_Util.generate_pretty_object_output(object_list), [ 'OBJECT ID HELD VISIBLE DISTANCE DIRECTION ', 'id1 True True 0 None ', 'really_long_id2 False False 1234.5678 (10,20,30)' ])
def step(self, action, **kwargs): super().step(action, **kwargs) if self.__goal.last_step is not None and self.__goal.last_step < self.__step_number: print("MCS Warning: You have passed the last step of this scene. Skipping your action." + \ "Please call controller.end_scene() now.") return None if ',' in action: action, kwargs = MCS_Util.input_to_action_and_params(action) if not action in self.ACTION_LIST: print("MCS Warning: The given action '" + action + "' is not valid. Exchanging it with the 'Pass' action.") action = "Pass" self.__step_number += 1 if self.__debug_to_terminal: print( "===============================================================================" ) print("STEP: " + str(self.__step_number)) print("ACTION: " + action) params = self.validate_and_convert_params(action, **kwargs) # Only call mcs_action_to_ai2thor_action AFTER calling validate_and_convert_params action = self.mcs_action_to_ai2thor_action(action) return self.wrap_output( self.__controller.step(self.wrap_step(action=action, **params)))
def test_generate_pretty_object_output(self): object_list = [ MCS_Object(uuid='id1', held=True, position=None, distance_in_world=0, direction=None), MCS_Object(uuid='really_long_id2', held=False, position={ 'x': 1, 'y': 2, 'z': 3 }, distance_in_world=1234567890987654321, direction={ 'x': 10000, 'y': 20000, 'z': 30000 }) ] self.assertEqual(MCS_Util.generate_pretty_object_output(object_list), [ 'OBJECT ID HELD POSITION (WORLD) DISTANCE (WORLD) DIRECTION (WORLD) ', 'id1 True None 0 None ', 'really_long_id2 False (1,2,3) 1234567890987654321 (10000,20000,30000)' ])
def test_is_number(self): self.assertEqual(MCS_Util.is_number('0'), True) self.assertEqual(MCS_Util.is_number('1'), True) self.assertEqual(MCS_Util.is_number('12.34'), True) self.assertEqual(MCS_Util.is_number('01'), True) self.assertEqual(MCS_Util.is_number(''), False) self.assertEqual(MCS_Util.is_number('asdf'), False)
def test_input_to_action_and_params(self): self.assertEqual(MCS_Util.input_to_action_and_params('MoveBack'), ('MoveBack', {})) self.assertEqual(MCS_Util.input_to_action_and_params('RotateLook,rotation=12.34'), ('RotateLook', { 'rotation': 12.34 })) self.assertEqual(MCS_Util.input_to_action_and_params('PickupObject,objectId=testId'), ('PickupObject', { 'objectId': 'testId' })) self.assertEqual(MCS_Util.input_to_action_and_params('PushObject,objectId=testId,force=12.34'), ('PushObject', { 'objectId': 'testId', 'force': 12.34 })) self.assertEqual(MCS_Util.input_to_action_and_params('Foobar'), (None, {})) self.assertEqual(MCS_Util.input_to_action_and_params('MoveBack,key:value'), ('MoveBack', None))
def wrap_output(self, scene_event): if self.__debug_to_file and self.__output_folder is not None: with open( self.__output_folder + 'ai2thor_output_' + str(self.__step_number) + '.json', 'w') as json_file: json.dump({"metadata": scene_event.metadata}, json_file, sort_keys=True, indent=4) image, depth_mask, object_mask = self.save_images(scene_event) step_output = MCS_Step_Output( action_list=self.retrieve_action_list(self.__goal, self.__step_number), depth_mask_list=[depth_mask], goal=self.__goal, head_tilt=self.retrieve_head_tilt(scene_event), image_list=[image], object_list=self.retrieve_object_list(scene_event), object_mask_list=[object_mask], pose=self.retrieve_pose(scene_event), return_status=self.retrieve_return_status(scene_event), step_number=self.__step_number) self.__head_tilt = step_output.head_tilt if self.__debug_to_terminal: print("RETURN STATUS: " + step_output.return_status) print("OBJECTS (" + str(len(step_output.object_list)) + " TOTAL):") for line in MCS_Util.generate_pretty_object_output( step_output.object_list): print(" " + line) if self.__debug_to_file and self.__output_folder is not None: with open( self.__output_folder + 'mcs_output_' + str(self.__step_number) + '.json', 'w') as json_file: json_file.write(str(step_output)) return step_output
def input_commands(controller): print('Enter your command:') userInput = input().split(',') if(userInput[0] == 'exit'): print("Exiting Human Input Mode") return if(userInput[0] == 'help'): print_commands() return input_commands(controller) # Check for shortcut key, if attempted shortcut key, map and check valid key try: if len(userInput[0]) == 1: userInput[0] = MCS_Action[MCS_Action_Keys(userInput[0] ).name].value except: print("You entered an invalid shortcut key, please try again. (Type 'help' to display commands again)") print("You entered: " + userInput[0]) return input_commands(controller) print('You entered command: ') print(*userInput) action, params = MCS_Util.input_to_action_and_params(','.join(userInput)) if action is None: print("You entered an invalid command, please try again. (Type 'help' to display commands again)") return input_commands(controller) if params is None: print("ERROR: Parameters should be separated by commas, and look like this example: rotation=45") return input_commands(controller) output = controller.step(action, **params); return input_commands(controller)
def test_class_to_str_with_empty_class(self): self.assertEqual(MCS_Util.class_to_str(My_Emptyclass()), "{}")
def test_value_to_str_with_dict(self): self.assertEqual(MCS_Util.value_to_str({}), "{}") self.assertEqual(MCS_Util.value_to_str({ "number": 1, "string": "a" }), "{\n \"number\": 1,\n \"string\": \"a\"\n}")
def test_verify_material_enum_string(self): self.assertEqual(MCS_Util.verify_material_enum_string('Ceramic'), True) self.assertEqual(MCS_Util.verify_material_enum_string('Plastic'), True) self.assertEqual(MCS_Util.verify_material_enum_string('Foobar'), False) self.assertEqual(MCS_Util.verify_material_enum_string(''), False)
def test_class_to_str_with_class(self): self.maxDiff = 10000 expected = "{\n \"my_boolean\": True,\n \"my_float\": 1.234,\n \"my_integer\": 0,\n \"my_string\": \"a\",\n \"my_list\": [\n 1,\n \"b\",\n {\n \"my_integer\": 2,\n \"my_string\": \"c\",\n \"my_list\": [\n 3,\n \"d\"\n ]\n }\n ],\n \"my_dict\": {\n \"my_integer\": 4,\n \"my_string\": \"e\",\n \"my_list\": [\n 5,\n \"f\"\n ],\n \"my_dict\": {\n \"my_integer\": 6,\n \"my_string\": \"g\"\n }\n },\n \"my_list_empty\": [],\n \"my_dict_empty\": {},\n \"my_subclass\": {\n \"my_integer\": 7,\n \"my_string\": \"h\",\n \"my_list\": [\n 8,\n \"i\"\n ],\n \"my_dict\": {\n \"my_integer\": 9,\n \"my_string\": \"j\"\n }\n }\n}" self.assertEqual(MCS_Util.class_to_str(My_Class()), expected)
def test_value_to_str_with_string(self): self.assertEqual(MCS_Util.value_to_str(""), "\"\"") self.assertEqual(MCS_Util.value_to_str("a b c d"), "\"a b c d\"")
def validate_and_convert_params(self, action, **kwargs): moveMagnitude = self.MAX_MOVE_DISTANCE rotation = kwargs.get(self.ROTATION_KEY, self.DEFAULT_ROTATION) horizon = kwargs.get(self.HORIZON_KEY, self.DEFAULT_HORIZON) amount = kwargs.get(self.AMOUNT_KEY, self.DEFAULT_AMOUNT) force = kwargs.get(self.FORCE_KEY, self.DEFAULT_FORCE) objectDirectionX = kwargs.get(self.OBJECT_DIRECTION_X_KEY, self.DEFAULT_DIRECTION) objectDirectionY = kwargs.get(self.OBJECT_DIRECTION_Y_KEY, self.DEFAULT_DIRECTION) objectDirectionZ = kwargs.get(self.OBJECT_DIRECTION_Z_KEY, self.DEFAULT_DIRECTION) receptacleObjectDirectionX = kwargs.get(self.RECEPTACLE_DIRECTION_X, self.DEFAULT_DIRECTION) receptacleObjectDirectionY = kwargs.get(self.RECEPTACLE_DIRECTION_Y, self.DEFAULT_DIRECTION) receptacleObjectDirectionZ = kwargs.get(self.RECEPTACLE_DIRECTION_Z, self.DEFAULT_DIRECTION) # Check params that should be numbers if not MCS_Util.is_number(rotation, self.ROTATION_KEY): rotation = self.DEFAULT_ROTATION if not MCS_Util.is_number(horizon, self.HORIZON_KEY): horizon = self.DEFAULT_HORIZON if not MCS_Util.is_number(amount, self.AMOUNT_KEY): # The default for open/close is 1, the default for "Move" actions is 0.5 if action in self.OBJECT_MOVE_ACTIONS: amount = self.DEFAULT_OBJECT_MOVE_AMOUNT else: amount = self.DEFAULT_AMOUNT if not MCS_Util.is_number(force, self.FORCE_KEY): force = self.DEFAULT_FORCE # Check object directions are numbers if not MCS_Util.is_number(objectDirectionX, self.OBJECT_DIRECTION_X_KEY): objectDirectionX = self.DEFAULT_DIRECTION if not MCS_Util.is_number(objectDirectionY, self.OBJECT_DIRECTION_Y_KEY): objectDirectionY = self.DEFAULT_DIRECTION if not MCS_Util.is_number(objectDirectionZ, self.OBJECT_DIRECTION_Z_KEY): objectDirectionZ = self.DEFAULT_DIRECTION # Check receptacle directions are numbers if not MCS_Util.is_number(receptacleObjectDirectionX, self.RECEPTACLE_DIRECTION_X): receptacleObjectDirectionX = self.DEFAULT_DIRECTION if not MCS_Util.is_number(receptacleObjectDirectionY, self.RECEPTACLE_DIRECTION_Y): receptacleObjectDirectionY = self.DEFAULT_DIRECTION if not MCS_Util.is_number(receptacleObjectDirectionZ, self.RECEPTACLE_DIRECTION_Z): receptacleObjectDirectionZ = self.DEFAULT_DIRECTION # Check that params that should fall in a range are in that range horizon = MCS_Util.is_in_range(horizon, self.MIN_HORIZON, self.MAX_HORIZON, self.DEFAULT_HORIZON, \ self.HORIZON_KEY) amount = MCS_Util.is_in_range(amount, self.MIN_AMOUNT, self.MAX_AMOUNT, self.DEFAULT_AMOUNT, self.AMOUNT_KEY) force = MCS_Util.is_in_range(force, self.MIN_FORCE, self.MAX_FORCE, self.DEFAULT_FORCE, self.FORCE_KEY) # TODO Consider the current "head tilt" value while validating the input "horizon" value. # Set the Move Magnitude to the appropriate amount based on the action if action in self.FORCE_ACTIONS: moveMagnitude = force * self.MAX_BABY_FORCE if action in self.OBJECT_MOVE_ACTIONS: moveMagnitude = amount if action in self.MOVE_ACTIONS: moveMagnitude = amount * self.MAX_MOVE_DISTANCE rotation_vector = {} rotation_vector['y'] = rotation object_vector = {} object_vector['x'] = objectDirectionX object_vector['y'] = objectDirectionY object_vector['z'] = objectDirectionZ receptacle_vector = {} receptacle_vector['x'] = receptacleObjectDirectionX receptacle_vector['y'] = receptacleObjectDirectionY receptacle_vector['z'] = receptacleObjectDirectionZ return dict(objectId=kwargs.get("objectId", None), receptacleObjectId=kwargs.get("receptacleObjectId", None), rotation=rotation_vector, horizon=horizon, moveMagnitude=moveMagnitude, objectDirection=object_vector, receptacleObjectDirection=receptacle_vector)
def test_value_to_str_with_list(self): self.assertEqual(MCS_Util.value_to_str([]), "[]") self.assertEqual(MCS_Util.value_to_str([1, "a"]), "[\n 1,\n \"a\"\n]")
def test_value_to_str_with_integer(self): self.assertEqual(MCS_Util.value_to_str(0), "0") self.assertEqual(MCS_Util.value_to_str(1234), "1234")
def test_is_in_range(self): self.assertEqual(MCS_Util.is_in_range(0, 0, 1, 1234), 0) self.assertEqual(MCS_Util.is_in_range(0.5, 0, 1, 1234), 0.5) self.assertEqual(MCS_Util.is_in_range(1, 0, 1, 1234), 1) self.assertEqual(MCS_Util.is_in_range(-1, 0, 1, 1234), 1234) self.assertEqual(MCS_Util.is_in_range(1.01, 0, 1, 1234), 1234) self.assertEqual(MCS_Util.is_in_range(100, 0, 1, 1234), 1234) self.assertEqual(MCS_Util.is_in_range(2, 2, 4, 1234), 2) self.assertEqual(MCS_Util.is_in_range(2.1, 2, 4, 1234), 2.1) self.assertEqual(MCS_Util.is_in_range(4, 2, 4, 1234), 4) self.assertEqual(MCS_Util.is_in_range(1.9, 2, 4, 1234), 1234) self.assertEqual(MCS_Util.is_in_range(-3, 2, 4, 1234), 1234) self.assertEqual(MCS_Util.is_in_range(4.1, 2, 4, 1234), 1234) self.assertEqual(MCS_Util.is_in_range(-2, -2, 2, 1234), -2) self.assertEqual(MCS_Util.is_in_range(0, -2, 2, 1234), 0) self.assertEqual(MCS_Util.is_in_range(2, -2, 2, 1234), 2) self.assertEqual(MCS_Util.is_in_range(-2.1, -2, 2, 1234), 1234) self.assertEqual(MCS_Util.is_in_range(2.1, -2, 2, 1234), 1234) self.assertEqual(MCS_Util.is_in_range(200, -2, 2, 1234), 1234) self.assertEqual(MCS_Util.is_in_range(-4, -4, -2, 1234), -4) self.assertEqual(MCS_Util.is_in_range(-2.1, -4, -2, 1234), -2.1) self.assertEqual(MCS_Util.is_in_range(-2, -4, -2, 1234), -2) self.assertEqual(MCS_Util.is_in_range(-5, -4, -2, 1234), 1234) self.assertEqual(MCS_Util.is_in_range(-1, -4, -2, 1234), 1234) self.assertEqual(MCS_Util.is_in_range(3, -4, -2, 1234), 1234)
def __str__(self): return MCS_Util.class_to_str(self)
def test_value_to_str_with_boolean(self): self.assertEqual(MCS_Util.value_to_str(True), "True") self.assertEqual(MCS_Util.value_to_str(False), "False")
def test_value_to_str_with_float(self): self.assertEqual(MCS_Util.value_to_str(0.0), "0.0") self.assertEqual(MCS_Util.value_to_str(1234.5678), "1234.5678")
def input_commands(controller, previous_output, config_data): if previous_output.action_list is not None and len( previous_output.action_list) < len(commandList): print('Only actions available during this step:') for action in previous_output.action_list: print(' ' + action) else: print('All actions available during this step.') if previous_output.action_list is not None and len( previous_output.action_list) == 1: print('Automatically selecting the only available action...') userInput = previous_output.action_list[1] else: print('Enter your command:') userInput = input().split(',') if (userInput[0].lower() == 'exit'): print("Exiting Human Input Mode") return if (userInput[0].lower() == 'help'): print_commands() return input_commands(controller, previous_output, config_data) if (userInput[0].lower() == 'reset'): output = controller.start_scene(config_data) return input_commands(controller, output, config_data) # Check for shortcut key, if attempted shortcut key, map and check valid key try: if len(userInput[0]) == 1: userInput[0] = MCS_Action[MCS_Action_Keys(userInput[0]).name].value except: print( "You entered an invalid shortcut key, please try again. (Type 'help' to display commands again)" ) print("You entered: " + userInput[0]) return input_commands(controller, previous_output, config_data) print('You entered command:') print(*userInput) action, params = MCS_Util.input_to_action_and_params(','.join(userInput)) if action is None: print( "You entered an invalid command, please try again. (Type 'help' to display commands again)" ) return input_commands(controller, previous_output, config_data) if params is None: print( "ERROR: Parameters should be separated by commas, and look like this example: rotation=45" ) return input_commands(controller, previous_output, config_data) output = controller.step(action, **params) print( '===============================================================================' ) return input_commands(controller, output, config_data)