11"""
22opencv renderer class.
33"""
4- import cv2
54import numpy as np
5+ import cv2
6+ import platform
67
78
89class OpenCVRenderer :
@@ -12,32 +13,64 @@ def __init__(self, sim):
1213 self .height = 800
1314
1415 self .sim = sim
15- self .camera_name = self .sim .model .camera_id2name (0 )
16-
16+ self .set_camera (camera_id = 0 )
17+ self ._window_name = "offscreen render"
18+ self ._has_window = False
1719 self .keypress_callback = None
1820
19- def set_camera (self , camera_id ):
21+ def set_camera (self , camera_id = None , camera_name = None ):
2022 """
2123 Set the camera view to the specified camera ID.
24+
2225 Args:
23- camera_id (int): id of the camera to set the current viewer to
26+ camera_id (int or list): id(s) of the camera to set the current viewer to
27+ camera_name (str or list or None): name(s) of the camera to set the current viewer to
2428 """
25- self .camera_name = self .sim .model .camera_id2name (camera_id )
29+
30+ # enforce exactly one arg
31+ assert (camera_id is not None ) or (camera_name is not None )
32+ assert (camera_id is None ) or (camera_name is None )
33+
34+ if camera_id is not None :
35+ if isinstance (camera_id , int ):
36+ camera_id = [camera_id ]
37+ self .camera_names = [self .sim .model .camera_id2name (cam_id ) for cam_id in camera_id ]
38+ else :
39+ if isinstance (camera_name , str ):
40+ camera_name = [camera_name ]
41+ self .camera_names = list (camera_name )
2642
2743 def render (self ):
2844 # get frame with offscreen renderer (assumes that the renderer already exists)
29- im = self .sim .render (camera_name = self .camera_name , height = self .height , width = self .width )[..., ::- 1 ]
45+ im = [
46+ self .sim .render (camera_name = cam_name , height = self .height , width = self .width )[..., ::- 1 ]
47+ for cam_name in self .camera_names
48+ ]
49+ im = np .concatenate (im , axis = 1 ) # concatenate horizontally
3050
3151 # write frame to window
3252 im = np .flip (im , axis = 0 )
33- cv2 .imshow ("offscreen render" , im )
53+ cv2 .imshow (self ._window_name , im )
54+ if (platform .system () != "Darwin" ) and (not self ._has_window ):
55+ # move window to top left of screen, and ensure we only move window on creation
56+ cv2 .moveWindow (self ._window_name , 0 , 0 )
3457 key = cv2 .waitKey (1 )
35- if self .keypress_callback :
58+ if self .keypress_callback is not None :
3659 self .keypress_callback (key )
60+ self ._has_window = True
3761
3862 def add_keypress_callback (self , keypress_callback ):
3963 self .keypress_callback = keypress_callback
4064
65+ def close_window (self ):
66+ """
67+ Helper method to close the active window.
68+ """
69+ if self ._has_window :
70+ cv2 .destroyWindow (self ._window_name )
71+ cv2 .waitKey (1 )
72+ self ._has_window = False
73+
4174 def close (self ):
4275 """
4376 Any cleanup to close renderer.
@@ -47,4 +80,4 @@ def close(self):
4780 self .sim = None
4881
4982 # close window
50- cv2 . destroyAllWindows ()
83+ self . close_window ()
0 commit comments