Reputation: 15847
How are we supposed to implement the environment's render
method in gym, so that Monitor
's produced videos are not black (as they appear to me right now)? Or, alternatively, in which circumstances would those videos be black?
To give more context, I was trying to use the gym's wrapper Monitor
. This wrapper writes (every once in a while, how often exactly?) to a folder some .json
files and an .mp4
file, which I suppose represents the trajectory followed by the agent (which trajectory exactly?). How is this .mp4
file generated? I suppose it's generated from what is returned by the render
method. In my specific case, I am using a simple custom environment (i.e. a very simple grid world/maze), where I return a NumPy array that represents my environment's current state (or observation). However, the produced .mp4
files are black, while the array clearly is not black (because I am also printing it with matplotlib's imshow
). So, maybe Monitor
doesn't produce those videos from the render
method's return value. So, how exactly does Monitor produce those videos?
(In general, how should we implement render
, so that we can produce nice animations of our environments? Of course, the answer to this question depends also on the type of environment, but I would like to have some guidance)
Upvotes: 1
Views: 3192
Reputation: 11
This might not be an exhaustive answer, but here's how I did.
First I added rgb_array
to the render.modes
list in the metadata dictionary at the beginning of the class.
If you don't have such a thing, add the dictionary, like this:
class myEnv(gym.Env):
""" blah blah blah """
metadata = {'render.modes': ['human', 'rgb_array'], 'video.frames_per_second': 2 }
...
You can change the desired framerate of course, I don't know if every framerate will work though.
Then I changed my render
method. According to the input parameter mode
, if it is rgb_array
it returns a three dimensional numpy array, that is just a 'numpyed' PIL.Image()
(np.asarray(im)
, with im
being a PIL.Image()
).
If mode
is human
, just print the image or do something to show your environment in the way you like it.
As an example, my code is
def render(self, mode='human', close=False):
# Render the environment to the screen
im = <obtain image from env>
if mode == 'human':
plt.imshow(np.asarray(im))
plt.axis('off')
elif mode == 'rgb_array':
return np.asarray(im)
So basically return an rgb matrix.
Looking at the gym source code, it seems there are other ways that work, but I'm not an expert in video rendering so for those other way I can't help.
Regarding your question "how often exactly [are the videos saved]?", I can point you to this link that helped me for that.
As a final side note, video saving with a gym Monitor wrapper does not work for a mis-indentation (as of today 30/12/20, gym version 0.18.0), if you want to solve it do like this guy did.
(I'm sorry if my English sometimes felt weird, feel free to harshly correct me)
Upvotes: 1