Skip to content

orbitalgym.policies.plan_cache

Contact-gated plan-caching wrapper for any Policy. See Ground stations for the operational rationale.

Policy state

orbitalgym.policies.plan_cache.PlanCacheState

Cached H-tick plan and the cursor into it.

Each tick the policy emits plan[step_in_plan] if step_in_plan < plan_horizon, else a zero command. On an upload event the plan is refreshed (a fresh H-tick rollout from the lagged belief) and step_in_plan resets to 0.

belief_history is a ring buffer of recent post-sync beliefs of length replan_contacts_lag + 1. The lagged-belief lookup at upload time reads belief_history[0] (oldest = most lagged).

inner_state carries the wrapped inner planner's state across uploads. Stateless inner planners pass None (default) and the field is treated as a static null pytree leaf. Stateful inner planners (e.g. an MCTSPolicy that returns its tree, or a learned policy with RNN state) seed it via init_state(inner_init_state=...).

Wrapper

orbitalgym.policies.plan_cache.PlanCachePolicy dataclass

PlanCachePolicy(
    inner: Any,
    plan_horizon: int,
    schedule: ContactSchedule,
    dt: float,
    replan_contacts_lag: int = 1,
    upload_delay_s: float = 0.0,
    n_vehicles: int = 0,
    command_cls: Any = None,
)

Contact-gated finite-horizon plan-caching wrapper.

Wraps any inner Policy. At each upload event (entry into a contact window with the lag and upload-delay conditions satisfied), invokes the inner planner plan_horizon times against the lagged belief and stores the resulting H-tick command sequence. Each tick the policy emits plan[step_in_plan] if the cursor is still inside the plan, else a zero command (plan expired).

Default replan_contacts_lag=1 matches the operational picture: the belief synced this contact drives the plan uplinked next contact.

plan_horizon is the number of ticks the cached plan covers. Tune it to span slightly more than the longest expected inter-contact gap so every off-contact period stays plan-active. Plans shorter than the longest gap will leave the vehicle in safe-mode (zero Δv) for a portion of every off-contact period.

For a stateless inner planner (typical for a feedback law), all H slots are nearly identical (the lagged belief doesn't evolve across the H inner calls), so the plan effectively encodes "apply this Δv for H ticks, then go safe". For a stateful inner planner (e.g. a rollout-based optimizer that produces a sequence of differing commands), each slot can carry a different Δv.

init_state

init_state(
    belief: Any,
    inner_init_state: Any = None,
    key: Array | None = None,
) -> PlanCacheState

Build an initial PlanCacheState whose plan is computed from the initial belief — so the agent acts immediately at t=0, not after the first upload event.

The initial plan covers the first plan_horizon ticks; if the first upload event hasn't fired by tick plan_horizon, the cursor falls off the end of the plan and the policy emits zero Δv until the first upload arrives.

inner_init_state is forwarded into the inner planner so stateful inners (e.g. MCTS) start from a well-defined seed. key is required when the inner planner is non-deterministic (e.g. MCTS); for deterministic feedback-law inners pass any deterministic key. Defaults to jax.random.key(0) so the method is callable in pure-deterministic setups without threading a key through.