예제 #1
0
파일: studio.py 프로젝트: qyshen815/SMARTS
def _build_single_scenario(clean, allow_offset_map, scenario):
    import importlib.resources as pkg_resources

    from smarts.sstudio.sumo2mesh import generate_glb_from_sumo_network

    click.echo(f"build-scenario {scenario}")
    if clean:
        _clean(scenario)

    scenario_root = Path(scenario)
    map_net = str(scenario_root / "map.net.xml")
    if not allow_offset_map:
        SumoRoadNetwork.from_file(map_net, shift_to_origin=True)
    elif os.path.isfile(SumoRoadNetwork.shifted_net_file_path(map_net)):
        click.echo(
            "WARNING: {} already exists.  Remove it if you want to use unshifted/offset map.net.xml instead."
            .format(SumoRoadNetwork.shifted_net_file_name))
    map_glb = scenario_root / "map.glb"
    generate_glb_from_sumo_network(map_net, str(map_glb))

    requirements_txt = scenario_root / "requirements.txt"
    if requirements_txt.exists():
        import zoo.policies

        with pkg_resources.path(zoo.policies, "") as path:
            # Serve policies through the static file server, then kill after
            # we've installed scenario requirements
            pip_index_proc = subprocess.Popen(
                ["twistd", "-n", "web", "--path", path],
                # Hide output to keep display simple
                stdout=subprocess.DEVNULL,
                stderr=subprocess.STDOUT,
            )

            pip_install_cmd = [
                sys.executable,
                "-m",
                "pip",
                "install",
                "-r",
                str(requirements_txt),
            ]

            click.echo(
                f"Installing scenario dependencies via '{' '.join(pip_install_cmd)}'"
            )

            try:
                subprocess.check_call(pip_install_cmd,
                                      stdout=subprocess.DEVNULL)
            finally:
                pip_index_proc.terminate()
                pip_index_proc.wait()

    scenario_py = scenario_root / "scenario.py"
    if scenario_py.exists():
        subprocess.check_call([sys.executable, scenario_py])
예제 #2
0
    def __init__(
        self,
        scenario_root: str,
        route: str = None,
        missions: Dict[str, Mission] = None,
        social_agents: Dict[str, SocialAgent] = None,
        log_dir: str = None,
        surface_patches: list = None,
        traffic_history: str = None,
    ):

        self._logger = logging.getLogger(self.__class__.__name__)
        self._root = scenario_root
        self._route = route
        self._missions = missions or {}
        self._bubbles = Scenario._discover_bubbles(scenario_root)
        self._social_agents = social_agents or {}
        self._surface_patches = surface_patches
        self._log_dir = self._resolve_log_dir(log_dir)
        self._validate_assets_exist()

        if traffic_history:
            self._traffic_history = TrafficHistory(traffic_history)
            default_lane_width = self.traffic_history.lane_width
        else:
            self._traffic_history = None
            default_lane_width = None

        net_file = os.path.join(self._root, "map.net.xml")
        self._road_network = SumoRoadNetwork.from_file(
            net_file, default_lane_width=default_lane_width, lanepoint_spacing=1.0
        )
        self._net_file_hash = file_md5_hash(self._road_network.net_file)
        self._scenario_hash = path2hash(str(Path(self.root_filepath).resolve()))
예제 #3
0
파일: scenario.py 프로젝트: zbzhu99/SMARTS
    def __init__(
        self,
        scenario_root: str,
        route: str = None,
        missions: Dict[str, Mission] = None,
        social_agents: Dict[str, SocialAgent] = None,
        log_dir: str = None,
        surface_patches: list = None,
        traffic_history: str = None,
    ):

        self._logger = logging.getLogger(self.__class__.__name__)
        self._root = scenario_root
        self._route = route
        self._missions = missions or {}
        self._bubbles = Scenario._discover_bubbles(scenario_root)
        self._social_agents = social_agents or {}
        self._surface_patches = surface_patches
        self._log_dir = self._resolve_log_dir(log_dir)

        self._validate_assets_exist()
        self._road_network = SumoRoadNetwork.from_file(self.net_filepath)
        self._net_file_hash = file_md5_hash(self.net_filepath)
        self._waypoints = Waypoints(self._road_network, spacing=1.0)
        self._scenario_hash = path2hash(str(
            Path(self.root_filepath).resolve()))
        self._traffic_history_service = Traffic_history_service(
            traffic_history)
예제 #4
0
    def from_file(cls, net_file: str):
        """Constructs a route generator from the given file

        Args:
            net_file: The path to a '\\*.net.xml' file (generally 'map.net.xml')
        """
        # XXX: Spacing is crudely "large enough" so we less likely overlap vehicles
        road_network = SumoRoadNetwork.from_file(net_file, lanepoint_spacing=2.0)
        return cls(road_network)
예제 #5
0
 def map_bounding_box(self):
     # This function returns the following tuple:
     # (bbox length, bbox width, bbox center)
     net_file = os.path.join(self._root, "map.net.xml")
     road_network = SumoRoadNetwork.from_file(net_file)
     # 2D bbox in format (xmin, ymin, xmax, ymax)
     bounding_box = road_network.graph.getBoundary()
     bounding_box_length = bounding_box[2] - bounding_box[0]
     bounding_box_width = bounding_box[3] - bounding_box[1]
     bounding_box_center = [
         (bounding_box[0] + bounding_box[2]) / 2,
         (bounding_box[1] + bounding_box[3]) / 2,
         0,
     ]
     return (bounding_box_length, bounding_box_width, bounding_box_center)
