示例#1
0
    def start_torcs_process(self):
        if self.torcs_proc is not None:
            os.killpg(os.getpgid(self.torcs_proc.pid), signal.SIGKILL)
            time.sleep(0.5)
            self.torcs_proc = None

        self.test_torcs_server_port()

        if self._config.traffic:
            self.traffic_manager = traffic.MadrasTrafficManager(
                self.torcs_server_port, 1, self._config.traffic)

        TorcsEnv.__init__(self,
                          vision=self._config.vision,
                          throttle=self._config.throttle,
                          gear_change=self._config.gear_change,
                          visualise=self._config.visualise,
                          no_of_visualisations=self._config.no_of_visualisations,
                          torcs_server_port=self.torcs_server_port)

        command = None
        rank = MPI.COMM_WORLD.Get_rank()
        self.torcs_server_config.generate_torcs_server_config()
        self.madras_agent_port = self.torcs_server_port + self.torcs_server_config.num_traffic_cars
        if rank < self._config.no_of_visualisations and self._config.visualise:
            command = 'export TORCS_PORT={} && vglrun torcs -t 10000000 -nolaptime'.format(self.torcs_server_port)
        else:
            command = 'export TORCS_PORT={} && torcs -t 10000000 -r ~/.torcs/config/raceman/quickrace.xml -nolaptime'.format(self.torcs_server_port)
        if self._config.vision is True:
            command += ' -vision'
        if self._config.noisy_observations:
            command += ' -noisy'

        self.torcs_proc = subprocess.Popen([command], shell=True, preexec_fn=os.setsid)
        time.sleep(1)
示例#2
0
    def __init__(self,
                 vision=False,
                 throttle=True,
                 gear_change=False,
                 port=60934,
                 pid_assist=False,
                 CLIENT_MAX_STEPS=np.inf,
                 visualise=True,
                 no_of_visualisations=1):
        # If `visualise` is set to False torcs simulator will run in headless mode
        """Init Method."""
        self.torcs_proc = None
        self.pid_assist = pid_assist
        if self.pid_assist:
            self.action_dim = 2  # LanePos, Velocity
        else:
            self.action_dim = 3  # Accel, Steer, Brake
        TorcsEnv.__init__(self,
                          vision=False,
                          throttle=True,
                          gear_change=False,
                          visualise=visualise,
                          no_of_visualisations=no_of_visualisations)
        self.state_dim = 29  # No. of sensors input
        self.env_name = 'Madras_Env'
        self.port = port
        self.visualise = visualise
        self.no_of_visualisations = no_of_visualisations
        self.CLIENT_MAX_STEPS = CLIENT_MAX_STEPS
        self.client_type = 0  # Snakeoil client type
        self.initial_reset = True
        self.early_stop = True
        if self.pid_assist:
            self.PID_latency = 10
        else:
            self.PID_latency = 1
        self.accel_PID = PID(np.array([10.5, 0.05, 2.8]))  # accel PID
        self.steer_PID = PID(np.array([5.1, 0.001, 0.000001]))  # steer PID

        self.prev_lane = 0
        self.prev_angle = 0
        self.prev_vel = 0
        self.prev_dist = 0
        self.ob = None
        self.track_len = 7014.6
        self.seed()
        self.start_torcs_process()
示例#3
0
 def __init__(self, port, cfg, name='MadrasTraffic'):
     self.cfg = cfg
     self.name = name
     self.steer = 0.0
     self.accel = 0.0
     self.brake = 0.0
     self.env = TorcsEnv(
         vision=(cfg["vision"] if "vision" in cfg else False),
         throttle=(cfg["throttle"] if "throttle" in cfg else True),
         gear_change=(cfg["gear_change"]
                      if "gear_change" in cfg else False),
         visualise=(self.cfg["visualise"]
                    if "visualise" in self.cfg else False),
         name=self.name)
     self.PID_controller = PIDController(cfg["pid_settings"])
     self.port = port
     self.min_safe_dist = 0.005 * (
         cfg["min_safe_dist"] if "min_safe_dist" in cfg else 1)  # 1 meter
示例#4
0
    def step_pid(self, desire):
        """Execute single step with lane_pos, velocity controls."""

        lane_pos_scale = self._config.track_limits[
            'high'] - self._config.track_limits['low']
        desire[
            0] = self._config.track_limits['low'] + lane_pos_scale * desire[0]
        if self._config.normalize_actions:
            # [-1, 1] should correspond to [-self._config.target_speed,
            #                                self._config.target_speed]
            speed_scale = self._config.target_speed
            desire[1] *= speed_scale  # Now in m/s
            # convert to km/hr
            desire[1] *= 3600 / 1000  # Now in km/hr
        # Normalize to gym_torcs specs
        desire[1] /= self.default_speed

        reward = 0.0

        for PID_step in range(self._config.pid_settings['pid_latency']):
            a_t = self.PID_controller.get_action(desire)
            try:
                self.ob, r, done, info = TorcsEnv.step(self, PID_step,
                                                       self.client, a_t,
                                                       self._config.early_stop)
            except Exception as e:
                logging.debug("Exception {} caught at port {}".format(
                    str(e), self.torcs_server_port))

                self.wait_for_observation()
            game_state = {
                "torcs_reward": r,
                "torcs_done": done,
                "distance_traversed": self.client.S.d["distRaced"],
                "angle": self.client.S.d["angle"],
                "damage": self.client.S.d["damage"],
                "trackPos": self.client.S.d["trackPos"],
                "racePos": self.client.S.d["racePos"],
                "track": self.client.S.d["track"]
            }
            reward += self.reward_handler.get_reward(self._config, game_state)
            if self._config.pid_assist:
                self.PID_controller.update(self.ob)
            done = self.done_handler.get_done_signal(self._config, game_state)
            if done:
                self.client.R.d["meta"] = True  # Terminate the episode
                logging.info('Terminating PID {}'.format(
                    self.client.serverPID))
                break

        next_obs = self.observation_handler.get_obs(self.ob, self._config)
        info["distRaced"] = self.client.S.d["distRaced"]
        info["racePos"] = self.client.S.d["racePos"]

        return next_obs, reward, done, info
示例#5
0
    def reset(self, prev_step_info=None):
        """Reset Method. To be called at the end of each episode"""
        if self.initial_reset:
            while self.ob is None:
                try:
                    self.client = snakeoil3.Client(p=self.port,
                                                   vision=self.vision,
                                                   visualise=self.visualise)
                    # Open new UDP in vtorcs
                    self.client.MAX_STEPS = self.CLIENT_MAX_STEPS
                    self.client.get_servers_input(step=0)
                    # Get the initial input from torcs
                    raw_ob = self.client.S.d
                    # Get the current full-observation
                    self.ob = self.make_observation(raw_ob)
                except:
                    pass
            self.initial_reset = False

        else:
            try:
                self.ob, self.client = TorcsEnv.reset(self,
                                                      client=self.client,
                                                      relaunch=True)
            except Exception as e:
                self.ob = None
                while self.ob is None:
                    try:
                        print("Hard Reset")
                        # self.end(self.client)
                        self.client = snakeoil3.Client(p=self.port,
                                                       vision=self.vision)
                        # Open new UDP in vtorcs
                        self.client.MAX_STEPS = self.CLIENT_MAX_STEPS
                        self.client.get_servers_input(step=0)
                        # Get the initial input from torcs
                        raw_ob = self.client.S.d
                        # Get the current full-observation from torcs
                        self.ob = self.make_observation(raw_ob)
                    except:
                        pass

        self.distance_traversed = 0
        s_t = np.hstack((self.ob.angle, self.ob.track, self.ob.trackPos,
                         self.ob.speedX, self.ob.speedY, self.ob.speedZ,
                         self.ob.wheelSpinVel / 100.0, self.ob.rpm))

        self.prev_angle = 0.0
        self.prev_dist = 0.0
        self.prev_lane = 0.0
        self.accel_PID.reset_pid()
        self.steer_PID.reset_pid()
        return s_t
