示例#1
0
def test_graceful_interrupt(monkeypatch):
    """SMARTS should only throw a KeyboardInterript exception."""

    agent_spec = AgentSpec(
        interface=AgentInterface.from_type(AgentType.Laner),
        agent_builder=lambda: Agent.from_function(lambda _: "keep_lane"),
    )
    agent = agent_spec.build_agent()
    env = build_env(agent_spec)

    with pytest.raises(KeyboardInterrupt):
        obs = env.reset()

        # To simulate a user interrupting the sim (e.g. ctrl-c). We just need to
        # hook in to some function that SMARTS calls internally (like this one).
        with mock.patch(
            "smarts.core.sensors.Sensors.observe", side_effect=KeyboardInterrupt
        ):
            for episode in range(10):
                obs, _, _, _ = env.step({AGENT_ID: agent.act(obs)})

        assert episode == 0, "SMARTS should have been interrupted, ending early"

    with pytest.raises(SMARTSNotSetupError):
        env.step({AGENT_ID: agent.act(obs)})
def main(scenarios, sim_name, headless, num_episodes, seed):
    agent_spec = AgentSpec(
        interface=AgentInterface.from_type(AgentType.Tracker, max_episode_steps=None),
        agent_builder=TrackingAgent,
    )

    env = gym.make(
        "smarts.env:hiway-v0",
        scenarios=scenarios,
        agent_specs={AGENT_ID: agent_spec},
        sim_name=sim_name,
        headless=headless,
        visdom=False,
        fixed_timestep_sec=0.1,
        sumo_headless=True,
        seed=seed,
        # envision_record_data_replay_path="./data_replay",
    )

    for episode in episodes(n=num_episodes):
        agent = agent_spec.build_agent()
        observations = env.reset()
        episode.record_scenario(env.scenario_log)

        dones = {"__all__": False}
        while not dones["__all__"]:
            agent_obs = observations[AGENT_ID]
            agent_action = agent.act(agent_obs)
            observations, rewards, dones, infos = env.step({AGENT_ID: agent_action})
            episode.record_step(observations, rewards, dones, infos)

    env.close()
示例#3
0
def main(scenarios, headless, num_episodes, max_episode_steps=None):
    agent_spec = AgentSpec(
        interface=AgentInterface.from_type(
            AgentType.LanerWithSpeed, max_episode_steps=max_episode_steps
        ),
        agent_builder=ChaseViaPointsAgent,
    )

    env = gym.make(
        "smarts.env:hiway-v0",
        scenarios=scenarios,
        agent_specs={"SingleAgent": agent_spec},
        headless=headless,
        sumo_headless=True,
    )

    # Convert `env.step()` and `env.reset()` from multi-agent interface to
    # single-agent interface.
    env = SingleAgent(env=env)

    for episode in episodes(n=num_episodes):
        agent = agent_spec.build_agent()
        observation = env.reset()
        episode.record_scenario(env.scenario_log)

        done = False
        while not done:
            agent_action = agent.act(observation)
            observation, reward, done, info = env.step(agent_action)
            episode.record_step(observation, reward, done, info)

    env.close()
示例#4
0
def test_building_agent_with_tuple_params():
    agent_spec = AgentSpec(
        agent_params=(32, 41),
        agent_builder=lambda x, y: Agent.from_function(lambda _: (x, y)),
    )

    agent = agent_spec.build_agent()
    assert agent.act("dummy observation") == (32, 41)
示例#5
0
def train(training_scenarios, evaluation_scenarios, sim_name, headless,
          num_episodes, seed):
    agent_params = {"input_dims": 4, "hidden_dims": 7, "output_dims": 3}
    agent_spec = AgentSpec(
        interface=AgentInterface.from_type(AgentType.Standard,
                                           max_episode_steps=5000),
        agent_params=agent_params,
        agent_builder=PyTorchAgent,
        observation_adapter=observation_adapter,
    )

    env = gym.make(
        "smarts.env:hiway-v0",
        scenarios=training_scenarios,
        agent_specs={AGENT_ID: agent_spec},
        sim_name=sim_name,
        headless=headless,
        fixed_timestep_sec=0.1,
        seed=seed,
    )

    steps = 0
    for episode in episodes(n=num_episodes):
        agent = agent_spec.build_agent()
        observations = env.reset()
        episode.record_scenario(env.scenario_log)

        dones = {"__all__": False}
        while not dones["__all__"]:
            agent_obs = observations[AGENT_ID]
            agent_action = agent.act(agent_obs)
            observations, rewards, dones, infos = env.step(
                {AGENT_ID: agent_action})
            episode.record_step(observations, rewards, dones, infos)
            steps += 1

            if steps % 500 == 0:
                print("Evaluating agent")

                # We construct an evaluation agent based on the saved
                # state of the agent in training.
                model_path = tempfile.mktemp()
                agent.save(model_path)

                eval_agent_spec = agent_spec.replace(
                    agent_params=dict(agent_params, model_path=model_path))

                # Remove the call to ray.wait if you want evaluation to run
                # in parallel with training
                ray.wait([
                    evaluate.remote(eval_agent_spec, evaluation_scenarios,
                                    headless, seed)
                ])

    env.close()