예제 #6
0
파일: scenario.py 프로젝트: zbzhu99/SMARTS
    def discover_agent_missions(scenario_root, agents_to_be_briefed):
        """Returns a sequence of {agent_id: mission} mappings.

        If no missions are discovered we generate random ones. If there is only one
        agent to be briefed we return a list of `{agent_id: mission}` cycling through
        each mission. If there are multiple agents to be briefed we assume that each
        one is intended to get its own mission and that `len(agents_to_be_briefed) ==
        len(missions)`. In this case a list of one dictionary is returned.
        """

        net_file = os.path.join(scenario_root, "map.net.xml")
        road_network = SumoRoadNetwork.from_file(net_file)

        missions = []
        missions_file = os.path.join(scenario_root, "missions.pkl")
        if os.path.exists(missions_file):
            with open(missions_file, "rb") as f:
                missions = pickle.load(f)

            missions = [
                Scenario._extract_mission(actor_and_mission.mission,
                                          road_network)
                for actor_and_mission in missions
            ]

        if not missions:
            missions = [None for _ in range(len(agents_to_be_briefed))]

        if len(agents_to_be_briefed) == 1:
            # single-agent, so we cycle through all missions individually.
            return missions
        elif len(agents_to_be_briefed) > 1:
            # multi-agent, so we assume missions "drive" the agents (i.e. one
            # mission per agent) and we will not be cycling through missions.
            assert not missions or len(missions) == len(agents_to_be_briefed), (
                "You must either provide an equal number of missions ({}) to "
                "agents ({}) or provide no missions at all so they can be "
                "randomly generated.".format(len(missions),
                                             len(agents_to_be_briefed)))

        return missions
예제 #7
0
    def is_valid_scenario(scenario_root):
        """Checks if the scenario_root directory matches our expected scenario structure

        >>> Scenario.is_valid_scenario("scenarios/loop")
        True
        >>> Scenario.is_valid_scenario("scenarios/non_existant")
        False
        """
        paths = [
            os.path.join(scenario_root, "map.net.xml"),
        ]

        for f in paths:
            if not os.path.exists(f):
                return False

        # make sure we can load the sumo network
        net_file = os.path.join(scenario_root, "map.net.xml")
        net = SumoRoadNetwork.from_file(net_file)
        if net is None:
            return False

        return True
예제 #8
0
def road_network():
    return SumoRoadNetwork.from_file(
        "scenarios/intersections/4lane_t/map.net.xml")
예제 #9
0
 def resolve_edge_length(self, edge_id, lane_id):
     if not self._road_network:
         self._road_network = SumoRoadNetwork.from_file(
             self._road_network_path)
     lane = self._road_network.edge_by_id(edge_id).getLanes()[lane_id]
     return lane.getLength()
예제 #10
0
def generate_glb_from_sumo_network(sumo_net_file, out_glb_file):
    road_network = SumoRoadNetwork.from_file(net_file=sumo_net_file)
    glb = road_network.build_glb(scale=1000)
    glb.write_glb(out_glb_file)
예제 #11
0
    def _discover_social_agents_info(
        scenario,
    ) -> Sequence[Dict[str, SocialAgent]]:
        """Loops through the social agent mission pickles, instantiating corresponding
        implementations for the given types. The output is a list of
        {agent_id: (mission, locator)}, where each dictionary corresponds to the
        social agents to run for a given concrete Scenario (which translates to
        "per episode" when swapping).
        """
        scenario_root = (
            scenario.root_filepath if isinstance(scenario, Scenario) else scenario
        )
        net_file = os.path.join(scenario_root, "map.net.xml")
        road_network = SumoRoadNetwork.from_file(net_file)

        social_agents_path = os.path.join(scenario_root, "social_agents")
        if not os.path.exists(social_agents_path):
            return []

        # [ ( missions_file, agent_actor, Mission ) ]
        agent_bucketer = []

        # like dict.setdefault
        def setdefault(l: Sequence[Any], index: int, default):
            while len(l) < index + 1:
                l.append([])
            return l[index]

        file_match = os.path.join(social_agents_path, "*.pkl")
        for missions_file_path in glob.glob(file_match):
            with open(missions_file_path, "rb") as missions_file:
                count = 0
                missions = pickle.load(missions_file)

            for mission_and_actor in missions:
                # Each pickle file will contain a list of actor/mission pairs. The pairs
                # will most likely be generated in an M:N fashion
                # (i.e. A1: M1, A1: M2, A2: M1, A2: M2). The desired behavior is to have
                # a single pair per concrete Scenario (which would translate to
                # "per episode" when swapping)
                assert isinstance(
                    mission_and_actor.actor, sstudio_types.SocialAgentActor
                )

                actor = mission_and_actor.actor
                extracted_mission = Scenario._extract_mission(
                    mission_and_actor.mission, road_network
                )
                namespace = os.path.basename(missions_file_path)
                namespace = os.path.splitext(namespace)[0]

                setdefault(agent_bucketer, count, []).append(
                    (
                        SocialAgent(
                            id=SocialAgentId.new(actor.name, group=namespace),
                            name=actor.name,
                            is_boid=False,
                            is_boid_keep_alive=False,
                            agent_locator=actor.agent_locator,
                            policy_kwargs=actor.policy_kwargs,
                            initial_speed=actor.initial_speed,
                        ),
                        extracted_mission,
                    )
                )
                count += 1

        social_agents_info = []
        for l in agent_bucketer:
            social_agents_info.append(
                {agent.id: (agent, mission) for agent, mission in l}
            )

        return social_agents_info
예제 #12
0
 def _cache_road_network(self):
     if not self._road_network:
         self._road_network = SumoRoadNetwork.from_file(self._road_network_path)