交互式 GUI 与调试#

Genesis World 提供三种工具来理解场景正在做什么:在 Python shell 中交互式检查任意对象、直接把调试几何体绘制到查看器中,以及用查看器内的 GUI 面板手动驱动仿真。在搭建场景原型、排查位置放错的实体,或者检查某个坐标系、接触点又不想写绘图脚本时,都可以用它们。

本页有两个可运行示例作为支撑:

  • interactive_debugging.py 会把你带入 IPython shell,以检查已构建的场景。

  • draw_debug.py 把盒子、线段、箭头、球体和坐标系绘制到查看器中,然后再清除它们。

交互式检查对象#

每个 Genesis World 类都实现了 __repr__,会打印其类型、状态和可用属性,并带有格式和配色。与其猜测对象的字段或去读源码,不如在构建场景后进入交互式 shell,输入对象名称即可。这在 IPython、pdb、ipdb 或普通 Python shell 中都有效。

示例构建了一个最小场景,并把控制权交给 IPython:

import genesis as gs

gs.init()

scene = gs.Scene(show_viewer=False)

plane = scene.add_entity(gs.morphs.Plane())
franka = scene.add_entity(
    gs.morphs.MJCF(file="xml/franka_emika_panda/panda.xml"),
)

cam_0 = scene.add_camera()
scene.build()

# enter IPython's interactive mode
import IPython

IPython.embed()

直接运行脚本(先用 pip install ipython 安装 IPython),或把除最后一行之外的内容粘贴到已有的 IPython 会话中。接下来就可以从顶层开始逐层浏览场景。

输入 scene 查看场景中包含的内容:

gs.Scene 的 IPython repr,显示 is_built、dt、uid 和 solvers 等属性

第一行显示对象的类型(<gs.Scene>)。其下是可读的属性:is_built 为 True,时间步 dt 为 0.01 s,uid 是场景的唯一 ID,solvers 是物理求解器列表。可以继续深入查看任意属性。scene.solvers 是一个 gs.List,渲染方式相同:

scene.solvers 的 IPython repr,以 gs.List 形式呈现物理求解器

实体也是如此。检查 Franka 机械臂可以看到它的 geoms 和连杆:

Franka 实体的 IPython repr,显示其 geoms 和连杆

用 franka.links[0] 再深入一层:

单个连杆的 IPython repr,显示 geoms、vgeoms、inertial_mass、idx、entity 和 joint

一个连杆会暴露其碰撞 geom(geoms)、视觉 geom(vgeoms)、inertial_mass、它在场景中的全局索引(idx)、所属的 entity 以及它的 joint。

绘制调试几何体#

当 shell 里的数字不够用时,可以把几何体绘制到查看器中。scene.draw_debug_* 方法将图元直接渲染到场景里,让你看到目标位姿、包围盒或坐标系究竟落在哪里。它们仅用于可视化,不参与物理计算。

请在 scene.build() 之后调用,且场景需要有查看器或相机可供渲染。每次调用都会返回一个句柄,保存它并在之后传回即可移除该对象。

# Axis-aligned wireframe box, bounds in meters (Z-up)
debug_box = scene.draw_debug_box(
    bounds=[[-0.25, -0.25, 0], [0.25, 0.25, 0.5]],  # [[min], [max]]
    color=(1, 0, 1, 1),  # RGBA, magenta
    wireframe=True,
    wireframe_radius=0.005,
)

# Line segment between two points
debug_line = scene.draw_debug_line(start=(0.5, -0.25, 0.5), end=(0.5, 0.25, 0.5), radius=0.01, color=(1, 0, 0, 1))

# Arrow from pos along vec
debug_arrow = scene.draw_debug_arrow(pos=(1, 0, 0), vec=(0, 0, 1), radius=0.02, color=(1, 0, 0, 0.5))

# Single sphere and a batch of spheres
debug_sphere = scene.draw_debug_sphere(pos=(1.5, 0, 0.5), radius=0.1, color=(0, 0, 1, 0.5))
sphere_positions = np.array([[2, 0, 0.3], [2, 0, 0.5], [2, 0, 0.7]])
debug_spheres = scene.draw_debug_spheres(poss=sphere_positions, radius=0.05, color=(1, 1, 0, 0.5))

