Skip to content

Commit 2f2fb9b

Browse files
authored
Reduce viewer idle cpu (#753)
* Skip rendering in viewers when nothing changed PyrenderViewer and TrimeshSceneViewer re-rendered the scene on every refresh tick (e.g. 30 times per second) even when nothing had changed, keeping the CPU busy on a fully static view. Skip rendering entirely when self._redraw is False. Also force a redraw in TrimeshSceneViewer.save_image so the captured frame is freshly rendered rather than a potentially stale buffer. * Set default viewer update_interval back to 30Hz The default was lowered to 1Hz in #239 because rendering ran on every refresh tick, pushing idle CPU usage over 300%. Now that rendering is skipped when nothing changed, 30Hz no longer causes that, so restore the original 30Hz default for smooth interaction out of the box. * docs: update viewer update_interval default to 30Hz Reflect the new 1/30 default and note that the viewer only re-renders when the scene changes, so 30Hz no longer keeps the CPU busy on a static view.
1 parent b2bcbe1 commit 2f2fb9b

3 files changed

Lines changed: 22 additions & 13 deletions

File tree

docs/source/reference/viewers.rst

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ PyrenderViewer
7070
The viewer is initialized with specified resolution, update interval, and rendering flags. Key parameters include:
7171

7272
- ``resolution``: Window size (default: ``(640, 480)``)
73-
- ``update_interval``: Update frequency in seconds (default: ``1.0``)
73+
- ``update_interval``: Update frequency in seconds (default: ``1 / 30``, i.e. 30 Hz)
7474
- ``enable_collision_toggle``: Enable collision/visual mesh switching (default: ``True``)
7575
- ``title``: Window title (default: ``'scikit-robot PyrenderViewer'``)
7676

@@ -279,16 +279,17 @@ The following video demonstrates the interactive IK feature, where dragging the
279279
# Use viser viewer with visualize-urdf command (IK is enabled by default)
280280
skr visualize-urdf ~/.skrobot/pr2_description/pr2.urdf --viewer viser
281281
282-
.. caution::
282+
.. note::
283283

284-
To speed up the rendering cycle in **TrimeshSceneViewer** and **PyrenderViewer**, adjust the ``update_interval`` to the reciprocal of the desired frequency. For example, to achieve updates at 30 Hz, set the ``update_interval`` to 1/30. This change will increase the frequency at which the ``redraw()`` function is called, making the rendering process faster.
284+
Both **TrimeshSceneViewer** and **PyrenderViewer** update at 30 Hz by default (``update_interval=1/30``). The viewer only re-renders when the scene actually changes (e.g. after :func:`redraw`), so a static view stays cheap even at 30 Hz. The ``update_interval`` controls how often the ``redraw()`` request is polled: a smaller value gives a higher refresh rate (smoother interaction and animation) at the cost of more idle CPU, while a larger value lowers idle CPU usage.
285285

286286
Example usage:
287287

288288
.. code-block:: python
289289
290-
viewer = skrobot.viewers.TrimeshSceneViewer(resolution=(640, 480), update_interval=1.0/30) # Set update interval for 30 Hz
291-
viewer = skrobot.viewers.PyrenderViewer(resolution=(640, 480), update_interval=1.0/30) # Same for PyrenderViewer
290+
# 30 Hz is already the default; pass update_interval only to override it.
291+
viewer = skrobot.viewers.TrimeshSceneViewer(resolution=(640, 480), update_interval=1.0/30) # 30 Hz (default)
292+
viewer = skrobot.viewers.PyrenderViewer(resolution=(640, 480), update_interval=1.0) # 1 Hz, lower idle CPU
292293
293294
294295
Color Management

skrobot/viewers/_pyrender.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class PyrenderViewer(pyrender.Viewer):
9999
The resolution of the viewer. Default is (640, 480).
100100
update_interval : float, optional
101101
The update interval (in seconds) for the viewer. Default is
102-
1.0 seconds.
102+
1 / 30 seconds (30 Hz).
103103
title : str, optional
104104
The title of the viewer window. Default is 'scikit-robot PyrenderViewer'.
105105
enable_collision_toggle : bool, optional
@@ -123,7 +123,7 @@ class PyrenderViewer(pyrender.Viewer):
123123
# Class variable to hold the single instance of the class.
124124
_instance = None
125125

126-
def __init__(self, resolution=None, update_interval=1.0,
126+
def __init__(self, resolution=None, update_interval=1 / 30.0,
127127
render_flags=None, title=None, enable_collision_toggle=True):
128128
if getattr(self, '_initialized', False):
129129
return
@@ -279,7 +279,10 @@ def on_draw(self):
279279

280280
with self._render_lock:
281281
if not self._redraw:
282-
super(PyrenderViewer, self).on_draw()
282+
# Nothing changed since the last frame, so skip rendering
283+
# entirely. Without this, the scene is re-rendered on every
284+
# refresh tick (e.g. 30 times per second), which keeps the
285+
# CPU busy even when the view is completely static.
283286
return
284287
# apply latest angle-vector
285288
for link_id, (node, link) in self._visual_mesh_map.items():

skrobot/viewers/_trimesh.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class TrimeshSceneViewer(trimesh.viewer.SceneViewer):
5555
The resolution of the viewer. Default is (640, 480).
5656
update_interval : float, optional
5757
The update interval (in seconds) for the viewer. Default is
58-
1.0 seconds.
58+
1 / 30 seconds (30 Hz).
5959
title : str, optional
6060
The title of the viewer window. Default is 'scikit-robot TrimeshSceneViewer'.
6161
@@ -69,7 +69,7 @@ class TrimeshSceneViewer(trimesh.viewer.SceneViewer):
6969
_instance = None
7070
_version_warning_issued = False
7171

72-
def __init__(self, resolution=None, update_interval=1.0, title=None):
72+
def __init__(self, resolution=None, update_interval=1 / 30.0, title=None):
7373
if getattr(self, '_initialized', False):
7474
return
7575
if resolution is None:
@@ -145,9 +145,10 @@ def on_update(self, dt):
145145

146146
def on_draw(self):
147147
if not self._redraw:
148-
with self.lock:
149-
self._update_vertex_list()
150-
super(TrimeshSceneViewer, self).on_draw()
148+
# Nothing changed since the last frame, so skip rendering
149+
# entirely. Without this, the scene is re-rendered on every
150+
# refresh tick (e.g. 30 times per second), which keeps the
151+
# CPU busy even when the view is completely static.
151152
return
152153

153154
with self.lock:
@@ -263,6 +264,10 @@ def set_camera(self, *args, **kwargs):
263264
)
264265

265266
def save_image(self, file_obj):
267+
# Force a redraw so the freshly rendered frame is captured. on_draw
268+
# skips rendering when self._redraw is False, so without this the
269+
# buffer read back below could contain a stale frame.
270+
self._redraw = True
266271
self.switch_to()
267272
self.dispatch_events()
268273
self.dispatch_event('on_draw')

0 commit comments

Comments
 (0)