Log messages
Logging message is important to oversee the program status. MetaDrive adopts Python’s logging
module to log messages.
Global logger
We provide a wrapper in metadrive/engine/logger
to customize some features. We recommend using it to log messages to make the logging consistent. It is a global variable, so you can get the logger at anywhere of your code. Some classes like BaseEnv
may have a variable called logger
as well, which is actually the same as the global logger.
from metadrive.envs.base_env import BaseEnv
from metadrive.engine.logger import get_logger # get_logger
logger = get_logger()
# create environment
logger.info("Create environment\n")
env = BaseEnv(dict(use_render=False))
assert logger is env.logger # the environment.logger is the same as global logger
# reset environment
logger.info("Reset environment")
env.reset()
try:
for i in range(5):
logger.info("Simulate step {}".format(i))
env.step(env.action_space.sample())
finally:
logger.info("Close environment")
env.close()
[INFO] Create environment
[INFO] Environment: BaseEnv
[INFO] MetaDrive version: 0.4.2.3
[INFO] Sensors: [lidar: Lidar(), side_detector: SideDetector(), lane_line_detector: LaneLineDetector()]
[INFO] Render Mode: none
[INFO] Horizon (Max steps per agent): None
[WARNING] You are using DummyObservation which doesn't collect information from the environment. (observation_base.py:50)
[INFO] Reset environment
[INFO] Assets version: 0.4.2.3
[INFO] Known Pipes: glxGraphicsPipe
[WARNING] Can not find `start_seed` or `start_scenario_index`. Use 0 as `start_seed` (base_engine.py:572)
[INFO] Start Scenario Index: 0, Num Scenarios : 1
[WARNING] Can not find `start_seed` or `start_scenario_index`. Use 0 as `start_seed` (base_engine.py:572)
[WARNING] No map is provided. Set vehicle to position (0, 0) with heading 0 (base_vehicle.py:339)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[1], line 13
11 # reset environment
12 logger.info("Reset environment")
---> 13 env.reset()
14 try:
15 for i in range(5):
File ~/checkouts/readthedocs.org/user_builds/metadrive-simulator/envs/latest/lib/python3.11/site-packages/metadrive/envs/base_env.py:542, in BaseEnv.reset(self, seed)
539 assert (len(self.agents) == self.num_agents) or (self.num_agents == -1), \
540 "Agents: {} != Num_agents: {}".format(len(self.agents), self.num_agents)
541 assert self.config is self.engine.global_config is get_global_config(), "Inconsistent config may bring errors!"
--> 542 return self._get_reset_return(reset_info)
File ~/checkouts/readthedocs.org/user_builds/metadrive-simulator/envs/latest/lib/python3.11/site-packages/metadrive/envs/base_env.py:568, in BaseEnv._get_reset_return(self, reset_info)
565 def _get_reset_return(self, reset_info):
566 # TODO: figure out how to get the information of the before step
567 scene_manager_before_step_infos = reset_info
--> 568 scene_manager_after_step_infos = self.engine.after_step()
570 obses = {}
571 done_infos = {}
File ~/checkouts/readthedocs.org/user_builds/metadrive-simulator/envs/latest/lib/python3.11/site-packages/metadrive/engine/base_engine.py:462, in BaseEngine.after_step(self, *args, **kwargs)
460 assert list(self.managers.keys())[-1] == "record_manager", "Record Manager should have lowest priority"
461 for manager in self.managers.values():
--> 462 new_step_info = manager.after_step(*args, **kwargs)
463 step_infos = concat_step_infos([step_infos, new_step_info])
464 self.interface.after_step()
File ~/checkouts/readthedocs.org/user_builds/metadrive-simulator/envs/latest/lib/python3.11/site-packages/metadrive/manager/base_manager.py:309, in BaseAgentManager.after_step(self, *args, **kwargs)
307 def after_step(self, *args, **kwargs):
308 step_infos = self.try_actuate_agent({}, stage="after_step")
--> 309 step_infos.update(self.for_each_active_agents(lambda v: v.after_step()))
310 return step_infos
File ~/checkouts/readthedocs.org/user_builds/metadrive-simulator/envs/latest/lib/python3.11/site-packages/metadrive/manager/base_manager.py:402, in BaseAgentManager.for_each_active_agents(self, func, *args, **kwargs)
400 ret = dict()
401 for k, v in self.active_agents.items():
--> 402 ret[k] = func(v, *args, **kwargs)
403 return ret
File ~/checkouts/readthedocs.org/user_builds/metadrive-simulator/envs/latest/lib/python3.11/site-packages/metadrive/manager/base_manager.py:309, in BaseAgentManager.after_step.<locals>.<lambda>(v)
307 def after_step(self, *args, **kwargs):
308 step_infos = self.try_actuate_agent({}, stage="after_step")
--> 309 step_infos.update(self.for_each_active_agents(lambda v: v.after_step()))
310 return step_infos
File ~/checkouts/readthedocs.org/user_builds/metadrive-simulator/envs/latest/lib/python3.11/site-packages/metadrive/component/vehicle/base_vehicle.py:254, in BaseVehicle.after_step(self)
242 my_policy = self.engine.get_policy(self.name)
243 step_info.update(
244 {
245 "velocity": float(self.speed),
(...)
251 }
252 )
--> 254 lanes_heading = self.navigation.navi_arrow_dir
255 lane_0_heading = lanes_heading[0]
256 lane_1_heading = lanes_heading[1]
AttributeError: 'NoneType' object has no attribute 'navi_arrow_dir'
The logger can be used at everywhere. For example, it can be used in your manager.
from metadrive.envs.base_env import BaseEnv
from metadrive.engine.logger import get_logger # get_logger
from metadrive.manager.base_manager import BaseManager
logger = get_logger()
class MyMgr(BaseManager):
def __init__(self):
super(MyMgr, self).__init__()
logger.info("Init MyMgr...")
def after_step(self):
logger.info("Step {}...".format(self.episode_step))
return dict()
# create environment
env = BaseEnv(dict(use_render=False))
# reset environment
env.reset()
# add manager
env.engine.register_manager("my_mgr", MyMgr())
try:
for i in range(5):
env.step(env.action_space.sample())
finally:
env.close()
Log level
Similar to logging
module, one can change the log level to decide which log messages to be printed. Generally, MetaDrive uses logging.INFO
, logging.DEBUG
, and logging.WARNING
to classify log messages. By default, the log level is logging.INFO
and thus debug messages will be hidden. The log level can be set in environment config. The following example shows how to print more debug message by setting log_level=logging.DEBUG
. In addition, if debug=True
in the environment config, the log level will be set to logging.DEBUG
as well.
from metadrive.envs.base_env import BaseEnv
import logging
from metadrive.engine.logger import get_logger # get_logger
logger = get_logger()
# create environment
env = BaseEnv(dict(use_render=False, log_level=logging.DEBUG))
assert logger is env.logger # the environment.logger is the same as global logger
# reset environment
logger.debug("Reset environment")
env.reset()
try:
for i in range(5):
logger.debug("Simulate step {}".format(i))
env.step(env.action_space.sample())
finally:
logger.debug("Close environment")
env.close()
If you would like to turn off all log messages, changing the log_level to logging.WARNING
(or logging.CRITICAL
) can suppress messages logged by logging.info()
, logging.debug()
(or even logging.warn
).
from metadrive.engine.logger import set_log_level # get_logger
def run(): # define the simulation loop
# reset environment
logger.debug("Reset environment")
env.reset()
try:
for i in range(5):
logger.debug("Simulate step {}".format(i))
env.step(env.action_space.sample())
finally:
logger.debug("Close environment")
env.close()
set_log_level(logging.WARNING) # Or set it in environment config
run()
print("Turn off all messages...")
set_log_level(logging.CRITICAL) # Or set it in environment config
run()
Log once
Sometimes, we may want the message to be logged only once in one episode. In this case, we can use the log_once
key to notify the logger to show some messages only once until the next reset
is called.
from metadrive.envs.base_env import BaseEnv
import logging
# create environment
env = BaseEnv(dict(use_render=False, log_level=logging.CRITICAL))
# reset environment
env.reset()
try:
for i in range(5):
env.logger.critical("Step... (I will only show once)".format(i), extra={"log_once": True})
env.step(env.action_space.sample())
finally:
env.close()