Skip to content

Add dataclass and state machine for fine grained subtask tracking#758

Merged
peterd-NV merged 26 commits into
mainfrom
peterd/fine_grained_subtask_tracking
Jun 24, 2026
Merged

Add dataclass and state machine for fine grained subtask tracking#758
peterd-NV merged 26 commits into
mainfrom
peterd/fine_grained_subtask_tracking

Conversation

@peterd-NV

@peterd-NV peterd-NV commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR adds foundational machinery required for subtask progress tracking in Arena.

  • Adds a new ProgressObjective data class used to specify predicate groups for subtask tracking.
  • Adds a state machine (ProgressTrakcer) and runners (ProgressObjectiveRunner) for tracking predicate progression in Arena tasks.
  • Updates CompositeTaskBase and TaskBase with new interfaces to support subtask tracking
  • Adds test cases for the new data class and tracker

@peterd-NV peterd-NV changed the title Add FineGrainedSubtask dataclass and state machine Add dataclass and state machine for fine grained subtask tracking Jun 3, 2026

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Add FineGrainedSubtask dataclass and state machine

Summary: This PR introduces a fine-grained subtask tracking system with a FineGrainedSubtask dataclass and a FineGrainedStateMachine to monitor predicate progression across parallel environments. The design is well-structured — clean separation between the data definition (FineGrainedSubtask), the runner (FineGrainedSubtaskRunner), and the top-level orchestrator (FineGrainedStateMachine). Test coverage is thorough.


Findings

1. 🐛 Performance: Element-wise reset loop will be slow at scale

File: fine_grained_state_machine.py (lines 152–156)

def reset(self, env_ids) -> None:
    for group_name in self.fine_grained_subtask.group_names:
        for eid in env_ids:
            self.current_index[group_name][eid] = 0
            self.group_score[group_name][eid] = 0.0
            self.group_complete[group_name][eid] = False

This iterates element-by-element over env_ids for each group. With hundreds/thousands of environments, this will be significantly slower than vectorized indexing:

def reset(self, env_ids) -> None:
    if not isinstance(env_ids, torch.Tensor):
        env_ids = torch.as_tensor(env_ids, dtype=torch.long, device=self.device)
    for group_name in self.fine_grained_subtask.group_names:
        self.current_index[group_name][env_ids] = 0
        self.group_score[group_name][env_ids] = 0.0
        self.group_complete[group_name][env_ids] = False

Severity: Medium — correctness is fine but this will be a bottleneck in real training loops.


2. 🔍 State machine can advance multiple predicates in a single step (by design, but undocumented)

File: fine_grained_state_machine.py (lines 103–136)

The step() method iterates over all chain indices in a single call. If predicate p0 becomes True and p1 is already True at the same step, the state machine advances through both in one step() call. This is because after advancing past p0, the loop continues to chain_idx=1 and finds the env is now at_position.

Wait — actually re-reading more carefully: the advanced mask prevents double-advancing within a single step. Once advance_mask is set for an env, ~advanced blocks further evaluation. So each env can advance at most one predicate per step.

This is correct behavior but worth a brief docstring note on the single-advance-per-step invariant, since it's subtle and reviewers/future maintainers may miss it.


3. ⚠️ is_complete() and overall_score_per_env() recompute on every get_state() call

File: fine_grained_state_machine.py (lines 159–174, 187–228)

get_state() calls runner.is_complete() and runner.overall_score_per_env() per runner per env in the output loop. Each of these does a torch.stack + reduction. In a tight training loop where get_state() is called every step (via fine_grained_subtask_step_func), this could add up.

Consider caching is_complete and overall_score_per_env results per step (invalidated at each step() call) or computing them once at the end of step().

Severity: Low-Medium — depends on number of FGS runners and training throughput requirements.


4. 📝 _compute_composite_task_gating_mask assumes _current_subtask_idx is list-like or tensor

File: fine_grained_state_machine.py (lines 58–78)

if torch.is_tensor(current_idx):
    ci = current_idx.to(self.device)
else:
    ci = torch.as_tensor(current_idx, device=self.device)
return ci == int(self.fine_grained_subtask.parent_subtask_idx)

If _current_subtask_idx is a scalar int (not a list or tensor), torch.as_tensor(5) produces a 0-d tensor and ci == N returns a 0-d bool tensor, not (num_envs,). The comparison against composite_task_gating_mask downstream would then broadcast unexpectedly. This probably never happens in practice (composite tasks use per-env tensors), but a shape assertion or explicit broadcast would make it defensive.

