OMPE-88188: Add frame stacking support for explicit temporal info#5574
OMPE-88188: Add frame stacking support for explicit temporal info#5574jmart-nv wants to merge 3 commits into
Conversation
- Added `FrameStackBuffer` helper class which implements a ring buffer over the last N rendered frames. - Hooked up frame stacking in cartpole camera cfg which defaults to 2 for newton+warp and 1 for all other combos, with cli override. - Updated renderer docs to mention newton dependency on temporal information. - Added new unit tests for the buffer and cartpole integration.
Greptile SummaryThis PR introduces a
Confidence Score: 4/5Safe to merge with minor follow-up; the core ring-buffer logic is correct and well-tested, and the env wiring works for the current usage pattern. The ring-buffer arithmetic, init-on-reset behavior, and env integration are all verified by a thorough test suite. The main concerns are design-level: cfg.observation_space[-1] is mutated in-place before the parent constructor runs (safe only if configclass always deep-copies), update() returns shared internal storage that callers must clone (current code does so correctly), and the frame_stack=0 sentinel could be misread by users as disabled rather than auto-detect. None of these affect correctness in the current code paths, but they introduce fragility for future callers and config overrides. cartpole_camera_presets_env.py and cartpole_camera_presets_env_cfg.py deserve a second look — the in-place cfg mutation and the sentinel value design are the most likely sources of hard-to-diagnose bugs if the config machinery or user overrides change. Important Files Changed
Sequence DiagramsequenceDiagram
participant Env as CartpoleCameraPresetsEnv
participant Base as CartpoleCameraEnv
participant Buf as FrameStackBuffer
Note over Env: __init__
Env->>Env: resolve_cfg_presets(cfg)
Env->>Env: _resolve_frame_stack_default() → 1 or 2
Env->>Env: "bump cfg.observation_space[-1] *= frame_stack"
Env->>Base: super().__init__(cfg)
Env->>Buf: FrameStackBuffer(single_shape, frame_stack, device)
Note over Env: per-step loop
Env->>Base: super()._get_observations()
Base-->>Env: obs[policy] shape (N,H,W,C)
Env->>Buf: update(obs[policy])
Buf->>Buf: fill history slots for reset envs (init path)
Buf->>Buf: copy current frame into _history[frame_idx]
Buf->>Buf: rebuild _stacked via narrow+copy_
Buf-->>Env: "_stacked (N,H,W,C*K) shared ref"
Env->>Env: .clone() → obs[policy]
Note over Env: on episode reset
Env->>Base: super()._reset_idx(env_ids)
Env->>Buf: reset(env_ids) marks envs for init
Note over Buf: next update() fills all history slots with first post-reset frame
Reviews (1): Last reviewed commit: "OMPE-88188: Add frame stacking support f..." | Re-trigger Greptile |
- Update reset API to accept sequence of ints or torch tensor. - Changed frame_stack default sentinel to `-1` to better communicate intent; `0` is now treated as "no stacking" (synonym for `1`.) - Cleaned up observation space logic to avoid in-place mutation. - Updated tests.
There was a problem hiding this comment.
Code Review: Frame Stacking for Temporal Observations
This PR adds a well-designed FrameStackBuffer utility and integrates it into the cartpole camera presets task. The implementation addresses a real need—providing explicit temporal information for Newton+Warp where implicit temporal data isn't available. Overall structure is clean, but I found a few issues worth addressing.
Summary
Strengths:
- Ring buffer design avoids per-frame allocations
- Auto-detection of Newton+Warp combo is convenient
- Comprehensive unit tests for the buffer itself
- Good documentation of the temporal info requirement
Areas for improvement: See inline comments below.
- Added assertion for contiguity of frame stack buffer. - Added new test for ring buffer shifting behavior.
|
|
||
| .. note:: | ||
|
|
||
| **Temporal information for camera-based RL.** Unlike RTX modes with temporal |
There was a problem hiding this comment.
I think this would be better placed for https://isaac-sim.github.io/IsaacLab/develop/source/overview/core-concepts/renderers.html since it's a general note around the renderer behavior difference.
| import torch | ||
|
|
||
|
|
||
| class FrameStackBuffer: |
There was a problem hiding this comment.
I think we can avoid a FrameStackBuffer class all together and use the existing CircularBuffer implementation instead.
This can become:
- Add a
stacked_imageManagerTermBase in isaaclab/envs/mdp/observations.py so manager-based environments can reference this mdp in the environment config. - For the direct env cartpole task, use
CircularBufferdirectly in the task (keeping it task-local), but don't invent a new helper class for the ring buffer.
Description
This enables frame stacking for newton+warp by default in the cartpole camera presets task.
Newton Frame Stacking: Provides explicit temporal data to newton.
RTX uses DLSS anti-aliasing by default, which provides implicit temporal data. The newton_renderer does not provide temporal data. However, newton's energy-conserving physics solver requires temporal velocity data in order to compensate for the lack of damping, which causes convergence problems when paired with newton_renderer.
This commit provides explicit temporal information via 2-frame stacking by default for cartpole-camera when using newton+newton_renderer. This allows newton to provide the damping it needs to converge at the same rate as physx. This adds 36% GPU memory overhead, but the wall clock overhead is negligible.
The default for all other physics/renderer backends is still stack size = 1 (disabled) since physx has implicit damping built-in via its TGS solver, and RTX provides temporal data implicitly.
Implementation:
A new
FrameStackBufferhelper class implements a ring buffer of the last N rendered frames which can supply explicit temporal observations to a policy. Tasks can then instantiate this buffer on startup and update it each frame.Added new unit tests for the frame stack buffer and cartpole integration, and updated the documentation with a note about newton's dependency on temporal data.
Note: This is a task-local re-implementation of the closed PR #5232
Type of change
Checklist
pre-commitchecks with./isaaclab.sh --formatconfig/extension.tomlfileCONTRIBUTORS.mdor my name already exists there