Skip to content

Commit

Permalink
0.2.6: update URDF helper + example docs
Browse files Browse the repository at this point in the history
  • Loading branch information
brentyi committed Aug 29, 2024
1 parent c6a1abe commit fa7d606
Show file tree
Hide file tree
Showing 31 changed files with 303 additions and 75 deletions.
1 change: 1 addition & 0 deletions docs/source/examples/01_image.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ NeRFs), or images to render as 3D textures.
import imageio.v3 as iio
import numpy as onp
import viser
Expand Down
1 change: 1 addition & 0 deletions docs/source/examples/02_gui.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Examples of basic GUI elements that we can create, read from, and write to.
import time
import numpy as onp
import viser
Expand Down
3 changes: 2 additions & 1 deletion docs/source/examples/03_gui_callbacks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ we get updates.
import time
import numpy as onp
import viser
from typing_extensions import assert_never
import viser
def main() -> None:
server = viser.ViserServer()
Expand Down
1 change: 1 addition & 0 deletions docs/source/examples/05_camera_commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ corresponding client automatically.
import time
import numpy as onp
import viser
import viser.transforms as tf
Expand Down
1 change: 1 addition & 0 deletions docs/source/examples/06_mesh.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Visualize a mesh. To get the demo data, see ``./assets/download_dragon_mesh.sh``
import numpy as onp
import trimesh
import viser
import viser.transforms as tf
Expand Down
3 changes: 2 additions & 1 deletion docs/source/examples/07_record3d_visualizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ Parse and stream record3d captures. To get the demo data, see ``./assets/downloa
import numpy as onp
import tyro
from tqdm.auto import tqdm
import viser
import viser.extras
import viser.transforms as tf
from tqdm.auto import tqdm
def main(
Expand Down
1 change: 1 addition & 0 deletions docs/source/examples/08_smpl_visualizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ See here for download instructions:
import numpy as np
import numpy as onp
import tyro
import viser
import viser.transforms as tf
Expand Down
102 changes: 74 additions & 28 deletions docs/source/examples/09_urdf_visualizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ and viser. It can also take a path to a local URDF file as input.
import time
import numpy as onp
import tyro
import viser
import yourdfpy
from robot_descriptions.loaders.yourdfpy import load_robot_description
import viser
from viser.extras import ViserUrdf
# A subset of robots available in the robot_descriptions package.
Expand All @@ -52,38 +53,67 @@ and viser. It can also take a path to a local URDF file as input.
)
def main() -> None:
# Start viser server.
server = viser.ViserServer()
# Logic for updating the visualized robot.
gui_joints: list[viser.GuiInputHandle[float]] = []
initial_angles: list[float] = []
def update_robot_model(robot_name: str) -> None:
server.scene.reset()
class ControllableViserRobot:
"""Helper class that creates a robot + GUI elements for controlling it."""
def __init__(
self,
urdf: yourdfpy.URDF,
server: viser.ViserServer,
):
loading_modal = server.gui.add_modal("Loading URDF...")
with loading_modal:
server.gui.add_markdown("See terminal for progress!")
# Create a helper for adding URDFs to Viser. This just adds meshes to the scene,
# helps us set the joint angles, etc.
urdf = ViserUrdf(
self._viser_urdf = ViserUrdf(
server,
# This can also be set to a path to a local URDF file.
urdf_or_path=load_robot_description(robot_name),
urdf_or_path=urdf,
)
loading_modal.close()
for gui_joint in gui_joints:
gui_joint.remove()
gui_joints.clear()
# Create sliders in GUI to control robot.
(
self._slider_handles,
self._initial_angles,
) = self._create_gui_elements(server, self._viser_urdf)
self.update_cfg(onp.array([slider.value for slider in self._slider_handles]))
def update_cfg(self, configuration: onp.ndarray) -> None:
"""Update the configuration, both the GUI handles and the visualized
robot."""
assert len(configuration) == len(self._slider_handles)
for i, slider in enumerate(self._slider_handles):
slider.value = configuration[i]
# self._viser_urdf.update_cfg(configuration)
def reset_joints(self) -> None:
"""Reset all of the joints."""
for g, initial_angle in zip(self._slider_handles, self._initial_angles):
g.value = initial_angle
for joint_name, (lower, upper) in urdf.get_actuated_joint_limits().items():
def remove(self) -> None:
"""Remove the URDF and all GUI elements."""
self._viser_urdf.remove()
for slider in self._slider_handles:
slider.remove()
@staticmethod
def _create_gui_elements(
server: viser.ViserServer, viser_urdf: ViserUrdf
) -> tuple[list[viser.GuiInputHandle[float]], list[float]]:
"""Crfeate slider for each joint of the robot."""
slider_handles: list[viser.GuiInputHandle[float]] = []
initial_angles: list[float] = []
for joint_name, (
lower,
upper,
) in viser_urdf.get_actuated_joint_limits().items():
lower = lower if lower is not None else -onp.pi
upper = upper if upper is not None else onp.pi
initial_angle = 0.0 if lower < 0 and upper > 0 else (lower + upper) / 2.0
slider = server.gui.add_slider(
label=joint_name,
Expand All @@ -93,29 +123,45 @@ and viser. It can also take a path to a local URDF file as input.
initial_value=initial_angle,
)
slider.on_update( # When sliders move, we update the URDF configuration.
lambda _: urdf.update_cfg(onp.array([gui.value for gui in gui_joints]))
lambda _: viser_urdf.update_cfg(
onp.array([slider.value for slider in slider_handles])
)
)
gui_joints.append(slider)
slider_handles.append(slider)
initial_angles.append(initial_angle)
return slider_handles, initial_angles
# Apply initial joint angles.
urdf.update_cfg(onp.array([gui.value for gui in gui_joints]))
def main() -> None:
# Start viser server.
server = viser.ViserServer()
# We use a dropdown to select the robot.
robot_model_name = server.gui.add_dropdown("Robot model", ROBOT_MODEL_LIST)
robot_model_name.on_update(lambda _: update_robot_model(robot_model_name.value))
robot = ControllableViserRobot(
load_robot_description(robot_model_name.value), server
)
# Remove the old robot and add a new one whenever the dropdown changes.
@robot_model_name.on_update
def _(_) -> None:
nonlocal robot
robot.remove()
robot = ControllableViserRobot(
load_robot_description(robot_model_name.value), server
)
# Create joint reset button.
reset_button = server.gui.add_button("Reset")
@reset_button.on_click
def _(_):
for g, initial_angle in zip(gui_joints, initial_angles):
g.value = initial_angle
robot.reset_joints()
# Sleep forever.
while True:
time.sleep(10.0)
if __name__ == "__main__":
tyro.cli(main)
main()
3 changes: 2 additions & 1 deletion docs/source/examples/10_realsense.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ pyrealsense2.
import numpy as np
import numpy.typing as npt
import pyrealsense2 as rs # type: ignore
import viser
from tqdm.auto import tqdm
import viser
@contextlib.contextmanager
def realsense_pipeline(fps: int = 30):
Expand Down
3 changes: 2 additions & 1 deletion docs/source/examples/11_colmap_visualizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ Visualize COLMAP sparse reconstruction outputs. To get demo data, see ``./assets
import imageio.v3 as iio
import numpy as onp
import tyro
from tqdm.auto import tqdm
import viser
import viser.transforms as tf
from tqdm.auto import tqdm
from viser.extras.colmap import (
read_cameras_binary,
read_images_binary,
Expand Down
1 change: 1 addition & 0 deletions docs/source/examples/12_click_meshes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Click on meshes to select them. The index of the last clicked mesh is displayed
import time
import matplotlib
import viser
Expand Down
2 changes: 1 addition & 1 deletion docs/source/examples/14_markdown.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.. Comment: this file is automatically generated by `update_example_docs.py`.
It should not be modified manually.
Markdown Demonstration
Markdown demonstration
==========================================


Expand Down
3 changes: 2 additions & 1 deletion docs/source/examples/15_gui_in_scene.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.. Comment: this file is automatically generated by `update_example_docs.py`.
It should not be modified manually.
3D GUI Elements
3D GUI elements
==========================================


Expand All @@ -19,6 +19,7 @@ performed on them.
from typing import Optional
import numpy as onp
import viser
import viser.transforms as tf
Expand Down
1 change: 1 addition & 0 deletions docs/source/examples/17_background_composite.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ be useful when we want a 2D image to occlude 3D geometry, such as for NeRF rende
import numpy as onp
import trimesh
import trimesh.creation
import viser
server = viser.ViserServer()
Expand Down
1 change: 1 addition & 0 deletions docs/source/examples/18_splines.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Make a ball with some random splines.
import time
import numpy as onp
import viser
Expand Down
3 changes: 2 additions & 1 deletion docs/source/examples/19_get_renders.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.. Comment: this file is automatically generated by `update_example_docs.py`.
It should not be modified manually.
Get Renders
Get renders
==========================================


Expand All @@ -17,6 +17,7 @@ Example for getting renders from a client's viewport to the Python API.
import imageio.v3 as iio
import numpy as onp
import viser
Expand Down
3 changes: 2 additions & 1 deletion docs/source/examples/20_scene_pointer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ To get the demo data, see ``./assets/download_dragon_mesh.sh``.
import trimesh
import trimesh.creation
import trimesh.ray
import viser
import viser.transforms as tf
from viser.theme import TitlebarConfig
Expand Down Expand Up @@ -81,7 +82,7 @@ To get the demo data, see ``./assets/download_dragon_mesh.sh``.
client.scene.remove_pointer_callback()
# Get the first hit position (based on distance from the ray origin).
hit_pos = min(hit_pos, key=lambda x: onp.linalg.norm(x - origin))
hit_pos = hit_pos[onp.argmin(onp.sum((hit_pos - origin) ** 2, axis=-1))]
# Create a sphere at the hit location.
hit_pos_mesh = trimesh.creation.icosphere(radius=0.1)
Expand Down
2 changes: 1 addition & 1 deletion docs/source/examples/21_set_up_direction.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.. Comment: this file is automatically generated by `update_example_docs.py`.
It should not be modified manually.
Set Up Direction
Set up direction
==========================================


Expand Down
3 changes: 2 additions & 1 deletion docs/source/examples/22_games.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ Some two-player games implemented using scene click events.
import numpy as onp
import trimesh.creation
from typing_extensions import assert_never
import viser
import viser.transforms as tf
from typing_extensions import assert_never
def main() -> None:
Expand Down
5 changes: 3 additions & 2 deletions docs/source/examples/23_plotly.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.. Comment: this file is automatically generated by `update_example_docs.py`.
It should not be modified manually.
Plotly.
Plotly
==========================================


Expand All @@ -18,9 +18,10 @@ Examples of visualizing plotly plots in Viser.
import numpy as onp
import plotly.express as px
import plotly.graph_objects as go
import viser
from PIL import Image
import viser
def create_sinusoidal_wave(t: float) -> go.Figure:
"""Create a sinusoidal wave plot, starting at time t."""
Expand Down
Loading

0 comments on commit fa7d606

Please sign in to comment.