[Task Clean-up] Dexterous Part 3/11: Add success-rate metrics to the reorientation Direct tasks#6413
[Task Clean-up] Dexterous Part 3/11: Add success-rate metrics to the reorientation Direct tasks#6413hujc7 wants to merge 5 commits into
Conversation
The Direct reorientation environments now log a behavioral Metrics/success_rate signal (goal-reach streaks per episode) and threshold-independent episode orientation-error diagnostics, per the Task Clean-up standard where success rate gates task health and reward stays diagnostic. Shared helpers land in isaaclab_tasks.core.utils. Also fixes hand resets that could initialize joints below their lower position limits. Validated by full training runs on PhysX, Newton, and OVPhysX; the Shadow Direct task reaches success-rate 1.0 on PhysX.
Greptile SummaryThis PR adds behavioral
Confidence Score: 4/5Safe to merge; all new behaviour is additive (metrics, diagnostics, safer resets) and the reward math is functionally unchanged from the original. The core reward logic, success tracking, and joint-reset fix are all correct. The two findings are cosmetic: an unreachable torch.abs() on a provably non-negative value, and a repeated quaternion-distance computation (up to three times per step) that produces identical results each time. Neither affects training correctness or runtime safety. reorient_direct_env.py and mdp/rewards.py are worth a second look for the redundant evaluate_reorient_success calls; no other files require special attention. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Env as ReorientDirectEnv
participant Dones as _get_dones()
participant Rewards as _get_rewards()
participant DRR as direct_reorient_reward()
participant Rec as EpisodeErrorRecorder
participant Reset as _reset_idx()
Env->>Dones: step()
Dones->>Dones: "evaluate_reorient_success() [if max_consecutive_success > 0]"
Dones-->>Env: (terminated, truncated)
Env->>Rewards: _get_rewards()
Rewards->>Rewards: evaluate_reorient_success() → orientation_error
Rewards->>Rec: update(orientation_error)
Rewards->>DRR: compute_rewards() → direct_reorient_reward()
DRR->>DRR: evaluate_reorient_success() [3rd call, same data]
DRR-->>Rewards: reward, goal_resets, successes, consecutive_successes
Rewards-->>Env: total_reward
Env->>Reset: _reset_idx(env_ids)
Reset->>Reset: "_last_episode_success = successes >= threshold"
Reset->>Rec: "reset(env_ids) → {mean, median, p90}"
Reset->>Reset: log Metrics/success_rate
Reset->>Reset: "log Diagnostics/episode_min_orientation_error_*"
Reset->>Reset: sample_joint_positions_within_limits()
Reset-->>Env: done
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Env as ReorientDirectEnv
participant Dones as _get_dones()
participant Rewards as _get_rewards()
participant DRR as direct_reorient_reward()
participant Rec as EpisodeErrorRecorder
participant Reset as _reset_idx()
Env->>Dones: step()
Dones->>Dones: "evaluate_reorient_success() [if max_consecutive_success > 0]"
Dones-->>Env: (terminated, truncated)
Env->>Rewards: _get_rewards()
Rewards->>Rewards: evaluate_reorient_success() → orientation_error
Rewards->>Rec: update(orientation_error)
Rewards->>DRR: compute_rewards() → direct_reorient_reward()
DRR->>DRR: evaluate_reorient_success() [3rd call, same data]
DRR-->>Rewards: reward, goal_resets, successes, consecutive_successes
Rewards-->>Env: total_reward
Env->>Reset: _reset_idx(env_ids)
Reset->>Reset: "_last_episode_success = successes >= threshold"
Reset->>Rec: "reset(env_ids) → {mean, median, p90}"
Reset->>Reset: log Metrics/success_rate
Reset->>Reset: "log Diagnostics/episode_min_orientation_error_*"
Reset->>Reset: sample_joint_positions_within_limits()
Reset-->>Env: done
|
| orientation_error = direct_reorient_rotation_distance(object_quat, target_quat) | ||
| return torch.abs(orientation_error) <= success_tolerance, orientation_error |
There was a problem hiding this comment.
torch.abs() is redundant here. direct_reorient_rotation_distance computes 2 * arcsin(clamp(norm, max=1)), where the clamped norm is in [0, 1] and arcsin returns [0, π/2], so the product is always in [0, π]. Applying torch.abs on a provably non-negative tensor is a no-op and slightly misleads readers into thinking the value could be negative.
| orientation_error = direct_reorient_rotation_distance(object_quat, target_quat) | |
| return torch.abs(orientation_error) <= success_tolerance, orientation_error | |
| orientation_error = direct_reorient_rotation_distance(object_quat, target_quat) | |
| return orientation_error <= success_tolerance, orientation_error |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
The shared general functions move from torch.jit.script to Warp kernels with signature-identical wrappers; randomized parity tests against the replaced torch implementation guard the numerics on CPU and CUDA. The Direct env's jit delegation shims lose their decorators (TorchScript cannot compile Warp launches).
The shared reward/success math moves to Warp kernels with parity tests against the previous torch implementation, and the task-defining constants (goal-marker position, fingertip names) move to a shared constants module consumed by the Direct cfg and, later, the manager counterparts.
The reward wrappers now require caller-owned output buffers so the hot loop allocates nothing per step; the Direct environment allocates them once in __init__. The task-constants module gains the per-variant scalar values consumed by the Direct cfgs and, later, the manager counterparts.
The reward kernels launch directly on Warp-native environment state (ProxyArray views) with caller-owned, view-cached buffers, so the hot loop allocates and converts nothing per step. The task-constants module gains the per-variant scalar values consumed by the Direct cfgs and, later, the manager counterparts.
Summary
Metrics/success_ratesignal (goal-reach streaks per episode) and threshold-independent episode orientation-error diagnostics to the existing Direct reorientation environments, per the Task Clean-up standard (success rate gates task health; reward stays diagnostic).isaaclab_tasks.core.utils(EpisodeErrorRecorder,sample_joint_positions_within_limits) with unit tests.Dependencies
Review updates (2026-07-09)