def _handle_message(action: bytes, data: List[bytes]) -> bytes: from drivebuildclient.aiExchangeMessages_pb2 import Bool if action == b"isRunning": sid = SimulationID() sid.ParseFromString(data[0]) result = Bool() result.value = _is_simulation_running(sid) elif action == b"vids": sid = SimulationID() sid.ParseFromString(data[0]) result = _get_vids(sid) elif action == b"pollSensors": sid = SimulationID() sid.ParseFromString(data[0]) result = _poll_sensors(sid) elif action == b"verify": sid = SimulationID() sid.ParseFromString(data[0]) result = _verify(sid) elif action == b"requestAiFor": sid = SimulationID() sid.ParseFromString(data[0]) vid = VehicleID() vid.ParseFromString(data[1]) result = _request_ai_for(sid, vid) elif action == b"storeVerificationCycle": sid = SimulationID() sid.ParseFromString(data[0]) started = Num() started.ParseFromString(data[1]) finished = Num() finished.ParseFromString(data[2]) result = _store_verification_cycle( sid, datetime.fromtimestamp(started.num), datetime.fromtimestamp(finished.num)) elif action == b"steps": sid = SimulationID() sid.ParseFromString(data[0]) steps = Num() steps.ParseFromString(data[1]) result = Void() if _is_simulation_running(sid): _get_data(sid).scenario.bng.step(steps.num) result.message = "Simulated " + str( steps.num) + " steps in simulation " + sid.sid + "." else: result.message = "Simulation " + sid.sid + " is not running anymore." elif action == b"stop": sid = SimulationID() sid.ParseFromString(data[0]) test_result = TestResult() test_result.ParseFromString(data[1]) _control_sim(sid, test_result.result, False) result = Void() else: message = "The action \"" + action.decode() + "\" is unknown." _logger.info(message) result = Void() result.message = message return result.SerializeToString()
def _store_verification_cycle(sid: SimulationID, started: datetime, finished: datetime) -> Void: vehicles = _get_data(sid).scenario.vehicles.keys() void = Void() if _is_simulation_running(sid): for vehicle in vehicles: vid = VehicleID() vid.vid = vehicle.vid request = DataRequest() request.request_ids.extend(vehicle.requests) data = _request_data(sid, vid, request) args = { "sid": sid.sid, "vid": vid.vid, "tick": _get_data(sid).scenario.bng.current_tick, "data": data.SerializeToString(), "started": _time_to_string(started), "finished": _time_to_string(finished) } _DB_CONNECTION.run_query( """ INSERT INTO verificationcycles VALUES (:sid, :vid, :tick, :data, :started, :finished); """, args) void.message = "Stored data of the current runtime verification cycle of simulation " + sid.sid + "." else: void.message = "Skipped storing the data of the current runtime verification cycle since simulation " \ + sid.sid + " does not run anymore." return void
def _request_control_avs(self, vids: List[str]) -> None: from drivebuildclient.aiExchangeMessages_pb2 import VehicleID import dill as pickle for v in vids: # print(self.sid.sid + ": Request control for " + v) mode = self.get_current_movement_mode(v) if not mode: # If there is no movement mode file assume participant is still in mode of initial state test_case = pickle.loads(self.pickled_test_case) mode = [ p.initial_state.mode for p in test_case.scenario.participants if p.id == v ][0] if mode in [ MovementMode.AUTONOMOUS, MovementMode.TRAINING, MovementMode._BEAMNG ]: vid = VehicleID() vid.vid = v message = self.send_message_to_sim_node( b"requestAiFor", [self.serialized_sid, vid.SerializeToString()]) _logger.debug(message) elif mode == MovementMode.MANUAL: pass # No AI to request else: _logger.warning(self.sid.sid + ":" + v + ": Can not handle movement mode " + (mode.name if mode else "None"))
def extract_vid() -> Tuple[Optional[bytes], Optional[VehicleID]]: from flask import request serialized_vid_b = request.args.get("vid", default=None) if serialized_vid_b: serialized_vid = serialized_vid_b.encode() vid = VehicleID() vid.ParseFromString(serialized_vid) return serialized_vid, vid else: return None, None
def _start_moose_test(): from drivebuildclient.aiExchangeMessages_pb2 import VehicleID from drivebuildclient.AIExchangeService import AIExchangeService from dummy_ai import DummyAI from os.path import dirname, join from pathlib import Path service = AIExchangeService("localhost", 8383) upload_result = service.run_tests("test", "test", Path(join(dirname(__file__), "scenario"))) if upload_result and upload_result.submissions: for test_name, sid in upload_result.submissions.items(): vid = VehicleID() vid.vid = "ego" DummyAI(service).start(sid, vid)
def main() -> None: from drivebuildclient.AIExchangeService import AIExchangeService from drivebuildclient.aiExchangeMessages_pb2 import VehicleID from common.dummy_ai import DummyAI from pathlib import Path from os.path import dirname, join service = AIExchangeService("localhost", 5000) upload_result = service.run_tests( "test", "test", Path(join(dirname(__file__), "providedFiles"))) if upload_result and upload_result.submissions: for test_name, sid in upload_result.submissions.items(): vid = VehicleID() vid.vid = "ego" DummyAI(service).start(sid, vid)
def control(self, sid: SimulationID, vid: VehicleID, commands: Control) -> Optional[Void]: """ Control the simulation or a certain vehicle in the simulation. :param sid: The ID the simulation either to control or containing th vehicle to control. :param vid: The ID of the vehicle to possibly control. :param commands: The command either controlling a simulation or a vehicle in a simualtion. To define a command controlling a simulation you can use commands like: control = Control() control.simCommand.command = Control.SimCommand.Command.SUCCEED # Force simulation to succeed control.simCommand.command = Control.SimCommand.Command.FAIL # Force simulation to fail control.simCommand.command = Control.SimCommand.Command.CANCEL # Force simulation to be cancelled/skipped For controlling a vehicle you have to define steering, acceleration and brake values: control = Control() control.avCommand.accelerate = <Acceleration intensity having a value between 0.0 and 1.0> control.avCommand.steer = <A steering value between -1.0 and 1.0 (Negative value steers left; a positive one steers right)> control.avCommand.brake = <Brake intensity having a value between 0.0 and 1.0> :return: A Void object possibly containing a info message. """ from drivebuildclient.httpUtil import do_mixed_request response = do_mixed_request(self.host, self.port, "/ai/control", { "sid": sid.SerializeToString(), "vid": vid.SerializeToString() }, commands.SerializeToString()) if response.status == 200: void = Void() void.ParseFromString(b"".join(response.readlines())) return void else: AIExchangeService._print_error(response)
def request_data(self, sid: SimulationID, vid: VehicleID, request: DataRequest) -> DataResponse: """ Request data of a certain vehicle contained by a certain simulation. :param sid: The ID of the simulation the vehicle to request data about is part of. :param vid: The ID of the vehicle to get collected data from. :param request: The types of data to be requested about the given vehicle. A DataRequest object is build like the following: request = DataRequest() request.request_ids.extend(["id_1", "id_2",..., "id_n"]) NOTE: You have to use extend(...)! An assignment like request.request_ids = [...] will not work due to the implementation of Googles protobuffer. :return: The data the simulation collected about the given vehicle. The way of accessing the data is dependant on the type of data you requested. To find out how to access the data properly you should set a break point and checkout the content of the returned value using a debugger. """ from drivebuildclient.httpUtil import do_get_request response = do_get_request( self.host, self.port, "/ai/requestData", { "request": request.SerializeToString(), "sid": sid.SerializeToString(), "vid": vid.SerializeToString() }) if response.status == 200: result = b"".join(response.readlines()) data_response = DataResponse() data_response.ParseFromString(result) return data_response else: AIExchangeService._print_error(response)
def wait_for_simulator_request( self, sid: SimulationID, vid: VehicleID) -> SimStateResponse.SimState: """ Waits for the simulation with ID sid to request the car with ID vid. This call blocks until the simulation requests the appropriate car in the given simulation. :param sid: The ID of the simulation the vehicle is included in. :param vid: The ID of the vehicle in the simulation to wait for. :return: The current state of the simulation at the point when the call to this function returns. The return value should be used to check whether the simulation is still running. Another vehicle or the even user may have stopped the simulation. """ from drivebuildclient.httpUtil import do_get_request response = do_get_request(self.host, self.port, "/ai/waitForSimulatorRequest", { "sid": sid.SerializeToString(), "vid": vid.SerializeToString() }) if response.status == 200: result = b"".join(response.readlines()) sim_state = SimStateResponse() sim_state.ParseFromString(result) return sim_state.state else: AIExchangeService._print_error(response)
def get_trace( self, sid: SimulationID, vid: Optional[VehicleID] = None ) -> List[Tuple[str, str, int, DataResponse]]: """ Return all the collected data of a single or all participants in a simulation. :param sid: The simulation to request all the collected data from. :param vid: The vehicle whose collected data has to be returned. If None this method returns all the collected data. :return: The JSON serialized object representing all the collected data of a simulation or a participant in a simulation. """ from drivebuildclient.httpUtil import do_get_request import dill as pickle args = {"sid": sid.SerializeToString()} if vid: args["vid"] = vid.SerializeToString() response = do_get_request(self.host, self.port, "/stats/trace", args) if response.status == 200: response_content = b"".join(response.readlines()) trace_data = pickle.loads(response_content) trace = [] for entry in trace_data: sid = SimulationID() sid.sid = str(entry[0]) vid = VehicleID() vid.vid = entry[1] data = DataResponse() data.ParseFromString(entry[3]) trace.append((sid, vid, entry[2], data)) return trace else: AIExchangeService._print_error(response) return "The trace could not be retrieved."
def _handle_vehicle(sid: SimulationID, vid: str, requests: List[str]) -> None: vid_obj = VehicleID() vid_obj.vid = vid while True: print(sid.sid + ": Test status: " + service.get_status(sid)) print(vid + ": Wait") sim_state = service.wait_for_simulator_request(sid, vid_obj) # wait() if sim_state is SimStateResponse.SimState.RUNNING: print(vid + ": Request data") request = DataRequest() request.request_ids.extend(requests) data = service.request_data(sid, vid_obj, request) # request() # print(data) print(vid + ": Wait for control") control = Control() while not is_pressed("space"): # Wait for the user to trigger manual drive pass print(vid + ": Control") if is_pressed("s"): control.simCommand.command = Control.SimCommand.Command.SUCCEED elif is_pressed("f"): control.simCommand.command = Control.SimCommand.Command.FAIL elif is_pressed("c"): control.simCommand.command = Control.SimCommand.Command.CANCEL else: accelerate = 0 steer = 0 brake = 0 if is_pressed("up"): accelerate = 1 if is_pressed("down"): brake = 1 if is_pressed("right"): steer = steer + 1 if is_pressed("left"): steer = steer - 1 control.avCommand.accelerate = accelerate control.avCommand.steer = steer control.avCommand.brake = brake service.control(sid, vid_obj, control) # control() else: print(sid.sid + ": The simulation is not running anymore (State: " + SimStateResponse.SimState.Name(sim_state) + ").") print(sid.sid + ": Final result: " + service.get_result(sid)) break
def _main() -> None: from pathlib import Path _configure_asfault() test = _generate_asfault_test() lanes = _get_lanes(test) dbe_content = _generate_dbe(lanes) temp_dbe_file = NamedTemporaryFile(mode="w", delete=False, suffix=".dbe.xml") temp_dbe_file.write(dbe_content) temp_dbe_file.close() # FIXME Choose lane based on some ranking? dbc_content = _generate_dbc(lanes[0], basename(temp_dbe_file.name)) temp_dbc_file = NamedTemporaryFile(mode="w", delete=False, suffix=".dbc.xml") temp_dbc_file.write(dbc_content) temp_dbc_file.close() service = AIExchangeService("defender.fim.uni-passau.de", 8383) submission_result = service.run_tests("test", "test", Path(temp_dbe_file.name), Path(temp_dbc_file.name)) if submission_result and submission_result.submissions: for test_name, sid in submission_result.submissions.items(): vid = VehicleID() vid.vid = "ego" while True: sim_state = service.wait_for_simulator_request(sid, vid) if sim_state != SimStateResponse.SimState.RUNNING: break print("Result of \"" + test_name + "\": " + service.get_result(sid)) break # NOTE Assume only one test was uploaded else: _LOGGER.warning("DriveBuild denied running the given test.") remove(temp_dbe_file.name) remove(temp_dbc_file.name)
def main(): print("parameters: ") for i in range(1, len(sys.argv)): print(sys.argv[i]) data_request_path = sys.argv[1] ai_path = sys.argv[2] working_directory = sys.argv[3] """ data_request_path = "C:\\sbse4tac-ws-2019-self-driving-car-e2edriving\\ai\\data_requests.py" ai_path = "C:\\sbse4tac-ws-2019-self-driving-car-e2edriving\\run_db.py" working_directory = "C:\\sbse4tac-ws-2019-self-driving-car-e2edriving" """ service = AIExchangeService("localhost", 8383) vid = VehicleID() vid.vid = "ego" tg = TestGenerator() tg.set_difficulty("easy") while True: for paths in tg.getTest(): criteria = paths[1] environment = paths[0] # edit the xml spec = importlib.util.spec_from_file_location( "AI", data_request_path) foo = importlib.util.module_from_spec(spec) # Actually run the import spec.loader.exec_module(foo) # get ai element double_backslash_dbc_path = str(criteria).replace( "\\", "\\" + "\\") tree = parse(double_backslash_dbc_path) root = tree.getroot() for i in range(0, len(root.getchildren())): if root.getchildren( )[i].tag == "{http://drivebuild.com}participants": participant_block = root.getchildren()[i].getchildren()[0] for j in range(0, len(participant_block)): part_child = participant_block.getchildren()[j] if part_child.tag == "{http://drivebuild.com}ai": pass part_child.clear() foo.add_data_requests(part_child, "ego") pass # write the changed xml # TODO pretty print f = open(double_backslash_dbc_path, "w") f.write(tostring(root, pretty_print=True).decode("utf-8")) f.close() # ai: _Element = ai_tag.makeelement(_tag="speed") submission_result = service.run_tests("test", "test", environment, criteria) # Interact with a simulation if submission_result and submission_result.submissions: for test_name, sid in submission_result.submissions.items(): ai_process = subprocess.Popen([env_path, ai_path, sid.sid], cwd=working_directory) sim_state = service.wait_for_simulator_request(sid, vid) while sim_state is SimStateResponse.SimState.RUNNING: sleep(5) sim_state = service.wait_for_simulator_request( sid, vid) # TODO Use a trap or try except to ensure we kill the process kill_process(ai_process) sleep(5) tg.onTestFinished(sid, vid)
def _handle_main_app_message(action: bytes, data: List[bytes]) -> bytes: from google.protobuf.message import DecodeError if action == b"runTests": user = User() try: user.ParseFromString(data[1]) result = _run_tests(data[0], user) except DecodeError: _logger.exception("Running a test failed since \"" + str(data[1]) + "\" can not be parsed to an User") result = SubmissionResult() result.message.message = "The user parameter could not be parsed." elif action == b"waitForSimulatorRequest": sid = SimulationID() sid.ParseFromString(data[0]) vid = VehicleID() vid.ParseFromString(data[1]) result = _wait_for_simulator_request(sid, vid) elif action == b"control": sid = SimulationID() sid.ParseFromString(data[0]) vid = VehicleID() vid.ParseFromString(data[1]) control = Control() control.ParseFromString(data[2]) result = _control(sid, vid, control) elif action == b"requestData": sid = SimulationID() sid.ParseFromString(data[0]) vid = VehicleID() vid.ParseFromString(data[1]) request = DataRequest() request.ParseFromString(data[2]) result = _request_data(sid, vid, request) elif action == b"requestSocket": client = create_client(MAIN_APP_HOST, MAIN_APP_PORT) client_thread = Thread(target=process_requests, args=(client, _handle_main_app_message)) client_thread.daemon = True _logger.info("_handle_main_app_message --> " + str(client.getsockname())) client_thread.start() result = Void() result.message = "Connected another client socket to the main app." elif action == b"runningTests": user = User() user.ParseFromString(data[0]) result = _get_running_tests(user) elif action == b"stop": sid = SimulationID() sid.ParseFromString(data[0]) test_result = TestResult() test_result.ParseFromString(data[1]) _control_sim(sid, test_result.result, False) result = Void() result.message = "Stopped simulation " + sid.sid + "." else: message = "The action \"" + action.decode() + "\" is unknown." _logger.info(message) result = Void() result.message = message return result.SerializeToString()