genesis.vis.viewer 源代码

import numpy as np

import genesis as gs
import genesis.utils.geom as gu

try:
    from genesis.ext import pyrender
except:
    print("Failed to import pyrender. Rendering will not work.")
from genesis.repr_base import RBC
from genesis.utils.tools import Rate


class ViewerLock:
    def __init__(self, pyrender_viewer):
        self._pyrender_viewer = pyrender_viewer

    def __enter__(self):
        self._pyrender_viewer.render_lock.acquire()

    def __exit__(self, exc_type, exc_value, traceback):
        self._pyrender_viewer.render_lock.release()


class DummyViewerLock:
    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_value, traceback):
        pass


[文档]class Viewer(RBC): def __init__(self, options, context): self._res = options.res self._refresh_rate = options.refresh_rate self._max_FPS = options.max_FPS self._camera_init_pos = options.camera_pos self._camera_init_lookat = options.camera_lookat self._camera_up = options.camera_up self._camera_fov = options.camera_fov self.context = context if self._max_FPS is not None: self.rate = Rate(self._max_FPS)
[文档] def build(self, scene): self.scene = scene # set viewer camera self.setup_camera() # viewer if gs.platform == "Linux": run_in_thread = True auto_start = True elif gs.platform == "macOS": run_in_thread = False auto_start = False gs.logger.warning( "Non-linux system detected. In order to use the interactive viewer, you need to manually run simulation in a separate thread and then start viewer. See `examples/render_on_macos.py`." ) elif gs.platform == "Windows": run_in_thread = False auto_start = False gs.raise_exception("Viewer has some issues on Windows. Can anyone help?") self._pyrender_viewer = pyrender.Viewer( context=self.context, viewport_size=self._res, run_in_thread=run_in_thread, auto_start=auto_start, view_center=self._camera_init_lookat, shadow=self.context.shadow, plane_reflection=self.context.plane_reflection, viewer_flags={ "window_title": f"Genesis {gs.__version__}", "refresh_rate": self._refresh_rate, }, ) if auto_start: self._pyrender_viewer.wait_until_initialized() self.lock = ViewerLock(self._pyrender_viewer) gs.logger.info(f"Viewer created. Resolution: ~<{self._res[0]}×{self._res[1]}>~, max_FPS: ~<{self._max_FPS}>~.")
[文档] def start(self): # used for starting viewer thread in non-linux OS self._pyrender_viewer.start()
[文档] def stop(self): # used for closing viewer thread in non-linux OS self._pyrender_viewer.close_external()
[文档] def is_alive(self): return self._pyrender_viewer.is_active
[文档] def setup_camera(self): pos = np.array(self._camera_init_pos) up = np.array(self._camera_up) lookat = np.array(self._camera_init_lookat) yfov = self._camera_fov / 180.0 * np.pi z = pos - lookat R = gu.z_up_to_R(z, up=up) pose = gu.trans_R_to_T(pos, R) self._camera_node = self.context.add_node(pyrender.PerspectiveCamera(yfov=yfov), pose=pose)
[文档] def update(self): with self.lock: buffer_updates = self.context.update() for buffer_id, buffer_data in buffer_updates.items(): self._pyrender_viewer.pending_buffer_updates[buffer_id] = buffer_data # lock FPS if self._max_FPS is not None: self.rate.sleep()
[文档] def set_camera_pose(self, pose=None, pos=None, lookat=None): """ Set viewer camera pose. Parameters ---------- pose : [4,4] float, optional Camera-to-world pose. If provided, `pos` and `lookat` will be ignored. pos : (3,) float, optional Camera position. lookat : (3,) float, optional Camera lookat point. """ if pose is None: if pos is None: pos = np.array(self._camera_init_pos) else: pos = np.array(pos) if lookat is None: lookat = np.array(self._camera_init_lookat) else: lookat = np.array(lookat) up = np.array(self._camera_up) z = pos - lookat R = gu.z_up_to_R(z, up=up) pose = gu.trans_R_to_T(pos, R) else: if np.array(pose).shape != (4, 4): gs.raise_exception("pose should be a 4x4 matrix.") self._pyrender_viewer._trackball.set_camera_pose(pose)
# ------------------------------------------------------------------------------------ # ----------------------------------- properties ------------------------------------- # ------------------------------------------------------------------------------------ @property def res(self): return self._res @property def refresh_rate(self): return self._refresh_rate @property def max_FPS(self): return self._max_FPS @property def camera_pos(self): """ Get the camera's current position. """ return np.array(self._pyrender_viewer._trackball._n_pose[:3, 3]) @property def camera_lookat(self): """ Get the camera's current lookat point. """ pos = np.array(self._pyrender_viewer._trackball._n_pose[:3, 3]) z = self._pyrender_viewer._trackball._n_pose[:3, 2] return pos - z @property def camera_pose(self): """ Get the camera's current pose represented by a 4x4 matrix. """ return np.array(self._pyrender_viewer._trackball._n_pose) @property def camera_up(self): return self._camera_up @property def camera_fov(self): return self._camera_fov