Hello @Siddarth_Naik,
Thank you for the response. I am using 2.0 (I updated from the IDE and Antigravity together), and am using a macOS Tahoe 26.5.1, and am running more of medium sized projects (research, creating small sites, etc.) This issue occurs over every available model. For example, my limit reset today at around 4:30 and by 6:30 with maybe 3-5 prompts max, I reached the limit. Though I am on the free plan, I do not believe it should be this quick, as when I began to use Antigravity I had a much more generous limits. Additionally, I am not on the admin account of this computer (for privacy reasons), and I repeatedly get a notification from Antigravity asking to enter the admin password to add a “helper tool”. I have entered the password numerous times, and the request keeps coming up every 20-30 minutes. For sample prompts, this is one of the most extreme in depth prompts I have given it, and immediately after working on it, the individual quota was reached. # Project Overview
Build a **Multi-Agent Reinforcement Learning (MARL)** system where N autonomous spacecraft
agents learn cooperative collision avoidance policies against a catalog of orbital debris,
using centralised training with decentralised execution (CTDE).
**Stack:**
- Python 3.11+
- PyTorch + TorchRL (or RLlib)
- Gymnasium (custom orbital env)
- Poliastro / Basilisk-lite for orbital mechanics
- ONNX for edge export
- Weights & Biases for experiment tracking
Phase 1 — Repository Scaffold
```
Create the full project directory structure:
marl_orbital/
├── CLAUDE.md # this file
├── README.md
├── pyproject.toml # PEP 517, managed by uv or pip
├── requirements.txt
├── configs/
│ ├── env_config.yaml # orbital sim parameters
│ ├── agent_config.yaml # network architecture
│ └── train_config.yaml # hyperparameters
├── envs/
│ ├── _init_.py
│ ├── orbital_env.py # Gymnasium multi-agent env
│ ├── dynamics.py # 6-DOF spacecraft dynamics (Clohessy-Wiltshire)
│ ├── debris_catalog.py # TLE loader & propagator
│ └── reward.py # reward shaping functions
├── agents/
│ ├── _init_.py
│ ├── actor.py # decentralised actor network
│ ├── critic.py # centralised critic (sees all obs)
│ └── comm.py # differentiable communication (TarMAC-style)
├── algorithms/
│ ├── _init_.py
│ ├── mappo.py # Multi-Agent PPO
│ ├── maddpg.py # Multi-Agent DDPG (comparison baseline)
│ └── buffer.py # shared replay / rollout buffer
├── training/
│ ├── runner.py # main training loop
│ ├── evaluator.py # evaluation harness
│ └── curriculum.py # curriculum scheduler (debris density)
├── deployment/
│ ├── export_onnx.py # export actor to ONNX
│ └── inference.py # edge-ready inference wrapper
├── analysis/
│ ├── plots.py # matplotlib / plotly visualisations
│ └── metrics.py # miss distance, ΔV, Pareto frontier
└── tests/
├── test_env.py
├── test_agents.py
└── test_algorithms.py
Create every _init_.py and stub every .py file with a module docstring
and TODO comments. Create pyproject.toml with all dependencies.
```
Phase 2 — Orbital Environment
```
Implement envs/dynamics.py:
- Class SpacecraftDynamics with 6-DOF state: [x, y, z, vx, vy, vz] in Hill frame
- Clohessy-Wiltshire (CW) equations for relative motion around circular reference orbit
- Continuous-thrust control input: delta_v vector [dvx, dvy, dvz] in m/s
- Runge-Kutta 4 integrator, configurable timestep (default 10s)
- State bounds check: alert if re-entry altitude crossed
- Method: step(state, action, dt) → next_state
- Method: relative_distance(state_a, state_b) → float (metres)
Implement envs/debris_catalog.py:
- Class DebrisCatalog
- Load TLE data from a bundled sample file (include 20 representative LEO debris TLEs
as a Python list literal — do not require internet access)
- Use sgp4 library to propagate debris positions at time t
- Method: get_positions(t_epoch_seconds) → list of [x,y,z] in ECI frame
- Method: transform_to_hill(debris_eci, chief_eci, chief_velocity) → relative [x,y,z]
- Caching: cache propagation results at 1s resolution for speed
Implement envs/reward.py:
- Function compute_reward(agent_state, debris_positions, action, params) → float
- Terms:
- Collision penalty: -1000 if any debris within 200m
- Proximity shaping: -exp(-dist/500) for nearest debris (smooth gradient)
- Fuel cost: -||action||^2 * fuel_weight (penalise ΔV use)
- Survival bonus: +0.1 per timestep alive (encourage longevity)
- Team collision penalty: -500 if two agents within 100m of each other
- All weights configurable via configs/env_config.yaml
```
Phase 3 — Multi-Agent Gymnasium Environment
```
Implement envs/orbital_env.py as a PettingZoo ParallelEnv
(install pettingzoo, gymnasium):
class OrbitalDebrisEnv(ParallelEnv):
metadata = {“render_modes”: [“human”, “rgb_array”], “name”: “orbital_debris_v0”}
Observation space per agent (Box, float32):
- Own relative state vs chief: 6 values [x,y,z,vx,vy,vz]
- Nearest K debris relative positions + velocities: K*6 values (K=10 default)
- Other agents’ relative positions: (N-1)*3 values
- Remaining fuel fraction: 1 value
- Time remaining in episode: 1 value
Total: 6 + 60 + (N-1)*3 + 2 = variable, flatten to fixed size with N_AGENTS param
Action space per agent (Box, float32):
- [dvx, dvy, dvz] clipped to [-max_thrust, max_thrust] m/s per step
- max_thrust configurable (default 0.01 m/s, simulating small cold-gas thruster)
Episode:
- Duration: 1000 steps (default)
- Reset: randomise N_AGENTS spacecraft near reference orbit within 2km box
- Termination: any agent’s fuel reaches 0, or collision occurs
- Truncation: max steps reached
Implement render() using matplotlib 3D scatter for debris cloud + spacecraft positions.
Include type hints throughout. Add _all_ export list.
```
Phase 4 — Actor & Centralised Critic Networks
```
Implement agents/actor.py:
class SpacecraftActor(nn.Module):
- Input: observation vector (obs_dim,)
- Architecture:
LayerNorm(obs_dim)
→ Linear(obs_dim, 256) → ELU
→ Linear(256, 256) → ELU
→ Linear(256, 128) → ELU
→ Linear(128, action_dim) # action_dim = 3
→ Tanh * max_thrust # bound actions
- Add method get_action(obs) → (action, log_prob) using Normal distribution
with learned log_std parameter
- Use orthogonal initialisation
Implement agents/critic.py:
class CentralisedCritic(nn.Module):
- Input: concatenated observations of ALL agents [N_AGENTS * obs_dim]
- Architecture:
LayerNorm(global_obs_dim)
→ Linear(global_obs_dim, 512) → ELU
→ Linear(512, 256) → ELU
→ Linear(256, 1)
- Returns V(s) — single scalar value estimate
- Note: only used during training, not deployed on spacecraft
Implement agents/comm.py (optional communication module):
class TarMACComm(nn.Module):
- Soft attention over messages from all other agents
- Each agent encodes a key+value from hidden state
- Query from current hidden state attends over others’ keys
- Output: context vector concatenated to actor’s hidden state
- Make it optional (bypass with identity if comm_enabled=False in config)
```
Phase 5 — MAPPO Algorithm
```
Implement algorithms/mappo.py:
class MAPPO:
Hyperparameters (all configurable via configs/train_config.yaml):
- clip_eps: 0.2
- value_loss_coef: 0.5
- entropy_coef: 0.01
- max_grad_norm: 0.5
- gamma: 0.99
- gae_lambda: 0.95
- ppo_epochs: 10
- mini_batch_size: 256
- lr_actor: 3e-4
- lr_critic: 1e-3
Methods:
\__init_\_(actors: list\[SpacecraftActor\], critic: CentralisedCritic, config)
compute_gae(rewards, values, dones, last_value) -> advantages, returns
update(rollout_batch) -> dict of loss metrics
- Iterate ppo_epochs
- Compute ratio = new_log_prob / old_log_prob
- Clipped surrogate loss (separate per agent, mean across agents)
- Centralised value loss (MSE, clipped)
- Entropy bonus (mean across agents)
- Gradient clipping per network
- Return: {actor_loss, value_loss, entropy, approx_kl}
Implement algorithms/buffer.py:
class RolloutBuffer:
- Stores: obs, actions, log_probs, rewards, dones, values
for all N_AGENTS simultaneously
- compute_returns_and_advantages() using GAE
- get_mini_batches(batch_size) → iterator of shuffled mini-batches
- clear() method
- Support variable N_AGENTS
```
Phase 6 — Training Runner
```
Implement training/runner.py:
class MARLTrainer:
def _init_(self, config_path: str):
- Load all YAML configs
- Initialise env, actors (one per agent), shared critic
- Initialise MAPPO
- Initialise W&B run (wandb.init) with full config logged
- Create checkpoint directory
def train(self, total_timesteps: int):
Main loop:
1. Collect rollout:
- Reset env, collect N_STEPS steps from all agents
- Store (obs, action, log_prob, reward, done, value) in buffer
- Handle termination and truncation correctly
2. Compute last values for GAE
3. Update networks via MAPPO.update(buffer)
4. Log to W&B: episode_reward_mean, collision_rate, fuel_used_mean,
actor_loss, value_loss, entropy, approx_kl, fps
5. Every EVAL_FREQ episodes: run evaluator, log eval metrics
6. Every SAVE_FREQ episodes: save checkpoint
7. Print progress bar via tqdm
def save_checkpoint(self, path: str):
- Save all actor state_dicts, critic state_dict, optimiser states,
training step, config
def load_checkpoint(self, path: str):
- Restore all of the above
Implement training/curriculum.py:
class CurriculumScheduler:
- Phase 1 (0–25%): 5 debris objects, slow relative velocities
- Phase 2 (25–60%): 20 debris, realistic LEO velocities
- Phase 3 (60–85%): 50 debris, include conjunction events
- Phase 4 (85–100%): full catalog, adversarial debris injection
- update(progress_fraction) → updates env config in place
- Log curriculum phase to W&B
```
Phase 7 — Evaluation & Metrics
```
Implement training/evaluator.py:
class Evaluator:
def evaluate(self, actors, env, n_episodes=100) → dict:
Run n_episodes with deterministic actions (mean of policy, no sampling).
Return:
- collision_rate: fraction of episodes with at least one collision
- mean_miss_distance_m: mean closest approach to any debris (metres)
- mean_delta_v_ms: mean total ΔV consumed per agent per episode (m/s)
- survival_rate: fraction of agents that survived full episode
- inter_agent_min_dist_m: mean minimum separation between agents
- pareto_data: list of (delta_v, miss_distance) per episode for Pareto plot
Implement analysis/metrics.py:
Functions:
compute_pareto_frontier(delta_v_list, miss_dist_list) → (pf_dv, pf_md)
- Returns the non-dominated set
compute_conjunction_warning(agent_state, debris_positions, horizon_steps,
dynamics, threshold_m=1000) → bool
- Propagate forward horizon_steps to check for predicted conjunctions
Implement analysis/plots.py:
Functions:
plot_training_curves(wandb_run_id) → saves PNG
plot_pareto_frontier(pareto_data) → saves PNG
plot_orbital_trajectories(episode_log) → 3D matplotlib animation, saves GIF
plot_collision_heatmap(eval_results) → saves PNG
```
Phase 8 — Deployment Export
```
Implement deployment/export_onnx.py:
def export_actor_to_onnx(actor: SpacecraftActor, obs_dim: int,
output_path: str, opset_version: int = 17):
- Create dummy input tensor
- torch.onnx.export with dynamic batch axis
- Verify with onnxruntime: run dummy inference, compare outputs to PyTorch
- Print model size in KB
- Assert max output diff < 1e-5
def export_all_actors(checkpoint_path: str, output_dir: str):
- Load checkpoint, export each actor separately
- Also export a single “shared actor” if weights are shared
Implement deployment/inference.py:
class OrbitalAvoidanceInference:
- Load ONNX model via onnxruntime.InferenceSession
- Method: get_action(obs: np.ndarray) → np.ndarray (deterministic, mean action)
- Method: get_action_batch(obs_batch: np.ndarray) → np.ndarray
- Latency benchmark: measure mean inference time over 1000 calls
- Target: < 5ms on CPU (suitable for on-board computer)
```
Phase 9 — Tests
```
Implement tests/test_env.py using pytest:
test_env_reset_shapes: assert obs shapes match declared spaces for N=2,3,5 agents
test_env_step_returns: step with zero action, check all return types
test_env_collision_terminates: place agent inside debris radius, check termination
test_reward_components: verify each reward term activates correctly
test_debris_catalog_loads: assert catalog returns positions array
test_dynamics_energy_conservation: CW orbit should conserve relative energy
(without thrust) within 0.1% over 100 steps
Implement tests/test_agents.py:
test_actor_forward_pass: random obs -> action shape \[3\]
test_actor_bounded_output: all actions within \[-max_thrust, max_thrust\]
test_critic_forward_pass: concat all obs -> scalar value
test_comm_module: assert output shape unchanged with/without comm
Implement tests/test_algorithms.py:
test_buffer_fill_and_retrieve: fill buffer, check shapes
test_gae_computation: known reward sequence -> verify advantage signs
test_mappo_update_runs: short rollout -> update -> check losses are finite
test_gradient_flow: after update, verify actor/critic params changed
Run all tests and fix any failures.
```
Phase 10 — Documentation & README
```
Write README.md with:
- Project title and one-paragraph abstract
- Architecture diagram (ASCII art version of the layer diagram)
- Quick-start:
uv pip install -r requirements.txt
python -m training.runner --config configs/train_config.yaml
python -m training.evaluator --checkpoint checkpoints/best.pt
python -m deployment.export_onnx --checkpoint checkpoints/best.pt
- Configuration reference (table of all YAML keys and their meanings)
- Algorithm details: MAPPO equations, reward function, CW dynamics equations
written in LaTeX-style markdown
- Results section (placeholder tables for collision rate, ΔV cost, training curves)
- References:
- Lowe et al. 2017 (MADDPG)
- Schulman et al. 2017 (PPO)
- Yu et al. 2021 (MAPPO)
- Clohessy & Wiltshire 1960 (CW dynamics)
- ESA Space Debris Office reports
Create configs/train_config.yaml with all hyperparameters fully commented.
Create configs/env_config.yaml with all environment parameters fully commented.
Create configs/agent_config.yaml with all network parameters fully commented.
```
Phase 11 — Full Integration Run
```
-
Run the full test suite: pytest tests/ -v --tb=short
Fix any remaining failures.
-
Run a short smoke-training:
python -m training.runner \
–config configs/train_config.yaml \
–total-timesteps 50000 \
–n-agents 3 \
–no-wandb
The run should complete without errors and show decreasing collision rate.
-
Export the resulting checkpoint to ONNX:
python -m deployment.export_onnx \
–checkpoint checkpoints/latest.pt \
–output-dir deployment/models/
-
Run inference benchmark:
python -m deployment.inference --model deployment/models/actor_0.onnx
-
Generate evaluation plots:
python -m analysis.plots --checkpoint checkpoints/latest.pt
-
Print a final summary table:
| Metric |
Value |
| Collision rate (eval) |
X% |
| Mean ΔV per episode |
X m/s |
| Inference latency |
X ms |
| Model size (ONNX) |
X KB |
\`\`\`
Optional Extensions (tell Claude Code to do these after Phase 11)
```
Extension A — Hierarchical policy:
Add a high-level “conjunction planner” agent that sets waypoints for
the low-level thrust agents. Implement as a two-timescale MAPPO.
Extension B — Adversarial debris:
Add an adversarial agent that controls a subset of debris to maximise
collisions. Train with self-play. Evaluate robustness.
Extension C — Transfer to Basilisk:
Port the environment to NASA’s Basilisk simulator for higher-fidelity
spacecraft dynamics. Use the same ONNX policy weights (zero-shot transfer).
Extension D — Real TLE catalog:
Fetch live TLE data from space-track.org API (requires free account).
Test on current LEO debris population (~20,000 tracked objects).
Extension E — Hardware-in-the-loop:
Wrap inference.py as a ROS 2 node. Publish /cmd_thrust topic.
Subscribe to /spacecraft_state and /debris_positions topics.
```
Dependency List
```toml
pyproject.toml [project.dependencies]
dependencies = [
“torch>=2.3”,
“torchvision”,
“gymnasium>=0.29”,
“pettingzoo>=1.24”,
“numpy>=1.26”,
“scipy>=1.13”,
“sgp4>=2.23”,
“poliastro>=0.17”,
“pyyaml>=6.0”,
“wandb>=0.17”,
“onnx>=1.16”,
“onnxruntime>=1.18”,
“matplotlib>=3.9”,
“plotly>=5.22”,
“tqdm>=4.66”,
“pytest>=8.2”,
“pytest-cov”,
“typer>=0.12”,
]
```
If there is any way to help me fix this issue or allow me access to more credits (I am a college student and researcher in the US), I would greatly appreciate it because Antigravity is an amazing product with so much portential to help me with coding/projects. Thank you so much for your time.