相机传感器#
相机传感器在离屏状态下把场景渲染成 RGB 图像,并通过传感器流水线返回,全程不涉及查看器窗口。用 scene.add_sensor(...) 添加一个,推进仿真,然后调用 read() 就能以张量形式拿回像素。它是一个完整的 传感器:在 read() 时惰性渲染,接入 scene.read_sensors() 的批量读取路径,并且像其他传感器一样挂载到运动的连杆上。
Genesis World 还有另外两种观察场景的方式:
查看器(
show_viewer=True)是人眼观看的交互窗口。它实时渲染,但不向你的代码返回任何内容。参见 可视化。可视化相机(
scene.add_camera().render(...))按需渲染颜色、深度、分割和表面法线图像,并可通过start_recording()录制视频。当你需要这四种通道或场景视频时使用它。参见 渲染。
完整脚本见 examples/sensors/camera_as_sensor.py。
最小示例#
import genesis as gs
gs.init(backend=gs.gpu)
scene = gs.Scene(show_viewer=False)
scene.add_entity(gs.morphs.Plane())
scene.add_entity(gs.morphs.Sphere(radius=0.5, pos=(0.0, 0.0, 2.0)))
camera = scene.add_sensor(
gs.sensors.RasterizerCameraOptions(
res=(500, 600), # (width, height), pixels
pos=(3.0, 0.0, 2.0), # world frame when unattached, meters
lookat=(0.0, 0.0, 1.0),
fov=60.0, # vertical field of view, degrees
),
)
scene.build()
scene.step()
data = camera.read()
print(data.rgb.shape) # (600, 500, 3) - (H, W, 3), H and W from res=(W, H)
add_sensor 返回传感器对象;请通过它而不是全局句柄来操作相机。默认渲染器是光栅化器,因此在任何平台上都无需额外配置即可运行。
read() 返回什么#
read() 会在当前场景状态过期时先渲染,然后返回 CameraReturnType,这是一个仅含颜色图像字段的 NamedTuple:
data = camera.read()
rgb = data.rgb # shape ([n_envs,] H, W, 3), dtype uint8, values 0-255
图像形状为 (H, W, 3),其中 H = res[1]、W = res[0]:res 是 (width, height),而数组按行主序为 (height, width),以符合 NumPy 的图像惯例。只有当场景在构建时包含环境(scene.build(n_envs=...))才会出现前导的 n_envs 轴;未批处理的 scene.build() 会去掉它。
传入 envs_idx 可读取部分环境:
data = camera.read(envs_idx=[0, 2])
print(data.rgb.shape) # (2, H, W, 3)
示例用 matplotlib 保存每一帧;read() 返回的是 GPU 张量,因此要先转换:
from genesis.utils.misc import tensor_to_array
data = camera.read()
rgb = data.rgb[0] if data.rgb.ndim > 3 else data.rgb # drop the env axis if present
plt.imsave("frame.png", tensor_to_array(rgb))
渲染后端#
三种后端都能渲染 RGB。它们共用下面的通用选项,在速度、保真度和平台支持上有所不同:
选项类 |
后端 |
环境 |
最适合 |
|---|---|---|---|
OpenGL |
串行 |
在任意平台上快速实时渲染 |
|
LuisaRender |
单环境 |
照片级离线渲染 |
|
Madrona(GPU) |
并行 |
高吞吐 RL 训练(仅 CUDA) |
通过选择对应的选项类来选定后端。光栅化器和批渲染器会据此自行完成设置,而光线追踪相机还需要在场景上设置其渲染器 gs.Scene(renderer=gs.renderers.RayTracer(...)),否则会在构建时报错。若需要照片级的路径追踪,建议使用 Nyx 渲染器 中介绍的 Nyx 渲染器。
通用参数(所有后端):
gs.sensors.RasterizerCameraOptions(
res=(512, 512), # (width, height), pixels
pos=(3.5, 0.0, 1.5), # camera position; link-relative when attached
lookat=(0.0, 0.0, 0.0),
up=(0.0, 0.0, 1.0),
fov=60.0, # vertical field of view, degrees
lights=[], # per-camera lights, backend-specific dicts
)
后端专用选项包括 near / far 裁剪平面(光栅化器和批渲染器,单位米)、model / spp / denoise 以及薄透镜景深控制(光线追踪器),还有 use_rasterizer(批渲染器)。完整列表和默认值参见 genesis/options/sensors/camera.py 中的选项类。
将相机挂载到连杆#
设置 entity_idx(以及可选的 link_idx_local)即可把相机挂载到实体上。相机随后每步跟随该连杆的运动,因此 read() 始终从当前位姿渲染:
camera = scene.add_sensor(
gs.sensors.RasterizerCameraOptions(
res=(500, 600),
pos=(0.0, 0.0, 1.0), # relative to the link frame once attached
lookat=(0.0, 0.0, 0.0),
fov=70.0,
entity_idx=robot.idx, # -1 or None for a static, world-fixed camera
link_idx_local=0, # which link of the entity to mount on
),
)
若需要相对连杆固定的挂载变换,传入 offset_T,即 4×4 齐次矩阵。一旦提供,它的优先级高于 pos_offset / euler_offset:
import numpy as np
gs.sensors.RasterizerCameraOptions(
# ... res, fov, entity_idx, link_idx_local as above ...
offset_T=np.eye(4), # camera pose relative to the attached link
)
多环境#
使用 n_envs 构建可一次渲染所有环境。批渲染器在 GPU 上并行运行它们;光栅化器则串行渲染:
scene.build(n_envs=4)
scene.step()
data = camera.read()
print(data.rgb.shape) # (4, H, W, 3)
Note
场景中所有 BatchRendererCameraOptions 相机必须使用相同的分辨率。
注意事项与常见陷阱#
Note
相机传感器只返回 RGB。 read() 只返回颜色图像,不含其他内容。若需要深度、分割掩码或表面法线,请使用可视化相机的 render() 方法(参见 渲染),或针对深度使用 深度相机光线投射传感器。
Warning
相机传感器不支持 history_length。它们在 read() 时惰性渲染,并绕过支撑历史缓冲区的共享传感器缓存,因此设置该项会在构造时报错。请改为每步读取一次。