dstl / YAWNING-TITAN

YAWNING TITAN is an abstract, graph based cyber-security simulation environment that supports the training of intelligent agents for autonomous cyber operations.
MIT License
57 stars 17 forks source link

[BUG] Rendering and GIF saving is broken #56

Closed timdudman closed 1 year ago

timdudman commented 1 year ago

Describe the bug When rendering, a small blank window is displayed and then later the final frame flashes up before the window closes.

When trying to save a GIF, the same happens, except there are two small blank windows, and th following error is produced after the final frame flashes up:

Traceback (most recent call last):
  File "C:\Work\YT\YAWNING-TITAN\main.py", line 36, in <module>
    loop.gif_action_loop(save_gif=True, render_network=True)
  File "C:\Work\YT\YAWNING-TITAN\src\yawning_titan\envs\generic\core\action_loops.py", line 117, in gif_action_loop
    webm_path = os.path.join(
  File "C:\Users\t_dudman\AppData\Local\Programs\Python\Python310\lib\ntpath.py", line 104, in join
    path = os.fspath(path)
TypeError: expected str, bytes or os.PathLike object, not NoneType

To Reproduce Run the following script:

from stable_baselines3.common.env_checker import check_env
from stable_baselines3.common.evaluation import evaluate_policy
from stable_baselines3 import PPO
from stable_baselines3.ppo import MlpPolicy as PPOMlp

from yawning_titan.envs.generic.core.blue_interface import BlueInterface
from yawning_titan.envs.generic.core.red_interface import RedInterface
from yawning_titan.envs.generic.generic_env import GenericNetworkEnv
from yawning_titan.envs.generic.core.network_interface import NetworkInterface
from yawning_titan.networks.network_db import default_18_node_network
from yawning_titan.game_modes.game_mode_db import default_game_mode
from yawning_titan.envs.generic.core.action_loops import ActionLoop

game_mode = default_game_mode()

network = default_18_node_network()
network_interface = NetworkInterface(game_mode=game_mode, network=network)

red = RedInterface(network_interface)
blue = BlueInterface(network_interface)

env = GenericNetworkEnv(red, blue, network_interface)

check_env(env, warn=True)

# reset anything changed during the check
_ = env.reset()

agent = PPO(PPOMlp, env, verbose=1)

agent.learn(total_timesteps=1000)

evaluate_policy(agent, env, n_eval_episodes=10)

loop = ActionLoop(env, agent, episode_count=1)
loop.gif_action_loop(save_gif=True, render_network=True)

Change save_gif=True to save_gif=False to see the other problem.

Expected behaviour Rendering and GIF saving should work.

Environment:

Additional context As discussed with CM.

ChrisMcCarthyDev commented 1 year ago

Hi @timdudman thanks for raising this. We've added this to our backlog as a P1 bug. We'll provide an update once we have a fix and it can be released.

timdudman commented 1 year ago

Thanks Chris.

ChrisMcCarthyDev commented 1 year ago

Hi @timdudman. Yawning-Titan v2.0.1 has just been released which fixes this issue.. https://github.com/dstl/YAWNING-TITAN/releases/tag/v2.0.1

Running the following script will create a gif in ~/yawning_titan/images and a webm in ~/yawning_titan/videos

from stable_baselines3.common.env_checker import check_env
from stable_baselines3.common.evaluation import evaluate_policy
from stable_baselines3 import PPO
from stable_baselines3.ppo import MlpPolicy as PPOMlp

from yawning_titan.envs.generic.core.blue_interface import BlueInterface
from yawning_titan.envs.generic.core.red_interface import RedInterface
from yawning_titan.envs.generic.generic_env import GenericNetworkEnv
from yawning_titan.envs.generic.core.network_interface import NetworkInterface
from yawning_titan.networks.network_db import default_18_node_network
from yawning_titan.game_modes.game_mode_db import default_game_mode
from yawning_titan.envs.generic.core.action_loops import ActionLoop

game_mode = default_game_mode()

network = default_18_node_network()
network_interface = NetworkInterface(game_mode=game_mode, network=network)

red = RedInterface(network_interface)
blue = BlueInterface(network_interface)

env = GenericNetworkEnv(red, blue, network_interface)

check_env(env, warn=True)

# reset anything changed during the check
_ = env.reset()

agent = PPO(PPOMlp, env, verbose=1)

agent.learn(total_timesteps=1000)

evaluate_policy(agent, env, n_eval_episodes=10)

loop = ActionLoop(env, agent, episode_count=1)
loop.gif_action_loop(save_gif=True, render_network=True)
timdudman commented 1 year ago

Thanks @ChrisMcCarthyDev.

To get the WEBM aswell you need to add an extra flag to gif_action_loop.

loop.gif_action_loop(save_gif=True, save_webm=True, render_network=True)

And the GIF and WEBM look good.

The other issue of "when rendering, a small blank window is displayed and then later the final frame flashes up before the window closes" remains. The same issue is seen when calling environment.render() directly. Is there any way to see 'live' animation?

timdudman commented 1 year ago

@ChrisMcCarthyDev I can add plt.pause(0.2) at the end of yawning_titan.envs.generic.helpers.graph2plot.CustomEnvGraph.render which allows the animation to be seen live. I guess the reason it's not there is because you want to generate video for the GUI as quicly as possible?