示例#6
0
def test_building_agent_with_dict_params():
    agent_spec = AgentSpec(
        agent_params={
            "y": 2,
            "x": 1
        },
        agent_builder=lambda x, y: Agent.from_function(lambda _: x / y),
    )

    agent = agent_spec.build_agent()
    assert agent.act("dummy observation") == 1 / 2
示例#7
0
def test_graceful_shutdown():
    """SMARTS should not throw any exceptions when shutdown."""
    agent_spec = AgentSpec(
        interface=AgentInterface.from_type(AgentType.Laner),
        agent_builder=lambda: Agent.from_function(lambda _: "keep_lane"),
    )
    env = build_env(agent_spec)
    agent = agent_spec.build_agent()
    obs = env.reset()
    for _ in range(10):
        obs = env.step({AGENT_ID: agent.act(obs)})

    env.close()
        def on_trigger(ctx: Dict[str, Any]):
            # Define agent specs to be assigned
            agent_spec = AgentSpec(
                interface=AgentInterface(waypoints=True, action=ActionSpaceType.Lane),
                agent_builder=BasicAgent,
            )

            # Select a random sample from candidates
            k = ctx.get("vehicles_to_replace_randomly", 0)
            if k <= 0:
                logger.warning(
                    "default (0) or negative value specified for replacement. Replacing all valid vehicle candidates."
                )
                sample = ctx["vehicle_candidates"]
            else:
                logger.info(
                    f"Choosing {k} vehicles randomly from {len(ctx['vehicle_candidates'])} valid vehicle candidates."
                )
                sample = random.sample(ctx["vehicle_candidates"], k)
            assert len(sample) != 0

            for veh_id in sample:
                # Map selected vehicles to agent ids & specs
                agent_id = f"agent-{veh_id}"
                ctx["agents"][agent_id] = agent_spec.build_agent()

                # Create missions based on current state and traffic history
                positional, traverse = scenario.create_dynamic_traffic_history_mission(
                    veh_id, ctx["elapsed_sim_time"], ctx["positional_radius"]
                )

                # Take control of vehicles immediately
                try:
                    # Try to assign a PositionalGoal at the last recorded timestep
                    smarts.add_agent_and_switch_control(
                        veh_id, agent_id, agent_spec.interface, positional
                    )
                except PlanningError:
                    logger.warning(
                        f"Unable to create PositionalGoal for vehicle {veh_id}, falling back to TraverseGoal"
                    )
                    smarts.add_agent_and_switch_control(
                        veh_id, agent_id, agent_spec.interface, traverse
                    )
示例#9
0
def prepare_test_agent_and_environment(
    required_interface: Dict[str, Any],
    action_adapter: Callable = lambda action: action,
    info_adapter: Callable = lambda observation, reward, info: info,
    observation_adapter: Callable = lambda observation: observation,
    reward_adapter: Callable = lambda _, reward: reward,
    headless: bool = True,
) -> Tuple[Agent, UltraEnv]:
    if "waypoints" not in required_interface:
        required_interface["waypoints"] = Waypoints(lookahead=20)
    if "neighborhood_vehicles" not in required_interface:
        required_interface["neighborhood_vehicles"] = NeighborhoodVehicles(
            radius=200)
    if "action" not in required_interface:
        required_interface["action"] = ActionSpaceType.Lane

    agent_spec = AgentSpec(
        interface=AgentInterface(**required_interface),
        agent_builder=RandomAgent,
        agent_params={"action_type": required_interface["action"]},
        action_adapter=action_adapter,
        info_adapter=info_adapter,
        observation_adapter=observation_adapter,
        reward_adapter=reward_adapter,
    )
    agent = agent_spec.build_agent()

    environment = gym.make(
        "ultra.env:ultra-v0",
        agent_specs={AGENT_ID: agent_spec},
        scenario_info=("00", "easy"),
        headless=headless,
        timestep_sec=TIMESTEP_SEC,
        seed=SEED,
    )

    return agent, environment