Severity: Low — unlikely path but a potential silent logic error.


5. 💡 task_base.py imports are unconditional — consider lazy imports

File: task_base.py (lines 14–18)

from isaaclab_arena.tasks.fine_grained_state_machine import (
    make_fine_grained_subtask_events_cfg,
    make_fine_grained_subtask_termination_cfg,
)
from isaaclab_arena.tasks.fine_grained_subtask import FineGrainedSubtask

Every task (including those that don't use fine-grained tracking) now imports the full state machine module at class-load time. This pulls in torch and the state machine code even when unused. For a base class imported everywhere, lazy imports inside get_fine_grained_subtask_events_cfg() / get_fine_grained_subtask_termination_cfg() would keep startup lean.

Severity: Low — minor import overhead, not a correctness issue.


6. 🧪 Missing test: predicate raising an exception mid-chain

The test suite covers happy paths thoroughly (sequential advance, logical modes, gating, reset). However, there's no test for what happens if a predicate callable raises an exception. Currently, it would propagate unhandled and potentially leave the state machine in a partially-advanced state for that step.

Consider either:

  • Adding a test that documents this as expected behavior (exception propagates, caller handles it)
  • Or wrapping predicate evaluation in a try/except that logs and skips

Severity: Low — documentation/robustness concern.


7. 📝 Minor: Typo in docstrings — "parallelenvironments"

File: fine_grained_state_machine.py (lines 36, 177)

"across all parallelenvironments" → "across all parallel environments"


Positives

  • Clean architecture: The dataclass → runner → state machine layering is well-designed and extensible.
  • Thorough validation in FineGrainedSubtask.__post_init__ catches misconfiguration early.
  • Flexible input formats for predicate_groups with good normalization logic.
  • Composite task integration via dataclasses.replace with namespaced names is elegant.
  • Comprehensive test coverage (17 test cases) covering sequential advancement, out-of-order rejection, all logical modes, gating, reset isolation, and integration hooks.

Verdict

Good design, solid implementation, excellent tests. The vectorized reset (finding #1) is the most actionable improvement. The rest are minor hardening suggestions. 👍

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up note: Noticed the class rename in the latest commit (FineGrainedStateMachineFineGrainedSubtaskTrackingStateMachine). The new name better reflects the class's purpose — good clarification. The previous review findings still apply unchanged.

No new review generated — naming-only refactor.


Update (2026-06-05): Reviewed incremental changes 4c9aa2b..83f0ca3.

Previous findings status:

  • Fixed — Finding #7 (typo "parallelenvironments" → "parallel environments")
  • Findings #1#6 — original comments stand (not addressed in this push, which is fine given the scope of changes)

Summary of new changes:

Large push with several new features alongside the rename refactor:

  1. Rename: FineGrainedSubtaskFineGrainedProgressObjective, FineGrainedSubtaskTrackingStateMachineFineGrainedProgressTracker — cleaner naming, comprehensive rename across all references and tests. 👍
  2. NotNextTo relation — new loss strategy with proper gradient (no flat plateau) and solver integration tests. Well-designed.
  3. Variations systemVariationBase/BuildTimeVariationBase/RunTimeVariationBase with cfg-driven sampler wiring. Clean architecture with enable/disable toggle and apply_cfg. Good test coverage for camera extrinsics, HDR image, build-time, and run-time variations.
  4. CLI override specs — graph YAML can declare swappable --flag arguments that remap node asset names. Properly validated (duplicates, unknown targets).
  5. Graph spec Pydantic migrationArenaEnvGraphSpec now uses Pydantic validation instead of manual asserts. Spatial constraints use string-based registry lookup instead of enum. Removes special-case handling for at_pose/in.
  6. Chunked eval runner--chunk_size splits long sweeps across subprocesses to reclaim leaked memory. Appropriate TODO for metrics aggregation.
  7. Pooled placer reproducibility — per-env RNGs via get_rngs() replace random.choice/random.choices, making sample_with_replacement reproducible under placement_seed.

No new issues found in this push. Clean, well-tested changes. 👍


Update (2026-06-05): Reviewed incremental changes 83f0ca3..de73e3d.

Key change: Termination term → RecorderTerm 🎉

The fine-grained progress tracking has been moved from a TerminationTermCfg (that always returned False) to a proper RecorderTerm (FineGrainedProgressRecorder.record_post_step). This directly addresses the architectural concern discussed in this PR — using a termination term as a per-step hook was an anti-pattern.

Benefits:

  • Cleaner intent expression (this is observation/logging, not termination)
  • record_post_step returns (None, None) — records nothing, just ticks the state machine
  • No more zero-return termination term cluttering TerminationsCfg
  • Tests properly updated to verify the new interface

Previous findings status:

  • Fixed — Mid-function dead docstring (original finding about fine_grained_subtask_step_func placing docs mid-function). Now properly in the FineGrainedProgressRecorder class docstring.
  • Addressed — "Termination term always returns False" architectural smell. Replaced with RecorderTerm — the correct hook point.
  • Findings #1 (vectorized reset), #2 (split calls), #3#6 — original comments still stand (not in scope of this refactor).

Minor new finding:

  • 📝 Typo in FineGrainedProgressRecorder docstring (line 289): "state nachine" → "state machine"

Verdict:

Clean, well-scoped refactor. The move to RecorderTerm is the right architectural choice. 👍


Update (2026-06-05): Reviewed incremental changes de73e3d..680fa6d.

Previous findings status:

  • Fixed — Finding #2 (undocumented single-advance-per-step invariant). Now explicitly documented in step() and _step_group() docstrings.
  • Fixed — Finding #3 (is_complete()/overall_score_per_env() recomputed per env in get_state()). Now pre-computed once as (num_envs,) tensors outside the env loop and passed into get_state_for_env().
  • 📝 Typo "state nachine" (line 317 of fine_grained_progress_tracker.py) — still present from previous push, not addressed here.

Summary of new changes:

  1. step() refactored — Inner group-iteration logic extracted into _step_group(). Identical behavior, better readability and separation of concerns.
  2. get_state() optimizedcompleteness and scores tensors computed once per call, passed to new runner.get_state_for_env(env_idx, ...) method. Eliminates redundant torch.stack + reduction per env.
  3. Line-length fixes in fine_grained_progress_objective.py — cosmetic only.

No new issues found. Clean refactor addressing prior performance feedback. 👍


Update (2026-06-05): Reviewed incremental changes 680fa6d..24807a4.

Previous findings status:

  • Fixed — Finding #1 (vectorized reset). The element-wise for eid in env_ids loop is now replaced with torch.as_tensor + direct tensor indexing (self.current_index[group_name][env_ids] = 0). Exactly the optimization suggested. 👍
  • Fixed — Typo "state nachine" → "state machine" (line 317 of fine_grained_progress_tracker.py). Now corrected.

New change: Objective caching in task_base.py

  • Added _resolve_fine_grained_progress_objectives() — resolves get_fine_grained_progress_objectives() once and caches the result so events cfg and recorder cfg share the same objective instances. Prevents duplicate instantiation and ensures consistency between reset and step paths. Clean, correct pattern.

All original findings now addressed:

# Finding Status
1 Vectorized reset ✅ Fixed (this push)
2 Single-advance-per-step docstring ✅ Fixed (prior push)
3 Cached is_complete/overall_score_per_env ✅ Fixed (prior push)
4 Scalar _current_subtask_idx shape guard ⚪ Low-risk, not addressed (acceptable)
5 Lazy imports in task_base.py ⚪ Low priority, not addressed (acceptable)
6 Exception handling in predicates ⚪ Low priority, not addressed (acceptable)
7 Typo "parallelenvironments" ✅ Fixed (earlier push)

No new issues found. PR is in good shape. 🚀


Update (00693fb): Reviewed incremental changes. New commits add the agentic environment generation pipeline, env-graph spec refactoring (parent/child → subject/reference, type → kind), task transitions, and @agent_ready decorator. These changes are orthogonal to the fine-grained subtask tracking discussed in earlier comments. No new issues found — the architecture is clean with good test coverage.

@peterd-NV
peterd-NV marked this pull request as ready for review June 3, 2026 19:31
@greptile-apps

greptile-apps Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces a new progress_tracking module — a ProgressObjective dataclass and a ProgressTracker state machine — that gives Arena tasks fine-grained, per-predicate progress tracking across parallel environments. ArenaEnvBuilder is updated to wire objectives from TaskBase.get_progress_objectives() into both the reset event and a recorder that publishes per-step state to env.extras[\"progress_tracking\"].

  • ProgressObjective + ProgressTracker: dataclass defines named predicate chains grouped by ALL/ANY/CHOOSE completion logic; the tracker evaluates chains in order, advances at most one step per env per group per step, and uses topk-based scoring so objective scores reach 1.0 correctly for all three logical modes.
  • CompositeTaskBase integration: child objectives are namespaced and tagged with parent_subtask_idx for gating via _current_subtask_idx; dataclasses.replace safely re-runs __post_init__ to recompute canonical predicate groups.
  • Test suite: 17 tests cover predicate-group normalization, sequential advancement, all logical modes, tensor reset, composite gating, and the recorder's extras contract.

Confidence Score: 5/5

Safe to merge — all core logic (scoring, gating, tensor reset, composite namespacing) is correct and well-tested.

The tracker, runner, and builder wiring are all functionally correct. The two findings are minor interface/documentation concerns: the cumulative-event semantics in extras and the cache-key limitation in _ensure_progress_tracker both affect future extensibility rather than current correctness. The test suite is thorough and covers the edge cases that caused issues in the predecessor module.

isaaclab_arena/progress_tracking/progress_tracker.py — the cumulative-event publishing and the _ensure_progress_tracker cache semantics are worth a second look before downstream consumers start building reward shapers on top of the events dict.

Important Files Changed

Filename Overview
isaaclab_arena/progress_tracking/progress_tracker.py Core tracker implementation: ProgressObjectiveRunner (per-objective state machine) and ProgressTracker (orchestrator). The reset-with-tensor fix, topk-based scoring for logical modes, and gating mask for composite tasks are all correct. Two minor concerns: cumulative event semantics published to extras each step, and the cache key in _ensure_progress_tracker ignores the objectives argument.
isaaclab_arena/progress_tracking/progress_objective.py ProgressObjective dataclass with ALL/ANY/CHOOSE completion modes, score validation, and canonical predicate group normalization via post_init. dataclasses.replace is used safely in CompositeTaskBase — post_init recomputes canonical_predicate_groups correctly.
isaaclab_arena/progress_tracking/progress_tracking_utils.py Predicate group canonicalization helpers: normalizes six input shapes into canonical form and scales per-group scores to sum to 1.0. Type assertions catch mixed-type chains and empty containers cleanly.
isaaclab_arena/environments/arena_env_builder.py Integrates progress tracking into the env build pipeline: calls get_progress_objectives() once and threads the same list into both the events cfg and recorder cfg.
isaaclab_arena/tasks/composite_task_base.py Adds get_progress_objectives() that namespaces child objectives and sets parent_subtask_idx for composite-task gating. dataclasses.replace correctly re-runs post_init to recompute canonical_predicate_groups.
isaaclab_arena/tasks/task_base.py Adds default get_progress_objectives() returning an empty list — clean opt-in hook for subclasses.
isaaclab_arena/tests/test_progress_objective_tracking.py Comprehensive test suite covering predicate group shapes, sequential advancement, logical modes (ALL/ANY/CHOOSE), gating with parent_subtask_idx, tensor reset, recorder extras, and TaskBase/CompositeTaskBase integration.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Env as IsaacLab Env
    participant Builder as ArenaEnvBuilder
    participant Task as TaskBase / CompositeTaskBase
    participant EventsCfg as EventTermCfg (reset)
    participant RecorderCfg as ProgressTrackingRecorder
    participant Tracker as ProgressTracker
    participant Runner as ProgressObjectiveRunner

    Builder->>Task: get_progress_objectives()
    Task-->>Builder: [ProgressObjective, ...]
    Builder->>EventsCfg: make_progress_tracking_events_cfg(objectives)
    Builder->>RecorderCfg: make_progress_tracking_recorder_cfg(objectives)

    loop Every env.step()
        Env->>RecorderCfg: record_post_step()
        RecorderCfg->>Tracker: _ensure_progress_tracker(env, objectives)
        Tracker-->>RecorderCfg: cached ProgressTracker
        RecorderCfg->>Tracker: step(env, episode_length_buf)
        loop For each ProgressObjectiveRunner
            Tracker->>Runner: step(env, step_index)
            Runner->>Runner: _compute_composite_task_gating_mask(env)
            Runner->>Runner: _step_group() evaluate predicate, advance index, emit PredicateEvent
            Runner-->>Tracker: [PredicateEvent, ...]
        end
        Tracker->>Tracker: append events to _events[env_idx]
        RecorderCfg->>Tracker: get_state() + get_events()
        RecorderCfg->>Env: "extras[progress_tracking] = states + events"
    end

    loop On episode reset
        Env->>EventsCfg: progress_tracking_reset_func(env, env_ids, objectives)
        EventsCfg->>Tracker: reset(env_ids)
        Tracker->>Runner: reset(env_ids) for each runner
        Tracker->>Tracker: clear _events for reset env_ids
    end
Loading
%%{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 IsaacLab Env
    participant Builder as ArenaEnvBuilder
    participant Task as TaskBase / CompositeTaskBase
    participant EventsCfg as EventTermCfg (reset)
    participant RecorderCfg as ProgressTrackingRecorder
    participant Tracker as ProgressTracker
    participant Runner as ProgressObjectiveRunner

    Builder->>Task: get_progress_objectives()
    Task-->>Builder: [ProgressObjective, ...]
    Builder->>EventsCfg: make_progress_tracking_events_cfg(objectives)
    Builder->>RecorderCfg: make_progress_tracking_recorder_cfg(objectives)

    loop Every env.step()
        Env->>RecorderCfg: record_post_step()
        RecorderCfg->>Tracker: _ensure_progress_tracker(env, objectives)
        Tracker-->>RecorderCfg: cached ProgressTracker
        RecorderCfg->>Tracker: step(env, episode_length_buf)
        loop For each ProgressObjectiveRunner
            Tracker->>Runner: step(env, step_index)
            Runner->>Runner: _compute_composite_task_gating_mask(env)
            Runner->>Runner: _step_group() evaluate predicate, advance index, emit PredicateEvent
            Runner-->>Tracker: [PredicateEvent, ...]
        end
        Tracker->>Tracker: append events to _events[env_idx]
        RecorderCfg->>Tracker: get_state() + get_events()
        RecorderCfg->>Env: "extras[progress_tracking] = states + events"
    end

    loop On episode reset
        Env->>EventsCfg: progress_tracking_reset_func(env, env_ids, objectives)
        EventsCfg->>Tracker: reset(env_ids)
        Tracker->>Runner: reset(env_ids) for each runner
        Tracker->>Tracker: clear _events for reset env_ids
    end
Loading

Reviews (16): Last reviewed commit: "Merge branch 'main' of github.com:isaac-..." | Re-trigger Greptile

Comment thread isaaclab_arena/tasks/fine_grained_progress_tracker.py Outdated
Comment thread isaaclab_arena/tasks/fine_grained_subtask_tracking_state_machine.py Outdated
Comment thread isaaclab_arena/tasks/task_base.py Outdated
@cvolkcvolk

Copy link
Copy Markdown
Collaborator

Thanks for adding this! Going to be super useful once we have the full pipeline in.
One highler level thing that made it a little hard for me to follow at first: I think we've ended up overloading the word "subtask" a bit. Right now it means a few different things:

  • the composed tasks in CompositeTaskBase.subtasks (with SequentialTaskBase,...)
  • the Mimic datagen configs (SubTaskConfig)
  • and now the new progress chains (FineGrainedSubtask, FineGrainedSubtaskTerminationsCfg, FineGrainedSubtaskEventsCfg, ...)

So when reading "subtask" anywhere its not clear which one is meant if not already familiar.

If I read it correctly we've got two systems now that do opposite jobs (but read like siblings in the code):

  • The success termination: Decides whether the episode is done/passed.
  • The new FineGrainedSubtask tracking: Just watches and reports progress (grab → lift → place). Returns all-False every step, never ends the episode.

Currently "FineGrained" names the "resolution" of the Task, not the part that it has control over (Can it end the episode or not?)
And both (get_fine_grained_subtask_termination_cfg & actual termination configs) are registered as termination terms and sit side by side and look the same.

My proposal is to name by that question Can it end the episode or not?:

  • authoritative (can end the episode) → stays success / termination. No change.
  • observational (only tracks, never ends) → call it progress.

So the renames could be roughly:

  • FineGrainedSubtask → ProgressObjective
  • FineGrainedSubtaskTrackingStateMachine → ProgressTracker
  • get_fine_grained_subtasks() → get_progress_objectives()
  • env.extras["fine_grained_subtask"] → env.extras["progress"]
  • ...

Two side benefits:

  1. "subtask" goes back to meaning one thing: the composition unit in CompositeTaskBase.subtasks.
  2. Right now the tracking runs as a termination term. get_fine_grained_subtask_termination_cfg(), returning all-False every step, so it never terminates anything... Once we're calling it "progress," it's more clear it shouldn't live in terminations at all. We could move it to a recorder (like the existing SubtaskSuccessStateRecorder) so where it lives also tells you it's observational.

Comment thread isaaclab_arena/tasks/fine_grained_progress_tracker.py Outdated
Comment thread isaaclab_arena/tasks/fine_grained_progress_tracker.py Outdated
Comment thread isaaclab_arena/progress_tracking/progress_tracker.py Outdated
Comment thread isaaclab_arena/progress_tracking/progress_tracker.py Outdated
Comment thread isaaclab_arena/tasks/fine_grained_progress_tracker.py Outdated
@peterd-NV

Copy link
Copy Markdown
Collaborator Author

Thanks @cvolkcvolk for the review. I've gone ahead renamed from "FineGrainedSubtasks" to "FineGrainedProgressObjective" and "FineGrainedProgressTracker".

I kept the "FineGrained" terminology since I wanted to make it clear that the predicate chains we give tasks here can be made to be more detailed and include this notion of multiple "subtasks" in the progress (i.e. we can have multiple predicates or predicate groups for a single TaskBase).

Comment thread isaaclab_arena/progress_tracking/__init__.py Outdated
Comment thread isaaclab_arena/progress_tracking/fine_grained_progress_objective.py Outdated
Comment thread isaaclab_arena/progress_tracking/fine_grained_progress_tracker.py Outdated
Comment thread isaaclab_arena/progress_tracking/fine_grained_progress_tracker.py Outdated
Comment thread isaaclab_arena/tasks/composite_task_base.py Outdated
Comment thread isaaclab_arena/progress_tracking/fine_grained_progress_objective.py Outdated
Comment thread isaaclab_arena/progress_tracking/fine_grained_progress_tracker.py Outdated
@cvolkcvolk

Copy link
Copy Markdown
Collaborator

Thanks @cvolkcvolk for the review. I've gone ahead renamed from "FineGrainedSubtasks" to "FineGrainedProgressObjective" and "FineGrainedProgressTracker".

I kept the "FineGrained" terminology since I wanted to make it clear that the predicate chains we give tasks here can be made to be more detailed and include this notion of multiple "subtasks" in the progress (i.e. we can have multiple predicates or predicate groups for a single TaskBase).

Yeah fully agree on the explicit naming. However "Fine-grained" doesn't actually encode the concept "multiple predicate groups" or "subtasks" either :-)
Another thing with fine_grained_* and FineGrained* might suggest there's a coarse ProgressObjective somewhere, which there isn't (And it doesn't match the progress_tracking/ package name after our refactor anymore)

Comment thread isaaclab_arena/tasks/task_base.py Outdated
@peterd-NV

Copy link
Copy Markdown
Collaborator Author

Thanks @cvolkcvolk for the review. I've gone ahead renamed from "FineGrainedSubtasks" to "FineGrainedProgressObjective" and "FineGrainedProgressTracker".
I kept the "FineGrained" terminology since I wanted to make it clear that the predicate chains we give tasks here can be made to be more detailed and include this notion of multiple "subtasks" in the progress (i.e. we can have multiple predicates or predicate groups for a single TaskBase).

Yeah fully agree on the explicit naming. However "Fine-grained" doesn't actually encode the concept "multiple predicate groups" or "subtasks" either :-) Another thing with fine_grained_* and FineGrained* might suggest there's a coarse ProgressObjective somewhere, which there isn't (And it doesn't match the progress_tracking/ package name after our refactor anymore)

Looking at it again I think we can remove the FineGrained terminology entirely now that we've moved the "progress tracking" to it's own separate module and decoupled from "tasks." I think we can rename everything to ProgressObjective and ProgressTracker, and it's clear that each can have multiple predicates without the need for the term "fine-grained."

@alexmillane alexmillane left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! I just left a bunch of nits. Approved!

Comment thread isaaclab_arena/progress_tracking/progress_objective.py Outdated
Comment thread isaaclab_arena/progress_tracking/fine_grained_progress_objective.py Outdated
Comment thread isaaclab_arena/progress_tracking/progress_objective.py Outdated
Comment thread isaaclab_arena/progress_tracking/progress_objective.py Outdated
Comment thread isaaclab_arena/progress_tracking/progress_objective.py Outdated
Comment thread isaaclab_arena/progress_tracking/progress_tracker.py Outdated
Comment thread isaaclab_arena/progress_tracking/progress_tracker.py Outdated
Comment thread isaaclab_arena/progress_tracking/progress_tracker.py Outdated
Comment thread isaaclab_arena/progress_tracking/progress_tracker.py
Comment thread isaaclab_arena/tasks/composite_task_base.py Outdated
@peterd-NV
peterd-NV merged commit 80be13e into main Jun 24, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants