def race(self, driver): """ Let a driver race in a preconfigured quickrace :param driver: a driver object that generates actions based on sensors :return: driver fitness value after race """ if not self.connect(): raise IOError("could not connect to TORCS") start_time = timeit.default_timer() try: print "Start racing..." s = None lap_times = [] cur_lap_time = -10.0 timeout_reached = False recovery_lock = 0 max_speed = 0.0 avg_speed = RunningAverage() driver.prepare() while True: data = self.sock.recv(2048) if data.strip().startswith("("): s = SensorModel(string=data) action = driver.get_action(sensors=s) # save maximum speed for fitness function max_speed = max(max_speed, s['speedX']) avg_speed.add_value(float(s['speedX'])) # AUTORECOVERY: if off track, go backwards until back on track and then some more if self.auto_recover and (s.is_off_track() or recovery_lock > 0): action.gear = -1 action.accel = 0.4 action.clutch = 0.0 action.steering = s['angle'] / -2.0 if s.is_off_track(): recovery_lock = RECOVERY_LOCK else: recovery_lock -= 1 self.sock.sendto(str(action), self.server_address) if s['curLapTime'][0] < cur_lap_time: lap_times.append(cur_lap_time) print "lap %i: %0.2f seconds" % (len(lap_times), cur_lap_time) cur_lap_time = s['curLapTime'][0] else: if data.startswith("***shutdown***"): if s['curLapTime'][0] > 1: lap_times.append(s['curLapTime'][0]) print "--- END OF RACE --- finished at position %i, avg/max speed: %0.2f/%0.2f km/h" % ( int(s['racePos']), avg_speed.avg, max_speed) break if self.timeout is not None and s['curLapTime'] > self.timeout: print "--- RACE TIMEOUT REACHED ---" timeout_reached = True break if s is not None: print "lap times:", lap_times # print "distance raced:", s['distRaced'] return driver.compute_fitness(last_sensor=s, lap_times=lap_times, max_speed=max_speed, average_speed=avg_speed.avg, timeout_reached=timeout_reached) else: return 0.0 except KeyboardInterrupt: print "Exit client" except Exception as e: print "Client Error:", e finally: #print "race call took %0.1f seconds." % (timeit.default_timer() - start_time) self.close()