nbro
nbro

Reputation: 15847

In gym, how should we implement the environment's render method so that Monitor's produced videos are not black?

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

Answers (1)

stephan norsten
stephan norsten

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

Related Questions