URDF visualizer#
Requires yourdfpy and URDF. Any URDF supported by yourdfpy should work.
Examples:
1from __future__ import annotations
2
3import time
4from pathlib import Path
5from typing import List
6
7import numpy as onp
8import tyro
9import viser
10from viser.extras import ViserUrdf
11
12
13def main(urdf_path: Path) -> None:
14 server = viser.ViserServer()
15
16 # Create a helper for adding URDFs to Viser. This just adds meshes to the scene,
17 # helps us set the joint angles, etc.
18 urdf = ViserUrdf(server, urdf_path)
19
20 # Create joint angle sliders.
21 gui_joints: List[viser.GuiInputHandle[float]] = []
22 initial_angles: List[float] = []
23 for joint_name, (lower, upper) in urdf.get_actuated_joint_limits().items():
24 lower = lower if lower is not None else -onp.pi
25 upper = upper if upper is not None else onp.pi
26
27 initial_angle = 0.0 if lower < 0 and upper > 0 else (lower + upper) / 2.0
28 slider = server.add_gui_slider(
29 label=joint_name,
30 min=lower,
31 max=upper,
32 step=1e-3,
33 initial_value=initial_angle,
34 )
35 slider.on_update( # When sliders move, we update the URDF configuration.
36 lambda _: urdf.update_cfg(onp.array([gui.value for gui in gui_joints]))
37 )
38
39 gui_joints.append(slider)
40 initial_angles.append(initial_angle)
41
42 # Create joint reset button.
43 reset_button = server.add_gui_button("Reset")
44
45 @reset_button.on_click
46 def _(_):
47 for g, initial_angle in zip(gui_joints, initial_angles):
48 g.value = initial_angle
49
50 # Apply initial joint angles.
51 urdf.update_cfg(onp.array([gui.value for gui in gui_joints]))
52
53 while True:
54 time.sleep(10.0)
55
56
57if __name__ == "__main__":
58 tyro.cli(main)