def get(self, sim_id, command): """ Queries the simulation recorder for a value/status. See parameter description for supported query commands. :param sim_id: The simulation ID to command. :param command: The command to query, supported: [is-recording] :status 500: {0} :status 404: {1} :status 200: Success. The query was issued and value returned. """ # validate simulation id, allow any users/viewers to query recorder sim = _get_simulation_or_abort(sim_id) # validate the command type if command not in ['is-recording']: raise NRPServicesClientErrorException('Invalid recorder query: %s' % command, error_code=404) # command the recorder, return boolean state as a string try: state = str(sim.cle.command_simulation_recorder(SimulationRecorderRequest.STATE).value) return state, 200 # internal CLE ROS error if service call fails, notify frontend except ROSCLEClientException as e: raise NRPServicesGeneralException(str(e), 'CLE error', 500)
def setUp(self): self.patch_state = patch('hbp_nrp_backend.simulation_control.__Simulation.Simulation.state') self.mock_state = self.patch_state.start() self.patch_sm = patch('hbp_nrp_backend.simulation_control.__Simulation.StateMachineManager') self.mock_sm_manager = self.patch_sm.start() sm = StateMachineManager() self.mock_sm_manager_instance = MagicMock(name='SM_manager', wraps=sm) self.mock_sm_manager.return_value = self.mock_sm_manager_instance self.sm_instance_name = "Control1" self.sm_instance = sm.create_state_machine(self.sm_instance_name, 0) self.mock_sm_instance = MagicMock(name='SM_instance', sm_id=self.sm_instance_name, wraps=self.sm_instance) self.mock_sm_manager_instance.create_state_machine.return_value = self.mock_sm_instance self.mock_sm_manager_instance.get_state_machine =\ Mock(side_effect=lambda name: self.mock_sm_instance if name == self.sm_instance_name else None) load_data = { "experimentConfiguration": "experiments/experiment_data/test_1.exc", "gzserverHost": "local" } self.client.post('/simulation', data=json.dumps(load_data)) simulation = _get_simulation_or_abort(0) simulation.state = "paused"
def put(self, sim_id, transfer_function_name): """ Applies user changes to transfer function code :param sim_id: The simulation ID :param transfer_function_name: The name of the transfer function to be modified :< string data: The source code of the transfer function :status 404: {0} :status 403: {1} :status 401: {2} :status 400: {3} :status 200: Success. The transfer function was successfully patched """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_modify(simulation): raise NRPServicesWrongUserException() transfer_function_source = request.data error_message = simulation.cle.edit_simulation_transfer_function( transfer_function_name, transfer_function_source) if error_message: ex_msg = ("Transfer Function patch failed: {error_msg}\n" "Updated source:\n" "{tf_src}").format(error_msg=error_message, tf_src=str(transfer_function_source)) raise NRPServicesDuplicateNameException(ex_msg) if "duplicate" in error_message \ else NRPServicesTransferFunctionException(ex_msg) return 200
def setUp(self): self.path_can_view = patch('hbp_nrp_backend.__UserAuthentication.UserAuthentication.can_view') self.path_can_view.start().return_value = True self.patch_state = patch('hbp_nrp_backend.simulation_control.__Simulation.Simulation.state') self.mock_state = self.patch_state.start() self.patch_sm = patch('hbp_nrp_backend.simulation_control.__Simulation.StateMachineManager') self.mock_sm_manager = self.patch_sm.start() sm = StateMachineManager() self.mock_sm_manager_instance = MagicMock(name='SM_manager', wraps=sm) self.mock_sm_manager.return_value = self.mock_sm_manager_instance self.sm_instance_name = "Control1" self.sm_instance = sm.create_state_machine(self.sm_instance_name, 0, '/tmp/sim-dir') self.mock_sm_instance = MagicMock(name='SM_instance', sm_id=self.sm_instance_name, sim_dir='/tmp/sim-dir', wraps=self.sm_instance) self.mock_sm_manager_instance.create_state_machine.return_value = self.mock_sm_instance self.mock_sm_manager_instance.get_state_machine = Mock(side_effect=lambda name: self.mock_sm_instance if name == self.sm_instance_name else None) load_data = { "experimentID": "some_experiment_id", "gzserverHost": "local" } self.client.post('/simulation', data=json.dumps(load_data)) simulation = _get_simulation_or_abort(0) simulation.state = "paused"
def put(self, sim_id): """ Sets the simulation with the given name into a new state. Allowed values are: created, initialized, started, paused, stopped :param sim_id: The simulation id :< json string state: The state of the simulation to set :> json string state: The state of the simulation :status 404: {0} :status 401: {1} :status 400: The state transition is invalid :status 200: The state of the simulation with the given ID was successfully set """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_modify(simulation): raise NRPServicesWrongUserException() body = request.get_json(force=True) try: simulation.state = body['state'] except MachineError: raise NRPServicesStateException("Invalid transition (" + simulation.state + "->" + body['state'] + ")") return {'state': str(simulation.state)}, 200
def get(self, sim_id): """ Get brain data of the simulation specified with simulation ID. :param sim_id: The simulation ID :> json string brain_type: Type of the brain file ('h5' or 'py') :> json string data_type: type of the data field ('text' or 'base64') :> json string data: Contents of the brain file. Encoding given in field data_type :> json dict additional_populations: A dictionary indexed by population names and containing neuron indices. :status 500: {0} :status 404: {1} :status 200: Success. The experiment brain file was retrieved """ simulation = _get_simulation_or_abort(sim_id) result = simulation.cle.get_simulation_brain() return { 'data': result.brain_data, 'brain_type': result.brain_type, 'data_type': result.data_type, 'additional_populations': json.loads(result.brain_populations), }, 200
def post(self, sim_id): """ Extends the simulation timeout :param sim_id: The simulation id :status 404: {0} :status 402: Failed to extend the timeout :status 412: Failed due to simulation timeout type being 'simulation' :status 401: {1} :status 200: Success. The simulation timeout has been extended """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_modify(simulation): raise NRPServicesWrongUserException() if simulation.timeout_type == TimeoutType.SIMULATION: return {}, 412 new_timeout = simulation.kill_datetime + \ datetime.timedelta(minutes=SIMULATION_TIMEOUT_EXTEND) if not simulation.cle.extend_simulation_timeout(new_timeout): return {}, 402 simulation.kill_datetime = new_timeout return {}, 200
def put(self, sim_id, transfer_function_name, activate): """ Sets the activation state of the transfer function :param sim_id: The simulation ID :param transfer_function_name: The name of the transfer function to be modified :param activate A boolean denoting the new desired activation status :status 404: {0} :status 401: {1} :status 400: {2} :status 200: Success. The activation state of the TF has been successfully changed """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.matches_x_user_name_header( request, simulation.owner): raise NRPServicesWrongUserException() activate_bool = activate.lower( ) == "true" # convert unicode to boolean error_message = simulation.cle.activate_simulation_transfer_function( transfer_function_name, activate_bool) if error_message: raise NRPServicesTransferFunctionException( "Transfer function (de-)activation failed: " + error_message + "\n") return 200
def get(self, sim_id): """ Gets the simulation CSV recorders' content :param sim_id: The simulation ID whose transfer functions are retrieved will be saved :> json string file: CSV file name :> json array data: CSV data as a list of strings :status 500: Error when retrieving recorder files :status 404: {0} :status 401: {1} :status 200: Returns a list of recorded csv files and data """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.matches_x_user_name_header( request, simulation.owner): raise NRPServicesWrongUserException() response = [] csv_files = simulation.cle.get_simulation_CSV_recorders_files() if csv_files: for csv_file in csv_files: file_data = [] response.append({"file": csv_file.name, "data": file_data}) with open(csv_file.temporary_path) as csvfile: spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|') for row in spamreader: file_data.append(', '.join(row)) return response, 200
def test_simulation_state_machines_put_source_code_error(self): simulation = _get_simulation_or_abort(0) simulation.set_state_machine_code(self.sm_instance_name, SM) self.__put_initialization_side_effect(self.mock_sm_instance, Exception) response = self.client.put('/simulation/0/state-machines/Control1', data="ERROR") self.assertIsInstance(response, Response) self.assertEqual(response.status_code, 500)
def put(self, sim_id): """ Puts the structured transfer functions :param sim_id: The simulation id :status 500: Simulation in state [STATE]. Can't update transfer function :status 404: {0} :status 401: {1} :status 400: {2} :status 200: Success. The transfer function was successfully patched """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.matches_x_user_name_header( request, simulation.owner): raise NRPServicesWrongUserException() transfer_function = json.loads(request.data, object_hook=JSONObject) error_message = simulation.cle.set_structured_transfer_function( transfer_function) if error_message: raise NRPServicesTransferFunctionException( "Transfer function patch failed: " + error_message + "\n" + "Transfer function:\n" + request.data) return 200
def delete(self, sim_id, robot_id): """ Delete a robot from the simulation. :param sim_id: The simulation ID. :param robot_id: The robot ID. :status 500: {0} :status 404: {1} :status 401: {2} :status 400: Invalid request, the JSON parameters are incorrect :status 200: The requested robot was deleted successfully """ # pylint: disable=no-self-use sim = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_modify(sim): raise NRPServicesWrongUserException() try: res, err = SimulationRobot.__delete_robot(sim, robot_id) except ROSCLEClientException as e: raise NRPServicesGeneralException(str(e), 'CLE error', 500) if not res: return {'res': err}, 404 return {'res': 'success'}, 200
def get(self, sim_id): """ Gets the list of robots in the running simulation. """ # pylint: disable=no-self-use sim = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_view(sim): raise NRPServicesWrongUserException() try: robots = SimulationRobots.__get_simulation_robots(sim) except ROSCLEClientException as e: raise NRPServicesGeneralException(str(e), 'CLE error', 500) result = { 'robots': [{ ParamNames.ROBOT_ID: robot.robot_id, ParamNames.ROBOT_ABS_PATH: robot.robot_model, ParamNames.IS_CUSTOM: robot.is_custom, ParamNames.ROBOT_POSE: SimulationRobots.__jsonisePose(robot.pose) } for robot in robots] } return result, 200
def post(self, sim_id): """ Extends the simulation timeout :param sim_id: The simulation id :status 404: {0} :status 402: Failed to extend the timeout :status 401: {1} :status 200: Success. The simulation timeout has been extended """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.matches_x_user_name_header( request, simulation.owner): raise NRPServicesWrongUserException() new_timeout = simulation.kill_datetime + \ datetime.timedelta(minutes=SIMULATION_TIMEOUT_EXTEND) if not simulation.cle.extend_simulation_timeout(new_timeout): return {}, 402 simulation.kill_datetime = new_timeout return {}, 200
def post(self, sim_id, command): """ Issue user commands to the simulator recorder. See parameter description for supported query commands. :param sim_id: The simulation ID to command. :param command: The command to issue, supported: [start, stop, cancel, reset, save] :status 500: {0} :status 404: {1} :status 401: {2} :status 400: The command is invalid/refused by recorder - see message returned. :status 200: Success. The command was issued. """ # validate simulation id sim = _get_simulation_or_abort(sim_id) # only the simulation owner can command the recorder if not UserAuthentication.can_modify(sim): raise NRPServicesWrongUserException() # pure local command to save file to storage if command == 'save': try: file_name = sim.lifecycle.save_record_to_user_storage() return {'filename': file_name}, 200 except Exception as e: raise NRPServicesClientErrorException( 'Cannot copy record to client storage', error_code=404) else: # validate the remote command type valid_commands = { 'start': SimulationRecorderRequest.START, 'stop': SimulationRecorderRequest.STOP, 'cancel': SimulationRecorderRequest.CANCEL, 'reset': SimulationRecorderRequest.RESET } if command not in valid_commands: raise NRPServicesClientErrorException( 'Invalid recorder command: %s' % command, error_code=404) # command the recorder, if unsuccessful return the error message try: resp = sim.cle.command_simulation_recorder( valid_commands[command]) # check the command success, on failure return status 400 + error if not resp.value: raise NRPServicesClientErrorException(resp.message) # successful, return status 200 return 'success', 200 # internal CLE ROS error if service call fails, notify frontend except ROSCLEClientException as e: raise NRPServicesGeneralException(str(e), 'CLE error', 500)
def test_simulation_state_machines_delete_not_found(self): simulation = _get_simulation_or_abort(0) simulation.set_state_machine_code(self.sm_instance_name, SM) response = self.client.delete('/simulation/0/state-machines/Control2') self.assertRaises(NRPServicesStateMachineException) self.assertEqual(response.status_code, 404)
def get(self, sim_id): """ Gets all transfer functions (robot to neuron and neuron to robot) in a dictionary with string values. :param sim_id: The simulation ID :> json dict data: Dictionary containing all transfer functions ('name': 'source') :> json dict active: Dictionary containing a mask for active TFs ('name': 'isActive') :status 404: {0} :status 200: Transfer functions retrieved successfully """ simulation = _get_simulation_or_abort(sim_id) transfer_functions = dict() active_tfs_mask = dict() transfer_functions_list, active_tfs_mask_list = \ simulation.cle.get_simulation_transfer_functions() for tf, tf_active in zip(transfer_functions_list, active_tfs_mask_list): name = get_tf_name(tf) transfer_functions[name] = tf active_tfs_mask[name] = tf_active return dict(data=transfer_functions, active=active_tfs_mask), 200
def put(self, sim_id): """ Set the populations of the brain in a simulation with the specified simulation id. :param sim_id: The simulation ID :< json dict brain_populations: A dictionary indexed by population names and containing neuron indices :< json string brain_type: Type of the brain file ('h5' or 'py') :< param brain_populations: Contents of the brain file. Encoding given in field data_type :< json string data_type: type of the data field ('text' or 'base64') :< json string change_population: indicates if it has to be changes in the transfer functions :> json string message: Error Message if there is a syntax error in the code :status 404: {0} :status 200: Success. The populations of the brain where successfully set """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_modify(simulation): raise NRPServicesWrongUserException() body = request.get_json(force=True) result = simulation.cle.set_simulation_populations( brain_type=body['brain_type'], brain_populations=json.dumps(body['brain_populations']), data_type=body['data_type'], change_population=body['change_population']) if result.message: return {'error_message': result.message}, 400 return {'message': 'Success'}, 200
def put(self, sim_id, transfer_function_name): """ Applies user changes to transfer function code :param sim_id: The simulation ID :param transfer_function_name: The name of the transfer function to be modified :< string data: The source code of the transfer function :status 404: {0} :status 403: {1} :status 401: {2} :status 400: {3} :status 200: Success. The transfer function was successfully patched """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.matches_x_user_name_header( request, simulation.owner): raise NRPServicesWrongUserException() transfer_function_source = request.data error_message = simulation.cle.edit_simulation_transfer_function( transfer_function_name, transfer_function_source) if error_message and "duplicate" in error_message: raise NRPServicesDuplicateNameException( "Transfer function patch failed: " + error_message + "\n" + "Updated source:\n" + str(transfer_function_source)) elif error_message: raise NRPServicesTransferFunctionException( "Transfer function patch failed: " + error_message + "\n" + "Updated source:\n" + str(transfer_function_source)) return 200
def delete(self, sim_id, state_machine_name): """ Delete a state machine :param sim_id: The simulation ID :param state_machine_name: The name of the state machine to be deleted :status 500: {0} :status 404: {1} :status 401: {2} :status 200: The delete operation was successfully called. This does not imply that the state machine function was correctly deleted though. """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_modify(simulation): raise NRPServicesWrongUserException() failure_message = "State machine destruction failed: " try: ok, response_message = simulation.delete_state_machine( state_machine_name) if ok: return "Success. The state machine was successfully deleted.", 200 except Exception as e: info = exc_info() raise NRPServicesGeneralException( failure_message + " {0}: {1}".format(e.__class__.__name__, e.message), "State machine error", ), None, info[2] raise NRPServicesStateMachineException( failure_message + "\n" + response_message, 404)
def post(self, sim_id): """ Adds a new transfer function :param sim_id: The simulation ID :< string data: The source code of the transfer function :status 404: {0} :status 403: {1} :status 401: {2} :status 400: {3} :status 200: Success. The transfer function was successfully added """ simulation = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_modify(simulation): raise NRPServicesWrongUserException() transfer_function_source = request.data error_message = simulation.cle.add_simulation_transfer_function( transfer_function_source) if error_message: ex_msg = ("Adding a new Transfer Function failed: {error_msg}\n" "Updated source:\n" "{tf_src}").format(error_msg=error_message, tf_src=str(transfer_function_source)) raise NRPServicesDuplicateNameException(ex_msg) if "duplicate" in error_message \ else NRPServicesTransferFunctionException(ex_msg) return 200
def put(self, sim_id, experiment_id): """ Calls the CLE for resetting a given simulation to the last saved state in the storage. :param sim_id: The simulation ID. :param experiment_id: The experiment ID :> json resetType: the reset type the user wants to be performed, details about possible values are given in GazeboRosPackages/src/cle_ros_msgs/srv/ResetSimulation.srv :status 500: {0} :status 404: {1} :status 401: {2} :status 400: Invalid request, the JSON parameters are incorrect :status 200: The requested reset was performed successfully """ sim = _get_simulation_or_abort(sim_id) if not UserAuthentication.can_modify(sim): raise NRPServicesWrongUserException() req_body = request.get_json(force=True) context_id = req_body.get('contextId', None) for missing_par in (par for par in self.ResetRequest.required if par not in req_body): raise NRPServicesClientErrorException('Missing parameter {}'.format(missing_par)) for invalid_p in (par for par in req_body if par not in self.ResetRequest.resource_fields): raise NRPServicesClientErrorException('Invalid parameter {}'.format(invalid_p)) reset_type = req_body.get('resetType') rsr = srv.ResetSimulationRequest try: if reset_type == rsr.RESET_ROBOT_POSE: sim.cle.reset(reset_type) elif reset_type == rsr.RESET_WORLD: sim.cle.reset(reset_type, world_sdf=self._get_sdf_world_from_storage(experiment_id, context_id)) elif reset_type == rsr.RESET_FULL: brain_path, populations, _ = \ self._get_brain_info_from_storage(experiment_id, context_id) if sim.playback_path is None: self.reset_from_storage_all(sim, experiment_id, context_id) sim.cle.reset(reset_type, world_sdf=self._get_sdf_world_from_storage(experiment_id, context_id), brain_path=brain_path, populations=populations) else: return {}, 400 # Other reset modes are unsupported except ROSCLEClientException as e: raise NRPServicesGeneralException(str(e), 'CLE error', 500) return {}, 200
def get(self, sim_id): """ Gets simulation resource files of the experiment running for the simulation ID :param sim_id: The simulation ID :> json string resources: Resource files :status 500: {0} :status 404: {1}. Or, {2}. :status 200: Success. The simulation BIBI configuration files were retrieved """ simulation = _get_simulation_or_abort(sim_id) experiment_file = simulation.lifecycle.experiment_path if not os.path.isfile(experiment_file): raise NRPServicesClientErrorException( ErrorMessages.EXPERIMENT_CONF_FILE_NOT_FOUND_404, error_code=404) with open(experiment_file) as exd_file: experiment_dom = exp_conf_api_gen.CreateFromDocument( exd_file.read()) bibi_fullpath = os.path.join( simulation.lifecycle.simulation_root_folder, experiment_dom.bibiConf.src) if not os.path.isfile(bibi_fullpath): raise NRPServicesClientErrorException( ErrorMessages.EXPERIMENT_BIBI_FILE_NOT_FOUND_404, error_code=404) resources = [] for conf in experiment_dom.configuration: resources.append({'file': conf.src, 'type': conf.type}) with open(bibi_fullpath) as _file: bibi_dom = bibi_api_gen.CreateFromDocument(_file.read()) for conf in bibi_dom.configuration: resources.append({'file': conf.src, 'type': conf.type}) if simulation.private: for conf in resources: conf['file'] = os.path.join( '/config-from-cloned-folder', os.path.basename( simulation.lifecycle.simulation_root_folder), os.path.basename(conf['file'])) else: # Get the template experiment folder name, e.g., "template_husky" experiment_folder = os.path.basename( os.path.dirname(experiment_file)) for conf in resources: conf['file'] = os.path.join('/config-from-template-folder', experiment_folder, conf['file']) return {'resources': resources}, 200
def put(self, sim_id): """ Set brain file of the simulation specified with simulation ID. Depending on the type of brain file, it has to be transmitted as text or as base64 :param sim_id: The simulation ID :< json string brain_type: Type of the brain file ('h5' or 'py') :< json string data_type: type of the data field ('text' or 'base64') :< json string data: Contents of the brain file. Encoding given in field data_type :< json dict brain_populations: A dictionary indexed by population names and containing neuron indices :> json string error_message: Error Message if there is a syntax error in the code :> json int error_line: Line of code, where error occurred :> json int error_column: Column, where error occurred (if available) :> json bool handle_population_change: a flag indicating if user wants to change transfer functions according to population changes. :status 500: {0} :status 404: {1} :status 401: {2} :status 400: {3} :status 200: Success. The experiment brain file was replaced """ simulation = _get_simulation_or_abort(sim_id) storage_client = StorageClient() if not UserAuthentication.can_modify(simulation): raise NRPServicesWrongUserException() body = request.get_json(force=True) file_url = body.get('urls', {}).get('fileUrl') if file_url: # TODO: fix server certificate and remove verify with requests.get(file_url, verify=False) as h5: filename = os.path.basename(file_url) with open(os.path.join(simulation.lifecycle.sim_dir, filename), 'w') as f: f.write(h5.content) storage_client.create_or_update(simulation.token, simulation.experiment_id, filename, h5.content, "text/plain") result = simulation.cle.set_simulation_brain( brain_type=body['brain_type'], data=body['data'], data_type=body['data_type'], brain_populations=json.dumps(body['brain_populations'])) if result.error_message: # Error in given brain return { 'error_message': result.error_message, 'error_line': result.error_line, 'error_column': result.error_column }, 400 # Success return {'message': "Success"}, 200
def test_simulation_state_machines_delete_OK(self): self.mock_sm_manager_instance.state_machines = [self.mock_sm_instance] simulation = _get_simulation_or_abort(0) simulation.set_state_machine_code(self.sm_instance_name, SM) response = self.client.delete('/simulation/0/state-machines/Control1') self.assertEqual(response.status_code, 200)
def test_simulation_state_machines_get_ok2(self): self.mock_sm_manager_instance.state_machines = [self.mock_sm_instance] simulation = _get_simulation_or_abort(0) simulation.set_state_machine_code(self.sm_instance_name, SM) response = self.client.get('/simulation/0/state-machines') self.assertIsInstance(response, Response) self.assertMultiLineEqual(json.loads(response.data)["data"][self.sm_instance_name], SM) self.assertEqual(response.status_code, 200)
def test_simulation_state_machines_put_OK(self): simulation = _get_simulation_or_abort(0) simulation.set_state_machine_code(self.sm_instance_name, SM) response = self.client.put('/simulation/0/state-machines/Control1', data=SM) self.assertIsInstance(response, Response) self.assertEqual(response.status_code, 200) simulation.state = "paused" response = self.client.put('/simulation/0/state-machines/Control1', data=SM) self.assertIsInstance(response, Response) self.assertEqual(response.status_code, 200)
def get(self, sim_id): """ Gets the structured transfer functions :param sim_id: The simulation id :status 404: {0} :status 200: Success. The transfer functions were returned """ simulation = _get_simulation_or_abort(sim_id) tfs = [] transfer_functions_list = simulation.cle.get_structured_transfer_functions( ) for tf in transfer_functions_list: devices = [{ 'name': dev.name, 'type': dev.type, 'neurons': { 'name': dev.neurons.name, 'type': dev.neurons.type, 'ids': [{ 'id': n_id } for n_id in dev.neurons.ids], 'start': dev.neurons.start, 'stop': dev.neurons.stop, 'step': dev.neurons.step } } for dev in tf.devices] topics = [{ 'name': top.name, 'topic': top.topic, 'type': top.type, 'publishing': top.publishing } for top in tf.topics] variables = [{ 'name': var.name, 'type': var.type, 'initial_value': var.initial_value } for var in tf.variables] tf_e = { 'name': tf.name, 'code': tf.code, 'type': tf.type, 'devices': devices, 'topics': topics, 'variables': variables } tfs.append(tf_e) return {'transferFunctions': tfs}, 200
def put(self, sim_id, state_machine_name): """ Applies user changes to state machine code. If the simulation is paused or started, it will be paused. A stopped, created or failed simulation will fail the request with error code 403 :param sim_id: The simulation ID :param state_machine_name: The name of the state machine to be modified :< json string data: The source code of the state machine :status 404: {0} :status 401: {1} :status 400: {2} :status 200: Success. The code was successfully patched """ simulation = _get_simulation_or_abort(sim_id) assert simulation, Simulation if not UserAuthentication.matches_x_user_name_header(request, simulation.owner): raise NRPServicesWrongUserException() state_machine_source = request.data try: simulation.set_state_machine_code( state_machine_name, state_machine_source ) return "Success. The code was successfully patched.", 200 except (AttributeError, NameError) as e: info = exc_info() raise NRPServicesStateMachineException(e.message, 400), None, info[2] except SyntaxError as e: info = exc_info() args_txt = "" for text in e.args: args_txt += " {0}".format(text) raise NRPServicesStateMachineException( "The source code is invalid: " "SyntaxError in line {0}{1}.".format(e.lineno, args_txt), 400 ), None, info[2] except Exception as e: info = exc_info() raise NRPServicesGeneralException( "Update of state machine code failed. " "{0}: {1}".format( e.__class__.__name__, e.message ), "State machine error" ), None, info[2]
def post(self, sim_id): """ Save the current running experiment SDF back to the storage :param sim_id: The sim_id :param context_id: The context_id of the experiment :status 500: Error saving file :status 200: Success. File written. """ # pylint: disable=too-many-locals simulation = _get_simulation_or_abort(sim_id) try: rospy.wait_for_service('/gazebo/export_world_sdf', 3) except rospy.ROSException as exc: raise NRPServicesUnavailableROSService(str(exc)) dump_sdf_world = rospy.ServiceProxy('/gazebo/export_world_sdf', ExportWorldSDF) try: sdf_string = dump_sdf_world().sdf_dump tree = ET.fromstring(sdf_string) # Erase all robots from the SDF robots = simulation.cle.get_simulation_robots() for robot in robots: for m in tree.findall(".//model[@name='" + robot.robot_id + "']"): m.getparent().remove(m) sdf_string = ET.tostring(tree, encoding='utf8', method='xml') except rospy.ServiceException as exc: raise NRPServicesClientErrorException( "Service did not process request:" + str(exc)) client = StorageClient() # find the sdf world filename from the .exc exp_xml_file_path = client.clone_file( 'experiment_configuration.exc', UserAuthentication.get_header_token(), simulation.experiment_id) experiment_file = client.parse_and_check_file_is_valid( exp_xml_file_path, exp_conf_api_gen.CreateFromDocument, exp_conf_api_gen.ExD_) world_file_name = experiment_file.environmentModel.src client.create_or_update(UserAuthentication.get_header_token(), simulation.experiment_id, world_file_name, sdf_string, "text/plain") return 200