Repository
future-robots
[](LICENSE) [](https://www.python.org/downloads/) [! · License MIT · Install via pip · Maintenance unmaintained
- License
- MIT
- Parameter
- Type
- shuffle_prob
- float
- image_mask_prob
- float
Specs
- ParameterType
- shuffle_probfloat
- image_mask_probfloat
- image_noise_probfloat
- mask_multiple_imagesbool
- max_masked_imagesint
- noise_stdfloat
- single_arm_idint/None
- FeatureLegacy
- Code ReuseCode Reuse
- ScalabilityScalability
- ConsistencyConsistency
- MaintainabilityMaintainability
- AugmentationAugmentation
- DeprecatedReplacement
- DroidDualInputs_atomDroidMultiInputs_atom(num_agents=2)
- DroidDualInputsDroidMultiInputs(num_agents=2)
- DroidTripleInputs_atomDroidMultiInputs_atom(num_agents=3)
- DroidTripleInputsDroidMultiInputs(num_agents=3)
- DroidQuadInputs_atomDroidMultiInputs_atom(num_agents=4)
- DroidQuadInputsDroidMultiInputs(num_agents=4)
- VariantDescription
- BaselineBaseline
- + Atom+ Atom
- + MoE+ MoE
README
🌱 Future
Future is a research ecosystem working toward one goal: agentic, open-ended VLA policies — agents that decompose a goal into atomic skills, compose them on the fly, and coordinate multiple effectors to solve tasks they were never explicitly trained on.
Its first work, MA-VLA (Multi-Arm Vision-Language-Action Model for Collaboration and Compositional Generalization), introduces multi-arm compositional generalization and is accepted to ECCV 2026. More works are on the way. 🚀
📋 Table of Contents
- Features
- Installation
- Quick Start
- Data Processing
- Training Modes
- Deployment
- Data Transform Configuration
- Architecture Matrix
- Advanced Usage
- Roadmap
- Citation
✨ Features
- 🔄 Unified Multi-Agent Support: Single codebase for 2-4 robot arms
- 🎯 Flexible Training Modes:
- Unified model (one model controls all arms)
- Separate model (dedicated model per arm)
- 🎨 Rich Data Augmentation: Image masking, Gaussian noise, agent order shuffling
- 🧩 Mixture of Experts (MoE): Advanced architecture for 3+ arms
- 📊 Atomic Action Learning: Fine-grained action decomposition for compositional generalization
- 🧪 MACG Benchmark: Multi-Arm Compositional Generalization data-generation pipeline
- ⚡ Scalable Design: Easy to extend to 5+ arms
🚀 Installation
Prerequisites
- Python 3.10+
- CUDA-compatible GPU
- Git LFS
Setup
# Clone the repository
git clone https://github.com/yourusername/multivla-pi0.git
cd multivla-pi0
# Install dependencies
GIT_LFS_SKIP_SMUDGE=1 uv sync
GIT_LFS_SKIP_SMUDGE=1 uv pip install -e .
# Activate environment
source .venv/bin/activate
🎯 Quick Start
1. Prepare Your Dataset
# Generate atomic action dataset
python scripts/tasks/convert_h5_lerobot_stackcubes.py \
--h5_path path/to/h5file/with/phase \
--output_dir path/to/output \
--task_name your_task_name \
--use_phase
# Compute normalization statistics
uv run scripts/compute_norm_stats.py --config-name your_config_name
2. Train Your Model
Unified Training (one model for all arms):
XLA_PYTHON_CLIENT_MEM_FRACTION=1 uv run scripts/train.py pi0_base_3arms_stackcubes_mavla \
--exp-name=mavla_unified_threestackcubes \
--overwrite
Separate Training (one model per arm):
XLA_PYTHON_CLIENT_MEM_FRACTION=1 uv run scripts/train.py pi0_base_3arms_stackcubes_agent0 \
--exp-name=mavla_separate_agent0 \
--overwrite
3. Deploy the Model
python server_agent0.py \
--config pi0_base_3arms_stackcubes_atom_shuffle \
--checkpoint_dir /path/to/checkpoint/directory \
--port 20019
📊 Data Processing
Phase Assignment
Assign task phases to trajectory segments for atomic action learning.
# Implementation coming soon
# This will enable automatic phase labeling for complex multi-step tasks
Language Instruction Assignment
Step 1: Generate Atomic Action Dataset
Convert H5 format data to LeRobot-compatible format with phase annotations:
python scripts/tasks/convert_h5_lerobot_stackcubes.py \
--h5_path /path/to/your/h5_file_with_phases.h5 \
--output_dir /path/to/empty/output/directory \
--task_name stackcubes \
--use_phase
Parameters:
--h5_path: Path to H5 file containing trajectory data with phase labels--output_dir: Empty directory for output (will be created if not exists)--task_name: Task identifier (e.g., stackcubes, takephoto, passshoe)--use_phase: Enable phase-based atomic action generation
Step 2: Compute Normalization Statistics
Calculate mean and standard deviation for action normalization:
uv run scripts/compute_norm_stats.py --config-name <config_name>
Note: Ensure shuffle_prob=0.0 in your config when computing statistics to avoid data randomization.
MACG Data Generation
Data Generation for Multi-arm Compositional Generalization Benchmark
# set phase for stack macg task
python scripts/set_atom/macg/set_phases_to_h5_threestackcube.py
# generate video
python scripts/set_atom/macg/visualize_phases_threestackcube.py
# generate dataset
python scripts/set_atom/macg/placefactory/convert_h5_lerobot_placefactory.py --h5_path dataset/placefactory_order_123_20251216_with_phases.h5 --output_dir dataset/placefactory --task_name placefactory --use_phase
# compute the norm states
uv run scripts/compute_norm_stats.py --config-name pi0_base_3arms_placefactory_mavla_macg
# start run :)
XLA_PYTHON_CLIENT_MEM_FRACTION=1 uv run scripts/train.py pi0_base_3arms_placefactory_mavla_macg \
--exp-name=macg_placefactory \
--overwrite
🎓 Training Modes
Unified Arm Training
Description: Single model learns to control all robot arms simultaneously. The model receives observations from all arms and outputs actions for all arms in one forward pass.
Advantages:
- ✅ Shared representation learning across arms
- ✅ Better generalization to new configurations
- ✅ Single model deployment
- ✅ Implicit coordination learning
Example: 3-arm stack cubes task
XLA_PYTHON_CLIENT_MEM_FRACTION=1 uv run scripts/train.py pi0_base_3arms_stackcubes_mavla \
--exp-name=mavla_unified_threestackcubes \
--overwrite
Configuration:
data_transforms=lambda model_config: _transforms.Group(
inputs=[droid_policy.DroidMultiInputs_atom(
action_dim=model_config.action_dim,
num_agents=3,
model_type=ModelType.PI0,
shuffle_prob=0.5,
image_mask_prob=0.3
)],
outputs=[droid_policy.DroidMultiOutputs_atom(num_agents=3)]
)
Separate Arm Training
Description: Train individual models for each robot arm. Each model specializes in controlling a single arm using the single_arm_id parameter to filter the data.
Advantages:
- ✅ Specialized control per arm
- ✅ Independent optimization
- ✅ Modular deployment (hot-swap arms)
- ✅ Easier debugging and analysis
Example: Train models for a 3-arm system
Agent 0:
XLA_PYTHON_CLIENT_MEM_FRACTION=1 uv run scripts/train.py pi0_base_3arms_stackcubes_agent0 \
--exp-name=mavla_separate_agent0 \
--overwrite
Agent 1:
XLA_PYTHON_CLIENT_MEM_FRACTION=1 uv run scripts/train.py pi0_base_3arms_stackcubes_agent1 \
--exp-name=mavla_separate_agent1 \
--overwrite
Agent 2:
XLA_PYTHON_CLIENT_MEM_FRACTION=1 uv run scripts/train.py pi0_base_3arms_stackcubes_agent2 \
--exp-name=mavla_separate_agent2 \
--overwrite
Configuration:
data_transforms=lambda model_config: _transforms.Group(
inputs=[droid_policy.DroidMultiInputs_atom(
action_dim=model_config.action_dim,
num_agents=3,
model_type=ModelType.PI0,
shuffle_prob=0.0, # Disable shuffling for single-arm training
image_mask_prob=0.0, # Disable masking for single-arm training
single_arm_id=0 # Target arm ID (0, 1, 2, ...)
)],
outputs=[droid_policy.DroidMultiOutputs_atom(
num_agents=3,
single_arm_id=0 # Must match input single_arm_id
)]
)
Key Parameter: single_arm_id
- Purpose: Filters multi-agent data to extract single-arm trajectories for specialized training
- Type:
intorNone - Values:
0, 1, 2, ...: Train on specific arm's data onlyNone: Train on all arms (unified mode)
- Usage: Set the same
single_arm_idin bothDroidMultiInputs_atomandDroidMultiOutputs_atom - Data Augmentation: When using
single_arm_id, setshuffle_prob=0.0andimage_mask_prob=0.0to ensure consistent single-arm behavior
🌐 Deployment
Unified Model Deployment
Note: the following code now support Robofactory but not support Robotwin. We will update Robotwin later.
Deploy a single model serving all robot arms:
python server.py \
--config pi0_base_3arms_stackcubes_mavla \
--checkpoint_dir /path/to/unified/checkpoint \
--port 20019
Separate Model Deployment
Deploy individual models for each arm with memory-efficient settings:
# Agent 0 (Port 20019)
XLA_PYTHON_CLIENT_PREALLOCATE=false \
XLA_PYTHON_CLIENT_MEM_FRACTION=0.4 \
python server_agent0.py \
--config pi0_base_3arms_stackcubes_agent0 \
--checkpoint_dir /path/to/agent0/checkpoint \
--port 20019
# Agent 1 (Port 20020)
XLA_PYTHON_CLIENT_PREALLOCATE=false \
XLA_PYTHON_CLIENT_MEM_FRACTION=0.4 \
python server_agent1.py \
--config pi0_base_3arms_stackcubes_agent1 \
--checkpoint_dir /path/to/agent1/checkpoint \
--port 20020
# Agent 2 (Port 20021)
XLA_PYTHON_CLIENT_PREALLOCATE=false \
XLA_PYTHON_CLIENT_MEM_FRACTION=0.4 \
python server_agent2.py \
--config pi0_base_3arms_stackcubes_agent2 \
--checkpoint_dir /path/to/agent2/checkpoint \
--port 20021
Memory Management:
XLA_PYTHON_CLIENT_PREALLOCATE=false: Disable pre-allocation for flexible memory usageXLA_PYTHON_CLIENT_MEM_FRACTION=0.4: Limit each model to 40% GPU memory (adjust based on your GPU)
🔧 Data Transform Configuration
Unified Multi-Agent Transform Classes
The codebase uses unified data transform classes that support 2-4 robot arms with a single num_agents parameter, replacing 6+ redundant legacy classes.
Training with Data Augmentation (atom version)
For multi-arm unified training:
DroidMultiInputs_atom(
action_dim=32, # Model action dimension (padded)
num_agents=3, # Number of robot arms (2-4)
model_type=ModelType.PI0, # Model architecture
shuffle_prob=0.5, # Agent order shuffling probability
image_mask_prob=0.3, # Image masking probability
image_noise_prob=0.2, # Gaussian noise probability
mask_multiple_images=True, # Allow multiple image masking
max_masked_images=4, # Max images to mask simultaneously
noise_std=0.02, # Gaussian noise standard deviation
single_arm_id=None # None for unified training
)
DroidMultiOutputs_atom(
num_agents=3,
single_arm_id=None
)
For single-arm separate training:
DroidMultiInputs_atom(
action_dim=32,
num_agents=3,
model_type=ModelType.PI0,
shuffle_prob=0.0, # Disable for single-arm
image_mask_prob=0.0, # Disable for single-arm
image_noise_prob=0.0, # Disable for single-arm
single_arm_id=0 # Target arm (0, 1, 2, ...)
)
DroidMultiOutputs_atom(
num_agents=3,
single_arm_id=0 # Must match input
)
Inference (non-atom version)
For deployment without atomic action learning:
DroidMultiInputs(
action_dim=32,
num_agents=3,
model_type=ModelType.PI0,
task_instruction="Stack the cubes" # Fixed task instruction
)
DroidMultiOutputs(num_agents=3)
📖 Data Augmentation Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
shuffle_prob |
float |
0.0 |
Probability to shuffle agent order (states, actions, prompts) |
image_mask_prob |
float |
0.0 |
Probability to mask images to zeros (1-N images) |
image_noise_prob |
float |
0.0 |
Probability to add Gaussian noise to images |
mask_multiple_images |
bool |
True |
Allow masking multiple images simultaneously |
max_masked_images |
int |
4 |
Maximum number of images to mask at once |
noise_std |
float |
0.02 |
Standard deviation of Gaussian noise |
single_arm_id |
int/None |
None |
Target arm ID for separate training (None for unified) |
Smart Augmentation Logic:
- When all agents have identical instructions, shuffling and masking are automatically disabled to maintain consistency
- When
single_arm_idis set, augmentation probabilities should typically be set to 0.0
🏆 Benefits of Unified Classes
| Feature | Legacy | Unified |
|---|---|---|
| Code Reuse | 6+ redundant classes | 1 unified class |
| Scalability | Hard-coded for 2/3/4 arms | Easy to extend to 5+ arms |
| Consistency | Inconsistent APIs | Uniform interface |
| Maintainability | Multiple files to update | Single source of truth |
| Augmentation | Limited support | Full feature parity |
⚠️ Legacy Classes (Deprecated)
The following classes remain for backward compatibility but are deprecated:
| Deprecated | Replacement |
|---|---|
DroidDualInputs_atom |
DroidMultiInputs_atom(num_agents=2) |
DroidDualInputs |
DroidMultiInputs(num_agents=2) |
DroidTripleInputs_atom |
DroidMultiInputs_atom(num_agents=3) |
DroidTripleInputs |
DroidMultiInputs(num_agents=3) |
DroidQuadInputs_atom |
DroidMultiInputs_atom(num_agents=4) |
DroidQuadInputs |
DroidMultiInputs(num_agents=4) |
Migration: All training configs in config.py have been updated to use unified classes.
📐 Architecture Matrix
| Arms | Task | Baseline | + Atom | + MoE | Status |
|---|---|---|---|---|---|
| 1 | Individual | ❌ | ❌ | ❌ | 🔜 Coming Soon |
| 2 | Pass Shoe | ✅ | ✅ | ❌ | ✅ Available |
| 3 | Stack Cubes | ✅ | ✅ | ✅ | ✅ Available |
| 4 | Take Photo | ✅ | ❌ | ✅ | ✅ Available |
| 4 | Long Pipeline | ✅ | ❌ | ✅ | ✅ Available |
Legend:
- Baseline: Standard multi-agent VLA
- + Atom: Atomic action learning with phase decomposition
- + MoE: Mixture of Experts architecture (available for 3+ arms)
🔬 Advanced Usage
Creating a Custom Config
Define a new training configuration in config.py:
TrainConfig(
name="my_3arms_custom_task",
# Model configuration
model=pi0.Pi0Config(
action_dim=32, # 3 agents × 8 dims = 24, padded to 32
action_horizon=50, # Action prediction horizon
max_token_len=220, # Maximum token length
),
# Data configuration
data=SimpleDataConfig(
repo_id="path/to/your/dataset",
assets=AssetsConfig(
assets_dir="path/to/assets",
asset_id="your_asset_id"
),
# Data transforms with augmentation
data_transforms=lambda model_config: _transforms.Group(
inputs=[droid_policy.DroidMultiInputs_atom(
action_dim=model_config.action_dim,
num_agents=3,
model_type=ModelType.PI0,
shuffle_prob=0.5, # 50% shuffle
image_mask_prob=0.3, # 30% masking
image_noise_prob=0.2 # 20% noise
)],
outputs=[droid_policy.DroidMultiOutputs_atom(num_agents=3)],
),
base_config=DataConfig(prompt_from_task=True),
),
# Weight initialization
weight_loader=weight_loaders.CheckpointWeightLoader(
"path/to/pretrained/params"
),
# Training hyperparameters
lr_schedule=_optimizer.CosineDecaySchedule(
warmup_steps=300,
peak_lr=3e-5,
decay_steps=10000,
decay_lr=1e-6,
),
num_train_steps=15000,
batch_size=32,
log_interval=50,
save_interval=1000,
)
Key Configuration Tips
-
Action Dimension: Set to nearest power of 2 above
num_agents × action_dim_per_arm- 2 arms × 8 dims = 16 →
action_dim=16or32 - 3 arms × 8 dims = 24 →
action_dim=32 - 4 arms × 8 dims = 32 →
action_dim=32
- 2 arms × 8 dims = 16 →
-
Token Length: Increase for more images
- 2 arms + 1 global:
max_token_len=150-180 - 3 arms + 1 global:
max_token_len=200-220 - 4 arms + 1 global:
max_token_len=250-280
- 2 arms + 1 global:
-
Data Augmentation:
- High diversity tasks: increase
shuffle_probandimage_mask_prob - Low diversity tasks: use conservative augmentation
- Single-arm training: set all augmentation to 0.0
- High diversity tasks: increase
-
Training Steps:
- Small datasets (<1000 episodes): 5000-10000 steps
- Medium datasets (1000-5000 episodes): 10000-20000 steps
- Large datasets (>5000 episodes): 20000-50000 steps
📝 Development Notes
Configuration Management
All modifications correspond to specific config files. You can trace model and data processing files through the config system:
# Find config by name
grep -n "name=\"your_config_name\"" src/openpi/training/config.py
Version Control
Use git commit history to track changes:
# View file history
git log --follow -- src/openpi/policies/droid_policy.py
# Compare versions
git diff <commit1> <commit2> -- src/openpi/training/config.py
Model Variants
| Variant | Description | Use Case |
|---|---|---|
| Baseline | Standard multi-agent VLA | General-purpose coordination |
| + Atom | Atomic action learning | Complex multi-step tasks |
| + MoE | Mixture of Experts | High-capacity for 3+ arms |
🗺️ Roadmap
This codebase evolves alongside our research program toward open-ended agentic embodied policies.
- [x] MA-VLA (ECCV 2026) — Unified multi-arm VLA, atomic action learning, MACG benchmark
- [x] Unified 2–4 arm training & deployment (unified / separate modes)
- [x] Mixture of Experts (MoE) for 3+ arms
- [ ] Single-arm baselines and broader task coverage
- [ ] Agentic skill composition — decompose goals into atomic skills and compose them at inference
- [ ] Open-ended task generalization — solve unseen task combinations without task-specific training
- [ ] Long-horizon planning and closed-loop self-correction
🚧 Each step builds on the last: from collaboration → compositional generalization → open-ended agentic policies.
📚 Citation
If you find MA-VLA or this codebase useful in your research, please cite:
comming soon
🤝 Contributing
We welcome contributions! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
We would like to thank the following projects for their inspiration and contributions to the robotics community:
- OpenPI - Physical Intelligence foundation
📧 Contact
For questions and discussions:
- Open an Issue
- Start a Discussion
Training with Data Augmentation ( atom version)
1
-
For multi-arm unified training:
Inference (non- atom version)
1
-
For deployment without atomic action learning: