From 32f64ee7b946bc78a57bea67dcb1001bacddea19 Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Fri, 4 Sep 2026 21:19:02 +0000 Subject: [PATCH] Tune quickstart capture framing and downsampling for documentation media The quickstart GIFs rendered the OVRTX path tracer straight to their 320x240 publication size, so robot silhouettes and shadow edges aliased badly, and the per-task focal lengths left the subject occupying a small part of the frame with a large empty floor area around it. Capture at 1280x960 and let the generator downsample with lanczos, which resolves the detail that rendering directly to the final size destroyed. Tighten the focal lengths per task to the largest value that keeps the subject inside the published crop. The safe value is scene-specific rather than a fixed ratio: Cartpole clips its pole above 21, and Kuka Allegro is held at 24 because its lift policy raises the arm above the pose a zero action holds. Ease the denoiser from 2:2:6:6 to 1:1:3:3 now that supersampling rather than blurring removes the path-tracer noise, and widen the GIF palette from 128 to 256 colors with sierra2_4a dithering to avoid banding on the smoother gradients. --- tools/docs/media/capture_quickstart.py | 25 +++++++++++++++++-------- tools/docs/media/generate_quickstart.sh | 20 ++++++++++---------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/tools/docs/media/capture_quickstart.py b/tools/docs/media/capture_quickstart.py index 8e10677341b3..2b405c257c93 100644 --- a/tools/docs/media/capture_quickstart.py +++ b/tools/docs/media/capture_quickstart.py @@ -29,6 +29,8 @@ from isaaclab_tasks.core.velocity.config.g1.flat_env_cfg import G1FlatEnvCfg from isaaclab_tasks.utils import resolve_task_config, setup_preset_cli +# Focal lengths are tuned per task to the tightest framing that still keeps the subject inside the +# published crop; the safe value differs per scene, so they are not a fixed ratio of one another. _TASK_CONFIGS = { "Isaac-Cartpole": "capture_quickstart:CartpoleCaptureCfg", "Isaac-Lift-KukaAllegro": "capture_quickstart:KukaAllegroCaptureCfg", @@ -43,7 +45,7 @@ class CartpoleCaptureCfg(CartpoleEnvCfg): def __post_init__(self): super().__post_init__() - _configure_capture(self, focal_length=18.0) + _configure_capture(self, focal_length=21.0) @configclass @@ -52,7 +54,7 @@ class G1FlatCaptureCfg(G1FlatEnvCfg): def __post_init__(self): super().__post_init__() - _configure_capture(self, focal_length=20.0) + _configure_capture(self, focal_length=29.0) @configclass @@ -61,7 +63,9 @@ class KukaAllegroCaptureCfg(KukaAllegroLiftEnvCfg): def __post_init__(self): super().__post_init__() - _configure_capture(self, focal_length=22.0) + # Held to 24 rather than the tighter framing the other tasks take: the lift policy raises + # the arm well above the pose a zero action holds, and 26 already leaves little headroom. + _configure_capture(self, focal_length=24.0) @configclass @@ -70,7 +74,7 @@ class FrankaCabinetCaptureCfg(FrankaCabinetEnvCfg): def __post_init__(self): super().__post_init__() - _configure_capture(self, focal_length=22.0) + _configure_capture(self, focal_length=32.0) def configure_playback() -> list[str]: @@ -97,7 +101,7 @@ def main(): env_cfg, _ = resolve_task_config(args.task, "", play_mode=True) env_cfg.scene.num_envs = 1 env_cfg.seed = 42 - _configure_resolved_sim(env_cfg.sim, focal_length=22.0) + _configure_resolved_sim(env_cfg.sim, focal_length=32.0) env_cfg.video_recorders = [ VideoRecorderCfg( source="visualizer:newton_rtx", @@ -144,15 +148,20 @@ def _configure_capture(env_cfg: object, focal_length: float): def _configure_resolved_sim(sim_cfg: SimulationCfg, focal_length: float): - """Attach a headless 320 by 240 OVRTX visualizer to a simulation config.""" + """Attach a headless 1280 by 960 OVRTX visualizer to a simulation config. + + Captures at four times the 320 by 240 publication size so the generator can downsample the + path-traced frames, which resolves robot silhouettes and shadow edges that alias away when + the path tracer renders straight to the final size. + """ default_camera = sim_cfg.default_visualizer_cfg or VisualizerCfg() sim_cfg.visualizer_cfgs = [ NewtonRTXVisualizerCfg( eye=default_camera.eye, lookat=default_camera.lookat, focal_length=focal_length, - window_width=320, - window_height=240, + window_width=1280, + window_height=960, headless=True, rtx_environment="default", render_settings={"omni:rtx:quality": ("Int", 100)}, diff --git a/tools/docs/media/generate_quickstart.sh b/tools/docs/media/generate_quickstart.sh index 8bbb3d5ba616..3ce7542dfda1 100755 --- a/tools/docs/media/generate_quickstart.sh +++ b/tools/docs/media/generate_quickstart.sh @@ -75,12 +75,12 @@ ffmpeg -y -v error \ -i "${WORK_DIR}/random/random_0000.mp4" \ -i "${WORK_DIR}/play/play_0000.mp4" \ -filter_complex \ - "[0:v]select='not(mod(n,5))',setpts=N/(12*TB),hqdn3d=2:2:6:6,drawbox=x=8:y=8:w=112:h=28:color=black@0.65:t=fill,drawtext=font='DejaVu Sans':text='zero_agent':fontcolor=white:fontsize=16:x=16:y=13[zero]; - [1:v]select='not(mod(n,5))',setpts=N/(12*TB),hqdn3d=2:2:6:6,drawbox=x=8:y=8:w=134:h=28:color=black@0.65:t=fill,drawtext=font='DejaVu Sans':text='random_agent':fontcolor=white:fontsize=16:x=16:y=13[random]; - [2:v]select='not(mod(n,5))',setpts=N/(12*TB),hqdn3d=2:2:6:6,drawbox=x=8:y=8:w=58:h=28:color=black@0.65:t=fill,drawtext=font='DejaVu Sans':text='play':fontcolor=white:fontsize=16:x=16:y=13[play]; + "[0:v]select='not(mod(n,5))',setpts=N/(12*TB),scale=320:240:flags=lanczos,hqdn3d=1:1:3:3,drawbox=x=8:y=8:w=112:h=28:color=black@0.65:t=fill,drawtext=font='DejaVu Sans':text='zero_agent':fontcolor=white:fontsize=16:x=16:y=13[zero]; + [1:v]select='not(mod(n,5))',setpts=N/(12*TB),scale=320:240:flags=lanczos,hqdn3d=1:1:3:3,drawbox=x=8:y=8:w=134:h=28:color=black@0.65:t=fill,drawtext=font='DejaVu Sans':text='random_agent':fontcolor=white:fontsize=16:x=16:y=13[random]; + [2:v]select='not(mod(n,5))',setpts=N/(12*TB),scale=320:240:flags=lanczos,hqdn3d=1:1:3:3,drawbox=x=8:y=8:w=58:h=28:color=black@0.65:t=fill,drawtext=font='DejaVu Sans':text='play':fontcolor=white:fontsize=16:x=16:y=13[play]; [zero][random][play]hstack=inputs=3,split[frames][palette_frames]; - [palette_frames]palettegen=max_colors=128:stats_mode=diff[palette]; - [frames][palette]paletteuse=dither=bayer:bayer_scale=4:diff_mode=rectangle" \ + [palette_frames]palettegen=max_colors=256:stats_mode=diff[palette]; + [frames][palette]paletteuse=dither=sierra2_4a:diff_mode=rectangle" \ -loop 0 "${OUTPUT_DIR}/agent-comparison.gif" ffmpeg -y -v error \ @@ -88,12 +88,12 @@ ffmpeg -y -v error \ -i "${WORK_DIR}/g1/g1_0000.mp4" \ -i "${WORK_DIR}/kuka_allegro/kuka_allegro_0000.mp4" \ -filter_complex \ - "[0:v]crop=320:180:0:30,select='not(mod(n,5))',setpts=N/(12*TB),hqdn3d=2:2:6:6,drawbox=x=8:y=8:w=82:h=28:color=black@0.65:t=fill,drawtext=font='DejaVu Sans':text='Cartpole':fontcolor=white:fontsize=16:x=16:y=13[cartpole]; - [1:v]crop=320:180:0:30,select='not(mod(n,5))',setpts=N/(12*TB),hqdn3d=2:2:6:6,drawbox=x=8:y=8:w=128:h=28:color=black@0.65:t=fill,drawtext=font='DejaVu Sans':text='G1 locomotion':fontcolor=white:fontsize=16:x=16:y=13[g1]; - [2:v]crop=320:180:0:30,select='not(mod(n,5))',setpts=N/(12*TB),hqdn3d=2:2:6:6,drawbox=x=8:y=8:w=116:h=28:color=black@0.65:t=fill,drawtext=font='DejaVu Sans':text='Kuka Allegro':fontcolor=white:fontsize=16:x=16:y=13[kuka]; + "[0:v]crop=1280:720:0:120,select='not(mod(n,5))',setpts=N/(12*TB),scale=320:180:flags=lanczos,hqdn3d=1:1:3:3,drawbox=x=8:y=8:w=82:h=28:color=black@0.65:t=fill,drawtext=font='DejaVu Sans':text='Cartpole':fontcolor=white:fontsize=16:x=16:y=13[cartpole]; + [1:v]crop=1280:720:0:120,select='not(mod(n,5))',setpts=N/(12*TB),scale=320:180:flags=lanczos,hqdn3d=1:1:3:3,drawbox=x=8:y=8:w=128:h=28:color=black@0.65:t=fill,drawtext=font='DejaVu Sans':text='G1 locomotion':fontcolor=white:fontsize=16:x=16:y=13[g1]; + [2:v]crop=1280:720:0:120,select='not(mod(n,5))',setpts=N/(12*TB),scale=320:180:flags=lanczos,hqdn3d=1:1:3:3,drawbox=x=8:y=8:w=116:h=28:color=black@0.65:t=fill,drawtext=font='DejaVu Sans':text='Kuka Allegro':fontcolor=white:fontsize=16:x=16:y=13[kuka]; [cartpole][g1][kuka]hstack=inputs=3,split[frames][palette_frames]; - [palette_frames]palettegen=max_colors=128:stats_mode=diff[palette]; - [frames][palette]paletteuse=dither=bayer:bayer_scale=4:diff_mode=rectangle" \ + [palette_frames]palettegen=max_colors=256:stats_mode=diff[palette]; + [frames][palette]paletteuse=dither=sierra2_4a:diff_mode=rectangle" \ -loop 0 "${OUTPUT_DIR}/task-sampler.gif" for output in agent-comparison.gif task-sampler.gif; do