颜色为 [0, 1] 范围内的 RGBA,第四个通道是 alpha。要绘制坐标系,传入 4x4 变换矩阵。当 color=None 时,三个轴使用标准的红/绿/蓝配色:

T = np.eye(4)
T[:3, 3] = [2.5, 0, 0.5]  # translation, meters (Z-up)
debug_frame = scene.draw_debug_frame(T=T, axis_length=0.5, origin_size=0.03, axis_radius=0.02)

调试几何体会在步进之间持续存在,直到你将其移除。可以用句柄清除单个对象,或一次性清除全部:

scene.clear_debug_object(debug_box)  # remove a single object by handle
scene.clear_debug_objects()          # remove all remaining debug objects

可用的图元如下:

方法

绘制内容

关键参数

draw_debug_line

一条线段

start、end、radius、color

draw_debug_arrow

从某点沿向量方向的箭头

pos、vec、radius、color

draw_debug_sphere / draw_debug_spheres

一个或多个球体

pos / poss、radius、color

draw_debug_box

轴对齐的盒子

bounds、color、wireframe、wireframe_radius

draw_debug_frame / draw_debug_frames

一个或多个坐标系

T / Ts、axis_length、origin_size、axis_radius

完整的签名和默认值见 场景。

场景自行绘制的标记展示的是上一步计算的结果:visualize_contact 的接触箭头,以及用 draw_debug=True 创建的传感器的标记。它们在查看器每次刷新时都会重新绘制。像 entity.set_pos(...) 这样移动场景的 setter,会在其涉及的环境中隐藏这些标记,直到下一步,因为它们展示的接触和传感器读数属于之前的位姿。

交互式 GUI 面板#

ImGui 叠加层在查看器之上添加一个 Dear ImGui 面板,让你无需修改代码即可驱动仿真。它提供:

  • 仿真控制:播放、暂停、单步和重置。

  • 实体浏览器,包含每个自由度的关节滑块、自由关节的四元数分组,以及可视化模式开关(视觉、碰撞、线框)。

  • 相机位置和注视点滑块,以及阴影、坐标系和视锥可见性开关。

  • 场景重建按钮,会用当前实体重新运行 scene.build(),便于在不重启脚本的情况下迭代 URDF 和 MJCF。

Note

该叠加层随 Genesis World 的 render extras 一起提供。启用 GUI 之前请先安装:

pip install "genesis-world[render]"

如果你的 Python 和操作系统组合没有预编译的 imgui-bundle wheel(例如 Linux aarch64 上的 Python 3.10),请改用 pip install imgui-bundle 安装,它会从源码构建并需要 CMake。在缺少该依赖的情况下启用 GUI 会抛出错误,并指回到这一步。

获取面板最简单的方式是在 ViewerOptions 上设置 enable_gui=True。查看器会自动挂载叠加层,并让它在内部管理场景编辑,因此一个普通的 gs.Scene 就是全部设置:

scene = gs.Scene(
    viewer_options=gs.options.ViewerOptions(
        camera_pos=(2.0, 2.0, 1.5),
        camera_lookat=(0.0, 0.0, 0.5),
        enable_gui=True,
    ),
    show_viewer=True,
)

启用 enable_gui=True 后,查看器会关闭帮助文本叠加层和默认键盘控制,因为 ImGui 会捕获输入,否则这些输入会与那些按键绑定冲突。

要添加你自己的控件,获取自动挂载的插件并注册一个面板。回调会收到实时的 ImGui 模块,因此你可以调用它的任意控件:

from genesis.ext.pyrender.overlay import ImGuiOverlayPlugin

plugin = next(p for p in scene.viewer.plugins if isinstance(p, ImGuiOverlayPlugin))


def custom_panel(imgui):
    imgui.text("Custom Demo Panel")
    imgui.text("This panel was registered via register_panel()")


plugin.register_panel(custom_panel)

完整示例见 imgui_joint_control.py。它加载一个 Franka 机械臂和一个盒子,演示实体浏览器、仿真控制、场景重建以及自定义面板。

另请参阅#