Log messages

Click and Open In Colab

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()