示例#6
0
    def step_vanilla(self, action):
        """Execute single step with steer, acceleration, brake controls."""
        if self._config.normalize_actions:
            # action[1] = (action[1] + 1) / 2.0  # acceleration back to [0, 1]
            # action[2] = (action[2] + 1) / 2.0  # brake back to [0, 1]
            action[0] = self.clip(action[0], -1, 1)
            action[1] = self.clip(action[1], 0, 1)
            action[2] = self.clip(action[2], 0, 1)

        # print(action)
        r = 0.0
        try:
            self.ob, r, done, info = TorcsEnv.step(self, 0, self.client,
                                                   action,
                                                   self._config.early_stop)

        except Exception as e:

            logging.debug("Exception {} caught at port {}".format(
                str(e), self.torcs_server_port))

            self.wait_for_observation()

        if done:
            print('torce_done is True')

        game_state = {
            "torcs_reward": r,
            "torcs_done": done,
            "distance_traversed": self.client.S.d['distRaced'],
            "angle": self.client.S.d["angle"],
            "damage": self.client.S.d["damage"],
            "trackPos": self.client.S.d["trackPos"],
            "racePos": self.client.S.d["racePos"],
            "track": self.client.S.d["track"]
        }
        reward = self.reward_handler.get_reward(self._config, game_state,
                                                action)
        done = self.done_handler.get_done_signal(self._config, game_state)
        if done:
            if self._config.traffic:
                self.traffic_manager.kill_all_traffic_agents()
            self.client.R.d["meta"] = True  # Terminate the episode
            logging.info('Terminating PID {}'.format(self.client.serverPID))
            # print(self.ob)

        next_obs = self.observation_handler.get_obs(self.ob, self._config)

        info["distRaced"] = self.client.S.d["distRaced"]
        info["racePos"] = self.client.S.d["racePos"]
        return next_obs, reward, done, info
示例#7
0
    def reset(self):
        """Reset Method to be called at the end of each episode."""
        self.step_num = 0
        if not self.initial_reset:
            self.torcs_server_config.generate_torcs_server_config()
            self.madras_agent_port = self.torcs_server_port + self.torcs_server_config.num_traffic_cars
            self.client.port = self.madras_agent_port  # This is very bad code! But we wont need it any way in v2
            logging.info("Num traffic cars in server {}".format(
                self.torcs_server_config.num_traffic_cars))

        if self._config.traffic:
            self.traffic_manager.reset(
                self.torcs_server_config.num_traffic_cars)

        self._config.track_len = self.torcs_server_config.track_length

        if self.initial_reset:
            self.wait_for_observation()
            self.initial_reset = False

        else:
            while True:
                try:
                    self.ob, self.client = TorcsEnv.reset(self,
                                                          client=self.client,
                                                          relaunch=True)
                except Exception:
                    self.wait_for_observation()

                if not np.any(np.asarray(self.ob.track) < 0):
                    break
                else:
                    logging.info(
                        "Reset: Reset failed as agent started off track. Retrying..."
                    )

        self.distance_traversed = 0
        s_t = self.observation_handler.get_obs(self.ob, self._config)
        if self._config.pid_assist:
            self.PID_controller.reset()
        self.reward_handler.reset()
        self.done_handler.reset()
        logging.info("Reset: Starting new episode")
        if np.any(np.asarray(self.ob.track) < 0):
            logging.info("Reset produced bad track values.")
        return s_t
示例#8
0
def playTraffic(port=3101, target_vel=50.0, angle=0.0, sleep=0):
    """Traffic Play function."""
    env = TorcsEnv(vision=False, throttle=True, gear_change=False)
    ob = None
    while ob is None:
        try:
            client = snakeoil3.Client(p=port, vision=False)
            client.MAX_STEPS = np.inf
            client.get_servers_input(step=0)
            obs = client.S.d
            ob = env.make_observation(obs)
        except:
            pass
    episode_count = cfg['traffic']['max_eps']
    max_steps = cfg['traffic']['max_steps_eps']
    early_stop = 0
    velocity_i = target_vel / 300.0
    accel_pid = PID(np.array([10.5, 0.05, 2.8]))
    steer_pid = PID(np.array([5.1, 0.001, 0.000001]))
    steer = 0.0
    accel = 0.0
    brake = 0
    A = cfg['traffic']['amplitude'] / 300.0
    T = cfg['traffic']['time_period']
    # print(velocity_i)
    for i in range(episode_count):
        info = {'termination_cause': 0}
        steer = 0.0
        accel = 0.0
        brake = 0
        S = 0.0
        for step in range(max_steps):
            a_t = np.asarray([steer, accel, brake])  # [steer, accel, brake]
            try:
                ob, r_t, done, info = env.step(step, client, a_t, early_stop)
                if done:
                    pass
            except Exception as e:
                print("Exception caught at point A at port " + str(i) + str(e))
                ob = None
                while ob is None:
                    try:
                        client = snakeoil3.Client(p=port, vision=False)
                        client.MAX_STEPS = np.inf
                        client.get_servers_input(step=0)
                        obs = client.S.d
                        ob = env.make_observation(obs)
                    except:
                        pass
                    continue
            if (step <= sleep):
                print("WAIT" + str(port))
                continue
            velocity = velocity_i + A * math.sin(step / T)
            opp = ob.opponents
            front = np.array([opp[15], opp[16], opp[17], opp[18], opp[19]])
            closest_front = np.min(front)
            if (step % T == 0):
                print("VEL_CHANGE: ", velocity * 300.0)
            vel_error = velocity - ob.speedX
            angle_error = -(ob.trackPos - angle) / 10 + ob.angle
            steer_pid.update_error(angle_error)
            accel_pid.update_error(vel_error)
            accel = accel_pid.output()
            steer = steer_pid.output()
            if accel < 0:
                brake = 1
            else:
                brake = 0
            if closest_front < ((float(0.5 * ob.speedX * 100) + 10.0) / 200.0):
                brake = 1
            else:
                brake = 0

        try:
            if 'termination_cause' in info.keys() and info['termination_cause'] == 'hardReset':
                print('Hard reset by some agent')
                ob, client = env.reset(client=client, relaunch=True)

        except Exception as e:
            print("Exception caught at point B at port " + str(i) + str(e) )
            ob = None
            while ob is None:
                try:
                    client = snakeoil3.Client(p=port, vision=False)  # Open new UDP in vtorcs
                    client.MAX_STEPS = np.inf
                    client.get_servers_input(0)  # Get the initial input from torcs
                    obs = client.S.d  # Get the current full-observation from torcs
                    ob = env.make_observation(obs)
                except:
                    print("Exception caught at at point C at port " + str(i) + str(e))
示例#9
0
    def step(self, desire):
        """Step method to be called at each time step."""
        r_t = 0

        for PID_step in range(self.PID_latency):
            # Implement the desired trackpos and velocity using PID
            if self.pid_assist:
                self.accel_PID.update_error((desire[1] - self.prev_vel))
                self.steer_PID.update_error(
                    (-(self.prev_lane - desire[0]) / 10 + self.prev_angle))
                if self.accel_PID.output() < 0.0:
                    brake = 1
                else:
                    brake = 0
                a_t = np.asarray(
                    [self.steer_PID.output(),
                     self.accel_PID.output(), brake])
            else:
                a_t = desire
            try:
                self.ob, r, done, info = TorcsEnv.step(self, PID_step,
                                                       self.client, a_t,
                                                       self.early_stop)
            except Exception as e:
                print(("Exception caught at port " + str(e)))
                self.ob = None
                while self.ob is None:
                    try:
                        self.client = snakeoil3.Client(p=self.port,
                                                       vision=self.vision)
                        # Open new UDP in vtorcs
                        self.client.MAX_STEPS = self.CLIENT_MAX_STEPS
                        self.client.get_servers_input(0)
                        # Get the initial input from torcs
                        raw_ob = self.client.S.d
                        # Get the current full-observation from torcs
                        self.ob = self.make_observation(raw_ob)
                    except:
                        pass
                    continue
            self.prev_vel = self.ob.speedX
            self.prev_angle = self.ob.angle
            self.prev_lane = self.ob.trackPos
            if (math.isnan(r)):
                r = 0.0
            r_t += r  # accumulate rewards over all the time steps

            self.distance_traversed = self.client.S.d['distRaced']
            r_t += (self.distance_traversed - self.prev_dist) /\
                self.track_len
            self.prev_dist = deepcopy(self.distance_traversed)
            if self.distance_traversed >= self.track_len:
                done = True
            if done:
                # self.reset()
                break

        s_t1 = np.hstack((self.ob.angle, self.ob.track, self.ob.trackPos,
                          self.ob.speedX, self.ob.speedY, self.ob.speedZ,
                          self.ob.wheelSpinVel / 100.0, self.ob.rpm))

        return s_t1, r_t, done, info
