forked from Lifelong-Robot-Learning/LIBERO
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8299841
commit 4f0dd18
Showing
1,108 changed files
with
2,829,483 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
*~ | ||
.hydra | ||
*pyc | ||
datasets | ||
results | ||
outputs/* | ||
/MUJOCO_LOG.TXT | ||
wandb | ||
experiments/ | ||
clip/ | ||
gpt/ | ||
bert/ | ||
logs/ | ||
|
||
*.mp4 | ||
libero.egg-info/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
# LIBERO: Benchmarking Knowledge Transfer in Lifelong Robot Learning | ||
|
||
<div align="center"> | ||
|
||
[[Website]](https://libero-project.github.io) | ||
[[Paper]]() | ||
[[Docs]]() | ||
|
||
</div> | ||
|
||
<p align="center"> | ||
<img src="https://github.com/Lifelong-Robot-Learning/LIBERO/blob/main/misc/fig1.png" width="800"> | ||
</p> | ||
|
||
**LIBERO** is designed for studying knowledge transfer in multitask and lifelong robot learning problems. Successfully resolving these problems require both declarative knowledge about objects/spatial relationships and procedural knowledge about motion/behaviors. **LIBERO** provides: | ||
- A procedural generation pipeline that could in principle generate an infinite number of manipulation tasks. | ||
- 130 tasks grouped into four task suites: **LIBERO-Spatial**, **LIBERO-Object**, **LIBERO-Goal**, and **LIBERO-100**. The first three task suites have controlled distribution shifts, meaning that they require the transfer of a specific type of knowledge. In contrast, **LIBERO-100** consists of 100 manipulation tasks that require the transfer of entangled knowledge. **LIBERO-100** is further splitted into **LIBERO-90** for pretraining a policy and **LIBERO-10** for testing the agent's downstream lifelong learning performance. | ||
- five research topics (**bottom** of the above figure). | ||
- three visuomotor policy network architectures. | ||
- three lifelong learning algorithms with the sequential finetuning and multitask learning baselines. | ||
|
||
--- | ||
|
||
|
||
# Contents | ||
|
||
- [Installation](#Installation) | ||
- [Dataset](#Dataset) | ||
- [Getting Started](#Getting-Started) | ||
- [Retrieve Task](##Retrieve-Task) | ||
- [Training](##Training) | ||
- [Evaluation](##Evaluation) | ||
- [Citation](#Citation) | ||
- [License](#License) | ||
|
||
|
||
# Installtion | ||
Please run the following commands in the given order to install the dependency for **LIBERO**. | ||
``` | ||
conda create -n libero python=3.8.13 | ||
pip install -r requirements.txt | ||
pip install torch==1.11.0+cu113 torchvision==0.12.0+cu113 torchaudio==0.11.0 --extra-index-url https://download.pytorch.org/whl/cu113 | ||
``` | ||
|
||
Then install the `libero` package: | ||
``` | ||
git clone https://github.com/Lifelong-Robot-Learning/LIBERO.git | ||
cd LIBERO | ||
pip install -e . | ||
``` | ||
|
||
# Datasets | ||
We provide high-quality human teleoperation demonstrations for the four task suites in **LIBERO**. To download the demonstration dataset, run: | ||
```python | ||
python benchmark_scripts/download_libero_datasets.py | ||
``` | ||
By default, the dataset will be stored under the ```LIBERO``` folder and all four datasets will be downloaded. To download a specific dataset, use | ||
```python | ||
python benchmark_scripts/download_libero_datasets.py --datasets DATASET | ||
``` | ||
where ```DATASET``` is chosen from `[libero_spatial, libero_object, libero_object, libero_goal`. | ||
|
||
|
||
# Getting Started | ||
|
||
## Retrieve Task | ||
|
||
The following is a minimal example of retrieving a specific task from a specific task suite. | ||
```python | ||
from libero.libero import benchmark | ||
from libero.libero.envs import OffScreenRenderEnv | ||
|
||
|
||
benchmark_dict = benchmark.get_benchmark_dict() | ||
task_suite_name = "libero_10" # can also choose libero_spatial, libero_object, etc. | ||
task_suite = benchmark_dict[task_suite_name]() | ||
|
||
# retrieve a specific task | ||
task_id = 0 | ||
task = task_suite.get_task[task_id] | ||
task_name = task.name | ||
task_description = task.language | ||
task_bddl_file = os.path.join(get_libero_path("bddl_files"), task.problem_folder, task.bddl_file) | ||
print(f"[info] retrieving task {task_id} from suite {task_suite_name}, the " + \ | ||
f"language instruction is {task_description}, and the bddl file is {task_bddl_file}") | ||
|
||
# step over the environment | ||
env_args = { | ||
"bddl_file_name": task_bddl_file, | ||
"camera_heights": 128, | ||
"camera_widths": 128 | ||
} | ||
env = OffScreenRenderEnv(**env_args) | ||
env.seed(0) | ||
env.reset() | ||
init_states = task_suite.get_task_init_states(task_id) # for benchmarking purpose, we fix the a set of initial states | ||
init_state_id = 0 | ||
env.set_init_state(init_states[init_state_id]) | ||
|
||
dummy_action = [0.] * 7 | ||
for step in range(10): | ||
obs, reward, done, info = env.step(dymmy_action) | ||
env.close() | ||
``` | ||
Currently, we only support sparse reward function (i.e., the agent receives `+1` when the task is finished). As sparse-reward RL is extremely hard to learn, currently we mainly focus on lifelong imitation learning. | ||
|
||
## Training | ||
To start a lifelong learning experiment, please choose: | ||
- `BENCHMARK` from `[LIBERO_SPATIAL, LIBERO_OBJECT, LIBERO_GOAL, LIBERO_90, LIBERO_10]` | ||
- `POLICY` from `[bc_rnn_policy, bc_transformer_policy, bc_vilt_policy]` | ||
- `ALGO` from `[base, er, ewc, packnet, multitask]` | ||
|
||
then run the following: | ||
|
||
```shell | ||
export CUDA_VISIBLE_DEVICES=GPU_ID && \ | ||
export MUJOCO_EGL_DEVICE_ID=GPU_ID && \ | ||
python libero/lifelong/main.py seed=SEED \ | ||
benchmark_name=BENCHMARK | ||
policy=POLICY \ | ||
lifelong=ALGO | ||
``` | ||
Please see the documentation for the details of reproducing the study results. | ||
|
||
## Evaluation | ||
|
||
By default the policies will be evaluated on the fly during training. If you have limited computing resource of GPUs, we offer an evaluation script for you to evaluate models separately. | ||
|
||
```shell | ||
python libero/lifelong/evaluate.py --benchmark BENCHMARK_NAME \ | ||
--task_id TASK_ID \ | ||
--algo ALGO_NAME \ | ||
--policy POLICY_NAME \ | ||
--seed SEED | ||
``` | ||
|
||
# Citation | ||
If you find **LIBERO** to be useful in your own research, please consider citing our paper: | ||
|
||
```bibtex | ||
@misc{liu2023libero, | ||
title={LIBERO: Benchmarking Knowledge Transfer for Lifelong Robot Learning}, | ||
author={Bo Liu and Yifeng Zhu and Chongkai Gao and Yihao Feng and Qiang Liu and Yuke Zhu and Peter Stone}, | ||
year={2023}, | ||
eprint={2306.03310}, | ||
archivePrefix={arXiv}, | ||
primaryClass={cs.AI} | ||
} | ||
``` | ||
|
||
# License | ||
|
||
| Component | License | | ||
|-----------|----------------------------------------------------------------------------------------------------------------------| | ||
| Codebase | [MIT License](LICENSE) | | ||
| Dataset | [Creative Commons Attribution 4.0 International (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/legalcode) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
""" | ||
This script is to test if users can successfully load all the environments, the benchmark initial states in their machines | ||
""" | ||
import os | ||
from termcolor import colored | ||
import cv2 | ||
import h5py | ||
import subprocess | ||
import shutil | ||
import numpy as np | ||
|
||
from pathlib import Path | ||
|
||
# import init_path | ||
from libero.libero import benchmark, get_libero_path | ||
|
||
|
||
# def render_task(task, bddl_file, init_states, demo_file): | ||
# env_args = { | ||
# "bddl_file_name": bddl_file, | ||
# "camera_heights": 128, | ||
# "camera_widths": 128 | ||
# } | ||
|
||
# env = OffScreenRenderEnv(**env_args) | ||
# env.reset() | ||
# obs = env.set_init_state(init_states[0]) | ||
# for _ in range(5): | ||
# obs, _, _, _ = env.step([0.] * 7) | ||
# images = [obs["agentview_image"]] | ||
|
||
# with h5py.File(demo_file, "r") as f: | ||
# states = f["data/demo_0/states"][()] | ||
# obs = env.set_init_state(states[-1]) | ||
|
||
# images.append(obs["agentview_image"]) | ||
# images = np.concatenate(images, axis=1) | ||
# cv2.imwrite(f"benchmark_tasks/{task.problem}-{task.language}.png", images[::-1, :, ::-1]) | ||
# env.close() | ||
|
||
|
||
def main(): | ||
|
||
benchmark_root_path = get_libero_path("benchmark_root") | ||
init_states_default_path = get_libero_path("init_states") | ||
datasets_default_path = get_libero_path("datasets") | ||
bddl_files_default_path = get_libero_path("bddl_files") | ||
|
||
# Check all the files | ||
task_tuples = [] | ||
demo_files = [] | ||
for benchmark_name in [ | ||
"libero_object", | ||
"libero_goal", | ||
"libero_spatial", | ||
"libero_10", | ||
"libero_90", | ||
]: | ||
benchmark_instance = benchmark.get_benchmark_dict()[benchmark_name]() | ||
num_tasks = benchmark_instance.get_num_tasks() | ||
# see how many tasks involved in the benchmark | ||
print(f"{num_tasks} tasks in the benchmark {benchmark_instance.name}: ") | ||
|
||
# Check if all the task names and their bddl file names | ||
task_names = benchmark_instance.get_task_names() | ||
print("The benchmark contains the following tasks:") | ||
for task_id in range(num_tasks): | ||
task_name = task_names[task_id] | ||
task = benchmark_instance.get_task(task_id) | ||
bddl_file = os.path.join( | ||
bddl_files_default_path, task.problem_folder, task.bddl_file | ||
) | ||
assert os.path.exists(bddl_file), f"{bddl_file} does not exist!" | ||
init_states_path = os.path.join( | ||
init_states_default_path, task.problem_folder, task.init_states_file | ||
) | ||
assert os.path.exists( | ||
init_states_path | ||
), f"{init_states_path} does not exist!" | ||
demo_file = os.path.join( | ||
datasets_default_path, | ||
benchmark_instance.get_task_demonstration(task_id), | ||
) | ||
assert os.path.exists(demo_file), f"{demo_file} does not exist!" | ||
init_states = benchmark_instance.get_task_init_states(task_id) | ||
task_tuples.append((benchmark_name, task_id, bddl_file, demo_file)) | ||
demo_files.append(demo_file) | ||
|
||
print(colored("All the files exist!", "green")) | ||
processes = [] | ||
if os.path.exists("benchmark_tasks"): | ||
shutil.rmtree("benchmark_tasks") | ||
|
||
for i in range(len(task_tuples)): | ||
command = f"python benchmark_scripts/render_single_task.py --benchmark_name {task_tuples[i][0]} --task_id {task_tuples[i][1]} --bddl_file {task_tuples[i][2]} --demo_file {task_tuples[i][3]}" | ||
p = subprocess.Popen(command, shell=True) | ||
processes.append(p) | ||
if i % 10 == 9: | ||
for p in processes: | ||
p.wait() | ||
processes = [] | ||
|
||
count = len(list(Path("benchmark_tasks").glob("*.png"))) | ||
print(f"Expected 130 tasks, Rendered {count} tasks successfully.") | ||
if count < 130: | ||
print(colored("Some tasks failed to render!", "red")) | ||
for demo_file in demo_files: | ||
if not os.path.exists( | ||
os.path.join( | ||
"benchmark_tasks", demo_file.split("/")[-1].replace(".hdf5", ".png") | ||
) | ||
): | ||
print(demo_file) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import init_path | ||
import argparse | ||
import os | ||
|
||
import libero.libero.utils.download_utils as download_utils | ||
from libero.libero import get_libero_path | ||
|
||
|
||
def parse_args(): | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument( | ||
"--download-dir", | ||
type=str, | ||
default=get_libero_path("datasets"), | ||
) | ||
parser.add_argument( | ||
"--datasets", | ||
type=str, | ||
choices=["all", "libero_goal", "libero_spatial", "libero_object", "libero_100"], | ||
default="all", | ||
) | ||
return parser.parse_args() | ||
|
||
|
||
def main(): | ||
|
||
args = parse_args() | ||
|
||
# Ask users to specify the download directory of datasets | ||
os.makedirs(args.download_dir, exist_ok=True) | ||
print(f"Datasets downloaded to {args.download_dir}") | ||
print(f"Downloading {args.datasets} datasets") | ||
|
||
# If not, download | ||
download_utils.libero_dataset_download( | ||
download_dir=args.download_dir, datasets=args.datasets | ||
) | ||
|
||
# (TODO) If datasets exist, check if datasets are the same as benchmark | ||
|
||
# Check if datasets exist first | ||
download_utils.check_libero_dataset(download_dir=args.download_dir) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import sys | ||
import os | ||
|
||
path = os.path.dirname(os.path.realpath(__file__)) | ||
sys.path.insert(0, os.path.join(path, "../")) | ||
|
||
# import robosuite.utils.macros as macros | ||
# macros.IMAGE_CONVENTION = "opencv" |
Oops, something went wrong.