示例#10
0
def main(
    script: str,
    scenarios: Sequence[str],
    headless: bool,
    seed: int,
    vehicles_to_replace: int,
    episodes: int,
):
    assert vehicles_to_replace > 0
    assert episodes > 0
    logger = logging.getLogger(script)
    logger.setLevel(logging.INFO)

    logger.debug("initializing SMARTS")

    smarts = SMARTS(
        agent_interfaces={},
        traffic_sim=None,
        envision=None if headless else Envision(),
    )
    random_seed(seed)
    traffic_history_provider = smarts.get_provider_by_type(
        TrafficHistoryProvider)
    assert traffic_history_provider

    scenario_list = Scenario.get_scenario_list(scenarios)
    scenarios_iterator = Scenario.variations_for_all_scenario_roots(
        scenario_list, [])
    for scenario in scenarios_iterator:
        logger.debug("working on scenario {}".format(scenario.name))

        veh_missions = scenario.discover_missions_of_traffic_histories()
        if not veh_missions:
            logger.warning("no vehicle missions found for scenario {}.".format(
                scenario.name))
            continue
        veh_start_times = {
            v_id: mission.start_time
            for v_id, mission in veh_missions.items()
        }

        k = vehicles_to_replace
        if k > len(veh_missions):
            logger.warning(
                "vehicles_to_replace={} is greater than the number of vehicle missions ({})."
                .format(vehicles_to_replace, len(veh_missions)))
            k = len(veh_missions)

        # XXX replace with AgentSpec appropriate for IL model
        agent_spec = AgentSpec(
            interface=AgentInterface.from_type(AgentType.Imitation),
            agent_builder=ReplayCheckerAgent,
            agent_params=smarts.fixed_timestep_sec,
        )

        for episode in range(episodes):
            logger.info(f"starting episode {episode}...")
            agentid_to_vehid = {}
            agent_interfaces = {}

            # Build the Agents for the to-be-hijacked vehicles
            # and gather their missions
            agents = {}
            dones = {}
            ego_missions = {}
            sample = {}

            if scenario.traffic_history.dataset_source == "Waymo":
                # For Waymo, we only hijack the vehicle that was autonomous in the dataset
                waymo_ego_id = scenario.traffic_history.ego_vehicle_id
                if waymo_ego_id is not None:
                    assert (
                        k == 1
                    ), f"do not specify -k > 1 when just hijacking Waymo ego vehicle (it was {k})"
                    veh_id = str(waymo_ego_id)
                    sample = {veh_id}
                else:
                    logger.warning(
                        f"Waymo ego vehicle id not mentioned in the dataset. Hijacking a random vehicle."
                    )

            if not sample:
                # For other datasets, hijack a sample of the recorded vehicles
                # Pick k vehicle missions to hijack with agent
                # and figure out which one starts the earliest
                sample = scenario.traffic_history.random_overlapping_sample(
                    veh_start_times, k)

            if len(sample) < k:
                logger.warning(
                    f"Unable to choose {k} overlapping missions.  allowing non-overlapping."
                )
                leftover = set(veh_start_times.keys()) - sample
                sample.update(set(random.sample(leftover, k - len(sample))))

            agent_spec.interface.max_episode_steps = max([
                scenario.traffic_history.vehicle_final_exit_time(veh_id) / 0.1
                for veh_id in sample
            ])
            history_start_time = None
            logger.info(f"chose vehicles: {sample}")
            for veh_id in sample:
                agent_id = f"ego-agent-IL-{veh_id}"
                agentid_to_vehid[agent_id] = veh_id
                agent_interfaces[agent_id] = agent_spec.interface
                if (not history_start_time
                        or veh_start_times[veh_id] < history_start_time):
                    history_start_time = veh_start_times[veh_id]

            for agent_id in agent_interfaces.keys():
                agent = agent_spec.build_agent()
                veh_id = agentid_to_vehid[agent_id]
                agent.load_data_for_vehicle(veh_id, scenario,
                                            history_start_time)
                agents[agent_id] = agent
                dones[agent_id] = False
                mission = veh_missions[veh_id]
                ego_missions[agent_id] = replace(
                    mission,
                    start_time=mission.start_time - history_start_time)

            # Tell the traffic history provider to start traffic
            # at the point when the earliest agent enters...
            traffic_history_provider.start_time = history_start_time
            # and all the other agents to offset their missions by this much too
            scenario.set_ego_missions(ego_missions)
            logger.info(f"offsetting sim_time by: {history_start_time}")

            # Take control of vehicles with corresponding agent_ids
            smarts.switch_ego_agents(agent_interfaces)

            # Finally start the simulation loop...
            logger.info(f"starting simulation loop...")
            observations = smarts.reset(scenario)
            while not all(done for done in dones.values()):
                actions = {
                    agent_id: agents[agent_id].act(agent_obs)
                    for agent_id, agent_obs in observations.items()
                }
                logger.debug("stepping @ sim_time={} for agents={}...".format(
                    smarts.elapsed_sim_time, list(observations.keys())))
                observations, rewards, dones, infos = smarts.step(actions)

                for agent_id in agents.keys():
                    if dones.get(agent_id, False):
                        if not observations[agent_id].events.reached_goal:
                            logger.warning(
                                "agent_id={} exited @ sim_time={}".format(
                                    agent_id, smarts.elapsed_sim_time))
                            logger.warning("   ... with {}".format(
                                observations[agent_id].events))
                        else:
                            logger.info(
                                "agent_id={} reached goal @ sim_time={}".
                                format(agent_id, smarts.elapsed_sim_time))
                            logger.debug("   ... with {}".format(
                                observations[agent_id].events))
                        del observations[agent_id]

    smarts.destroy()