示例#10
0
class MadrasTrafficAgent(object):
    def __init__(self, port, cfg, name='MadrasTraffic'):
        self.cfg = cfg
        self.name = name
        self.steer = 0.0
        self.accel = 0.0
        self.brake = 0.0
        self.env = TorcsEnv(
            vision=(cfg["vision"] if "vision" in cfg else False),
            throttle=(cfg["throttle"] if "throttle" in cfg else True),
            gear_change=(cfg["gear_change"]
                         if "gear_change" in cfg else False),
            visualise=(self.cfg["visualise"]
                       if "visualise" in self.cfg else False),
            name=self.name)
        self.PID_controller = PIDController(cfg["pid_settings"])
        self.port = port
        self.min_safe_dist = 0.005 * (
            cfg["min_safe_dist"] if "min_safe_dist" in cfg else 1)  # 1 meter

    def wait_for_observation(self):
        """Refresh client and wait for a valid observation to come in."""
        self.ob = None
        while self.ob is None:
            logging.debug("{} Still waiting for observation at {}".format(
                self.name, self.port))

            try:
                self.client = snakeoil3.Client(
                    p=self.port,
                    vision=(self.cfg["vision"]
                            if "vision" in self.cfg else False),
                    visualise=(self.cfg["visualise"]
                               if "visualise" in self.cfg else False),
                    name=self.name)
                # Open new UDP in vtorcs
                self.client.MAX_STEPS = self.cfg[
                    "client_max_steps"] if "client_max_steps" in self.cfg else np.inf
                self.client.get_servers_input(0)
                # Get the initial input from torcs
                raw_ob = self.client.S.d
                # Get the current full-observation from torcs
                self.ob = self.env.make_observation(raw_ob)
            except:
                pass

    def get_action(self):
        raise NotImplementedError(
            "Successor classes must implement this method")

    def flag_off(self, random_seed=0):
        del random_seed
        self.wait_for_observation()
        logging.debug("[{}]: My server is PID: {}".format(
            self.name, self.client.serverPID))

        self.is_alive = True
        while True:
            if self.is_alive:
                action = self.get_action()
                try:
                    self.ob, _, done, info = self.env.step(
                        0, self.client, action)

                except Exception as e:
                    logging.debug(
                        "Exception {} caught by {} traffic agent at port {}".
                        format(str(e), self.name, self.port))
                    self.wait_for_observation()
                self.detect_and_prevent_imminent_crash_out_of_track()
                self.PID_controller.update(self.ob)
                if done:
                    self.is_alive = False
                    logging.debug("{} died.".format(self.name))

    def get_front_opponents(self):
        return np.array([
            self.ob.opponents[16],
            self.ob.opponents[17],
            self.ob.opponents[18],
        ])

    def detect_and_prevent_imminent_crash_out_of_track(self):
        while True:
            min_dist_from_track = np.min(self.ob.track)
            if min_dist_from_track <= self.min_safe_dist:
                closest_dist_sensor_id = np.argmin(self.ob.track)
                if closest_dist_sensor_id < 9:
                    action = [1, 0, 1]
                elif closest_dist_sensor_id > 9:
                    action = [-1, 0, 1]
                else:
                    action = [0, 0, 1]
                self.ob, _, _, _ = self.env.step(0, self.client, action)
            else:
                break

    def get_collision_cone_radius(self):
        speed = self.ob.speedX * self.env.default_speed * (1000.0 / 3600.0
                                                           )  # speed in m/sec
        collision_time_window = self.cfg[
            "collision_time_window"] if "collision_time_window" in self.cfg else 1
        collision_cone_radius = collision_time_window * speed
        return collision_cone_radius / 200.0  # Normalizing

    def avoid_impending_collision(self):
        # If the opponent in front is too close, brake
        opponents_in_front = self.get_front_opponents()
        closest_front = np.min(opponents_in_front)
        frontal_distance_threshold = self.get_collision_cone_radius()
        if closest_front < frontal_distance_threshold:
            self.brake = 1
        else:
            self.brake = 0