def run(self): # Set up shared memory map (offset makes it so bot only writes to its own input!) and map to buffer buff = mmap.mmap(-1, ctypes.sizeof(bi.GameInputPacket), INPUT_SHARED_MEMORY_TAG) bot_input = bi.GameInputPacket.from_buffer(buff) player_input = bot_input.sPlayerInput[self.index] player_input_lock = (ctypes.c_long).from_address( ctypes.addressof(player_input)) # Set up shared memory for game data game_data_shared_memory = mmap.mmap( -1, ctypes.sizeof(gd.GameTickPacketWithLock), OUTPUT_SHARED_MEMORY_TAG) bot_output = gd.GameTickPacketWithLock.from_buffer( game_data_shared_memory) lock = ctypes.c_long(0) game_tick_packet = gd.GameTickPacket( ) # We want to do a deep copy for game inputs so people don't mess with em # Create Ratelimiter r = rate_limiter.RateLimiter(GAME_TICK_PACKET_REFRESHES_PER_SECOND) last_tick_game_time = None # What the tick time of the last observed tick was last_call_real_time = datetime.now() # When we last called the Agent # Find car with same name and assign index for i in range(MAX_CARS): if str(bot_output.gamecars[i].wName) == self.name: self.index = i continue # Get bot module agent_module = importlib.import_module(self.module_name) # Create bot from module agent = agent_module.Agent(self.name, self.team, self.index) last_module_modification_time = os.stat(agent_module.__file__).st_mtime # Run until main process tells to stop while not self.terminateEvent.is_set(): before = datetime.now() # Read from game data shared memory game_data_shared_memory.seek( 0) # Move to beginning of shared memory ctypes.memmove( ctypes.addressof(lock), game_data_shared_memory.read(ctypes.sizeof(lock)), ctypes.sizeof(lock) ) # dll uses InterlockedExchange so this read will return the correct value! if lock.value != REFRESH_IN_PROGRESS: game_data_shared_memory.seek( 4, os.SEEK_CUR) # Move 4 bytes past error code ctypes.memmove( ctypes.addressof(game_tick_packet), game_data_shared_memory.read( ctypes.sizeof(gd.GameTickPacket)), ctypes.sizeof( gd.GameTickPacket)) # copy shared memory into struct # Run the Agent only if the gameInfo has updated. tick_game_time = game_tick_packet.gameInfo.TimeSeconds should_call_while_paused = datetime.now( ) - last_call_real_time >= MAX_AGENT_CALL_PERIOD if tick_game_time != last_tick_game_time or should_call_while_paused: last_tick_game_time = tick_game_time last_call_real_time = datetime.now() try: # Reload the Agent if it has been modified. new_module_modification_time = os.stat( agent_module.__file__).st_mtime if new_module_modification_time != last_module_modification_time: last_module_modification_time = new_module_modification_time print('Reloading Agent: ' + agent_module.__file__) importlib.reload(agent_module) old_agent = agent agent = agent_module.Agent(self.name, self.team, self.index) # Retire after the replacement initialized properly. if hasattr(old_agent, 'retire'): old_agent.retire() # Call agent controller_input = agent.get_output_vector( game_tick_packet) if not controller_input: raise Exception( 'Agent "{}" did not return a player_input tuple.'. format(agent_module.__file__)) # Write all player inputs player_input.fThrottle = controller_input[0] player_input.fSteer = controller_input[1] player_input.fPitch = controller_input[2] player_input.fYaw = controller_input[3] player_input.fRoll = controller_input[4] player_input.bJump = controller_input[5] player_input.bBoost = controller_input[6] player_input.bHandbrake = controller_input[7] except Exception as e: traceback.print_exc() # Workaround for windows streams behaving weirdly when not in command prompt sys.stdout.flush() sys.stderr.flush() # Ratelimit here after = datetime.now() # print('Latency of ' + self.name + ': ' + str(after - before)) r.acquire(after - before) if hasattr(agent, 'retire'): agent.retire() # If terminated, send callback self.callbackEvent.set()
def run(self): # Set up shared memory map (offset makes it so bot only writes to its own input!) and map to buffer filename = "" buff = mmap.mmap(-1, ctypes.sizeof(bi.GameInputPacket), INPUT_SHARED_MEMORY_TAG) bot_input = bi.GameInputPacket.from_buffer(buff) player_input = bot_input.sPlayerInput[self.index] player_input_lock = (ctypes.c_long).from_address( ctypes.addressof(player_input)) # Set up shared memory for game data game_data_shared_memory = mmap.mmap( -1, ctypes.sizeof(gd.GameTickPacketWithLock), OUTPUT_SHARED_MEMORY_TAG) bot_output = gd.GameTickPacketWithLock.from_buffer( game_data_shared_memory) lock = ctypes.c_long(0) game_tick_packet = gd.GameTickPacket( ) # We want to do a deep copy for game inputs so people don't mess with em # Create Ratelimiter r = rate_limiter.RateLimiter(GAME_TICK_PACKET_REFRESHES_PER_SECOND) last_tick_game_time = None # What the tick time of the last observed tick was last_call_real_time = datetime.now() # When we last called the Agent # Find car with same name and assign index for i in range(MAX_CARS): if str(bot_output.gamecars[i].wName) == self.name: self.index = i continue # Get bot module agent_module = importlib.import_module(self.module_name) # Create bot from module agent = self.load_agent(agent_module) if hasattr(agent, 'create_model_hash'): self.model_hash = agent.create_model_hash() else: self.model_hash = 0 self.server_manager.set_model_hash(self.model_hash) last_module_modification_time = os.stat(agent_module.__file__).st_mtime if hasattr(agent, 'is_evaluating'): self.is_eval = agent.is_evaluating self.server_manager.set_is_eval(self.is_eval) if self.save_data: filename = self.create_file_name() print('creating file ' + filename) self.create_new_file(filename) old_time = 0 counter = 0 last_module_modification_time = os.stat(agent_module.__file__).st_mtime # Run until main process tells to stop while not self.terminateEvent.is_set(): before = datetime.now() before2 = time.time() # Read from game data shared memory game_data_shared_memory.seek( 0) # Move to beginning of shared memory ctypes.memmove( ctypes.addressof(lock), game_data_shared_memory.read(ctypes.sizeof(lock)), ctypes.sizeof(lock) ) # dll uses InterlockedExchange so this read will return the correct value! if lock.value != REFRESH_IN_PROGRESS: game_data_shared_memory.seek( 4, os.SEEK_CUR) # Move 4 bytes past error code ctypes.memmove( ctypes.addressof(game_tick_packet), game_data_shared_memory.read( ctypes.sizeof(gd.GameTickPacket)), ctypes.sizeof( gd.GameTickPacket)) # copy shared memory into struct if game_tick_packet.gameInfo.bMatchEnded: print('\n\n\n\n Match has ended so ending bot loop\n\n\n\n\n') break import sys sys.stdout.flush() controller_input = None # Run the Agent only if the gameInfo has updated. tick_game_time = game_tick_packet.gameInfo.TimeSeconds should_call_while_paused = datetime.now( ) - last_call_real_time >= MAX_AGENT_CALL_PERIOD if tick_game_time != last_tick_game_time or should_call_while_paused: last_tick_game_time = tick_game_time last_call_real_time = datetime.now() try: # Reload the Agent if it has been modified. new_module_modification_time = os.stat( agent_module.__file__).st_mtime if new_module_modification_time != last_module_modification_time: last_module_modification_time = new_module_modification_time print('Reloading Agent: ' + agent_module.__file__) importlib.reload(agent_module) old_agent = agent agent = self.load_agent(agent_module) # Retire after the replacement initialized properly. if hasattr(old_agent, 'retire'): old_agent.retire() # Call agent controller_input = agent.get_output_vector( game_tick_packet) if not controller_input: raise Exception( 'Agent "{}" did not return a player_input tuple.'. format(agent_module.__file__)) # Write all player inputs player_input.fThrottle = controller_input[0] player_input.fSteer = controller_input[1] player_input.fPitch = controller_input[2] player_input.fYaw = controller_input[3] player_input.fRoll = controller_input[4] player_input.bJump = controller_input[5] player_input.bBoost = controller_input[6] player_input.bHandbrake = controller_input[7] except Exception as e: traceback.print_exc() # Workaround for windows streams behaving weirdly when not in command prompt sys.stdout.flush() sys.stderr.flush() current_time = game_tick_packet.gameInfo.TimeSeconds if self.save_data and game_tick_packet.gameInfo.bRoundActive and not old_time == current_time and not current_time == -10: np_input = self.input_converter.create_input_array( game_tick_packet, passed_time=current_time - old_time) np_output = np.array(controller_input, dtype=np.float32) self.input_array = np.append(self.input_array, np_input) self.output_array = np.append(self.output_array, np_output) if self.frames % self.batch_size == 0 and not self.frames == 0: print('writing big array', self.frames % (self.batch_size * self.upload_size)) compressor.write_array_to_file(self.game_file, self.input_array) compressor.write_array_to_file(self.game_file, self.output_array) self.input_array = np.array([]) self.output_array = np.array([]) if self.frames % (self.batch_size * self.upload_size ) == 0 and not self.frames == 0: print('adding new file and uploading') self.file_number += 1 self.game_file.close() print('creating file ' + filename) self.maybe_compress_and_upload(filename) filename = self.create_file_name() self.create_new_file(filename) self.maybe_delete(self.file_number - 3) if self.frames % ( self.batch_size * self.upload_size * self.retry_size) == 0 and not self.frames == 0: try: self.server_manager.retry_files() except Exception: print('failed to retry uploading files') self.frames += 1 old_time = current_time # Ratelimit here after = datetime.now() after2 = time.time() # cant ever drop below 40 frames if after2 - before2 > 0.025: print('Too slow for ' + self.name + ': ' + str(after2 - before2) + ' frames since slowdown ' + str(counter)) counter = 0 else: counter += 1 r.acquire(after - before) if hasattr(agent, 'retire'): agent.retire() # If terminated, send callback print("something ended closing file") if self.save_data: self.maybe_compress_and_upload(filename) self.server_manager.retry_files() print('done with bot') self.callbackEvent.set()
return current_game_info RAW_DATA_PATH = '../../FlowBot Training Data/raw/training_data_' SAMPLE_RATE = 100 # per second (approximated) SHARED_MEMORY_TAG = 'Local\\RLBotOutput' REFRESH_IN_PROGRESS = 1 if __name__ == '__main__': # Set up shared memory for game data game_data_shared_memory = mmap.mmap( -1, ctypes.sizeof(gd.GameTickPacketWithLock), SHARED_MEMORY_TAG) # This lock ensures that a read cannot start while the dll is writing to shared memory. lock = ctypes.c_long(0) game_tick_packet = gd.GameTickPacket() file_path = RAW_DATA_PATH + str(int(time.time())) + '.txt' count = 0 discarded = 0 with open(file_path, 'a') as tdFile: while True: # Read from game data shared memory game_data_shared_memory.seek( 0) # Move to beginning of shared memory ctypes.memmove( ctypes.addressof(lock), game_data_shared_memory.read(ctypes.sizeof(lock)), ctypes.sizeof(lock) ) # dll uses InterlockedExchange so this read will return the correct value!
def run(self): # Set up shared memory map (offset makes it so bot only writes to its own input!) and map to buffer buff = mmap.mmap(-1, ctypes.sizeof(bi.GameInputPacket), INPUT_SHARED_MEMORY_TAG) bot_input = bi.GameInputPacket.from_buffer(buff) player_input = bot_input.sPlayerInput[self.index] player_input_lock = (ctypes.c_long).from_address( ctypes.addressof(player_input)) # Set up shared memory for game data game_data_shared_memory = mmap.mmap( -1, ctypes.sizeof(gd.GameTickPacketWithLock), OUTPUT_SHARED_MEMORY_TAG) bot_output = gd.GameTickPacketWithLock.from_buffer( game_data_shared_memory) lock = ctypes.c_long(0) game_tick_packet = gd.GameTickPacket( ) # We want to do a deep copy for game inputs so people don't mess with em # Get bot module agent_module = importlib.import_module(self.module_name) # Create Ratelimiter r = rate_limiter.RateLimiter(RATE_LIMITED_ACTIONS_PER_SECOND) # Find car with same name and assign index for i in range(MAX_CARS): if str(bot_output.gamecars[i].wName) == self.name: self.index = i continue # Create bot from module agent = agent_module.Agent(self.name, self.team, self.index) # Run until main process tells to stop while not self.terminateEvent.is_set(): before = datetime.now() # Read from game data shared memory game_data_shared_memory.seek( 0) # Move to beginning of shared memory ctypes.memmove( ctypes.addressof(lock), game_data_shared_memory.read(ctypes.sizeof(lock)), ctypes.sizeof(lock) ) # dll uses InterlockedExchange so this read will return the correct value! if lock.value != REFRESH_IN_PROGRESS: game_data_shared_memory.seek( 4, os.SEEK_CUR) # Move 4 bytes past error code ctypes.memmove( ctypes.addressof(game_tick_packet), game_data_shared_memory.read( ctypes.sizeof(gd.GameTickPacket)), ctypes.sizeof( gd.GameTickPacket)) # copy shared memory into struct # Call agent controller_input = agent.get_output_vector(game_tick_packet) # Write all player inputs player_input.fThrottle = controller_input[0] player_input.fSteer = controller_input[1] player_input.fPitch = controller_input[2] player_input.fYaw = controller_input[3] player_input.fRoll = controller_input[4] player_input.bJump = controller_input[5] player_input.bBoost = controller_input[6] player_input.bHandbrake = controller_input[7] # Ratelimit here after = datetime.now() # print('Latency of ' + self.name + ': ' + str(after - before)) r.acquire(after - before) # If terminated, send callback self.callbackEvent.set()