Skip to content

Commit

Permalink
Sumo integration (metadriverse#598)
Browse files Browse the repository at this point in the history
* add time me prefix

* let's have a base agent manager

* rename vehicle in base_env to agent

* env.vehicle -> env.agent

* self.vehicles -> self.agents and self.vehicle -> self.agent

* format

* format

* finish -> _finish

* check agent manager

* show lines for traffic light

* refactor agent manager

* add before_step

* move the get_Action_space to agentManager

* runnable return dict

* update drawer and lights

* format

* light

* cull

* new sensor creation

* wise sensor creation and multi rendering

* update sensor creation

* fix test

* fix

* optimize

* format

* fix bug

* format

* fix test

* fix bug

* format

* fix bug

* fix bug

* format

* fix bug
  • Loading branch information
QuanyiLi authored Jan 18, 2024
1 parent 6d52930 commit c1431f5
Show file tree
Hide file tree
Showing 108 changed files with 1,430 additions and 1,069 deletions.
22 changes: 11 additions & 11 deletions bridges/ros_bridge/ros_socket_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def run(self, test=False):

env.reset()
print(HELP_MESSAGE)
env.vehicle.expert_takeover = False
env.agent.expert_takeover = False
while True:
o = env.step([0, 0])
if test:
Expand All @@ -79,17 +79,17 @@ def run(self, test=False):
print(msg)
del image_data # explicit delete to free memory

lidar_data, objs = env.vehicle.lidar.perceive(
env.vehicle,
lidar_data, objs = env.agent.lidar.perceive(
env.agent,
env.engine.physics_world.dynamic_world,
env.vehicle.config["lidar"]["num_lasers"],
env.vehicle.config["lidar"]["distance"],
env.agent.config["lidar"]["num_lasers"],
env.agent.config["lidar"]["distance"],
height=1.0,
)

ego_x = env.vehicle.position[0]
ego_y = env.vehicle.position[1]
ego_theta = np.arctan2(env.vehicle.heading[1], env.vehicle.heading[0])
ego_x = env.agent.position[0]
ego_y = env.agent.position[1]
ego_theta = np.arctan2(env.agent.heading[1], env.agent.heading[0])

num_data = struct.pack('i', len(objs))
obj_data = []
Expand Down Expand Up @@ -123,9 +123,9 @@ def run(self, test=False):
del obj_data # explicit delete to free memory

# convert lidar data to xyz
lidar_data = np.array(lidar_data) * env.vehicle.config["lidar"]["distance"]
lidar_range = env.vehicle.lidar._get_lidar_range(
env.vehicle.config["lidar"]["num_lasers"], env.vehicle.lidar.start_phase_offset
lidar_data = np.array(lidar_data) * env.agent.config["lidar"]["distance"]
lidar_range = env.agent.lidar._get_lidar_range(
env.agent.config["lidar"]["num_lasers"], env.agent.lidar.start_phase_offset
)
point_x = lidar_data * np.cos(lidar_range)
point_y = lidar_data * np.sin(lidar_range)
Expand Down
2 changes: 1 addition & 1 deletion documentation/source/action.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@
" extra = random.randint(0, 9)\n",
" action={\"action\": [0., 0.], \"extra\": extra}\n",
" _,_,_,_,info = env.step(action)\n",
" extra_ = env.engine.get_policy(env.vehicle.id).extra_input\n",
" extra_ = env.engine.get_policy(env.agent.id).extra_input\n",
" assert extra == extra_\n",
" print(\"Extra info this step is: {}\".format(extra))\n",
"finally:\n",
Expand Down
2 changes: 1 addition & 1 deletion documentation/source/points_and_lines.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
"source": [
"env.reset() # launch the simulation\n",
"try:\n",
" drawer = env.engine.make_line_drawer(env.vehicle.origin, thickness=5)\n",
" drawer = env.engine.make_line_drawer(env.agent.origin, thickness=5)\n",
" # rotate the drawer by 90 degree, as +x is at the right side of the car.\n",
" drawer.setH(90) \n",
" for i in range(100):\n",
Expand Down
2 changes: 1 addition & 1 deletion documentation/source/reward_cost_done.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@
" TerminationState.SUCCESS: \u001b[36mself\u001b[39;49;00m._is_arrive_destination(vehicle),\n",
" TerminationState.MAX_STEP: max_step,\n",
" TerminationState.ENV_SEED: \u001b[36mself\u001b[39;49;00m.current_seed,\n",
" \u001b[37m# TerminationState.CURRENT_BLOCK: self.vehicle.navigation.current_road.block_ID(),\u001b[39;49;00m\n",
" \u001b[37m# TerminationState.CURRENT_BLOCK: self.agent.navigation.current_road.block_ID(),\u001b[39;49;00m\n",
" \u001b[37m# crash_vehicle=False, crash_object=False, crash_building=False, out_of_road=False, arrive_dest=False,\u001b[39;49;00m\n",
" }\n",
"\n",
Expand Down
22 changes: 11 additions & 11 deletions documentation/source/rl_environments.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@
" training_env.reset(seed=env_seed)\n",
" lane_nums.add(training_env.current_map.config[\"lane_num\"]) \n",
" lane_widths.add(training_env.current_map.config[\"lane_width\"])\n",
" vehicle_models.add(training_env.vehicle.__class__.__name__)\n",
" vehicle_models.add(training_env.agent.__class__.__name__)\n",
" traffic_models = set([obj.__class__ for obj in training_env.engine.traffic_manager.spawned_objects.values()])\n",
" traffic_vehicle_models = traffic_vehicle_models.union(traffic_models)\n",
" assert vehicle_type[training_env.vehicle.config[\"vehicle_model\"]] is training_env.vehicle.__class__\n",
" assert vehicle_type[training_env.agent.config[\"vehicle_model\"]] is training_env.agent.__class__\n",
" \n",
"training_env.close()\n",
"\n",
Expand Down Expand Up @@ -761,14 +761,14 @@
" training_env.reset(seed=env_seed)\n",
" lane_nums.add(training_env.current_map.config[\"lane_num\"]) \n",
" lane_widths.add(training_env.current_map.config[\"lane_width\"])\n",
" vehicle_models.add(training_env.vehicle.__class__.__name__)\n",
" vehicle_models.add(training_env.agent.__class__.__name__)\n",
" traffic_models = set([obj.__class__ for obj in training_env.engine.traffic_manager.spawned_objects.values()])\n",
" traffic_vehicle_models = traffic_vehicle_models.union(traffic_models)\n",
" assert vehicle_type[training_env.vehicle.config[\"vehicle_model\"]] is training_env.vehicle.__class__\n",
" assert vehicle_type[training_env.agent.config[\"vehicle_model\"]] is training_env.agent.__class__\n",
" \n",
" # collect more\n",
" for k, v in to_collect_set.items():\n",
" v.add(training_env.vehicle.config[k])\n",
" v.add(training_env.agent.config[k])\n",
" \n",
"training_env.close()\n",
"\n",
Expand Down Expand Up @@ -912,7 +912,7 @@
" TerminationState.SUCCESS: \u001b[36mself\u001b[39;49;00m._is_arrive_destination(vehicle),\n",
" TerminationState.MAX_STEP: max_step,\n",
" TerminationState.ENV_SEED: \u001b[36mself\u001b[39;49;00m.current_seed,\n",
" \u001b[37m# TerminationState.CURRENT_BLOCK: self.vehicle.navigation.current_road.block_ID(),\u001b[39;49;00m\n",
" \u001b[37m# TerminationState.CURRENT_BLOCK: self.agent.navigation.current_road.block_ID(),\u001b[39;49;00m\n",
" \u001b[37m# crash_vehicle=False, crash_object=False, crash_building=False, out_of_road=False, arrive_dest=False,\u001b[39;49;00m\n",
" }\n",
"\n",
Expand Down Expand Up @@ -1085,7 +1085,7 @@
" cone=env.engine.spawn_object(TrafficCone, position=[20, 7], heading_theta=0)\n",
" for _ in range(100):\n",
" o,r,d,_,info = env.step([0, 1])\n",
" if env.vehicle.crash_object:\n",
" if env.agent.crash_object:\n",
" assert info[\"cost\"] == -5\n",
" break\n",
" env.engine.clear_objects([cone.id])\n",
Expand Down Expand Up @@ -1240,7 +1240,7 @@
"try:\n",
" while True:\n",
" last_o=o\n",
" o,r,tm,_,i=env.step({agent_id: [0, 1] for agent_id in env.vehicles.keys()})\n",
" o,r,tm,_,i=env.step({agent_id: [0, 1] for agent_id in env.agents.keys()})\n",
" m = env.render(mode=\"topdown\", \n",
" film_size = (1000, 1000),\n",
" screen_size = (1000, 1000),\n",
Expand All @@ -1250,7 +1250,7 @@
" break\n",
" \n",
" # for test only\n",
" assert len(env.vehicles)<=env.config[\"num_agents\"]\n",
" assert len(env.agents)<=env.config[\"num_agents\"]\n",
" if not env.config[\"allow_respawn\"]:\n",
" assert len(o)<=len(last_o)\n",
"finally:\n",
Expand Down Expand Up @@ -1465,7 +1465,7 @@
"metadata": {},
"source": [
"## GymWrapper\n",
"Some legacy training frameworks may use the `openai.gym` interface whose `step()` function returns `obs`, `reward`, `termination`, and `info`. For making MetaDrive compatible with these training code, we provide an official wrapper for **all** environments of MetaDrive. The wrapped environment will have an `openai.gym` style APIs. Also, you can access all properties and methods of wrapped env using the same syntax. For example, we can still access the ego car via `env.vehicle`, even if the env is wrapped on top of `MetaDriveEnv`. "
"Some legacy training frameworks may use the `openai.gym` interface whose `step()` function returns `obs`, `reward`, `termination`, and `info`. For making MetaDrive compatible with these training code, we provide an official wrapper for **all** environments of MetaDrive. The wrapped environment will have an `openai.gym` style APIs. Also, you can access all properties and methods of wrapped env using the same syntax. For example, we can still access the ego car via `env.agent`, even if the env is wrapped on top of `MetaDriveEnv`. "
]
},
{
Expand Down Expand Up @@ -1531,7 +1531,7 @@
" o = gym_env.reset()\n",
" o,r,d,i = gym_env.step([0,0])\n",
" assert gym_env.config[\"accident_prob\"] == 1.0\n",
" print(\"Vehicle id:\", gym_env.vehicle.id)\n",
" print(\"Vehicle id:\", gym_env.agent.id)\n",
" ret=gym_env.render(mode=\"topdown\", \n",
" window=False,\n",
" camera_position=(50, -70))\n",
Expand Down
5 changes: 3 additions & 2 deletions metadrive/base_class/base_runnable.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def before_step(self, *args, **kwargs):
"""
Do Information fusion and then analyze and wait for decision
"""
pass
return {}

def set_action(self, *args, **kwargs):
"""
Expand All @@ -63,12 +63,13 @@ def step(self, *args, **kwargs):
time. However some runnable instances who don't belong to the physics world and their actions are not force need
to implement this function to get the action accumulated result respect to time.
"""
pass
return {}

def after_step(self, *args, **kwargs):
"""
After advancing all objects for a time period, their state should be updated for statistic or other purpose
"""
return {}

def reset(self, random_seed=None, *args, **kwargs):
"""
Expand Down
2 changes: 1 addition & 1 deletion metadrive/component/sensors/rgb_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def _setup_effect(self):
fbprops.float_color = True
fbprops.set_rgba_bits(16, 16, 16, 16)
fbprops.set_depth_bits(24)
fbprops.set_multisamples(self.engine.pbrpipe.msaa_samples)
fbprops.set_multisamples(16)
self.scene_tex = p3d.Texture()
self.scene_tex.set_format(p3d.Texture.F_rgba16)
self.scene_tex.set_component_type(p3d.Texture.T_float)
Expand Down
46 changes: 40 additions & 6 deletions metadrive/component/traffic_light/base_traffic_light.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import numpy as np

from metadrive.base_class.base_object import BaseObject
from metadrive.constants import CamMask
from metadrive.scenario.scenario_description import ScenarioDescription
Expand All @@ -21,12 +23,23 @@ class BaseTrafficLight(BaseObject):
PLACE_LONGITUDE = 5

def __init__(
self, lane, position=None, name=None, random_seed=None, config=None, escape_random_seed_assertion=False
self,
lane,
position=None,
name=None,
random_seed=None,
config=None,
escape_random_seed_assertion=False,
draw_line=False,
show_model=True,
):
super(BaseTrafficLight, self).__init__(name, random_seed, config, escape_random_seed_assertion)
self.set_metadrive_type(MetaDriveType.TRAFFIC_LIGHT)
self.lane = lane
self.status = MetaDriveType.LIGHT_UNKNOWN
self._draw_line = draw_line
self._show_model = show_model
self._lane_center_line = None

self.lane_width = lane.width_at(0) if lane else 4
air_wall = generate_static_box_physics_body(
Expand All @@ -48,7 +61,7 @@ def __init__(
self.current_light = None

if self.render:
if len(BaseTrafficLight.TRAFFIC_LIGHT_MODEL) == 0:
if len(BaseTrafficLight.TRAFFIC_LIGHT_MODEL) == 0 and self._show_model:
for color in ["green", "red", "yellow", "unknown"]:
model = self.loader.loadModel(
AssetLoader.file_path("models", "traffic_light", "{}.gltf".format(color))
Expand All @@ -58,44 +71,65 @@ def __init__(
model.hide(CamMask.Shadow)
BaseTrafficLight.TRAFFIC_LIGHT_MODEL[color] = model
self.origin.setScale(0.5, 1.2, 1.2)
if self._draw_line:
self._line_drawer = self.engine.make_line_drawer(thickness=2)
self._lane_center_line = np.array([[p[0], p[1], 0.4] for p in self.lane.get_polyline()])

def before_step(self, *args, **kwargs):
self.set_status(*args, **kwargs)

def set_status(self, status):
"""
People should overwrite this method to parse traffic light status and to determine which traffic light to set
"""
pass

def _try_draw_line(self, color):
if self._draw_line:
self._line_drawer.reset()
self._line_drawer.draw_lines([self._lane_center_line], [[color for _ in self._lane_center_line]])

def set_green(self):
if self.render:
if self.current_light is not None:
self.current_light.detachNode()
self.current_light = BaseTrafficLight.TRAFFIC_LIGHT_MODEL["green"].instanceTo(self.origin)
if self._show_model:
self.current_light = BaseTrafficLight.TRAFFIC_LIGHT_MODEL["green"].instanceTo(self.origin)
self._try_draw_line([3 / 255, 255 / 255, 3 / 255])
self.status = MetaDriveType.LIGHT_GREEN

def set_red(self):
if self.render:
if self.current_light is not None:
self.current_light.detachNode()
self.current_light = BaseTrafficLight.TRAFFIC_LIGHT_MODEL["red"].instanceTo(self.origin)
if self._show_model:
self.current_light = BaseTrafficLight.TRAFFIC_LIGHT_MODEL["red"].instanceTo(self.origin)
self._try_draw_line([252 / 255, 0 / 255, 0 / 255])
self.status = MetaDriveType.LIGHT_RED

def set_yellow(self):
if self.render:
if self.current_light is not None:
self.current_light.detachNode()
self.current_light = BaseTrafficLight.TRAFFIC_LIGHT_MODEL["yellow"].instanceTo(self.origin)
if self._show_model:
self.current_light = BaseTrafficLight.TRAFFIC_LIGHT_MODEL["yellow"].instanceTo(self.origin)
self._try_draw_line([252 / 255, 227 / 255, 3 / 255])
self.status = MetaDriveType.LIGHT_YELLOW

def set_unknown(self):
if self.render:
if self.current_light is not None:
self.current_light.detachNode()
self.current_light = BaseTrafficLight.TRAFFIC_LIGHT_MODEL["unknown"].instanceTo(self.origin)
if self._show_model:
self.current_light = BaseTrafficLight.TRAFFIC_LIGHT_MODEL["unknown"].instanceTo(self.origin)
self.status = MetaDriveType.LIGHT_UNKNOWN

def destroy(self):
super(BaseTrafficLight, self).destroy()
self.lane = None
if self._draw_line:
self._line_drawer.reset()
self._line_drawer.removeNode()

@property
def top_down_color(self):
Expand Down
10 changes: 5 additions & 5 deletions metadrive/engine/base_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from metadrive.engine.core.engine_core import EngineCore
from metadrive.engine.interface import Interface
from metadrive.engine.logger import get_logger, reset_logger
from metadrive.manager.base_manager import BaseManager

from metadrive.pull_asset import pull_asset
from metadrive.utils import concat_step_infos
from metadrive.utils.utils import is_map_related_class
Expand Down Expand Up @@ -530,7 +530,7 @@ def _stop_replay(self):
return
self.STOP_REPLAY = not self.STOP_REPLAY

def register_manager(self, manager_name: str, manager: BaseManager):
def register_manager(self, manager_name: str, manager):
"""
Add a manager to BaseEngine, then all objects can communicate with this class
:param manager_name: name shouldn't exist in self._managers and not be same as any class attribute
Expand Down Expand Up @@ -595,9 +595,9 @@ def current_map(self):
return None

@property
def current_track_vehicle(self):
def current_track_agent(self):
if self.main_camera is not None:
return self.main_camera.current_track_vehicle
return self.main_camera.current_track_agent
elif "default_agent" in self.agents:
return self.agents["default_agent"]
else:
Expand Down Expand Up @@ -661,7 +661,7 @@ def _object_clean_check(self):
children = self.worldNP.getChildren()
assert len(children) == 0, "NodePath are not cleaned thoroughly. Remaining NodePath: {}".format(children)

def update_manager(self, manager_name: str, manager: BaseManager, destroy_previous_manager=True):
def update_manager(self, manager_name: str, manager, destroy_previous_manager=True):
"""
Update an existing manager with a new one
:param manager_name: existing manager name
Expand Down
7 changes: 5 additions & 2 deletions metadrive/engine/core/draw.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ def draw_lines(self, lineList, colorList=None):
for pointList, lineColor in zip(lineList, colorList):
self.moveTo(*pointList[0])
for point, seg_color, in zip(pointList[1:], lineColor):
assert len(seg_color) == 4, "color vector should have 4 component, get {} instead".format(
assert 3 <= len(seg_color) <= 4, "color vector should have 3 or 4 component, get {} instead".format(
len(seg_color)
)
self.setColor(LVecBase4f(*seg_color))
if len(seg_color) == 4:
self.setColor(LVecBase4f(*seg_color))
else:
self.setColor(LVecBase4f(*seg_color, 1.0))
self.drawTo(*point)
self.create()

Expand Down
9 changes: 8 additions & 1 deletion metadrive/engine/core/engine_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ def __init__(self, global_config):
# # "No allowed to change ptr of global config, which may cause issue"
# pass
# else:
config = global_config
self.main_window_disabled = False
if "main_camera" not in global_config["sensors"]:
# reduce size as we don't use the main camera content for improving efficiency
config["window_size"] = (1, 1)
self.main_window_disabled = True

self.pid = os.getpid()
EngineCore.global_config = global_config
self.mode = global_config["_render_mode"]
Expand Down Expand Up @@ -182,7 +189,7 @@ def __init__(self, global_config):

super(EngineCore, self).__init__(windowType=self.mode)
logger.info("Known Pipes: {}".format(*GraphicsPipeSelection.getGlobalPtr().getPipeTypes()))
if self.global_config["window_size"] == (1, 1):
if self.main_window_disabled and self.mode != RENDER_MODE_NONE:
self.win.setActive(False)

self._all_panda_tasks = self.taskMgr.getAllTasks()
Expand Down
Loading

0 comments on commit c1431f5

Please sign in to comment.