示例#11
0
import gym
from smarts.core.agent import Agent
from smarts.core.agent_interface import AgentInterface, AgentType
from smarts.zoo.agent_spec import AgentSpec

agent_id = "Agent-007"
agent_spec = AgentSpec(
    interface=AgentInterface.from_type(AgentType.Laner),
    agent_params={"agent_function": lambda _: "keep_lane"},
    agent_builder=Agent.from_function,
)

env = gym.make(
    "smarts.env:hiway-v0",
    scenarios=["scenarios/loop"],
    agent_specs={agent_id: agent_spec},
)

agent = agent_spec.build_agent()
observations = env.reset()
dones = {"__all__": False}
while not dones["__all__"]:
    action = agent.act(observations[agent_id])
    observations, _, dones, _ = env.step({agent_id: action})

env.close()
示例#12
0
    def test_observations_stacking(self):
        EPISODES = 3
        WIDTH = 64
        HEIGHT = WIDTH
        RESOLUTION = 50 / WIDTH
        ENVIRONMENT_STACK_SIZE = 4

        agent_spec = AgentSpec(
            interface=AgentInterface(
                waypoints=Waypoints(lookahead=1),
                neighborhood_vehicles=NeighborhoodVehicles(radius=10.0),
                rgb=RGB(width=WIDTH, height=HEIGHT, resolution=RESOLUTION),
                action=ActionSpaceType.Lane,
            ),
            agent_builder=TestLaneAgent,
        )
        agent = agent_spec.build_agent()

        environment = gym.make(
            "ultra.env:ultra-v0",
            agent_specs={AGENT_ID: agent_spec},
            scenario_info=("00", "easy"),
            headless=True,
            timestep_sec=0.1,
            seed=2,
        )

        def check_environment_observations_stack(environment):
            self.assertIsInstance(environment.smarts_observations_stack, deque)
            self.assertEqual(len(environment.smarts_observations_stack),
                             ENVIRONMENT_STACK_SIZE)
            self.assertIsInstance(environment.smarts_observations_stack[0],
                                  dict)
            self.assertTrue(
                all(
                    str(environment.smarts_observations_stack[0]) == str(
                        observations)
                    for observations in environment.smarts_observations_stack))

        def check_stacked_observations(environment, observations):
            self.assertIn(AGENT_ID, observations)
            self.assertTrue(AGENT_ID, observations[AGENT_ID].top_down_rgb)
            self.assertIsInstance(observations[AGENT_ID].top_down_rgb,
                                  TopDownRGB)
            self.assertEqual(
                observations[AGENT_ID].top_down_rgb.metadata,
                environment.smarts_observations_stack[-1]
                [AGENT_ID].top_down_rgb.metadata,
            )
            self.assertEqual(
                observations[AGENT_ID].top_down_rgb.data.shape,
                (ENVIRONMENT_STACK_SIZE, HEIGHT, WIDTH, 3),
            )
            # Ensure the stacked observation's TopDownRGB data is in the same order, and
            # and contains the same NumPy arrays as the environment's observation stack.
            self.assertTrue(
                all(
                    np.array_equal(
                        observations_from_stack[AGENT_ID].top_down_rgb.data,
                        observations[AGENT_ID].top_down_rgb.data[i],
                    ) for i, observations_from_stack in enumerate(
                        environment.smarts_observations_stack)))

        for _ in range(EPISODES):
            dones = {"__all__": False}
            observations = environment.reset()

            check_environment_observations_stack(environment)
            check_stacked_observations(environment, observations)

            while not dones["__all__"]:
                action = agent.act(observations[AGENT_ID])
                observations, _, dones, _ = environment.step(
                    {AGENT_ID: action})
                check_stacked_observations(environment, observations)

        environment.close()