From f5e76393eb661b007c75f291b45a9945499fa5a6 Mon Sep 17 00:00:00 2001 From: Simon Alibert <75076266+aliberts@users.noreply.github.com> Date: Mon, 6 May 2024 03:03:14 +0200 Subject: [PATCH 01/27] Release cleanup (#132) Co-authored-by: Kashif Rasul Co-authored-by: Alexander Soare Co-authored-by: Adil Zouitine Co-authored-by: Cadene --- .github/PULL_REQUEST_TEMPLATE.md | 26 ++- README.md | 205 ++++++++---------- examples/1_load_lerobot_dataset.py | 48 ++-- examples/2_evaluate_pretrained_policy.py | 111 ++++++++-- examples/3_train_policy.py | 28 ++- lerobot/__init__.py | 7 - .../datasets/_video_benchmark/README.md | 6 +- lerobot/common/datasets/lerobot_dataset.py | 38 +++- .../push_dataset_to_hub/aloha_hdf5_format.py | 8 +- lerobot/configs/default.yaml | 2 +- lerobot/scripts/eval.py | 23 +- lerobot/scripts/push_dataset_to_hub.py | 4 +- lerobot/scripts/train.py | 17 +- lerobot/scripts/visualize_dataset.py | 4 +- media/wandb.png | Bin 0 -> 416489 bytes pyproject.toml | 2 +- tests/test_available.py | 2 +- tests/test_datasets.py | 4 +- tests/test_examples.py | 14 +- 19 files changed, 312 insertions(+), 237 deletions(-) create mode 100644 media/wandb.png diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a9b733d4..4063e395 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,11 +1,15 @@ -# What does this PR do? +## What this does +Explain what this PR does. Feel free to tag your PR with the appropriate label(s). Examples: -- Fixes # (issue) -- Adds new dataset -- Optimizes something +| Title | Label | +|----------------------|-----------------| +| Fixes #[issue] | (๐Ÿ› Bug) | +| Adds new dataset | (๐Ÿ—ƒ๏ธ Dataset) | +| Optimizes something | (โšก๏ธ Performance) | -## How was it tested? +## How it was tested +Explain/show how you tested your changes. Examples: - Added `test_something` in `tests/test_stuff.py`. @@ -13,6 +17,7 @@ Examples: - Optimized `some_function`, it now runs X times faster than previously. ## How to checkout & try? (for the reviewer) +Provide a simple way for the reviewer to try out your changes. Examples: ```bash @@ -22,11 +27,8 @@ DATA_DIR=tests/data pytest -sx tests/test_stuff.py::test_something python lerobot/scripts/train.py --some.option=true ``` -## Before submitting -Please read the [contributor guideline](https://github.com/huggingface/lerobot/blob/main/CONTRIBUTING.md#submitting-a-pull-request-pr). - - -## Who can review? - -Anyone in the community is free to review the PR once the tests have passed. Feel free to tag +## SECTION TO REMOVE BEFORE SUBMITTING YOUR PR +**Note**: Anyone in the community is free to review the PR once the tests have passed. Feel free to tag members/contributors who may be interested in your PR. Try to avoid tagging more than 3 people. + +**Note**: Before submitting this PR, please read the [contributor guideline](https://github.com/huggingface/lerobot/blob/main/CONTRIBUTING.md#submitting-a-pull-request-pr). diff --git a/README.md b/README.md index ff4aa498..a305dbff 100644 --- a/README.md +++ b/README.md @@ -29,15 +29,15 @@ --- -๐Ÿค— LeRobot aims to provide models, datasets, and tools for real-world robotics in PyTorch. The goal is to lower the barrier for entry to robotics so that everyone can contribute and benefit from sharing datasets and pretrained models. +๐Ÿค— LeRobot aims to provide models, datasets, and tools for real-world robotics in PyTorch. The goal is to lower the barrier to entry to robotics so that everyone can contribute and benefit from sharing datasets and pretrained models. ๐Ÿค— LeRobot contains state-of-the-art approaches that have been shown to transfer to the real-world with a focus on imitation learning and reinforcement learning. -๐Ÿค— LeRobot already provides a set of pretrained models, datasets with human collected demonstrations, and simulated environments so that everyone can get started. In the coming weeks, the plan is to add more and more support for real-world robotics on the most affordable and capable robots out there. +๐Ÿค— LeRobot already provides a set of pretrained models, datasets with human collected demonstrations, and simulation environments to get started without assembling a robot. In the coming weeks, the plan is to add more and more support for real-world robotics on the most affordable and capable robots out there. -๐Ÿค— LeRobot hosts pretrained models and datasets on this HuggingFace community page: [huggingface.co/lerobot](https://huggingface.co/lerobot) +๐Ÿค— LeRobot hosts pretrained models and datasets on this Hugging Face community page: [huggingface.co/lerobot](https://huggingface.co/lerobot) -#### Examples of pretrained models and environments +#### Examples of pretrained models on simulation environments @@ -54,10 +54,12 @@ ### Acknowledgment -- ACT policy and ALOHA environment are adapted from [ALOHA](https://tonyzhaozh.github.io/aloha/) -- Diffusion policy and Pusht environment are adapted from [Diffusion Policy](https://diffusion-policy.cs.columbia.edu/) -- TDMPC policy and Simxarm environment are adapted from [FOWM](https://www.yunhaifeng.com/FOWM/) -- Abstractions and utilities for Reinforcement Learning come from [TorchRL](https://github.com/pytorch/rl) +- Thanks to Tony Zaho, Zipeng Fu and colleagues for open sourcing ACT policy, ALOHA environments and datasets. Ours are adapted from [ALOHA](https://tonyzhaozh.github.io/aloha) and [Mobile ALOHA](https://mobile-aloha.github.io). +- Thanks to Cheng Chi, Zhenjia Xu and colleagues for open sourcing Diffusion policy, Pusht environment and datasets, as well as UMI datasets. Ours are adapted from [Diffusion Policy](https://diffusion-policy.cs.columbia.edu) and [UMI Gripper](https://umi-gripper.github.io). +- Thanks to Nicklas Hansen, Yunhai Feng and colleagues for open sourcing TDMPC policy, Simxarm environments and datasets. Ours are adapted from [TDMPC](https://github.com/nicklashansen/tdmpc) and [FOWM](https://www.yunhaifeng.com/FOWM). +- Thanks to Vincent Moens and colleagues for open sourcing [TorchRL](https://github.com/pytorch/rl). It allowed for quick experimentations on the design of `LeRobot`. +- Thanks to Antonio Loquercio and Ashish Kumar for their early support. + ## Installation @@ -86,7 +88,7 @@ For instance, to install ๐Ÿค— LeRobot with aloha and pusht, use: pip install ".[aloha, pusht]" ``` -To use [Weights and Biases](https://docs.wandb.ai/quickstart) for experiments tracking, log in with +To use [Weights and Biases](https://docs.wandb.ai/quickstart) for experiment tracking, log in with ```bash wandb login ``` @@ -95,6 +97,7 @@ wandb login ``` . +โ”œโ”€โ”€ examples # contains demonstration examples, start here to learn about LeRobot โ”œโ”€โ”€ lerobot | โ”œโ”€โ”€ configs # contains hydra yaml files with all options that you can override in the command line | | โ”œโ”€โ”€ default.yaml # selected by default, it loads pusht environment and diffusion policy @@ -103,69 +106,84 @@ wandb login | โ”œโ”€โ”€ common # contains classes and utilities | | โ”œโ”€โ”€ datasets # various datasets of human demonstrations: aloha, pusht, xarm | | โ”œโ”€โ”€ envs # various sim environments: aloha, pusht, xarm -| | โ””โ”€โ”€ policies # various policies: act, diffusion, tdmpc -| โ””โ”€โ”€ scripts # contains functions to execute via command line -| โ”œโ”€โ”€ visualize_dataset.py # load a dataset and render its demonstrations -| โ”œโ”€โ”€ eval.py # load policy and evaluate it on an environment -| โ””โ”€โ”€ train.py # train a policy via imitation learning and/or reinforcement learning +| | โ”œโ”€โ”€ policies # various policies: act, diffusion, tdmpc +| | โ””โ”€โ”€ utils # various utilities +| โ””โ”€โ”€ scripts # contains functions to execute via command line +| โ”œโ”€โ”€ eval.py # load policy and evaluate it on an environment +| โ”œโ”€โ”€ train.py # train a policy via imitation learning and/or reinforcement learning +| โ”œโ”€โ”€ push_dataset_to_hub.py # convert your dataset into LeRobot dataset format and upload it to the Hugging Face hub +| โ””โ”€โ”€ visualize_dataset.py # load a dataset and render its demonstrations โ”œโ”€โ”€ outputs # contains results of scripts execution: logs, videos, model checkpoints -โ”œโ”€โ”€ .github -| โ””โ”€โ”€ workflows -| โ””โ”€โ”€ test.yml # defines install settings for continuous integration and specifies end-to-end tests โ””โ”€โ”€ tests # contains pytest utilities for continuous integration - ``` ### Visualize datasets -Check out [examples](./examples) to see how you can import our dataset class, download the data from the HuggingFace hub and use our rendering utilities. +Check out [example 1](./examples/1_load_lerobot_dataset.py) that illustrates how to use our dataset class which automatically download data from the Hugging Face hub. -Or you can achieve the same result by executing our script from the command line: +You can also locally visualize episodes from a dataset by executing our script from the command line: ```bash python lerobot/scripts/visualize_dataset.py \ -env=pusht \ -hydra.run.dir=outputs/visualize_dataset/example -# >>> ['outputs/visualize_dataset/example/episode_0.mp4'] + --repo-id lerobot/pusht \ + --episode-index 0 ``` +It will open `rerun.io` and display the camera streams, robot states and actions, like this: + +https://github-production-user-asset-6210df.s3.amazonaws.com/4681518/328035972-fd46b787-b532-47e2-bb6f-fd536a55a7ed.mov?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAVCODYLSA53PQK4ZA%2F20240505%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240505T172924Z&X-Amz-Expires=300&X-Amz-Signature=d680b26c532eeaf80740f08af3320d22ad0b8a4e4da1bcc4f33142c15b509eda&X-Amz-SignedHeaders=host&actor_id=24889239&key_id=0&repo_id=748713144 + + +Our script can also visualize datasets stored on a distant server. See `python lerobot/scripts/visualize_dataset.py --help` for more instructions. + ### Evaluate a pretrained policy -Check out [examples](./examples) to see how you can load a pretrained policy from HuggingFace hub, load up the corresponding environment and model, and run an evaluation. +Check out [example 2](./examples/2_evaluate_pretrained_policy.py) that illustrates how to download a pretrained policy from Hugging Face hub, and run an evaluation on its corresponding environment. -Or you can achieve the same result by executing our script from the command line: +We also provide a more capable script to parallelize the evaluation over multiple environments during the same rollout. Here is an example with a pretrained model hosted on [lerobot/diffusion_pusht](https://huggingface.co/lerobot/diffusion_pusht): ```bash python lerobot/scripts/eval.py \ --p lerobot/diffusion_pusht \ -eval_episodes=10 \ -hydra.run.dir=outputs/eval/example_hub + -p lerobot/diffusion_pusht \ + eval.n_episodes=10 \ + eval.batch_size=10 ``` -After training your own policy, you can also re-evaluate the checkpoints with: - +Note: After training your own policy, you can re-evaluate the checkpoints with: ```bash python lerobot/scripts/eval.py \ --p PATH/TO/TRAIN/OUTPUT/FOLDER \ -eval_episodes=10 \ -hydra.run.dir=outputs/eval/example_dir + -p PATH/TO/TRAIN/OUTPUT/FOLDER ``` See `python lerobot/scripts/eval.py --help` for more instructions. ### Train your own policy -Check out [examples](./examples) to see how you can start training a model on a dataset, which will be automatically downloaded if needed. +Check out [example 3](./examples/3_train_policy.py) that illustrates how to start training a model. -In general, you can use our training script to easily train any policy on any environment: +In general, you can use our training script to easily train any policy. To use wandb for logging training and evaluation curves, make sure you ran `wandb login`. Here is an example of training the ACT policy on trajectories collected by humans on the Aloha simulation environment for the insertion task: ```bash python lerobot/scripts/train.py \ -env=aloha \ -task=sim_insertion \ -repo_id=lerobot/aloha_sim_insertion_scripted \ -policy=act \ -hydra.run.dir=outputs/train/aloha_act + policy=act \ + env=aloha \ + env.task=AlohaInsertion-v0 \ + dataset_repo_id=lerobot/aloha_sim_insertion_human ``` -After training, you may want to revisit model evaluation to change the evaluation settings. In fact, during training every checkpoint is already evaluated but on a low number of episodes for efficiency. Check out [example](./examples) to evaluate any model checkpoint on more episodes to increase statistical significance. +The experiment directory is automatically generated and will show up in yellow in your terminal. It looks like `outputs/train/2024-05-05/20-21-12_aloha_act_default`. You can manually specify an experiment directory by adding this argument to the `train.py` python command: +```bash + hydra.run.dir=your/new/experiment/dir +``` + +A link to the wandb logs for the run will also show up in yellow in your terminal. Here is an example of logs from wandb: +![](media/wandb.png) + +You can deactivate wandb by adding these arguments to the `train.py` python command: +```bash + wandb.disable_artifact=true \ + wandb.enable=false +``` + +Note: For efficiency, during training every checkpoint is evaluated on a low number of episodes. After training, you may want to re-evaluate your best checkpoints on more episodes or change the evaluation settings. See `python lerobot/scripts/eval.py --help` for more instructions. + ## Contribute @@ -173,98 +191,40 @@ If you would like to contribute to ๐Ÿค— LeRobot, please check out our [contribut ### Add a new dataset -```python -# TODO(rcadene, AdilZouitine): rewrite this section -``` - -To add a dataset to the hub, first login and use a token generated from [huggingface settings](https://huggingface.co/settings/tokens) with write access: +To add a dataset to the hub, you need to login using a write-access token, which can be generated from the [Hugging Face settings](https://huggingface.co/settings/tokens): ```bash huggingface-cli login --token ${HUGGINGFACE_TOKEN} --add-to-git-credential ``` -Then you can upload it to the hub with: +Then move your dataset folder in `data` directory (e.g. `data/aloha_ping_pong`), and push your dataset to the hub with: ```bash -HF_HUB_ENABLE_HF_TRANSFER=1 huggingface-cli upload $HF_USER/$DATASET data/$DATASET \ ---repo-type dataset \ ---revision v1.0 +python lerobot/scripts/push_dataset_to_hub.py \ +--data-dir data \ +--dataset-id aloha_ping_ping \ +--raw-format aloha_hdf5 \ +--community-id lerobot ``` -You will need to set the corresponding version as a default argument in your dataset class: -```python - version: str | None = "v1.1", -``` -See: [`lerobot/common/datasets/pusht.py`](https://github.com/Cadene/lerobot/blob/main/lerobot/common/datasets/pusht.py) +See `python lerobot/scripts/push_dataset_to_hub.py --help` for more instructions. -For instance, for [lerobot/pusht](https://huggingface.co/datasets/lerobot/pusht), we used: -```bash -HF_USER=lerobot -DATASET=pusht -``` +If your dataset format is not supported, implement your own in `lerobot/common/datasets/push_dataset_to_hub/${raw_format}_format.py` by copying examples like [pusht_zarr](https://github.com/huggingface/lerobot/blob/main/lerobot/common/datasets/push_dataset_to_hub/pusht_zarr_format.py), [umi_zarr](https://github.com/huggingface/lerobot/blob/main/lerobot/common/datasets/push_dataset_to_hub/umi_zarr_format.py), [aloha_hdf5](https://github.com/huggingface/lerobot/blob/main/lerobot/common/datasets/push_dataset_to_hub/aloha_hdf5_format.py), or [xarm_pkl](https://github.com/huggingface/lerobot/blob/main/lerobot/common/datasets/push_dataset_to_hub/xarm_pkl_format.py). -If you want to improve an existing dataset, you can download it locally with: -```bash -mkdir -p data/$DATASET -HF_HUB_ENABLE_HF_TRANSFER=1 huggingface-cli download ${HF_USER}/$DATASET \ ---repo-type dataset \ ---local-dir data/$DATASET \ ---local-dir-use-symlinks=False \ ---revision v1.0 -``` - -Iterate on your code and dataset with: -```bash -DATA_DIR=data python train.py -``` - -Upload a new version (v2.0 or v1.1 if the changes are respectively more or less significant): -```bash -HF_HUB_ENABLE_HF_TRANSFER=1 huggingface-cli upload $HF_USER/$DATASET data/$DATASET \ ---repo-type dataset \ ---revision v1.1 \ ---delete "*" -``` - -Then you will need to set the corresponding version as a default argument in your dataset class: -```python - version: str | None = "v1.1", -``` -See: [`lerobot/common/datasets/pusht.py`](https://github.com/Cadene/lerobot/blob/main/lerobot/common/datasets/pusht.py) - - -Finally, you might want to mock the dataset if you need to update the unit tests as well: -```bash -python tests/scripts/mock_dataset.py --in-data-dir data/$DATASET --out-data-dir tests/data/$DATASET -``` ### Add a pretrained policy -```python -# TODO(rcadene, alexander-soare): rewrite this section -``` - -Once you have trained a policy you may upload it to the HuggingFace hub. - -Firstly, make sure you have a model repository set up on the hub. The hub ID looks like HF_USER/REPO_NAME. - -Secondly, assuming you have trained a policy, you need the following (which should all be in any of the subdirectories of `checkpoints` in your training output folder, if you've used the LeRobot training script): +Once you have trained a policy you may upload it to the Hugging Face hub using a hub id that looks like `${hf_user}/${repo_name}` (e.g. [lerobot/diffusion_pusht](https://huggingface.co/lerobot/diffusion_pusht)). +You first need to find the checkpoint located inside your experiment directory (e.g. `outputs/train/2024-05-05/20-21-12_aloha_act_default/checkpoints/002500`). It should contain: - `config.json`: A serialized version of the policy configuration (following the policy's dataclass config). -- `model.safetensors`: The `torch.nn.Module` parameters saved in [Hugging Face Safetensors](https://huggingface.co/docs/safetensors/index) format. -- `config.yaml`: This is the consolidated Hydra training configuration containing the policy, environment, and dataset configs. The policy configuration should match `config.json` exactly. The environment config is useful for anyone who wants to evaluate your policy. The dataset config just serves as a paper trail for reproducibility. - -To upload these to the hub, run the following with a desired revision ID. +- `model.safetensors`: A set of `torch.nn.Module` parameters, saved in [Hugging Face Safetensors](https://huggingface.co/docs/safetensors/index) format. +- `config.yaml`: A consolidated Hydra training configuration containing the policy, environment, and dataset configs. The policy configuration should match `config.json` exactly. The environment config is useful for anyone who wants to evaluate your policy. The dataset config just serves as a paper trail for reproducibility. +To upload these to the hub, run the following: ```bash -huggingface-cli upload $HUB_ID PATH/TO/OUTPUT/DIR --revision $REVISION_ID +huggingface-cli upload ${hf_user}/${repo_name} path/to/checkpoint/dir ``` -If you want this to be the default revision also run the following (don't worry, it won't upload the files again; it will just adjust the file pointers): - -```bash -huggingface-cli upload $HUB_ID PATH/TO/OUTPUT/DIR -``` - -See `eval.py` for an example of how a user may use your policy. +See [eval.py](https://github.com/huggingface/lerobot/blob/main/lerobot/scripts/eval.py) for an example of how other people may use your policy. ### Improve your code with profiling @@ -291,9 +251,14 @@ with profile( # insert code to profile, potentially whole body of eval_policy function ``` -```bash -python lerobot/scripts/eval.py \ ---config outputs/pusht/.hydra/config.yaml \ -pretrained_model_path=outputs/pusht/model.pt \ -eval_episodes=7 +## Citation + +If you want, you can cite this work with: +``` +@misc{cadene2024lerobot, + author = {Cadene, Remi and Alibert, Simon and Soare, Alexander and Gallouedec, Quentin and Zouitine, Adil and Wolf, Thomas}, + title = {LeRobot: State-of-the-art Machine Learning for Real-World Robotics in Pytorch}, + howpublished = "\url{https://github.com/huggingface/lerobot}", + year = {2024} +} ``` diff --git a/examples/1_load_lerobot_dataset.py b/examples/1_load_lerobot_dataset.py index f86199c5..3846926a 100644 --- a/examples/1_load_lerobot_dataset.py +++ b/examples/1_load_lerobot_dataset.py @@ -14,6 +14,7 @@ The script ends with examples of how to batch process data using PyTorch's DataL """ from pathlib import Path +from pprint import pprint import imageio import torch @@ -21,39 +22,36 @@ import torch import lerobot from lerobot.common.datasets.lerobot_dataset import LeRobotDataset -print("List of available datasets", lerobot.available_datasets) -# # >>> ['lerobot/aloha_sim_insertion_human', 'lerobot/aloha_sim_insertion_scripted', -# # 'lerobot/aloha_sim_transfer_cube_human', 'lerobot/aloha_sim_transfer_cube_scripted', -# # 'lerobot/pusht', 'lerobot/xarm_lift_medium'] +print("List of available datasets:") +pprint(lerobot.available_datasets) +# Let's take one for this example repo_id = "lerobot/pusht" -# You can easily load a dataset from a Hugging Face repositery +# You can easily load a dataset from a Hugging Face repository dataset = LeRobotDataset(repo_id) -# LeRobotDataset is actually a thin wrapper around an underlying Hugging Face dataset (see https://huggingface.co/docs/datasets/index for more information). -# TODO(rcadene): update to make the print pretty -print(f"{dataset=}") -print(f"{dataset.hf_dataset=}") +# LeRobotDataset is actually a thin wrapper around an underlying Hugging Face dataset +# (see https://huggingface.co/docs/datasets/index for more information). +print(dataset) +print(dataset.hf_dataset) -# and provides additional utilities for robotics and compatibility with pytorch -print(f"number of samples/frames: {dataset.num_samples=}") -print(f"number of episodes: {dataset.num_episodes=}") -print(f"average number of frames per episode: {dataset.num_samples / dataset.num_episodes:.3f}") +# And provides additional utilities for robotics and compatibility with Pytorch +print(f"\naverage number of frames per episode: {dataset.num_samples / dataset.num_episodes:.3f}") print(f"frames per second used during data collection: {dataset.fps=}") -print(f"keys to access images from cameras: {dataset.image_keys=}") +print(f"keys to access images from cameras: {dataset.camera_keys=}\n") # Access frame indexes associated to first episode episode_index = 0 from_idx = dataset.episode_data_index["from"][episode_index].item() to_idx = dataset.episode_data_index["to"][episode_index].item() -# LeRobot datasets actually subclass PyTorch datasets so you can do everything you know and love from working with the latter, like iterating through the dataset. -# Here we grab all the image frames. +# LeRobot datasets actually subclass PyTorch datasets so you can do everything you know and love from working +# with the latter, like iterating through the dataset. Here we grab all the image frames. frames = [dataset[idx]["observation.image"] for idx in range(from_idx, to_idx)] -# Video frames are now float32 in range [0,1] channel first (c,h,w) to follow pytorch convention. -# To visualize them, we convert to uint8 range [0,255] +# Video frames are now float32 in range [0,1] channel first (c,h,w) to follow pytorch convention. To visualize +# them, we convert to uint8 in range [0,255] frames = [(frame * 255).type(torch.uint8) for frame in frames] # and to channel last (h,w,c). frames = [frame.permute((1, 2, 0)).numpy() for frame in frames] @@ -62,9 +60,9 @@ frames = [frame.permute((1, 2, 0)).numpy() for frame in frames] Path("outputs/examples/1_load_lerobot_dataset").mkdir(parents=True, exist_ok=True) imageio.mimsave("outputs/examples/1_load_lerobot_dataset/episode_0.mp4", frames, fps=dataset.fps) -# For many machine learning applications we need to load the history of past observations or trajectories of future actions. -# Our datasets can load previous and future frames for each key/modality, -# using timestamps differences with the current loaded frame. For instance: +# For many machine learning applications we need to load the history of past observations or trajectories of +# future actions. Our datasets can load previous and future frames for each key/modality, using timestamps +# differences with the current loaded frame. For instance: delta_timestamps = { # loads 4 images: 1 second before current frame, 500 ms before, 200 ms before, and current frame "observation.image": [-1, -0.5, -0.20, 0], @@ -74,12 +72,12 @@ delta_timestamps = { "action": [t / dataset.fps for t in range(64)], } dataset = LeRobotDataset(repo_id, delta_timestamps=delta_timestamps) -print(f"{dataset[0]['observation.image'].shape=}") # (4,c,h,w) +print(f"\n{dataset[0]['observation.image'].shape=}") # (4,c,h,w) print(f"{dataset[0]['observation.state'].shape=}") # (8,c) -print(f"{dataset[0]['action'].shape=}") # (64,c) +print(f"{dataset[0]['action'].shape=}\n") # (64,c) -# Finally, our datasets are fully compatible with PyTorch dataloaders and samplers -# because they are just PyTorch datasets. +# Finally, our datasets are fully compatible with PyTorch dataloaders and samplers because they are just +# PyTorch datasets. dataloader = torch.utils.data.DataLoader( dataset, num_workers=0, diff --git a/examples/2_evaluate_pretrained_policy.py b/examples/2_evaluate_pretrained_policy.py index 001054f3..8481f0f5 100644 --- a/examples/2_evaluate_pretrained_policy.py +++ b/examples/2_evaluate_pretrained_policy.py @@ -5,23 +5,108 @@ training outputs directory. In the latter case, you might want to run examples/3 from pathlib import Path +import gym_pusht # noqa: F401 +import gymnasium as gym +import imageio +import numpy +import torch from huggingface_hub import snapshot_download -from lerobot.scripts.eval import eval +from lerobot.common.policies.diffusion.modeling_diffusion import DiffusionPolicy -# Get a pretrained policy from the hub. -pretrained_policy_name = "lerobot/diffusion_pusht" -pretrained_policy_path = Path(snapshot_download(pretrained_policy_name)) +# Create a directory to store the video of the evaluation +output_directory = Path("outputs/eval/example_pusht_diffusion") +output_directory.mkdir(parents=True, exist_ok=True) + +device = torch.device("cuda") + +# Download the diffusion policy for pusht environment +pretrained_policy_path = Path(snapshot_download("lerobot/diffusion_pusht")) # OR uncomment the following to evaluate a policy from the local outputs/train folder. # pretrained_policy_path = Path("outputs/train/example_pusht_diffusion") -# Override some config parameters to do with evaluation. -overrides = [ - "eval.n_episodes=10", - "eval.batch_size=10", - "device=cuda", -] +policy = DiffusionPolicy.from_pretrained(pretrained_policy_path) +policy.eval() +policy.to(device) -# Evaluate the policy and save the outputs including metrics and videos. -# TODO(rcadene, alexander-soare): dont call eval, but add the minimal code snippet to rollout -eval(pretrained_policy_path=pretrained_policy_path) +# Initialize evaluation environment to render two observation types: +# an image of the scene and state/position of the agent. The environment +# also automatically stops running after 300 interactions/steps. +env = gym.make( + "gym_pusht/PushT-v0", + obs_type="pixels_agent_pos", + max_episode_steps=300, +) + +# Reset the policy and environmens to prepare for rollout +policy.reset() +numpy_observation, info = env.reset(seed=42) + +# Prepare to collect every rewards and all the frames of the episode, +# from initial state to final state. +rewards = [] +frames = [] + +# Render frame of the initial state +frames.append(env.render()) + +step = 0 +done = False +while not done: + # Prepare observation for the policy running in Pytorch + state = torch.from_numpy(numpy_observation["agent_pos"]) + image = torch.from_numpy(numpy_observation["pixels"]) + + # Convert to float32 with image from channel first in [0,255] + # to channel last in [0,1] + state = state.to(torch.float32) + image = image.to(torch.float32) / 255 + image = image.permute(2, 0, 1) + + # Send data tensors from CPU to GPU + state = state.to(device, non_blocking=True) + image = image.to(device, non_blocking=True) + + # Add extra (empty) batch dimension, required to forward the policy + state = state.unsqueeze(0) + image = image.unsqueeze(0) + + # Create the policy input dictionary + observation = { + "observation.state": state, + "observation.image": image, + } + + # Predict the next action with respect to the current observation + with torch.inference_mode(): + action = policy.select_action(observation) + + # Prepare the action for the environment + numpy_action = action.squeeze(0).to("cpu").numpy() + + # Step through the environment and receive a new observation + numpy_observation, reward, terminated, truncated, info = env.step(numpy_action) + print(f"{step=} {reward=} {terminated=}") + + # Keep track of all the rewards and frames + rewards.append(reward) + frames.append(env.render()) + + # The rollout is considered done when the success state is reach (i.e. terminated is True), + # or the maximum number of iterations is reached (i.e. truncated is True) + done = terminated | truncated | done + step += 1 + +if terminated: + print("Success!") +else: + print("Failure!") + +# Get the speed of environment (i.e. its number of frames per second). +fps = env.metadata["render_fps"] + +# Encode all frames into a mp4 video. +video_path = output_directory / "rollout.mp4" +imageio.mimsave(str(video_path), numpy.stack(frames), fps=fps) + +print(f"Video of the evaluation is available in '{video_path}'.") diff --git a/examples/3_train_policy.py b/examples/3_train_policy.py index 69e3d34c..c5ce0d18 100644 --- a/examples/3_train_policy.py +++ b/examples/3_train_policy.py @@ -4,36 +4,42 @@ Once you have trained a model with this script, you can try to evaluate it on examples/2_evaluate_pretrained_policy.py """ -import os from pathlib import Path import torch -from omegaconf import OmegaConf -from lerobot.common.datasets.factory import make_dataset +from lerobot.common.datasets.lerobot_dataset import LeRobotDataset from lerobot.common.policies.diffusion.configuration_diffusion import DiffusionConfig from lerobot.common.policies.diffusion.modeling_diffusion import DiffusionPolicy -from lerobot.common.utils.utils import init_hydra_config +# Create a directory to store the training checkpoint. output_directory = Path("outputs/train/example_pusht_diffusion") -os.makedirs(output_directory, exist_ok=True) +output_directory.mkdir(parents=True, exist_ok=True) -# Number of offline training steps (we'll only do offline training for this example. +# Number of offline training steps (we'll only do offline training for this example.) # Adjust as you prefer. 5000 steps are needed to get something worth evaluating. training_steps = 5000 device = torch.device("cuda") log_freq = 250 # Set up the dataset. -hydra_cfg = init_hydra_config("lerobot/configs/default.yaml", overrides=["env=pusht"]) -dataset = make_dataset(hydra_cfg) +delta_timestamps = { + # Load the previous image and state at -0.1 seconds before current frame, + # then load current image and state corresponding to 0.0 second. + "observation.image": [-0.1, 0.0], + "observation.state": [-0.1, 0.0], + # Load the previous action (-0.1), the next action to be executed (0.0), + # and 14 future actions with a 0.1 seconds spacing. All these actions will be + # used to supervise the policy. + "action": [-0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4], +} +dataset = LeRobotDataset("lerobot/pusht", delta_timestamps=delta_timestamps) # Set up the the policy. # Policies are initialized with a configuration class, in this case `DiffusionConfig`. # For this example, no arguments need to be passed because the defaults are set up for PushT. # If you're doing something different, you will likely need to change at least some of the defaults. cfg = DiffusionConfig() -# TODO(alexander-soare): Remove LR scheduler from the policy. policy = DiffusionPolicy(cfg, dataset_stats=dataset.stats) policy.train() policy.to(device) @@ -69,7 +75,5 @@ while not done: done = True break -# Save the policy. +# Save a policy checkpoint. policy.save_pretrained(output_directory) -# Save the Hydra configuration so we have the environment configuration for eval. -OmegaConf.save(hydra_cfg, output_directory / "config.yaml") diff --git a/lerobot/__init__.py b/lerobot/__init__.py index ed8c220a..072f4bc7 100644 --- a/lerobot/__init__.py +++ b/lerobot/__init__.py @@ -85,13 +85,6 @@ available_datasets = list( itertools.chain(*available_datasets_per_env.values(), available_real_world_datasets) ) -# TODO(rcadene, aliberts, alexander-soare): Add real-world env with a gym API -available_datasets_without_env = ["lerobot/umi_cup_in_the_wild"] - -available_datasets = list( - itertools.chain(*available_datasets_per_env.values(), available_datasets_without_env) -) - available_policies = [ "act", "diffusion", diff --git a/lerobot/common/datasets/_video_benchmark/README.md b/lerobot/common/datasets/_video_benchmark/README.md index 10e8d12f..d802163f 100644 --- a/lerobot/common/datasets/_video_benchmark/README.md +++ b/lerobot/common/datasets/_video_benchmark/README.md @@ -37,16 +37,16 @@ How to decode videos? ## Variables **Image content** -We don't expect the same optimal settings for a dataset of images from a simulation, or from real-world in an appartment, or in a factory, or outdoor, etc. Hence, we run this bechmark on two datasets: `pusht` (simulation) and `umi` (real-world outdoor). +We don't expect the same optimal settings for a dataset of images from a simulation, or from real-world in an appartment, or in a factory, or outdoor, etc. Hence, we run this benchmark on two datasets: `pusht` (simulation) and `umi` (real-world outdoor). **Requested timestamps** -In this benchmark, we focus on the loading time of random access, so we are not interested about sequentially loading all frames of a video like in a movie. However, the number of consecutive timestamps requested and their spacing can greatly affect the `load_time_factor`. In fact, it is expected to get faster loading time by decoding a large number of consecutive frames from a video, than to load the same data from individual images. To reflect our robotics use case, we consider a few settings: +In this benchmark, we focus on the loading time of random access, so we are not interested in sequentially loading all frames of a video like in a movie. However, the number of consecutive timestamps requested and their spacing can greatly affect the `load_time_factor`. In fact, it is expected to get faster loading time by decoding a large number of consecutive frames from a video, than to load the same data from individual images. To reflect our robotics use case, we consider a few settings: - `single_frame`: 1 frame, - `2_frames`: 2 consecutive frames (e.g. `[t, t + 1 / fps]`), - `2_frames_4_space`: 2 consecutive frames with 4 frames of spacing (e.g `[t, t + 4 / fps]`), **Data augmentations** -We might revisit this benchmark and find better settings if we train our policies with various data augmentations to make them more robusts (e.g. robust to color changes, compression, etc.). +We might revisit this benchmark and find better settings if we train our policies with various data augmentations to make them more robust (e.g. robust to color changes, compression, etc.). ## Results diff --git a/lerobot/common/datasets/lerobot_dataset.py b/lerobot/common/datasets/lerobot_dataset.py index c8cfbd8e..f7bc5bd2 100644 --- a/lerobot/common/datasets/lerobot_dataset.py +++ b/lerobot/common/datasets/lerobot_dataset.py @@ -47,6 +47,7 @@ class LeRobotDataset(torch.utils.data.Dataset): @property def fps(self) -> int: + """Frames per second used during data collection.""" return self.info["fps"] @property @@ -61,15 +62,22 @@ class LeRobotDataset(torch.utils.data.Dataset): return self.hf_dataset.features @property - def image_keys(self) -> list[str]: - image_keys = [] + def camera_keys(self) -> list[str]: + """Keys to access image and video stream from cameras.""" + keys = [] for key, feats in self.hf_dataset.features.items(): - if isinstance(feats, datasets.Image): - image_keys.append(key) - return image_keys + self.video_frame_keys + if isinstance(feats, (datasets.Image, VideoFrame)): + keys.append(key) + return keys @property - def video_frame_keys(self): + def video_frame_keys(self) -> list[str]: + """Keys to access video frames that requires to be decoded into images. + + Note: It is empty if the dataset contains images only, + or equal to `self.cameras` if the dataset contains videos only, + or can even be a subset of `self.cameras` in a case of a mixed image/video dataset. + """ video_frame_keys = [] for key, feats in self.hf_dataset.features.items(): if isinstance(feats, VideoFrame): @@ -78,10 +86,12 @@ class LeRobotDataset(torch.utils.data.Dataset): @property def num_samples(self) -> int: + """Number of samples/frames.""" return len(self.hf_dataset) @property def num_episodes(self) -> int: + """Number of episodes.""" return len(self.hf_dataset.unique("episode_index")) @property @@ -121,6 +131,22 @@ class LeRobotDataset(torch.utils.data.Dataset): return item + def __repr__(self): + return ( + f"{self.__class__.__name__}(\n" + f" Repository ID: '{self.repo_id}',\n" + f" Version: '{self.version}',\n" + f" Split: '{self.split}',\n" + f" Number of Samples: {self.num_samples},\n" + f" Number of Episodes: {self.num_episodes},\n" + f" Type: {'video (.mp4)' if self.video else 'image (.png)'},\n" + f" Recorded Frames per Second: {self.fps},\n" + f" Camera Keys: {self.camera_keys},\n" + f" Video Frame Keys: {self.video_frame_keys if self.video else 'N/A'},\n" + f" Transformations: {self.transform},\n" + f")" + ) + @classmethod def from_preloaded( cls, diff --git a/lerobot/common/datasets/push_dataset_to_hub/aloha_hdf5_format.py b/lerobot/common/datasets/push_dataset_to_hub/aloha_hdf5_format.py index 694304f1..f51a59cd 100644 --- a/lerobot/common/datasets/push_dataset_to_hub/aloha_hdf5_format.py +++ b/lerobot/common/datasets/push_dataset_to_hub/aloha_hdf5_format.py @@ -142,12 +142,12 @@ def load_from_raw(raw_dir, out_dir, fps, video, debug): def to_hf_dataset(data_dict, video) -> Dataset: features = {} - image_keys = [key for key in data_dict if "observation.images." in key] - for image_key in image_keys: + keys = [key for key in data_dict if "observation.images." in key] + for key in keys: if video: - features[image_key] = VideoFrame() + features[key] = VideoFrame() else: - features[image_key] = Image() + features[key] = Image() features["observation.state"] = Sequence( length=data_dict["observation.state"].shape[1], feature=Value(dtype="float32", id=None) diff --git a/lerobot/configs/default.yaml b/lerobot/configs/default.yaml index 37695858..7cad0a1a 100644 --- a/lerobot/configs/default.yaml +++ b/lerobot/configs/default.yaml @@ -25,7 +25,7 @@ training: eval_freq: ??? save_freq: ??? log_freq: 250 - save_model: false + save_model: true eval: n_episodes: 1 diff --git a/lerobot/scripts/eval.py b/lerobot/scripts/eval.py index 2a61aaea..e4a9bfef 100644 --- a/lerobot/scripts/eval.py +++ b/lerobot/scripts/eval.py @@ -583,17 +583,18 @@ if __name__ == "__main__": pretrained_policy_path = Path( snapshot_download(args.pretrained_policy_name_or_path, revision=args.revision) ) - except HFValidationError: - logging.warning( - "The provided pretrained_policy_name_or_path is not a valid Hugging Face Hub repo ID. " - "Treating it as a local directory." - ) - except RepositoryNotFoundError: - logging.warning( - "The provided pretrained_policy_name_or_path was not found on the Hugging Face Hub. Treating " - "it as a local directory." - ) - pretrained_policy_path = Path(args.pretrained_policy_name_or_path) + except (HFValidationError, RepositoryNotFoundError) as e: + if isinstance(e, HFValidationError): + error_message = ( + "The provided pretrained_policy_name_or_path is not a valid Hugging Face Hub repo ID." + ) + else: + error_message = ( + "The provided pretrained_policy_name_or_path was not found on the Hugging Face Hub." + ) + + logging.warning(f"{error_message} Treating it as a local directory.") + pretrained_policy_path = Path(args.pretrained_policy_name_or_path) if not pretrained_policy_path.is_dir() or not pretrained_policy_path.exists(): raise ValueError( "The provided pretrained_policy_name_or_path is not a valid/existing Hugging Face Hub " diff --git a/lerobot/scripts/push_dataset_to_hub.py b/lerobot/scripts/push_dataset_to_hub.py index ca8c4600..dfac410b 100644 --- a/lerobot/scripts/push_dataset_to_hub.py +++ b/lerobot/scripts/push_dataset_to_hub.py @@ -60,7 +60,7 @@ import torch from huggingface_hub import HfApi from safetensors.torch import save_file -from lerobot.common.datasets.lerobot_dataset import LeRobotDataset +from lerobot.common.datasets.lerobot_dataset import CODEBASE_VERSION, LeRobotDataset from lerobot.common.datasets.push_dataset_to_hub._download_raw import download_raw from lerobot.common.datasets.push_dataset_to_hub.compute_stats import compute_stats from lerobot.common.datasets.utils import flatten_dict @@ -252,7 +252,7 @@ def main(): parser.add_argument( "--revision", type=str, - default="v1.2", + default=CODEBASE_VERSION, help="Codebase version used to generate the dataset.", ) parser.add_argument( diff --git a/lerobot/scripts/train.py b/lerobot/scripts/train.py index 6cbc8265..d5fedc84 100644 --- a/lerobot/scripts/train.py +++ b/lerobot/scripts/train.py @@ -8,7 +8,6 @@ import hydra import torch from datasets import concatenate_datasets from datasets.utils import disable_progress_bars, enable_progress_bars -from diffusers.optimization import get_scheduler from lerobot.common.datasets.factory import make_dataset from lerobot.common.datasets.utils import cycle @@ -55,6 +54,8 @@ def make_optimizer_and_scheduler(cfg, policy): cfg.training.adam_weight_decay, ) assert cfg.training.online_steps == 0, "Diffusion Policy does not handle online training." + from diffusers.optimization import get_scheduler + lr_scheduler = get_scheduler( cfg.training.lr_scheduler, optimizer=optimizer, @@ -336,7 +337,7 @@ def train(cfg: dict, out_dir=None, job_name=None): logging.info(f"{num_total_params=} ({format_big_number(num_total_params)})") # Note: this helper will be used in offline and online training loops. - def _maybe_eval_and_maybe_save(step): + def evaluate_and_checkpoint_if_needed(step): if step % cfg.training.eval_freq == 0: logging.info(f"Eval policy at step {step}") eval_info = eval_policy( @@ -392,9 +393,9 @@ def train(cfg: dict, out_dir=None, job_name=None): if step % cfg.training.log_freq == 0: log_train_info(logger, train_info, step, cfg, offline_dataset, is_offline) - # Note: _maybe_eval_and_maybe_save happens **after** the `step`th training update has completed, so we pass in - # step + 1. - _maybe_eval_and_maybe_save(step + 1) + # Note: evaluate_and_checkpoint_if_needed happens **after** the `step`th training update has completed, + # so we pass in step + 1. + evaluate_and_checkpoint_if_needed(step + 1) step += 1 @@ -460,9 +461,9 @@ def train(cfg: dict, out_dir=None, job_name=None): if step % cfg.training.log_freq == 0: log_train_info(logger, train_info, step, cfg, online_dataset, is_offline) - # Note: _maybe_eval_and_maybe_save happens **after** the `step`th training update has completed, so we pass - # in step + 1. - _maybe_eval_and_maybe_save(step + 1) + # Note: evaluate_and_checkpoint_if_needed happens **after** the `step`th training update has completed, + # so we pass in step + 1. + evaluate_and_checkpoint_if_needed(step + 1) step += 1 online_step += 1 diff --git a/lerobot/scripts/visualize_dataset.py b/lerobot/scripts/visualize_dataset.py index 44acd416..1835e90c 100644 --- a/lerobot/scripts/visualize_dataset.py +++ b/lerobot/scripts/visualize_dataset.py @@ -32,7 +32,7 @@ local$ rerun lerobot_pusht_episode_0.rrd ``` - Visualize data stored on a distant machine through streaming: -(You need to forward the websocket port to the distant machine, with +(You need to forward the websocket port to the distant machine, with `ssh -L 9087:localhost:9087 username@remote-host`) ``` distant$ python lerobot/scripts/visualize_dataset.py \ @@ -131,7 +131,7 @@ def visualize_dataset( rr.set_time_seconds("timestamp", batch["timestamp"][i].item()) # display each camera image - for key in dataset.image_keys: + for key in dataset.camera_keys: # TODO(rcadene): add `.compress()`? is it lossless? rr.log(key, rr.Image(to_hwc_uint8_numpy(batch[key][i]))) diff --git a/media/wandb.png b/media/wandb.png new file mode 100644 index 0000000000000000000000000000000000000000..8adc3d2aea39a718dccda009f55e8133690bf1b7 GIT binary patch literal 416489 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%0A$hNF=*Zc3KNT!GjkEvyVnJO@X>pYa|nux_Yd6{ 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 &_up_r~M$HeDwev4hG-MSKINp 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 NXJTk!P_B3O>R;69YgGUM literal 0 HcmV?d00001 diff --git a/pyproject.toml b/pyproject.toml index 32428845..d7bccbd5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,9 +4,9 @@ version = "0.1.0" description = "๐Ÿค— LeRobot: State-of-the-art Machine Learning for Real-World Robotics in Pytorch" authors = [ "Rรฉmi Cadรจne ", + "Simon Alibert ", "Alexander Soare ", "Quentin Gallouรฉdec ", - "Simon Alibert ", "Adil Zouitine ", "Thomas Wolf ", ] diff --git a/tests/test_available.py b/tests/test_available.py index e2dfeeb9..ead9296a 100644 --- a/tests/test_available.py +++ b/tests/test_available.py @@ -15,7 +15,7 @@ from tests.utils import require_env def test_available_env_task(env_name: str, task_name: list): """ This test verifies that all environments listed in `lerobot/__init__.py` can - be sucessfully imported โ€” if they're installed โ€” and that their + be successfully imported โ€” if they're installed โ€” and that their `available_tasks_per_env` are valid. """ package_name = f"gym_{env_name}" diff --git a/tests/test_datasets.py b/tests/test_datasets.py index 22b271be..1d93d48f 100644 --- a/tests/test_datasets.py +++ b/tests/test_datasets.py @@ -41,7 +41,7 @@ def test_factory(env_name, repo_id, policy_name): ) dataset = make_dataset(cfg) delta_timestamps = dataset.delta_timestamps - image_keys = dataset.image_keys + camera_keys = dataset.camera_keys item = dataset[0] @@ -71,7 +71,7 @@ def test_factory(env_name, repo_id, policy_name): else: assert item[key].ndim == ndim, f"{key}" - if key in image_keys: + if key in camera_keys: assert item[key].dtype == torch.float32, f"{key}" # TODO(rcadene): we assume for now that image normalization takes place in the model assert item[key].max() <= 1.0, f"{key}" diff --git a/tests/test_examples.py b/tests/test_examples.py index ccce4eb2..c1f3c1dc 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -46,7 +46,7 @@ def test_examples_3_and_2(): # Pass empty globals to allow dictionary comprehension https://stackoverflow.com/a/32897127/4391249. exec(file_contents, {}) - for file_name in ["model.safetensors", "config.json", "config.yaml"]: + for file_name in ["model.safetensors", "config.json"]: assert Path(f"outputs/train/example_pusht_diffusion/{file_name}").exists() path = "examples/2_evaluate_pretrained_policy.py" @@ -58,16 +58,16 @@ def test_examples_3_and_2(): file_contents = _find_and_replace( file_contents, [ - ('pretrained_policy_name = "lerobot/diffusion_pusht"', ""), - ("pretrained_policy_path = Path(snapshot_download(pretrained_policy_name))", ""), + ('pretrained_policy_path = Path(snapshot_download("lerobot/diffusion_pusht"))', ""), ( '# pretrained_policy_path = Path("outputs/train/example_pusht_diffusion")', 'pretrained_policy_path = Path("outputs/train/example_pusht_diffusion")', ), - ('"eval.n_episodes=10"', '"eval.n_episodes=1"'), - ('"eval.batch_size=10"', '"eval.batch_size=1"'), - ('"device=cuda"', '"device=cpu"'), + ('device = torch.device("cuda")', 'device = torch.device("cpu")'), + ("step += 1", "break"), ], ) - assert Path("outputs/train/example_pusht_diffusion").exists() + exec(file_contents, {}) + + assert Path("outputs/eval/example_pusht_diffusion/rollout.mp4").exists() From a8e245fb31c0cba9d83cb687625251e31071dccf Mon Sep 17 00:00:00 2001 From: Alexander Soare Date: Mon, 6 May 2024 07:27:01 +0100 Subject: [PATCH 02/27] Remove loss masking from diffusion policy (#135) --- .../diffusion/configuration_diffusion.py | 6 ++++++ .../policies/diffusion/modeling_diffusion.py | 2 +- lerobot/configs/policy/diffusion.yaml | 3 +++ .../pusht_diffusion/grad_stats.safetensors | Bin 47424 -> 47424 bytes .../pusht_diffusion/output_dict.safetensors | Bin 68 -> 68 bytes 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lerobot/common/policies/diffusion/configuration_diffusion.py b/lerobot/common/policies/diffusion/configuration_diffusion.py index 73fabefa..d7341c33 100644 --- a/lerobot/common/policies/diffusion/configuration_diffusion.py +++ b/lerobot/common/policies/diffusion/configuration_diffusion.py @@ -64,6 +64,9 @@ class DiffusionConfig: clip_sample_range: The magnitude of the clipping range as described above. num_inference_steps: Number of reverse diffusion steps to use at inference time (steps are evenly spaced). If not provided, this defaults to be the same as `num_train_timesteps`. + do_mask_loss_for_padding: Whether to mask the loss when there are copy-padded actions. See + `LeRobotDataset` and `load_previous_and_future_frames` for mor information. Note, this defaults + to False as the original Diffusion Policy implementation does the same. """ # Inputs / output structure. @@ -118,6 +121,9 @@ class DiffusionConfig: # Inference num_inference_steps: int | None = None + # Loss computation + do_mask_loss_for_padding: bool = False + def __post_init__(self): """Input validation (not exhaustive).""" if not self.vision_backbone.startswith("resnet"): diff --git a/lerobot/common/policies/diffusion/modeling_diffusion.py b/lerobot/common/policies/diffusion/modeling_diffusion.py index f5f64d80..91cf6dd0 100644 --- a/lerobot/common/policies/diffusion/modeling_diffusion.py +++ b/lerobot/common/policies/diffusion/modeling_diffusion.py @@ -268,7 +268,7 @@ class DiffusionModel(nn.Module): loss = F.mse_loss(pred, target, reduction="none") # Mask loss wherever the action is padded with copies (edges of the dataset trajectory). - if "action_is_pad" in batch: + if self.config.do_mask_loss_for_padding and "action_is_pad" in batch: in_episode_bound = ~batch["action_is_pad"] loss = loss * in_episode_bound.unsqueeze(-1) diff --git a/lerobot/configs/policy/diffusion.yaml b/lerobot/configs/policy/diffusion.yaml index 60061c38..2d611c88 100644 --- a/lerobot/configs/policy/diffusion.yaml +++ b/lerobot/configs/policy/diffusion.yaml @@ -95,3 +95,6 @@ policy: # Inference num_inference_steps: 100 + + # Loss computation + do_mask_loss_for_padding: false diff --git a/tests/data/save_policy_to_safetensors/pusht_diffusion/grad_stats.safetensors b/tests/data/save_policy_to_safetensors/pusht_diffusion/grad_stats.safetensors index 1b1142b2df89ad1d618c895c3bf0313cb8173125..f27cd6780a7c2b399ec47e7a27d0022ba30c5045 100644 GIT binary patch delta 1719 zcmX|=FZ%Ts}s(r%@ctUTNxBoQ++_csHpQSn$ri!Pw3z@mVGB2_pdT1l!1 zU6hxAgg|)&L6k=zl4Js+0TB@jg-RbrWZ8<}bPE3k%456~IhJuLO}3ZrYK@q>Y-c2To)`eb)(AExJpp-iABym}58q@p zq6POSU>Ypd7V#Tkg~e`7*ScDWzIU4#3)2HONwpk16kIq4Qr@nBpa-`! z6L$OIqwb&ZCySzBWNIHnM~K;B2Hpn-$qA^mM`SK15l-)QC%eSi5V!t}W@r3ia0tJS zPp+rHbjOmYERp`r#V;nAVE1^K^gKcazrTeoN>Fw}1lW9+Q9CcRTuqJEAw0-u|PizIPi$CDAS&q<-S&>IS5i>T1lB2<{~L`4Pv1mWN9 zp^u$^PHY}ZWcxqxJ=Hx8(oTu9-}I>jxUn^ckvw#UxgYYF<(C{;K+5NEEd1|oYi=Kl znSz2OXKnpt10BBfuf^EH)t{pBKCYmv-w#$ z#1sswGmU`|IA_D~?#!UD%LxqMbA}xd&BIIQ=?Tdcca^bl9Nzi8pV(w-fT44qWUuyH z_@c?1oZom3nI;N}3nDpM{oi|Jp{qGH7Hy5&uC-wcMplG0Hle_8y8Lc_XNOvjtMN^e z4)S~MA)&EEN3t*E`?*&YrMhTT#h*+=sdXFiNQVIQWhkck#ZiQ2FN+C#$VHOgI(v1} zNozEDB2gQnz6;$}mVR-wKeGiG7SI)h=KtgBH9$4W0nZA}EsIlZUeVIz zSwwO4;?6{nX^ae`u=h}VwgjBes&znt|n4BL<4Ny zb&gU557X1H#wB#@rY-bttjhoN@Mi7T9~Z-pTTFZTfl5~3*0}gcKRN$m!=-^;3Nm5Q zM0?HN&E&DX?uD#D_M9N2A!|7}_D@Rpp>z|^SojpW7-HQTac*N4;0n}SkLWE01Z-F`~f*5aI3D<3( zGkMXO)K`6rG^;QEpDmDjE1ZhZk4O6j?!0|yRm10M(GUMbGV3s5>4@K-0-s-LU;1!h znBT#zHgI-lCy_NijLwcZllage$~p9i6flp$9F&CpS9$Q8y{xl4L*RcpLc!?51r&y5 zDJ5p1$yAi+gy!am8#R=oVp5VP!P59xdu`be`-?vnG^A?%Q=W;{${7V!-g-gzGCqTf zm{?$P#xkhLH{a^u;4M^j(h}Xhb}99*g{IDybSwWg8GTH?(2f;Y@j|i%)bY2S2vemA z<~9?C>( Pt?Bc-gS6{CoasLR6e#%s delta 1719 zcmX|=eLPh89>*uV(3I7NY>H(m&tp8yIp_C1XRMW)t0cXyo^0#d$Y`X+-d&f}kfCg( zh7GfxAG(sKFmuj$ShgX%O08Y1x+IS%tFeySJBX^C$PGz z26@V6Ah}3EPug6BBO|+26ItcpgZJSY{U2CfcsY8k7V4fGqg&hZq5COcy`0B@r%3@m z-rf$P2S>4`T~c_q z#y=8LyeT}xEcY)?&K+YC>2KlIf}46>YXxvP8vgj_=RwjNz@+x(fob0eF`rQmer*G) zu#hhxFliL4aSMUX5(#s$UBdEXF2%>CGAJ7+iK@9s_+HzNh#WWx%dTdt`p(5eF1H)A znkV7H4t;#(n&iK@oNQp`j3VG0!vvyeXa`#qQ7^k41Wz*3@!=N-z#}yWvki;|ubVy1 zw{AMavrc^_-<}71+w7SNM@Qg9pXIxY5lEW+h|AKz)u7iOOFRm2gN$%1+*nA$32z(K zfv$NZGV2tCMr`~)$a3HP$B;Pxo+Uh`CzR`tn6u)|^}|mrfaaUy-jW_PZJSI_Z!(7N zKdh9|I&=JX|% z5$ud9#!Aopf;iM0w`+w@5Qmdg7qI-_RC}Z@)}&toCC+l(VVM{{2u{JSI2?lb@3jcK zfChLVI4D&?(iz|;y==kvZ=m9LE@wXC@!kn)!^EF}#bl}SvrCrHBl?(Dbao=Sbc5$wLkjW5O?*JDT4al~0a&)E3nDjY225J8d zrC{U@9x)op_FFpdJ@FiL^`)!bcg9GdqAQqLrC9^z)|rfB-uoShOqxr>!2e=Mg$(udzP-k1L zfGq3l%4f4%phmfp3BEan>aIjF6NyuQF4U0tmik4if?u5@AgDFvL)qkus71ZEyklmGLcm5XQ0$n zE=Py$MRbtweGu+XaZlgz2V2nTXejbSZQE_#OYc1pyo%q&_t)#xw<1RD$dTXmq1Uuc#^* zxLiT5sOhI74?mYuap?h6)IgDNAblULot6W#^!Da&;)+-S$3gtOhZt`OZMtVwMl9;h zH`iXyamNUUZO($kxrc<4w?82;$%mS} zJ%S?Ra+YtXhJp)3wnWE+t5-@`ns6}Pb<)2RnNwAQxqZ7>AcR-d;7fXacC)el`g(M@ zY7+DO$0!lg^cI`;A0;xw50%#2zGh!|w&re85}KTCRK9LIhSonU7K|_3 zfKCkkhUs24VslPCHDf_3=LQ>f)w77dwFmEV=|Vw{IDTKzi<$=%xUY1RDR@~Pz^mKb z;EsikIx|m3*2fyFRJYRKP3W|*M~;5yWV((Ii_zfe3rf$vwWuxbOTh=LJ=pv;@7_Tk zrDYoKKKB(D-ng{k$xAm->d$Kk^{Z=0wP%V5t(k_{nFd_(@C+23Jm0#k$yK;QtCXqy z+Lh#Rs_UgMGQJ=qa%C#hK}#~gtBL9DegF#pX}V=^-@9MnY7<5ax48Q$MT=#mOUp&| zm%QU7H*AUdq5C+gNHJ}hT31IN{K-hYqc({=YF^XorqCC5v~)8QUMpF_&pi1fSCXIhKBN!^*>hBQS`Mi*)~^nuqDXmqyLx0p2x+r+ SFSD?MOWDM4p>I4kq5cO59`5P@ diff --git a/tests/data/save_policy_to_safetensors/pusht_diffusion/output_dict.safetensors b/tests/data/save_policy_to_safetensors/pusht_diffusion/output_dict.safetensors index 77472bb50b2896c48a0a739eee9848e821769021..5f33535d5ad316f4cef55925a215428643ed2f52 100644 GIT binary patch delta 9 QcmZ>9nc%>3p0ULq01lS|@Bjb+ delta 9 QcmZ>9nc%?UzP#BU01jsZ4FCWD From eb6bfe01b2cab98649e580dfb55cd35a1f1c4ec4 Mon Sep 17 00:00:00 2001 From: Simon Alibert <75076266+aliberts@users.noreply.github.com> Date: Mon, 6 May 2024 17:38:29 +0200 Subject: [PATCH 03/27] Relax version contraints & poetry lock (#139) --- .pre-commit-config.yaml | 2 +- poetry.lock | 337 ++++++++++++++++++++-------------------- pyproject.toml | 2 +- 3 files changed, 170 insertions(+), 171 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 93b11ca9..913fcb5d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,7 +18,7 @@ repos: hooks: - id: pyupgrade - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.2 + rev: v0.4.3 hooks: - id: ruff args: [--fix] diff --git a/poetry.lock b/poetry.lock index 616f4a6a..26192e53 100644 --- a/poetry.lock +++ b/poetry.lock @@ -455,63 +455,63 @@ files = [ [[package]] name = "coverage" -version = "7.5.0" +version = "7.5.1" description = "Code coverage measurement for Python" optional = true python-versions = ">=3.8" files = [ - {file = "coverage-7.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:432949a32c3e3f820af808db1833d6d1631664d53dd3ce487aa25d574e18ad1c"}, - {file = "coverage-7.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2bd7065249703cbeb6d4ce679c734bef0ee69baa7bff9724361ada04a15b7e3b"}, - {file = "coverage-7.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbfe6389c5522b99768a93d89aca52ef92310a96b99782973b9d11e80511f932"}, - {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:39793731182c4be939b4be0cdecde074b833f6171313cf53481f869937129ed3"}, - {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85a5dbe1ba1bf38d6c63b6d2c42132d45cbee6d9f0c51b52c59aa4afba057517"}, - {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:357754dcdfd811462a725e7501a9b4556388e8ecf66e79df6f4b988fa3d0b39a"}, - {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a81eb64feded34f40c8986869a2f764f0fe2db58c0530d3a4afbcde50f314880"}, - {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:51431d0abbed3a868e967f8257c5faf283d41ec882f58413cf295a389bb22e58"}, - {file = "coverage-7.5.0-cp310-cp310-win32.whl", hash = "sha256:f609ebcb0242d84b7adeee2b06c11a2ddaec5464d21888b2c8255f5fd6a98ae4"}, - {file = "coverage-7.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:6782cd6216fab5a83216cc39f13ebe30adfac2fa72688c5a4d8d180cd52e8f6a"}, - {file = "coverage-7.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e768d870801f68c74c2b669fc909839660180c366501d4cc4b87efd6b0eee375"}, - {file = "coverage-7.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:84921b10aeb2dd453247fd10de22907984eaf80901b578a5cf0bb1e279a587cb"}, - {file = "coverage-7.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:710c62b6e35a9a766b99b15cdc56d5aeda0914edae8bb467e9c355f75d14ee95"}, - {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c379cdd3efc0658e652a14112d51a7668f6bfca7445c5a10dee7eabecabba19d"}, - {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fea9d3ca80bcf17edb2c08a4704259dadac196fe5e9274067e7a20511fad1743"}, - {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:41327143c5b1d715f5f98a397608f90ab9ebba606ae4e6f3389c2145410c52b1"}, - {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:565b2e82d0968c977e0b0f7cbf25fd06d78d4856289abc79694c8edcce6eb2de"}, - {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cf3539007202ebfe03923128fedfdd245db5860a36810136ad95a564a2fdffff"}, - {file = "coverage-7.5.0-cp311-cp311-win32.whl", hash = "sha256:bf0b4b8d9caa8d64df838e0f8dcf68fb570c5733b726d1494b87f3da85db3a2d"}, - {file = "coverage-7.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:9c6384cc90e37cfb60435bbbe0488444e54b98700f727f16f64d8bfda0b84656"}, - {file = "coverage-7.5.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fed7a72d54bd52f4aeb6c6e951f363903bd7d70bc1cad64dd1f087980d309ab9"}, - {file = "coverage-7.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cbe6581fcff7c8e262eb574244f81f5faaea539e712a058e6707a9d272fe5b64"}, - {file = "coverage-7.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad97ec0da94b378e593ef532b980c15e377df9b9608c7c6da3506953182398af"}, - {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd4bacd62aa2f1a1627352fe68885d6ee694bdaebb16038b6e680f2924a9b2cc"}, - {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:adf032b6c105881f9d77fa17d9eebe0ad1f9bfb2ad25777811f97c5362aa07f2"}, - {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ba01d9ba112b55bfa4b24808ec431197bb34f09f66f7cb4fd0258ff9d3711b1"}, - {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f0bfe42523893c188e9616d853c47685e1c575fe25f737adf473d0405dcfa7eb"}, - {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a9a7ef30a1b02547c1b23fa9a5564f03c9982fc71eb2ecb7f98c96d7a0db5cf2"}, - {file = "coverage-7.5.0-cp312-cp312-win32.whl", hash = "sha256:3c2b77f295edb9fcdb6a250f83e6481c679335ca7e6e4a955e4290350f2d22a4"}, - {file = "coverage-7.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:427e1e627b0963ac02d7c8730ca6d935df10280d230508c0ba059505e9233475"}, - {file = "coverage-7.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9dd88fce54abbdbf4c42fb1fea0e498973d07816f24c0e27a1ecaf91883ce69e"}, - {file = "coverage-7.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a898c11dca8f8c97b467138004a30133974aacd572818c383596f8d5b2eb04a9"}, - {file = "coverage-7.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07dfdd492d645eea1bd70fb1d6febdcf47db178b0d99161d8e4eed18e7f62fe7"}, - {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3d117890b6eee85887b1eed41eefe2e598ad6e40523d9f94c4c4b213258e4a4"}, - {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6afd2e84e7da40fe23ca588379f815fb6dbbb1b757c883935ed11647205111cb"}, - {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a9960dd1891b2ddf13a7fe45339cd59ecee3abb6b8326d8b932d0c5da208104f"}, - {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ced268e82af993d7801a9db2dbc1d2322e786c5dc76295d8e89473d46c6b84d4"}, - {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e7c211f25777746d468d76f11719e64acb40eed410d81c26cefac641975beb88"}, - {file = "coverage-7.5.0-cp38-cp38-win32.whl", hash = "sha256:262fffc1f6c1a26125d5d573e1ec379285a3723363f3bd9c83923c9593a2ac25"}, - {file = "coverage-7.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:eed462b4541c540d63ab57b3fc69e7d8c84d5957668854ee4e408b50e92ce26a"}, - {file = "coverage-7.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d0194d654e360b3e6cc9b774e83235bae6b9b2cac3be09040880bb0e8a88f4a1"}, - {file = "coverage-7.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33c020d3322662e74bc507fb11488773a96894aa82a622c35a5a28673c0c26f5"}, - {file = "coverage-7.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbdf2cae14a06827bec50bd58e49249452d211d9caddd8bd80e35b53cb04631"}, - {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3235d7c781232e525b0761730e052388a01548bd7f67d0067a253887c6e8df46"}, - {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2de4e546f0ec4b2787d625e0b16b78e99c3e21bc1722b4977c0dddf11ca84e"}, - {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0e206259b73af35c4ec1319fd04003776e11e859936658cb6ceffdeba0f5be"}, - {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2055c4fb9a6ff624253d432aa471a37202cd8f458c033d6d989be4499aed037b"}, - {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:075299460948cd12722a970c7eae43d25d37989da682997687b34ae6b87c0ef0"}, - {file = "coverage-7.5.0-cp39-cp39-win32.whl", hash = "sha256:280132aada3bc2f0fac939a5771db4fbb84f245cb35b94fae4994d4c1f80dae7"}, - {file = "coverage-7.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:c58536f6892559e030e6924896a44098bc1290663ea12532c78cef71d0df8493"}, - {file = "coverage-7.5.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:2b57780b51084d5223eee7b59f0d4911c31c16ee5aa12737c7a02455829ff067"}, - {file = "coverage-7.5.0.tar.gz", hash = "sha256:cf62d17310f34084c59c01e027259076479128d11e4661bb6c9acb38c5e19bb8"}, + {file = "coverage-7.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0884920835a033b78d1c73b6d3bbcda8161a900f38a488829a83982925f6c2e"}, + {file = "coverage-7.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:39afcd3d4339329c5f58de48a52f6e4e50f6578dd6099961cf22228feb25f38f"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b0ceee8147444347da6a66be737c9d78f3353b0681715b668b72e79203e4a"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a9ca3f2fae0088c3c71d743d85404cec8df9be818a005ea065495bedc33da35"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd215c0c7d7aab005221608a3c2b46f58c0285a819565887ee0b718c052aa4e"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4bf0655ab60d754491004a5efd7f9cccefcc1081a74c9ef2da4735d6ee4a6223"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:61c4bf1ba021817de12b813338c9be9f0ad5b1e781b9b340a6d29fc13e7c1b5e"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db66fc317a046556a96b453a58eced5024af4582a8dbdc0c23ca4dbc0d5b3146"}, + {file = "coverage-7.5.1-cp310-cp310-win32.whl", hash = "sha256:b016ea6b959d3b9556cb401c55a37547135a587db0115635a443b2ce8f1c7228"}, + {file = "coverage-7.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:df4e745a81c110e7446b1cc8131bf986157770fa405fe90e15e850aaf7619bc8"}, + {file = "coverage-7.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:796a79f63eca8814ca3317a1ea443645c9ff0d18b188de470ed7ccd45ae79428"}, + {file = "coverage-7.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fc84a37bfd98db31beae3c2748811a3fa72bf2007ff7902f68746d9757f3746"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6175d1a0559986c6ee3f7fccfc4a90ecd12ba0a383dcc2da30c2b9918d67d8a3"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fc81d5878cd6274ce971e0a3a18a8803c3fe25457165314271cf78e3aae3aa2"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:556cf1a7cbc8028cb60e1ff0be806be2eded2daf8129b8811c63e2b9a6c43bca"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9981706d300c18d8b220995ad22627647be11a4276721c10911e0e9fa44c83e8"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d7fed867ee50edf1a0b4a11e8e5d0895150e572af1cd6d315d557758bfa9c057"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ef48e2707fb320c8f139424a596f5b69955a85b178f15af261bab871873bb987"}, + {file = "coverage-7.5.1-cp311-cp311-win32.whl", hash = "sha256:9314d5678dcc665330df5b69c1e726a0e49b27df0461c08ca12674bcc19ef136"}, + {file = "coverage-7.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:5fa567e99765fe98f4e7d7394ce623e794d7cabb170f2ca2ac5a4174437e90dd"}, + {file = "coverage-7.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206"}, + {file = "coverage-7.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7"}, + {file = "coverage-7.5.1-cp312-cp312-win32.whl", hash = "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19"}, + {file = "coverage-7.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596"}, + {file = "coverage-7.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e2213def81a50519d7cc56ed643c9e93e0247f5bbe0d1247d15fa520814a7cd7"}, + {file = "coverage-7.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5037f8fcc2a95b1f0e80585bd9d1ec31068a9bcb157d9750a172836e98bc7a90"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3721c2c9e4c4953a41a26c14f4cef64330392a6d2d675c8b1db3b645e31f0e"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca498687ca46a62ae590253fba634a1fe9836bc56f626852fb2720f334c9e4e5"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cdcbc320b14c3e5877ee79e649677cb7d89ef588852e9583e6b24c2e5072661"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:57e0204b5b745594e5bc14b9b50006da722827f0b8c776949f1135677e88d0b8"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fe7502616b67b234482c3ce276ff26f39ffe88adca2acf0261df4b8454668b4"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9e78295f4144f9dacfed4f92935fbe1780021247c2fabf73a819b17f0ccfff8d"}, + {file = "coverage-7.5.1-cp38-cp38-win32.whl", hash = "sha256:1434e088b41594baa71188a17533083eabf5609e8e72f16ce8c186001e6b8c41"}, + {file = "coverage-7.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:0646599e9b139988b63704d704af8e8df7fa4cbc4a1f33df69d97f36cb0a38de"}, + {file = "coverage-7.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4cc37def103a2725bc672f84bd939a6fe4522310503207aae4d56351644682f1"}, + {file = "coverage-7.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc0b4d8bfeabd25ea75e94632f5b6e047eef8adaed0c2161ada1e922e7f7cece"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d0a0f5e06881ecedfe6f3dd2f56dcb057b6dbeb3327fd32d4b12854df36bf26"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9735317685ba6ec7e3754798c8871c2f49aa5e687cc794a0b1d284b2389d1bd5"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d21918e9ef11edf36764b93101e2ae8cc82aa5efdc7c5a4e9c6c35a48496d601"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c3e757949f268364b96ca894b4c342b41dc6f8f8b66c37878aacef5930db61be"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:79afb6197e2f7f60c4824dd4b2d4c2ec5801ceb6ba9ce5d2c3080e5660d51a4f"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1d0d98d95dd18fe29dc66808e1accf59f037d5716f86a501fc0256455219668"}, + {file = "coverage-7.5.1-cp39-cp39-win32.whl", hash = "sha256:1cc0fe9b0b3a8364093c53b0b4c0c2dd4bb23acbec4c9240b5f284095ccf7981"}, + {file = "coverage-7.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:dde0070c40ea8bb3641e811c1cfbf18e265d024deff6de52c5950677a8fb1e0f"}, + {file = "coverage-7.5.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312"}, + {file = "coverage-7.5.1.tar.gz", hash = "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c"}, ] [package.dependencies] @@ -522,13 +522,13 @@ toml = ["tomli"] [[package]] name = "datasets" -version = "2.19.0" +version = "2.19.1" description = "HuggingFace community-driven open-source library of datasets" optional = false python-versions = ">=3.8.0" files = [ - {file = "datasets-2.19.0-py3-none-any.whl", hash = "sha256:f57c5316e123d4721b970c68c1cb856505f289cda58f5557ffe745b49c011a8e"}, - {file = "datasets-2.19.0.tar.gz", hash = "sha256:0b47e08cc7af2c6800a42cadc4657b22a0afc7197786c8986d703c08d90886a6"}, + {file = "datasets-2.19.1-py3-none-any.whl", hash = "sha256:f7a78d15896f45004ccac1c298f3c7121f92f91f6f2bfbd4e4f210f827e6e411"}, + {file = "datasets-2.19.1.tar.gz", hash = "sha256:0df9ef6c5e9138cdb996a07385220109ff203c204245578b69cca905eb151d3a"}, ] [package.dependencies] @@ -1129,13 +1129,13 @@ test = ["pytest (>=8.1.0,<9.0.0)", "pytest-cov (>=5.0.0,<6.0.0)"] [[package]] name = "gym-pusht" -version = "0.1.0" +version = "0.1.1" description = "A gymnasium environment for PushT." optional = true python-versions = "<4.0,>=3.10" files = [ - {file = "gym_pusht-0.1.0-py3-none-any.whl", hash = "sha256:ad0841f3b03741eb08985b703eab4931653a44fd255c26e2c82a7f71cc4dc210"}, - {file = "gym_pusht-0.1.0.tar.gz", hash = "sha256:82b26ea753f28f0277c06839c68970a4ea872fae4710402349f872ae45de83f4"}, + {file = "gym_pusht-0.1.1-py3-none-any.whl", hash = "sha256:dcf8644713db48286e907aabb11e005b0592632e323baa40d1a4f2dfbbc76c3d"}, + {file = "gym_pusht-0.1.1.tar.gz", hash = "sha256:0d1c9ffd4ad0e2411efcc724003a365a853f20b6d596980c113e7ec181ac021f"}, ] [package.dependencies] @@ -1143,7 +1143,7 @@ gymnasium = ">=0.29.1,<0.30.0" opencv-python = ">=4.9.0.80,<5.0.0.0" pygame = ">=2.5.2,<3.0.0" pymunk = ">=6.6.0,<7.0.0" -scikit-image = ">=0.22.0,<0.23.0" +scikit-image = ">=0.22.0" shapely = ">=2.0.3,<3.0.0" [package.extras] @@ -1471,13 +1471,13 @@ files = [ [[package]] name = "jinja2" -version = "3.1.3" +version = "3.1.4" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, - {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, ] [package.dependencies] @@ -2407,6 +2407,7 @@ optional = false python-versions = ">=3.9" files = [ {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, + {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"}, {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"}, {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"}, {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"}, @@ -2427,6 +2428,7 @@ files = [ {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"}, {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"}, {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"}, + {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"}, {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"}, {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"}, {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"}, @@ -2868,74 +2870,74 @@ files = [ [[package]] name = "pymunk" -version = "6.6.0" -description = "Pymunk is a easy-to-use pythonic 2d physics library" +version = "6.7.0" +description = "Pymunk is a easy-to-use pythonic 2D physics library" optional = false python-versions = ">=3.7" files = [ - {file = "pymunk-6.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6da50dd97683337a290110d594fad07a75153d2d837b570ef972478d739c33f8"}, - {file = "pymunk-6.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bcd7d16a2b4d51d45d6780a701f65c8d5b36fdf545c3f4738910da41e2a9c4ee"}, - {file = "pymunk-6.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32c91a783b645267518588515acdc3ff315135297eef39386d488c4ff2a7c139"}, - {file = "pymunk-6.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74694f92f46fe54e2c033b598b2c38185f456711888955aa3f67003692a3ef91"}, - {file = "pymunk-6.6.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fe011afb3f7594a679ba35dc7a44e12c8c8aacb55e58d54f14bfe8b82959695c"}, - {file = "pymunk-6.6.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:60e5cc6e33f7e880418f75a7d6b5ac3eed47396bbe7c68ca47c389de3b5d1d3a"}, - {file = "pymunk-6.6.0-cp310-cp310-win32.whl", hash = "sha256:10518074e33d4fe723bce795f705ad3e850ecec9987559ec3fa072a6539c47ad"}, - {file = "pymunk-6.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:5b163b28f9500df1bb5e123e2dba2d1f255e63be6ca098544936a93c05022a43"}, - {file = "pymunk-6.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8322594fc68858bfc0142f2f7a100cfb4edb85678a75983ce2fc58ed763afb96"}, - {file = "pymunk-6.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c1d0be60b781d1b8bb11303b25936d01cdef7ccfcc3a68b0c2fd689f63ac11c"}, - {file = "pymunk-6.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9462200c47f3eb344373077dc01384cb16355a982ce0e33571201f3b7ee44487"}, - {file = "pymunk-6.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ede46cc44432b1316a402129fc225743f7e9f502d0d055790eab877627ddfd98"}, - {file = "pymunk-6.6.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3582cd67d6ac16f122d2b7100e0b00d9b55f97a0a7e21336df885166e2bffdc3"}, - {file = "pymunk-6.6.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e4247ede965df39d2fd7ae25e9360762cce61f4d39b95af91d29c1c556c80777"}, - {file = "pymunk-6.6.0-cp311-cp311-win32.whl", hash = "sha256:a77f9bb634ab216ac8991f73aa68b4dadfd6690e8cb17627a6646dc8fecd6126"}, - {file = "pymunk-6.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:2f579e8c5498b3e8c0686841f1f5e3adf1bdd32b339ee36001ebae19bbafc008"}, - {file = "pymunk-6.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ad6ca584a9ea1d6a1536ae158350d73dbbdc637f302a86019b7fb299120439c4"}, - {file = "pymunk-6.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b86be4ecfb86d4af26c3dd2e390884305c3b8604e5df8550fbb2968d3ac78411"}, - {file = "pymunk-6.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68006cfb71351b6f23a81f541a2eca56596e69977e051e46cfe93a5ffdc410ef"}, - {file = "pymunk-6.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:361d2fa43e65aa5e47dcb50e6b058b3814e19cbdb5bf062d2da78c2b3bdba192"}, - {file = "pymunk-6.6.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3c35975f4172b024e0bb1be6f57f1048dcb469a8cf257c30123d11a9fe57e2a"}, - {file = "pymunk-6.6.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:35a57546294656b5bb989e08426a4926e26a17726aef35daf34c2703ee54c0e9"}, - {file = "pymunk-6.6.0-cp312-cp312-win32.whl", hash = "sha256:a68480440b60bf5acf3a7a8db1eb571e13ed425d5b693a20020f2efa9cc09592"}, - {file = "pymunk-6.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:f7ed11a1e2a306e4213d88a1879ae0fb7c2c983a890fa1b35ed26b9392213c02"}, - {file = "pymunk-6.6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:49961e339571d14afa9ebc815190ebfdda69e6ffd433536451bb07d6bc55e430"}, - {file = "pymunk-6.6.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70d9d5edcb2e90eeea0afb322c82d75a02e6bb77a9ff08b86daa2245a2c2a4ef"}, - {file = "pymunk-6.6.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:622746251dda14507d3655b64c93a4509125c0a651265c473945f227ba5763ec"}, - {file = "pymunk-6.6.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:35277485eb69cc5dda3f15b139723c77d69b9271f9fedf4264d08e8afdea67d0"}, - {file = "pymunk-6.6.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ceadcf03988c51697a3357d6dd3c96dd60e48b993734346edf8955fcd3770466"}, - {file = "pymunk-6.6.0-cp37-cp37m-win32.whl", hash = "sha256:0d8e0e79135e86b6e0e686fd287f297488e728cb8276fc713cb33fdd7ce4f5f2"}, - {file = "pymunk-6.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:259a371150a9e264851d0a9caa85b5a19ba661f364da630a231a3eb326d49ca1"}, - {file = "pymunk-6.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e97ad1ce7fa3e9ea15622d1e0c45e2757f02e1c947a354888c2014799575c100"}, - {file = "pymunk-6.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4cd70ffc259b8069eabb54ed5c7cbc39d0f5158610791c14ad0437f6cb6d18d"}, - {file = "pymunk-6.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1cf85e95774a89b2adf084c0129d62f69eaa23b97b800892ddcfa7862b931bbb"}, - {file = "pymunk-6.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8d60b9fcde952d6e25c740a1ced5612ace59fa85e578986f7f053a538a681ed"}, - {file = "pymunk-6.6.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5652c423ea2769b1d44e33fd2b19f2a6f7f4a34acacec9a86b63c780ac611552"}, - {file = "pymunk-6.6.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:939e46d9021cb5bc6ac4dbecafe89245af2b8325787869983b0a99181e37fd39"}, - {file = "pymunk-6.6.0-cp38-cp38-win32.whl", hash = "sha256:7785f5ac0597be5693dd2da819233297984d324b6470bf31b76c71399f25a18e"}, - {file = "pymunk-6.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:26a0834207785878ba2bb244ab5616d9b6e09d01c2f19641f10247ca22d3c10e"}, - {file = "pymunk-6.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ed23f05a65687750cba4d6cde045147d28eee84e44cd33829b79601dc655adf3"}, - {file = "pymunk-6.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b2c23f2f182f91944c4ba5cfd6f652e873e6e8b113506c3eca255df5e6c79b6e"}, - {file = "pymunk-6.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c51b6de5869dcb103467d8ac75f62a1a9f43faa18bf12e37e89247b2d5554a61"}, - {file = "pymunk-6.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b44c4420b43cfdfedd2278e3beb60970a9a9564f1272c7cc74090931268ab43"}, - {file = "pymunk-6.6.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:4b8d9c14275fd4853ae863e38bec8a7ae4c7aef4417550ff74fc9f68f120fa00"}, - {file = "pymunk-6.6.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31631a91bf29dde9c4a5f1283056cb91d451fe352f35a440c5cb668b0de19ad5"}, - {file = "pymunk-6.6.0-cp39-cp39-win32.whl", hash = "sha256:832d83570d0781e2bcba555b0974e9a5f9ee592079dfd3b183a493cf0ceaac7f"}, - {file = "pymunk-6.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:88625cca15c90dc8c0c1b55113f0ff19a8e6601ac0981804d317660c0afde9e2"}, - {file = "pymunk-6.6.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8e27a8c7b762d43e91f18c320ad849c113dead500184d151aa14bd11a62c2c47"}, - {file = "pymunk-6.6.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad898ca45546f084b0d88f73c771e3de0d19acc65f1171a9dbdba171945a915"}, - {file = "pymunk-6.6.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:45f537c79e817330753e6ed220b3ff46b5b983266d5b85ce7c1381a77b33d1f3"}, - {file = "pymunk-6.6.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:609341ff1329e59ee7a67b622973064c213111e87916981bc45838f38981ba47"}, - {file = "pymunk-6.6.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:345b99d19cb848359fbefcaba54a5f1bcc8dd05b084563d693ca4d0622aa1079"}, - {file = "pymunk-6.6.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f33c418b758e06960fa28e0434c14818c0d9755f431045db05cc93e646df9b22"}, - {file = "pymunk-6.6.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59991310cb1a6f201878e9519cbb36ff746f825c9fac49fa76cf8c85b64bf7ad"}, - {file = "pymunk-6.6.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c7513caf1add221cfa1228c12e14e0997a7212e583a59f517b68e72b1f02e08f"}, - {file = "pymunk-6.6.0.tar.gz", hash = "sha256:89be7b6ba237e313c440edfb99612de59bf119e43976d5c76802907cb7a3911c"}, + {file = "pymunk-6.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4378774daf5cf2603c0558562221ba5a2ba9c6d7e4d830f4da9e1d6a00e6f3cd"}, + {file = "pymunk-6.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:badbdbf499f79c3e937ba7044c3ce3a665d6ae76c2a7df2408994e07fd78b34b"}, + {file = "pymunk-6.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46835d63bdcc579a488d2dfbc7cbec52bfc34a4ceb15086820d1372f70cb8695"}, + {file = "pymunk-6.7.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c63f0153bcb4080cd83f3d40cec4f525773ac0f4ac2bf9b9506c2fa8af7b4e41"}, + {file = "pymunk-6.7.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:72596e57997856817202580557a4f4b46a0b1ddf0fbbbadf978f46778d5aa642"}, + {file = "pymunk-6.7.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:43099a916c2bbd9740a740f259bb26341e8cb54fb0c06192ea0cc27606552596"}, + {file = "pymunk-6.7.0-cp310-cp310-win32.whl", hash = "sha256:2cf770c8ae5d14c51b7021768bf73b7c8c62d786d703dd9f6e1ec3ea12966f91"}, + {file = "pymunk-6.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:e0ea3a7cab752bc5078c202e40bf4db81435fd1d121190e851a960a1b9a070df"}, + {file = "pymunk-6.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:803c0dfb8be18a8fac5d37732d7db29589d6157594a22608fa5e34ee87a5ff8e"}, + {file = "pymunk-6.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e82f817cdddd3b9babebc1ce964eed55f8d5686475b92e3e6d3d22dca5b93f3c"}, + {file = "pymunk-6.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3693a1aeb4ce8a68574b3b7557c6a1e15ce420820b850f95f34ab24663fdcb11"}, + {file = "pymunk-6.7.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f32b352a87ad1705bfedef133253da697e9a0eeff764e125414a63231bfb06e"}, + {file = "pymunk-6.7.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7ec996c4305666336c3e2908b59e0644f4095a526ed2f96f0f8d35bdc41a4575"}, + {file = "pymunk-6.7.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7e54923293dfa51c41f222d967cb3b79872f35a4a892ae0bd31bad9cefd1b8a6"}, + {file = "pymunk-6.7.0-cp311-cp311-win32.whl", hash = "sha256:d4622c2927789d7bc834763569fb4a947c266702eb9e5f12f815bd841c49f669"}, + {file = "pymunk-6.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:031c74ed42e49474ca4fcdc11a9521c2084514d2213cb8b7df7cb50a66b66686"}, + {file = "pymunk-6.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c2316d188a9fc6d0661afc30fbb164a546b939faf359e98f082641ca41c924e2"}, + {file = "pymunk-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5f494effad0dbd873851b52b22c1a812fe36f1fb1e29d28759066cee1afca1e9"}, + {file = "pymunk-6.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:895deeae5a9c2ef3bbb842ef5d37e750160c8ba956a4149fbb89304eb7b4808e"}, + {file = "pymunk-6.7.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f672762c176ba51c2327f7a66db10c0adfb5f3caaa4f586098c62c169b311f87"}, + {file = "pymunk-6.7.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9f0e26d53cb5aaf22042de97638c356d25c1062198594390a18810f2992cd4b5"}, + {file = "pymunk-6.7.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c4985590a95d419a7684f2c01b33fc61e939debaae7b12d1cf0946070c1644f9"}, + {file = "pymunk-6.7.0-cp312-cp312-win32.whl", hash = "sha256:b63875005eee0126a0be32cfd9179be520a2f73235ae98408af2ba39255f8e07"}, + {file = "pymunk-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:4a9438d29c1f0397b45b328f74eaed097593de03d8d0546fa84c20c3a5f158e6"}, + {file = "pymunk-6.7.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:630ddc4a03f4ac9d5dfd13bb99e20146d804683212defb8d0633fbf4844035b4"}, + {file = "pymunk-6.7.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca0c565e7c8ff8bc2ee477ed712973609a77a229e813a7a18c499ff5b96415a7"}, + {file = "pymunk-6.7.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f0d79e89fc3ccee6007380a9df493017c178a606446a1382fc0e351bd48622d"}, + {file = "pymunk-6.7.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:827180ee032b3237be2980712cdfe1446c2f7aeeb7f13518ebb4cc022995d235"}, + {file = "pymunk-6.7.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c401a6068b376dcd3d25948b498cea410e15a93108c4d8e03c94f9b61767593b"}, + {file = "pymunk-6.7.0-cp37-cp37m-win32.whl", hash = "sha256:a38d8b70c6a7198fc0e746ab8dfedd70f9bf26579b6cd11789f3232f27d247fb"}, + {file = "pymunk-6.7.0-cp37-cp37m-win_amd64.whl", hash = "sha256:283746a11658288903af182605f1034bc5cffbb5de49fd4d8bea43330778ddfb"}, + {file = "pymunk-6.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8376aad8169a13a5368c597cf54b492f6dd6ef4c9273385af461b6f416f0205a"}, + {file = "pymunk-6.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0bf0ec5142ae387789eca6210a315508943a0af14faf337154c1c6b2e20abaad"}, + {file = "pymunk-6.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e5469182821d23e43e1fe50b21a313f798eefafc59b0f25dd69a7b579cdbbbc"}, + {file = "pymunk-6.7.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cee5c5da3f624c1b4f10e566f6322f354f0925dc081c1d6dfdb56fa94ff6b2b7"}, + {file = "pymunk-6.7.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:130234abfb503a9d3aba57161bf7520eb57c27278ad6f47888f862a2808b1f8d"}, + {file = "pymunk-6.7.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3532965ba0048057ce00eccbafca818586acabf77c4453d36e9be5f614dab260"}, + {file = "pymunk-6.7.0-cp38-cp38-win32.whl", hash = "sha256:3dca5b72c34f4957c039ced8bd58ca484b929f0f6c4fc4f8a2268d89999d3b13"}, + {file = "pymunk-6.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:aaac3b0a2446575cf0fa90745ef6b99cd786837e1baaf2f530febf2824d07276"}, + {file = "pymunk-6.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6ee13324c8fdfdab03069eef00aadfe06d353d9d6c5e4a93e190c9b214166f8b"}, + {file = "pymunk-6.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1fd1069c95061feebf7dfbbb32a2150e019d06001a0c8281442d27366d2a6f21"}, + {file = "pymunk-6.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7aeac2ba24977aae4e602a993c17c265f168374b018d09e13536c1df61cf4d5"}, + {file = "pymunk-6.7.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e78eb9f6b6a7656837698ea9a6ceea00d84959de3126e625de41cf240084dba6"}, + {file = "pymunk-6.7.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:927fa4262c62f409e79806ef282a3bee1dab5a69e680e5cf2ba26b58c850e9be"}, + {file = "pymunk-6.7.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c127f39bd23c93e82f0ee0adc1edbd8ebdda441d12f9d09987372be9852edb74"}, + {file = "pymunk-6.7.0-cp39-cp39-win32.whl", hash = "sha256:ce582ae06e6fe8e8d1ad10dc061fe5716b360ea04b79925532d96848741a5452"}, + {file = "pymunk-6.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:04874a4063270db73bd2e6b3522d2e6ffb193a183d06872bb1270385475412f8"}, + {file = "pymunk-6.7.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:032daa41f9219749e52b1ff3312cdff3eab24c31ec8495777da89003667137ad"}, + {file = "pymunk-6.7.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210e067b29fda70a8c21f09a9a900d0b917d425e6d47209426e5b88388bd2a06"}, + {file = "pymunk-6.7.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:046e510d76976c41cd92b3d5b985c930f0a568c2fb4f0632e40aaab4619ad481"}, + {file = "pymunk-6.7.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:27a4104a51ae690fc0feb2a567279234307decaf86214382a1dce89527365422"}, + {file = "pymunk-6.7.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8ac7b714a8fc83325519254c6734baa9dd1498210c6d5e51facfd829a6b2de09"}, + {file = "pymunk-6.7.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09b22ce73222c5f7cf061f6cd71097c94f57c89b6364acfc30f707ca1d3c67e2"}, + {file = "pymunk-6.7.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3313c5531e6678f249bc1cf84cb5c4993745e8652853f1962919678f6a0b4ec3"}, + {file = "pymunk-6.7.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d8aaaebdd546b9b76d4905039835910a5965fff816261ce2b9558a7607206f52"}, + {file = "pymunk-6.7.0.tar.gz", hash = "sha256:7b3bff3852c46a87b497a1a73bb36bb2b2f7e38be2e7c232498b857e79197560"}, ] [package.dependencies] cffi = ">=1.15.0" [package.extras] -dev = ["aafigure", "matplotlib", "pygame", "pyglet (<2.0.0)", "sphinx", "wheel"] +dev = ["aafigure", "matplotlib", "numpy", "pygame", "pyglet (<2.0.0)", "sphinx", "wheel"] [[package]] name = "pyopengl" @@ -3064,7 +3066,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -3381,51 +3382,46 @@ torch = ["safetensors[numpy]", "torch (>=1.10)"] [[package]] name = "scikit-image" -version = "0.22.0" +version = "0.23.2" description = "Image processing in Python" optional = true -python-versions = ">=3.9" +python-versions = ">=3.10" files = [ - {file = "scikit_image-0.22.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:74ec5c1d4693506842cc7c9487c89d8fc32aed064e9363def7af08b8f8cbb31d"}, - {file = "scikit_image-0.22.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:a05ae4fe03d802587ed8974e900b943275548cde6a6807b785039d63e9a7a5ff"}, - {file = "scikit_image-0.22.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a92dca3d95b1301442af055e196a54b5a5128c6768b79fc0a4098f1d662dee6"}, - {file = "scikit_image-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3663d063d8bf2fb9bdfb0ca967b9ee3b6593139c860c7abc2d2351a8a8863938"}, - {file = "scikit_image-0.22.0-cp310-cp310-win_amd64.whl", hash = "sha256:ebdbdc901bae14dab637f8d5c99f6d5cc7aaf4a3b6f4003194e003e9f688a6fc"}, - {file = "scikit_image-0.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:95d6da2d8a44a36ae04437c76d32deb4e3c993ffc846b394b9949fd8ded73cb2"}, - {file = "scikit_image-0.22.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:2c6ef454a85f569659b813ac2a93948022b0298516b757c9c6c904132be327e2"}, - {file = "scikit_image-0.22.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e87872f067444ee90a00dd49ca897208308645382e8a24bd3e76f301af2352cd"}, - {file = "scikit_image-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5c378db54e61b491b9edeefff87e49fcf7fdf729bb93c777d7a5f15d36f743e"}, - {file = "scikit_image-0.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:2bcb74adb0634258a67f66c2bb29978c9a3e222463e003b67ba12056c003971b"}, - {file = "scikit_image-0.22.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:003ca2274ac0fac252280e7179ff986ff783407001459ddea443fe7916e38cff"}, - {file = "scikit_image-0.22.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:cf3c0c15b60ae3e557a0c7575fbd352f0c3ce0afca562febfe3ab80efbeec0e9"}, - {file = "scikit_image-0.22.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5b23908dd4d120e6aecb1ed0277563e8cbc8d6c0565bdc4c4c6475d53608452"}, - {file = "scikit_image-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be79d7493f320a964f8fcf603121595ba82f84720de999db0fcca002266a549a"}, - {file = "scikit_image-0.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:722b970aa5da725dca55252c373b18bbea7858c1cdb406e19f9b01a4a73b30b2"}, - {file = "scikit_image-0.22.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:22318b35044cfeeb63ee60c56fc62450e5fe516228138f1d06c7a26378248a86"}, - {file = "scikit_image-0.22.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:9e801c44a814afdadeabf4dffdffc23733e393767958b82319706f5fa3e1eaa9"}, - {file = "scikit_image-0.22.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c472a1fb3665ec5c00423684590631d95f9afcbc97f01407d348b821880b2cb3"}, - {file = "scikit_image-0.22.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b7a6c89e8d6252332121b58f50e1625c35f7d6a85489c0b6b7ee4f5155d547a"}, - {file = "scikit_image-0.22.0-cp39-cp39-win_amd64.whl", hash = "sha256:5071b8f6341bfb0737ab05c8ab4ac0261f9e25dbcc7b5d31e5ed230fd24a7929"}, - {file = "scikit_image-0.22.0.tar.gz", hash = "sha256:018d734df1d2da2719087d15f679d19285fce97cd37695103deadfaef2873236"}, + {file = "scikit_image-0.23.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9a8db6c52f8d0e1474ea8320d7b8db442b4d6baa29dd0acbd02f8a49572f18a"}, + {file = "scikit_image-0.23.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:524b51a7440e46ed2ebbde7bc288bf2dde1dee2caafdd9513b2aca38a48223b7"}, + {file = "scikit_image-0.23.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b335c229170d787b3fb8c60d220f72049ccf862d5191a3cfda6ac84b995ac4e"}, + {file = "scikit_image-0.23.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08b10781efbd6b084f3c847ff4049b657241ea866b9e331b14bf791dcb3e6661"}, + {file = "scikit_image-0.23.2-cp310-cp310-win_amd64.whl", hash = "sha256:a207352e9a1956dda1424bbe872c7795345187138118e8be6a421aef3b988c2a"}, + {file = "scikit_image-0.23.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ee83fdb1843ee938eabdfeb9498623282935ea30aa20dffc5d5d16698efb4b2a"}, + {file = "scikit_image-0.23.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:a158f50d3df4867bbd1c698520ede8bc493e430ad83f54ac1f0d8f57b328779b"}, + {file = "scikit_image-0.23.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55de3326be124334b89314e9e04c8971ad98d6681e11a243f71bfb85ef9554b0"}, + {file = "scikit_image-0.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fce619a6d84fe40c1208fa579b646e93ce13ef0afc3652a23e9782b2c183291a"}, + {file = "scikit_image-0.23.2-cp311-cp311-win_amd64.whl", hash = "sha256:ee65669aa586e110346f567ed5c92d1bd63799a19e951cb83da3f54b0caf7c52"}, + {file = "scikit_image-0.23.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:15bfb4e8d7bd90a967e6a3c3ab6be678063fc45e950b730684a8db46a02ff892"}, + {file = "scikit_image-0.23.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:5736e66d01b11cd90988ec24ab929c80a03af28f690189c951886891ebf63154"}, + {file = "scikit_image-0.23.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3597ac5d8f51dafbcb7433ef1fdefdefb535f50745b2002ae0a5d651df4f063b"}, + {file = "scikit_image-0.23.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1978be2abe3c3c3189a99a411d48bbb1306f7c2debb3aefbf426e23947f26623"}, + {file = "scikit_image-0.23.2-cp312-cp312-win_amd64.whl", hash = "sha256:ae32bf0cb02b672ed74d28880ca6f88928ae8dd794d67e04fa3ff4836feb9bd6"}, + {file = "scikit_image-0.23.2.tar.gz", hash = "sha256:c9da4b2c3117e3e30364a3d14496ee5c72b09eb1a4ab1292b302416faa360590"}, ] [package.dependencies] -imageio = ">=2.27" -lazy_loader = ">=0.3" +imageio = ">=2.33" +lazy-loader = ">=0.4" networkx = ">=2.8" -numpy = ">=1.22" +numpy = ">=1.23" packaging = ">=21" -pillow = ">=9.0.1" -scipy = ">=1.8" +pillow = ">=9.1" +scipy = ">=1.9" tifffile = ">=2022.8.12" [package.extras] -build = ["Cython (>=0.29.32)", "build", "meson-python (>=0.14)", "ninja", "numpy (>=1.22)", "packaging (>=21)", "pythran", "setuptools (>=67)", "spin (==0.6)", "wheel"] +build = ["Cython (>=3.0.4)", "build", "meson-python (>=0.15)", "ninja", "numpy (>=2.0.0rc1)", "packaging (>=21)", "pythran", "setuptools (>=67)", "spin (==0.8)", "wheel"] data = ["pooch (>=1.6.0)"] -developer = ["pre-commit", "tomli"] -docs = ["PyWavelets (>=1.1.1)", "dask[array] (>=2022.9.2)", "ipykernel", "ipywidgets", "kaleido", "matplotlib (>=3.5)", "myst-parser", "numpydoc (>=1.6)", "pandas (>=1.5)", "plotly (>=5.10)", "pooch (>=1.6)", "pydata-sphinx-theme (>=0.14.1)", "pytest-runner", "scikit-learn (>=1.1)", "seaborn (>=0.11)", "sphinx (>=7.2)", "sphinx-copybutton", "sphinx-gallery (>=0.14)", "sphinx_design (>=0.5)", "tifffile (>=2022.8.12)"] -optional = ["PyWavelets (>=1.1.1)", "SimpleITK", "astropy (>=5.0)", "cloudpickle (>=0.2.1)", "dask[array] (>=2021.1.0)", "matplotlib (>=3.5)", "pooch (>=1.6.0)", "pyamg", "scikit-learn (>=1.1)"] -test = ["asv", "matplotlib (>=3.5)", "numpydoc (>=1.5)", "pooch (>=1.6.0)", "pytest (>=7.0)", "pytest-cov (>=2.11.0)", "pytest-faulthandler", "pytest-localserver"] +developer = ["ipython", "pre-commit", "tomli"] +docs = ["PyWavelets (>=1.1.1)", "dask[array] (>=2022.9.2)", "ipykernel", "ipywidgets", "kaleido", "matplotlib (>=3.6)", "myst-parser", "numpydoc (>=1.7)", "pandas (>=1.5)", "plotly (>=5.10)", "pooch (>=1.6)", "pydata-sphinx-theme (>=0.15.2)", "pytest-doctestplus", "pytest-runner", "scikit-learn (>=1.1)", "seaborn (>=0.11)", "sphinx (>=7.3)", "sphinx-copybutton", "sphinx-gallery (>=0.14)", "sphinx_design (>=0.5)", "tifffile (>=2022.8.12)"] +optional = ["PyWavelets (>=1.1.1)", "SimpleITK", "astropy (>=5.0)", "cloudpickle (>=0.2.1)", "dask[array] (>=2021.1.0)", "matplotlib (>=3.6)", "pooch (>=1.6.0)", "pyamg", "scikit-learn (>=1.1)"] +test = ["asv", "numpydoc (>=1.7)", "pooch (>=1.6.0)", "pytest (>=7.0)", "pytest-cov (>=2.11.0)", "pytest-doctestplus", "pytest-faulthandler", "pytest-localserver"] [[package]] name = "scipy" @@ -3471,13 +3467,13 @@ test = ["array-api-strict", "asv", "gmpy2", "hypothesis (>=6.30)", "mpmath", "po [[package]] name = "sentry-sdk" -version = "2.0.1" +version = "2.1.1" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = ">=3.6" files = [ - {file = "sentry_sdk-2.0.1-py2.py3-none-any.whl", hash = "sha256:b54c54a2160f509cf2757260d0cf3885b608c6192c2555a3857e3a4d0f84bdb3"}, - {file = "sentry_sdk-2.0.1.tar.gz", hash = "sha256:c278e0f523f6f0ee69dc43ad26dcdb1202dffe5ac326ae31472e012d941bee21"}, + {file = "sentry_sdk-2.1.1-py2.py3-none-any.whl", hash = "sha256:99aeb78fb76771513bd3b2829d12613130152620768d00cd3e45ac00cb17950f"}, + {file = "sentry_sdk-2.1.1.tar.gz", hash = "sha256:95d8c0bb41c8b0bc37ab202c2c4a295bb84398ee05f4cdce55051cd75b926ec1"}, ] [package.dependencies] @@ -3486,6 +3482,7 @@ urllib3 = ">=1.26.11" [package.extras] aiohttp = ["aiohttp (>=3.5)"] +anthropic = ["anthropic (>=0.16)"] arq = ["arq (>=0.23)"] asyncpg = ["asyncpg (>=0.23)"] beam = ["apache-beam (>=2.12)"] @@ -3501,6 +3498,8 @@ flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"] grpcio = ["grpcio (>=1.21.1)"] httpx = ["httpx (>=0.16.0)"] huey = ["huey (>=2)"] +huggingface-hub = ["huggingface-hub (>=0.22)"] +langchain = ["langchain (>=0.0.210)"] loguru = ["loguru (>=0.5)"] openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"] opentelemetry = ["opentelemetry-distro (>=0.35b0)"] @@ -3814,13 +3813,13 @@ tests = ["pytest", "pytest-cov"] [[package]] name = "tifffile" -version = "2024.4.24" +version = "2024.5.3" description = "Read and write TIFF files" optional = true python-versions = ">=3.9" files = [ - {file = "tifffile-2024.4.24-py3-none-any.whl", hash = "sha256:8d0b982f4b01ace358835ae6c2beb5a70cb7287f5d3a2e96c318bd5befa97b1f"}, - {file = "tifffile-2024.4.24.tar.gz", hash = "sha256:e329f36ac8ff3bbe7dd04609340be26b03c4b9e9a69235fc3ab33434157c38ea"}, + {file = "tifffile-2024.5.3-py3-none-any.whl", hash = "sha256:cac4d939156ff7f16d65fd689637808a7b5b3ad58f9c73327fc009b0aa32c7d5"}, + {file = "tifffile-2024.5.3.tar.gz", hash = "sha256:44521508ecc51ebaf0e47e9748913e9c7331a4e32fb571ff4dfc05cb8f4d8896"}, ] [package.dependencies] @@ -3933,13 +3932,13 @@ scipy = ["scipy"] [[package]] name = "tqdm" -version = "4.66.2" +version = "4.66.4" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" files = [ - {file = "tqdm-4.66.2-py3-none-any.whl", hash = "sha256:1ee4f8a893eb9bef51c6e35730cebf234d5d0b6bd112b0271e10ed7c24a02bd9"}, - {file = "tqdm-4.66.2.tar.gz", hash = "sha256:6cd52cdf0fef0e0f543299cfc96fec90d7b8a7e88745f411ec33eb44d5ed3531"}, + {file = "tqdm-4.66.4-py3-none-any.whl", hash = "sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644"}, + {file = "tqdm-4.66.4.tar.gz", hash = "sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb"}, ] [package.dependencies] @@ -4073,13 +4072,13 @@ sweeps = ["sweeps (>=0.2.0)"] [[package]] name = "werkzeug" -version = "3.0.2" +version = "3.0.3" description = "The comprehensive WSGI web application library." optional = false python-versions = ">=3.8" files = [ - {file = "werkzeug-3.0.2-py3-none-any.whl", hash = "sha256:3aac3f5da756f93030740bc235d3e09449efcf65f2f55e3602e1d851b8f48795"}, - {file = "werkzeug-3.0.2.tar.gz", hash = "sha256:e39b645a6ac92822588e7b39a692e7828724ceae0b0d702ef96701f90e70128d"}, + {file = "werkzeug-3.0.3-py3-none-any.whl", hash = "sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8"}, + {file = "werkzeug-3.0.3.tar.gz", hash = "sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18"}, ] [package.dependencies] @@ -4355,4 +4354,4 @@ xarm = ["gym-xarm"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.13" -content-hash = "d2066576dc4aebaf623c295fe626bf6805fd2ec26a6ba47fa5415204994aa922" +content-hash = "008a6af5ad9d9eafbd933c922c2c5d84fddae85aff8a9eefc0538b1319966f6e" diff --git a/pyproject.toml b/pyproject.toml index d7bccbd5..94ed5d03 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,7 +47,7 @@ huggingface-hub = "^0.21.4" robomimic = "0.2.0" gymnasium = "^0.29.1" cmake = "^3.29.0.1" -gym-pusht = { version = "^0.1.0", optional = true} +gym-pusht = { version = "^0.1.1", optional = true} gym-xarm = { version = "^0.1.0", optional = true} gym-aloha = { version = "^0.1.0", optional = true} pre-commit = {version = "^3.7.0", optional = true} From 26d9a070d80af25fdbef2e02c722574450ad1e36 Mon Sep 17 00:00:00 2001 From: Alexander Soare Date: Tue, 7 May 2024 09:09:21 +0100 Subject: [PATCH 04/27] Add policy and dataset tags to WandB logging (#144) --- lerobot/common/logger.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lerobot/common/logger.py b/lerobot/common/logger.py index 832eaa7e..8e7fe7f2 100644 --- a/lerobot/common/logger.py +++ b/lerobot/common/logger.py @@ -17,9 +17,10 @@ def log_output_dir(out_dir): def cfg_to_group(cfg, return_list=False): - """Return a wandb-safe group name for logging. Optionally returns group name as list.""" - # lst = [cfg.task, cfg.modality, re.sub("[^0-9a-zA-Z]+", "-", cfg.exp_name)] + """Return a group name for logging. Optionally returns group name as list.""" lst = [ + f"policy:{cfg.policy.name}", + f"dataset:{cfg.dataset_repo_id}", f"env:{cfg.env.name}", f"seed:{cfg.seed}", ] From 47de07658c3ee02c9b65b2632152c9311759a46b Mon Sep 17 00:00:00 2001 From: Alexander Soare Date: Wed, 8 May 2024 12:56:21 +0100 Subject: [PATCH 05/27] Override pretrained model config (#147) --- lerobot/common/policies/factory.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lerobot/common/policies/factory.py b/lerobot/common/policies/factory.py index 4819ca80..a819d18f 100644 --- a/lerobot/common/policies/factory.py +++ b/lerobot/common/policies/factory.py @@ -1,4 +1,5 @@ import inspect +import logging from omegaconf import DictConfig, OmegaConf @@ -8,9 +9,10 @@ from lerobot.common.utils.utils import get_safe_torch_device def _policy_cfg_from_hydra_cfg(policy_cfg_class, hydra_cfg): expected_kwargs = set(inspect.signature(policy_cfg_class).parameters) - assert set(hydra_cfg.policy).issuperset( - expected_kwargs - ), f"Hydra config is missing arguments: {set(expected_kwargs).difference(hydra_cfg.policy)}" + if not set(hydra_cfg.policy).issuperset(expected_kwargs): + logging.warning( + f"Hydra config is missing arguments: {set(expected_kwargs).difference(hydra_cfg.policy)}" + ) policy_cfg = policy_cfg_class( **{ k: v @@ -62,11 +64,18 @@ def make_policy( policy_cls, policy_cfg_class = get_policy_and_config_classes(hydra_cfg.policy.name) + policy_cfg = _policy_cfg_from_hydra_cfg(policy_cfg_class, hydra_cfg) if pretrained_policy_name_or_path is None: - policy_cfg = _policy_cfg_from_hydra_cfg(policy_cfg_class, hydra_cfg) + # Make a fresh policy. policy = policy_cls(policy_cfg, dataset_stats) else: - policy = policy_cls.from_pretrained(pretrained_policy_name_or_path) + # Load a pretrained policy and override the config if needed (for example, if there are inference-time + # hyperparameters that we want to vary). + # TODO(alexander-soare): This hack makes use of huggingface_hub's tooling to load the policy with, pretrained + # weights which are then loaded into a fresh policy with the desired config. This PR in huggingface_hub should + # make it possible to avoid the hack: https://github.com/huggingface/huggingface_hub/pull/2274. + policy = policy_cls(policy_cfg) + policy.load_state_dict(policy_cls.from_pretrained(pretrained_policy_name_or_path).state_dict()) policy.to(get_safe_torch_device(hydra_cfg.device)) From f5de57b385090da0cefed43ca4f2d832bb554af1 Mon Sep 17 00:00:00 2001 From: Alexander Soare Date: Wed, 8 May 2024 14:57:29 +0100 Subject: [PATCH 06/27] Fix SpatialSoftmax input shape (#150) --- .../common/policies/diffusion/modeling_diffusion.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lerobot/common/policies/diffusion/modeling_diffusion.py b/lerobot/common/policies/diffusion/modeling_diffusion.py index 91cf6dd0..a7ba5442 100644 --- a/lerobot/common/policies/diffusion/modeling_diffusion.py +++ b/lerobot/common/policies/diffusion/modeling_diffusion.py @@ -315,11 +315,13 @@ class DiffusionRgbEncoder(nn.Module): # Set up pooling and final layers. # Use a dry run to get the feature map shape. + # The dummy input should take the number of image channels from `config.input_shapes` and it should use the + # height and width from `config.crop_shape`. + dummy_input = torch.zeros(size=(1, config.input_shapes["observation.image"][0], *config.crop_shape)) with torch.inference_mode(): - feat_map_shape = tuple( - self.backbone(torch.zeros(size=(1, *config.input_shapes["observation.image"]))).shape[1:] - ) - self.pool = SpatialSoftmax(feat_map_shape, num_kp=config.spatial_softmax_num_keypoints) + dummy_feature_map = self.backbone(dummy_input) + feature_map_shape = tuple(dummy_feature_map.shape[1:]) + self.pool = SpatialSoftmax(feature_map_shape, num_kp=config.spatial_softmax_num_keypoints) self.feature_dim = config.spatial_softmax_num_keypoints * 2 self.out = nn.Linear(config.spatial_softmax_num_keypoints * 2, self.feature_dim) self.relu = nn.ReLU() From 460df2ccea1e8dbf3bb76f53ee6fde30761a00fc Mon Sep 17 00:00:00 2001 From: Akshay Kashyap Date: Wed, 8 May 2024 13:05:16 -0400 Subject: [PATCH 07/27] Support for DDIMScheduler in Diffusion Policy (#146) --- .../diffusion/configuration_diffusion.py | 8 ++++++++ .../policies/diffusion/modeling_diffusion.py | 18 ++++++++++++++++-- lerobot/configs/policy/diffusion.yaml | 1 + 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/lerobot/common/policies/diffusion/configuration_diffusion.py b/lerobot/common/policies/diffusion/configuration_diffusion.py index d7341c33..28a514ab 100644 --- a/lerobot/common/policies/diffusion/configuration_diffusion.py +++ b/lerobot/common/policies/diffusion/configuration_diffusion.py @@ -51,6 +51,7 @@ class DiffusionConfig: use_film_scale_modulation: FiLM (https://arxiv.org/abs/1709.07871) is used for the Unet conditioning. Bias modulation is used be default, while this parameter indicates whether to also use scale modulation. + noise_scheduler_type: Name of the noise scheduler to use. Supported options: ["DDPM", "DDIM"]. num_train_timesteps: Number of diffusion steps for the forward diffusion schedule. beta_schedule: Name of the diffusion beta schedule as per DDPMScheduler from Hugging Face diffusers. beta_start: Beta value for the first forward-diffusion step. @@ -110,6 +111,7 @@ class DiffusionConfig: diffusion_step_embed_dim: int = 128 use_film_scale_modulation: bool = True # Noise scheduler. + noise_scheduler_type: str = "DDPM" num_train_timesteps: int = 100 beta_schedule: str = "squaredcos_cap_v2" beta_start: float = 0.0001 @@ -144,3 +146,9 @@ class DiffusionConfig: raise ValueError( f"`prediction_type` must be one of {supported_prediction_types}. Got {self.prediction_type}." ) + supported_noise_schedulers = ["DDPM", "DDIM"] + if self.noise_scheduler_type not in supported_noise_schedulers: + raise ValueError( + f"`noise_scheduler_type` must be one of {supported_noise_schedulers}. " + f"Got {self.noise_scheduler_type}." + ) diff --git a/lerobot/common/policies/diffusion/modeling_diffusion.py b/lerobot/common/policies/diffusion/modeling_diffusion.py index a7ba5442..3115160f 100644 --- a/lerobot/common/policies/diffusion/modeling_diffusion.py +++ b/lerobot/common/policies/diffusion/modeling_diffusion.py @@ -13,6 +13,7 @@ import einops import torch import torch.nn.functional as F # noqa: N812 import torchvision +from diffusers.schedulers.scheduling_ddim import DDIMScheduler from diffusers.schedulers.scheduling_ddpm import DDPMScheduler from huggingface_hub import PyTorchModelHubMixin from robomimic.models.base_nets import SpatialSoftmax @@ -126,6 +127,19 @@ class DiffusionPolicy(nn.Module, PyTorchModelHubMixin): return {"loss": loss} +def _make_noise_scheduler(name: str, **kwargs: dict) -> DDPMScheduler | DDIMScheduler: + """ + Factory for noise scheduler instances of the requested type. All kwargs are passed + to the scheduler. + """ + if name == "DDPM": + return DDPMScheduler(**kwargs) + elif name == "DDIM": + return DDIMScheduler(**kwargs) + else: + raise ValueError(f"Unsupported noise scheduler type {name}") + + class DiffusionModel(nn.Module): def __init__(self, config: DiffusionConfig): super().__init__() @@ -138,12 +152,12 @@ class DiffusionModel(nn.Module): * config.n_obs_steps, ) - self.noise_scheduler = DDPMScheduler( + self.noise_scheduler = _make_noise_scheduler( + config.noise_scheduler_type, num_train_timesteps=config.num_train_timesteps, beta_start=config.beta_start, beta_end=config.beta_end, beta_schedule=config.beta_schedule, - variance_type="fixed_small", clip_sample=config.clip_sample, clip_sample_range=config.clip_sample_range, prediction_type=config.prediction_type, diff --git a/lerobot/configs/policy/diffusion.yaml b/lerobot/configs/policy/diffusion.yaml index 2d611c88..9a4aeb2a 100644 --- a/lerobot/configs/policy/diffusion.yaml +++ b/lerobot/configs/policy/diffusion.yaml @@ -85,6 +85,7 @@ policy: diffusion_step_embed_dim: 128 use_film_scale_modulation: True # Noise scheduler. + noise_scheduler_type: DDPM num_train_timesteps: 100 beta_schedule: squaredcos_cap_v2 beta_start: 0.0001 From 0ea7a8b2a32b76dd07b80ddee82c9434bdec193c Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Thu, 9 May 2024 02:13:51 +0900 Subject: [PATCH 08/27] refactor: update configuration_tdmpc.py (#153) Co-authored-by: Alexander Soare --- lerobot/common/policies/tdmpc/configuration_tdmpc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerobot/common/policies/tdmpc/configuration_tdmpc.py b/lerobot/common/policies/tdmpc/configuration_tdmpc.py index 82e3a507..00d00913 100644 --- a/lerobot/common/policies/tdmpc/configuration_tdmpc.py +++ b/lerobot/common/policies/tdmpc/configuration_tdmpc.py @@ -47,7 +47,7 @@ class TDMPCConfig: elite_weighting_temperature: The temperature to use for softmax weighting (by trajectory value) of the elites, when updating the gaussian parameters for CEM. gaussian_mean_momentum: Momentum (ฮฑ) used for EMA updates of the mean parameter ฮผ of the gaussian - paramters optimized in CEM. Updates are calculated as ฮผโป โ† ฮฑฮผโป + (1-ฮฑ)ฮผ. + parameters optimized in CEM. Updates are calculated as ฮผโป โ† ฮฑฮผโป + (1-ฮฑ)ฮผ. max_random_shift_ratio: Maximum random shift (as a proportion of the image size) to apply to the image(s) (in units of pixels) for training-time augmentation. If set to 0, no such augmentation is applied. Note that the input images are assumed to be square for this augmentation. From df914aa76ca5de7357e848ab4ffef51de693b93b Mon Sep 17 00:00:00 2001 From: Simon Alibert <75076266+aliberts@users.noreply.github.com> Date: Wed, 8 May 2024 19:21:58 +0200 Subject: [PATCH 09/27] Update dev docker build (#148) --- docker/lerobot-gpu/Dockerfile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docker/lerobot-gpu/Dockerfile b/docker/lerobot-gpu/Dockerfile index ab78937c..a2823dc2 100644 --- a/docker/lerobot-gpu/Dockerfile +++ b/docker/lerobot-gpu/Dockerfile @@ -7,6 +7,11 @@ ARG DEBIAN_FRONTEND=noninteractive # Install apt dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential cmake \ + git git-lfs openssh-client \ + nano vim \ + htop atop nvtop \ + sed gawk grep curl wget \ + tcpdump sysstat screen \ libglib2.0-0 libgl1-mesa-glx libegl1-mesa \ python${PYTHON_VERSION} python${PYTHON_VERSION}-venv \ && apt-get clean && rm -rf /var/lib/apt/lists/* @@ -18,7 +23,8 @@ ENV PATH="/opt/venv/bin:$PATH" RUN echo "source /opt/venv/bin/activate" >> /root/.bashrc # Install LeRobot -COPY . /lerobot +RUN git lfs install +RUN git clone https://github.com/huggingface/lerobot.git WORKDIR /lerobot RUN pip install --upgrade --no-cache-dir pip RUN pip install --no-cache-dir ".[test, aloha, xarm, pusht]" From 7bb5b15f4c0393ba16b73f6482611892301401d7 Mon Sep 17 00:00:00 2001 From: Simon Alibert <75076266+aliberts@users.noreply.github.com> Date: Wed, 8 May 2024 19:23:10 +0200 Subject: [PATCH 10/27] Remove dependencies upper bounds constraints (#145) --- poetry.lock | 110 +++++++++++++++++++++++-------------------------- pyproject.toml | 58 +++++++++++++------------- 2 files changed, 81 insertions(+), 87 deletions(-) diff --git a/poetry.lock b/poetry.lock index 26192e53..89676fab 100644 --- a/poetry.lock +++ b/poetry.lock @@ -131,17 +131,6 @@ files = [ {file = "antlr4-python3-runtime-4.9.3.tar.gz", hash = "sha256:f224469b4168294902bb1efa80a8bf7855f24c99aef99cbefc1bcd3cce77881b"}, ] -[[package]] -name = "appdirs" -version = "1.4.4" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -optional = false -python-versions = "*" -files = [ - {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, - {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, -] - [[package]] name = "asciitree" version = "0.3.3" @@ -1108,67 +1097,67 @@ protobuf = ["grpcio-tools (>=1.63.0)"] [[package]] name = "gym-aloha" -version = "0.1.0" +version = "0.1.1" description = "A gym environment for ALOHA" optional = true python-versions = "<4.0,>=3.10" files = [ - {file = "gym_aloha-0.1.0-py3-none-any.whl", hash = "sha256:62e36eeb09284422cbb7baca0292c6f65e38ec8774bf9b0bf7159ad5990cf29a"}, - {file = "gym_aloha-0.1.0.tar.gz", hash = "sha256:bab332f469ba5ffe655fc3e9647aead05d2cb3b950dfb1f299b9539b3857ad7e"}, + {file = "gym_aloha-0.1.1-py3-none-any.whl", hash = "sha256:2698037246dbb106828f0bc229b61007b0a21d5967c72cc373f7bc1083203584"}, + {file = "gym_aloha-0.1.1.tar.gz", hash = "sha256:614ae1cf116323e7b5ae2f0e9bd282c4f052aee15e839e5587ddce45995359bc"}, ] [package.dependencies] -dm-control = "1.0.14" -gymnasium = ">=0.29.1,<0.30.0" -imageio = {version = ">=2.34.0,<3.0.0", extras = ["ffmpeg"]} +dm-control = ">=1.0.14" +gymnasium = ">=0.29.1" +imageio = {version = ">=2.34.0", extras = ["ffmpeg"]} mujoco = ">=2.3.7,<3.0.0" [package.extras] -dev = ["debugpy (>=1.8.1,<2.0.0)", "pre-commit (>=3.7.0,<4.0.0)"] -test = ["pytest (>=8.1.0,<9.0.0)", "pytest-cov (>=5.0.0,<6.0.0)"] +dev = ["debugpy (>=1.8.1)", "pre-commit (>=3.7.0)"] +test = ["pytest (>=8.1.0)", "pytest-cov (>=5.0.0)"] [[package]] name = "gym-pusht" -version = "0.1.1" +version = "0.1.3" description = "A gymnasium environment for PushT." optional = true python-versions = "<4.0,>=3.10" files = [ - {file = "gym_pusht-0.1.1-py3-none-any.whl", hash = "sha256:dcf8644713db48286e907aabb11e005b0592632e323baa40d1a4f2dfbbc76c3d"}, - {file = "gym_pusht-0.1.1.tar.gz", hash = "sha256:0d1c9ffd4ad0e2411efcc724003a365a853f20b6d596980c113e7ec181ac021f"}, + {file = "gym_pusht-0.1.3-py3-none-any.whl", hash = "sha256:feeb02493a03d1aacc45d43d6397962c50ed779ab7e4019d73af11d2f0b3831b"}, + {file = "gym_pusht-0.1.3.tar.gz", hash = "sha256:c8e9a5256035ba49841ebbc7c32a06c4fa2daa52f5fad80da941b607c4553e28"}, ] [package.dependencies] -gymnasium = ">=0.29.1,<0.30.0" -opencv-python = ">=4.9.0.80,<5.0.0.0" -pygame = ">=2.5.2,<3.0.0" -pymunk = ">=6.6.0,<7.0.0" +gymnasium = ">=0.29.1" +opencv-python = ">=4.9.0" +pygame = ">=2.5.2" +pymunk = ">=6.6.0" scikit-image = ">=0.22.0" -shapely = ">=2.0.3,<3.0.0" +shapely = ">=2.0.3" [package.extras] -dev = ["debugpy (>=1.8.1,<2.0.0)", "pre-commit (>=3.7.0,<4.0.0)"] -test = ["pytest (>=8.1.0,<9.0.0)", "pytest-cov (>=5.0.0,<6.0.0)"] +dev = ["debugpy (>=1.8.1)", "pre-commit (>=3.7.0)"] +test = ["pytest (>=8.1.0)", "pytest-cov (>=5.0.0)"] [[package]] name = "gym-xarm" -version = "0.1.0" +version = "0.1.1" description = "A gym environment for xArm" optional = true python-versions = "<4.0,>=3.10" files = [ - {file = "gym_xarm-0.1.0-py3-none-any.whl", hash = "sha256:d10ac19a59d302201a9b8bd913530211b1058467b787ad91a657907e40cdbc13"}, - {file = "gym_xarm-0.1.0.tar.gz", hash = "sha256:fc05f9d02af1f0205275311669dc191ce431be484e221a96401eb544764eb986"}, + {file = "gym_xarm-0.1.1-py3-none-any.whl", hash = "sha256:3bd7e3c1c5521ba80a56536f01a5e11321580704d72160355ce47a828a8808ad"}, + {file = "gym_xarm-0.1.1.tar.gz", hash = "sha256:e455524561b02d06b92a4f7d524f448d84a7484d9a2dbc78600e3c66240e0fb7"}, ] [package.dependencies] -gymnasium = ">=0.29.1,<0.30.0" -gymnasium-robotics = ">=1.2.4,<2.0.0" +gymnasium = ">=0.29.1" +gymnasium-robotics = ">=1.2.4" mujoco = ">=2.3.7,<3.0.0" [package.extras] -dev = ["debugpy (>=1.8.1,<2.0.0)", "pre-commit (>=3.7.0,<4.0.0)"] -test = ["pytest (>=8.1.0,<9.0.0)", "pytest-cov (>=5.0.0,<6.0.0)"] +dev = ["debugpy (>=1.8.1)", "pre-commit (>=3.7.0)"] +test = ["pytest (>=8.1.0)", "pytest-cov (>=5.0.0)"] [[package]] name = "gymnasium" @@ -1258,13 +1247,13 @@ numpy = ">=1.17.3" [[package]] name = "huggingface-hub" -version = "0.21.4" +version = "0.23.0" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" optional = false python-versions = ">=3.8.0" files = [ - {file = "huggingface_hub-0.21.4-py3-none-any.whl", hash = "sha256:df37c2c37fc6c82163cdd8a67ede261687d80d1e262526d6c0ce73b6b3630a7b"}, - {file = "huggingface_hub-0.21.4.tar.gz", hash = "sha256:e1f4968c93726565a80edf6dc309763c7b546d0cfe79aa221206034d50155531"}, + {file = "huggingface_hub-0.23.0-py3-none-any.whl", hash = "sha256:075c30d48ee7db2bba779190dc526d2c11d422aed6f9044c5e2fdc2c432fdb91"}, + {file = "huggingface_hub-0.23.0.tar.gz", hash = "sha256:7126dedd10a4c6fac796ced4d87a8cf004efc722a5125c2c09299017fa366fa9"}, ] [package.dependencies] @@ -1277,15 +1266,16 @@ tqdm = ">=4.42.1" typing-extensions = ">=3.7.4.3" [package.extras] -all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] cli = ["InquirerPy (==0.3.4)"] -dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] hf-transfer = ["hf-transfer (>=0.1.4)"] -inference = ["aiohttp", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)"] -quality = ["mypy (==1.5.1)", "ruff (>=0.1.3)"] +inference = ["aiohttp", "minijinja (>=1.0)"] +quality = ["mypy (==1.5.1)", "ruff (>=0.3.0)"] tensorflow = ["graphviz", "pydot", "tensorflow"] -testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] +tensorflow-testing = ["keras (<3.0)", "tensorflow"] +testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] torch = ["safetensors", "torch"] typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] @@ -2587,7 +2577,7 @@ xmp = ["defusedxml"] name = "platformdirs" version = "4.2.1" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "platformdirs-4.2.1-py3-none-any.whl", hash = "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"}, @@ -4034,36 +4024,40 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [[package]] name = "wandb" -version = "0.16.6" +version = "0.17.0" description = "A CLI and library for interacting with the Weights & Biases API." optional = false python-versions = ">=3.7" files = [ - {file = "wandb-0.16.6-py3-none-any.whl", hash = "sha256:5810019a3b981c796e98ea58557a7c380f18834e0c6bdaed15df115522e5616e"}, - {file = "wandb-0.16.6.tar.gz", hash = "sha256:86f491e3012d715e0d7d7421a4d6de41abef643b7403046261f962f3e512fe1c"}, + {file = "wandb-0.17.0-py3-none-any.whl", hash = "sha256:b1b056b4cad83b00436cb76049fd29ecedc6045999dcaa5eba40db6680960ac2"}, + {file = "wandb-0.17.0-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:e1e6f04e093a6a027dcb100618ca23b122d032204b2ed4c62e4e991a48041a6b"}, + {file = "wandb-0.17.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:feeb60d4ff506d2a6bc67f953b310d70b004faa789479c03ccd1559c6f1a9633"}, + {file = "wandb-0.17.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7bed8a3dd404a639e6bf5fea38c6efe2fb98d416ff1db4fb51be741278ed328"}, + {file = "wandb-0.17.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56a1dd6e0e635cba3f6ed30b52c71739bdc2a3e57df155619d2d80ee952b4201"}, + {file = "wandb-0.17.0-py3-none-win32.whl", hash = "sha256:1f692d3063a0d50474022cfe6668e1828260436d1cd40827d1e136b7f730c74c"}, + {file = "wandb-0.17.0-py3-none-win_amd64.whl", hash = "sha256:ab582ca0d54d52ef5b991de0717350b835400d9ac2d3adab210022b68338d694"}, ] [package.dependencies] -appdirs = ">=1.4.3" -Click = ">=7.1,<8.0.0 || >8.0.0" +click = ">=7.1,<8.0.0 || >8.0.0" docker-pycreds = ">=0.4.0" -GitPython = ">=1.0.0,<3.1.29 || >3.1.29" +gitpython = ">=1.0.0,<3.1.29 || >3.1.29" +platformdirs = "*" protobuf = {version = ">=3.19.0,<4.21.0 || >4.21.0,<5", markers = "python_version > \"3.9\" or sys_platform != \"linux\""} psutil = ">=5.0.0" -PyYAML = "*" +pyyaml = "*" requests = ">=2.0.0,<3" sentry-sdk = ">=1.0.0" setproctitle = "*" setuptools = "*" [package.extras] -async = ["httpx (>=0.23.0)"] aws = ["boto3"] azure = ["azure-identity", "azure-storage-blob"] gcp = ["google-cloud-storage"] importers = ["filelock", "mlflow", "polars", "rich", "tenacity"] kubeflow = ["google-cloud-storage", "kubernetes", "minio", "sh"] -launch = ["PyYAML (>=6.0.0)", "awscli", "azure-containerregistry", "azure-identity", "azure-storage-blob", "boto3", "botocore", "chardet", "google-auth", "google-cloud-aiplatform", "google-cloud-artifact-registry", "google-cloud-compute", "google-cloud-storage", "iso8601", "kubernetes", "kubernetes-asyncio", "nbconvert", "nbformat", "optuna", "pydantic", "tomli", "typing-extensions"] +launch = ["awscli", "azure-containerregistry", "azure-identity", "azure-storage-blob", "boto3", "botocore", "chardet", "google-auth", "google-cloud-aiplatform", "google-cloud-artifact-registry", "google-cloud-compute", "google-cloud-storage", "iso8601", "kubernetes", "kubernetes-asyncio", "nbconvert", "nbformat", "optuna", "pydantic", "pyyaml (>=6.0.0)", "tomli", "typing-extensions"] media = ["bokeh", "moviepy", "numpy", "pillow", "plotly (>=5.18.0)", "rdkit-pypi", "soundfile"] models = ["cloudpickle"] perf = ["orjson"] @@ -4309,13 +4303,13 @@ multidict = ">=4.0" [[package]] name = "zarr" -version = "2.17.2" +version = "2.18.0" description = "An implementation of chunked, compressed, N-dimensional arrays for Python" optional = false python-versions = ">=3.9" files = [ - {file = "zarr-2.17.2-py3-none-any.whl", hash = "sha256:70d7cc07c24280c380ef80644151d136b7503b0d83c9f214e8000ddc0f57f69b"}, - {file = "zarr-2.17.2.tar.gz", hash = "sha256:2cbaa6cb4e342d45152d4a7a4b2013c337fcd3a8e7bc98253560180de60552ce"}, + {file = "zarr-2.18.0-py3-none-any.whl", hash = "sha256:7f8532b6a3f50f22e809e130e09353637ec8b5bb5e95a5a0bfaae91f63978b5d"}, + {file = "zarr-2.18.0.tar.gz", hash = "sha256:c3b7d2c85b8a42b0ad0ad268a36fb6886ca852098358c125c6b126a417e0a598"}, ] [package.dependencies] @@ -4354,4 +4348,4 @@ xarm = ["gym-xarm"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.13" -content-hash = "008a6af5ad9d9eafbd933c922c2c5d84fddae85aff8a9eefc0538b1319966f6e" +content-hash = "21dd1d7404ac774bd1139e8cda44ea8e3ed97c30e524f2ed862de431d3d5fa87" diff --git a/pyproject.toml b/pyproject.toml index 94ed5d03..56c84416 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,37 +28,37 @@ packages = [{include = "lerobot"}] [tool.poetry.dependencies] python = ">=3.10,<3.13" -termcolor = "^2.4.0" -omegaconf = "^2.3.0" -wandb = "^0.16.3" -imageio = {extras = ["ffmpeg"], version = "^2.34.0"} -gdown = "^5.1.0" -hydra-core = "^1.3.2" -einops = "^0.8.0" -pymunk = "^6.6.0" -zarr = "^2.17.0" -numba = "^0.59.0" +termcolor = ">=2.4.0" +omegaconf = ">=2.3.0" +wandb = ">=0.16.3" +imageio = {extras = ["ffmpeg"], version = ">=2.34.0"} +gdown = ">=5.1.0" +hydra-core = ">=1.3.2" +einops = ">=0.8.0" +pymunk = ">=6.6.0" +zarr = ">=2.17.0" +numba = ">=0.59.0" torch = "^2.2.1" -opencv-python = "^4.9.0.80" +opencv-python = ">=4.9.0" diffusers = "^0.27.2" -torchvision = "^0.18.0" -h5py = "^3.10.0" -huggingface-hub = "^0.21.4" +torchvision = ">=0.18.0" +h5py = ">=3.10.0" +huggingface-hub = ">=0.21.4" robomimic = "0.2.0" -gymnasium = "^0.29.1" -cmake = "^3.29.0.1" -gym-pusht = { version = "^0.1.1", optional = true} -gym-xarm = { version = "^0.1.0", optional = true} -gym-aloha = { version = "^0.1.0", optional = true} -pre-commit = {version = "^3.7.0", optional = true} -debugpy = {version = "^1.8.1", optional = true} -pytest = {version = "^8.1.0", optional = true} -pytest-cov = {version = "^5.0.0", optional = true} -datasets = "^2.19.0" -imagecodecs = { version = "^2024.1.1", optional = true } -pyav = "^12.0.5" -moviepy = "^1.0.3" -rerun-sdk = "^0.15.1" +gymnasium = ">=0.29.1" +cmake = ">=3.29.0.1" +gym-pusht = { version = ">=0.1.3", optional = true} +gym-xarm = { version = ">=0.1.1", optional = true} +gym-aloha = { version = ">=0.1.1", optional = true} +pre-commit = {version = ">=3.7.0", optional = true} +debugpy = {version = ">=1.8.1", optional = true} +pytest = {version = ">=8.1.0", optional = true} +pytest-cov = {version = ">=5.0.0", optional = true} +datasets = ">=2.19.0" +imagecodecs = { version = ">=2024.1.1", optional = true } +pyav = ">=12.0.5" +moviepy = ">=1.0.3" +rerun-sdk = ">=0.15.1" [tool.poetry.extras] @@ -104,5 +104,5 @@ ignore-init-module-imports = true [build-system] -requires = ["poetry-core>=1.5.0"] +requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" From e89521dfa02f42701c3732e67154300257c5c443 Mon Sep 17 00:00:00 2001 From: Alexander Soare Date: Thu, 9 May 2024 13:42:12 +0100 Subject: [PATCH 11/27] Enable tests for TD-MPC (#160) --- Makefile | 7 +++---- lerobot/configs/policy/tdmpc.yaml | 2 +- .../xarm_tdmpc/actions.safetensors | Bin 0 -> 928 bytes .../xarm_tdmpc/grad_stats.safetensors | Bin 0 -> 16904 bytes .../xarm_tdmpc/output_dict.safetensors | Bin 0 -> 240 bytes .../xarm_tdmpc/param_stats.safetensors | Bin 0 -> 36312 bytes tests/test_policies.py | 2 +- 7 files changed, 5 insertions(+), 6 deletions(-) create mode 100644 tests/data/save_policy_to_safetensors/xarm_tdmpc/actions.safetensors create mode 100644 tests/data/save_policy_to_safetensors/xarm_tdmpc/grad_stats.safetensors create mode 100644 tests/data/save_policy_to_safetensors/xarm_tdmpc/output_dict.safetensors create mode 100644 tests/data/save_policy_to_safetensors/xarm_tdmpc/param_stats.safetensors diff --git a/Makefile b/Makefile index 07aa4e97..a0163f94 100644 --- a/Makefile +++ b/Makefile @@ -22,9 +22,8 @@ test-end-to-end: ${MAKE} test-act-ete-eval ${MAKE} test-diffusion-ete-train ${MAKE} test-diffusion-ete-eval - # TODO(rcadene, alexander-soare): enable end-to-end tests for tdmpc - # ${MAKE} test-tdmpc-ete-train - # ${MAKE} test-tdmpc-ete-eval + ${MAKE} test-tdmpc-ete-train + ${MAKE} test-tdmpc-ete-eval ${MAKE} test-default-ete-eval test-act-ete-train: @@ -80,7 +79,7 @@ test-tdmpc-ete-train: policy=tdmpc \ env=xarm \ env.task=XarmLift-v0 \ - dataset_repo_id=lerobot/xarm_lift_medium_replay \ + dataset_repo_id=lerobot/xarm_lift_medium \ wandb.enable=False \ training.offline_steps=2 \ training.online_steps=2 \ diff --git a/lerobot/configs/policy/tdmpc.yaml b/lerobot/configs/policy/tdmpc.yaml index eb89033b..7e736850 100644 --- a/lerobot/configs/policy/tdmpc.yaml +++ b/lerobot/configs/policy/tdmpc.yaml @@ -1,7 +1,7 @@ # @package _global_ seed: 1 -dataset_repo_id: lerobot/xarm_lift_medium_replay +dataset_repo_id: lerobot/xarm_lift_medium training: offline_steps: 25000 diff --git a/tests/data/save_policy_to_safetensors/xarm_tdmpc/actions.safetensors b/tests/data/save_policy_to_safetensors/xarm_tdmpc/actions.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..0339ca0e30448daa5b30bea25c2dba2687927db5 GIT binary patch literal 928 zcmbb3dB{yRuB^{;Wj6@JG+Q?MLBvwZ$C9xziK0ht3IJKl0 zC~BZ%Vqg$ktD|H{s!pIj9Se}&S_S95F?QNQfA>9a5#Cq#NZVe}uG8-ExhMNxTw&Q4 zd_~iKUT}!rlip4HmS$+~YkqEQ|4FCa?xORaeN6GT`~K9J+WYu$+NGKv-xqthVV~*| z9edl@t+qR3PVd{7Ww%eaP|;qz>8$PZ(o6evZy(uPSs-sO{AjM-P46rFKA2nV%kk2; zKWDCJ_d@RHK8~LZ`zj7<*=IbHv{U@`b)Wq%jeU=k6zym0|FShbdw!pA3ERE{lN9Yg zbnw`nwLQ1*F{j|Z8%3h_YdG%PN(NorCv3*JPil>Xy|4dDTb(H{_tk|x+UpsvX8-#c zgPqLcqx&}g5#P5%P|AMMG6_5LqEGwk+W+jWd?;nVyQ$Icf8OVP3LeMzUfd&R-`0J` zHpk)dzHE;xd!J8Hv7efL)Hb;C>AuQt*S&A^l%O*7Gy9ZF^X>i~ md$P~s%(1<0qDJg(fAl#@c{r>@UM3O literal 0 HcmV?d00001 diff --git a/tests/data/save_policy_to_safetensors/xarm_tdmpc/grad_stats.safetensors b/tests/data/save_policy_to_safetensors/xarm_tdmpc/grad_stats.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..5520c643c53ca0f1b417465c3d0336aa96a990e0 GIT binary patch literal 16904 zcmb`OZHQgf6^17UYY8MGRIF018UGmFj`!@d&p!7vNDHA=q6zAl(!}xVT*s;TFmp#j zB0(Z;u_DcnVnu5)hG;~YNo+C6#6hF@fmKs~SRzVQgs8N^?;;3-@0r}}*=wJ3=VmQB zfoL+h&sux!Is19fxigD=U_0pY;3Q93t%N8`3uR&j3pv20?o zR&j3n9Tu~#*ea77ek`4s!54mR{*K0M%@}2J<4Gxg6HBbJ zx%oR9vo%{%HW+^-J;JO}HkiI+aoZ}ZG#Gw{5?+<5R%tMQkH%~*wW=J9KN=98W95=6 z=ceCbG21HR+|Lc)ojhC{mCLGFyYY#mWo0hdpvG?&~X&{SWAyLkU$GA2uEYLhHVIqoWZ1% zgO#ID%N~#09<&^VUe*J`V-6(Hf}_dNxUE6VQE282CY_wcPK0{)c-;1&=P2~E7N2wQ za})~N(YUQa&{1gU3?`i%EFFcK_IT{}uo0oBWAQl$Pe-As9gW)>M6E+nXE5R9zydG0 zAUqzkJ)nRKPNrCT&Vi(KXlh5}wgyq_P}CVrI=Sp-IdrwhK zmgfLcIuv!*nsjn-wGLhF@wk(Ns&%O9SbENZ1X}KbkmWgm0LyKI_?!bv>Cn~LQad}r zog7rHLsc8;IR}!`p{X5>+ZsfzLs4fi>DL@wtwUFPJa&87h)~r=e9pntIyAMTaa)6^ zbtvi#CY>BytwUFPJZ^hXwGLHn#OEAtsC8&+N8`2zQR`6D8B97kxH=A9?eUoH0R>!e zG8ySP2NGz((d20C*6>I*6m3^CP~4`V=$I%v zBS{AaMaM+Z9*o;q_Dq}Tc~E+=0i$A~W{2W71ue%!%Na>JEoeC=TJ~V<#xQxJ5v<oLHaEA%#4ZON75odSR|W18 z5Ecvx3v(2ZP98V#hUACdHMq+_oG>I#bS)7HzsU@Em5_MRvjlSyprgV`Z8jDm+zb>z z5kG>=wTw;?_CoOeKO~ZLt)XQn4(O=h-$wPSz+D0YOF{z690jCXfee$74AZ*?cNvH@ z35hgaO9=A_=qe!zr&k5;5)gP25_sk)Al(UMpoCs=!?W0#`x;*Bk|; zJAr2}3CUo+YjBr=NS2UDcA`XkygB~=$WNfFq%fg%tH50X0$NfS&fy zYp|Dr%`S{+xe`)iBcUaQ39VZN?h=sCY+*htC?MPk@KK{Ep>?mpTn6wcQFMyuN(i6D zfUay|I_p+}y99(YTNus?3P^VX`OFsPv+gyx%RoG{B%a+iDt#sk4p{!K&a&8TVf#qn znn6kDh;(I1y7Fn<))1pCiBW(FpS^+umVc?uvbb#_7+DgGW>C_J;jxh=DafaBTSMHj zB<=tvy{?gKEXg&qEN)u}FqQZPMBqJ+d?3)BoNG?q!WYvQ(}Lg#%v8B z!2GjkthK2*HY`2;!2-`e{V9*#9)7}y2;AX>(*q4e|3V0f+!mqdl<2tw6xskR@CtTB z_5(ja0avgg;%_$qO{K)jZo!>B;Z6`@PKlU1K%pJLQYmpW<#F4Co>QV{hm(E{!qO?R zbVy{kh%F(a?f`|h01Lc=i=@Njwg+9OMAxo8=>%czlvq0?a$AJBQzGsTP-qXZR7%`U zdEEA(@094<;iMCU#ZzMOkjQNjB2P1sZ$1C`$MK(fKl$Ic{&elL*}vYheE#&0SA5hs z`BxtQmnU9-@2xwgKiK`T`1M;}dw6>1qo0Uh|IHUWr?9x*>gY`U(UDtg z4?gg~lPmB1x;lCOgZr;rc6RlLe_m>mz6r?W|{ z`rXlkzgYaUI{vqG{fZ|WuWWp1a^9O4HBNc%)yj8Qx9btPo~q;Xdw=<>(Z*p({zWm#{^-sqRA2{P53D)_+z`uX6DqHs@hx!)Q zfAaXU>KiYfQJ;7JHPstGKCAwtRY#^j+?_1F+rIhCd-wg5z5n2nkH#DNx$G}qe|pKY JFFtm7>GxZf1gQW3 literal 0 HcmV?d00001 diff --git a/tests/data/save_policy_to_safetensors/xarm_tdmpc/output_dict.safetensors b/tests/data/save_policy_to_safetensors/xarm_tdmpc/output_dict.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..2321f31c7f291eccead6ce8b742f141faae46cac GIT binary patch literal 240 zcmZo*fPiYH#FVncypqK9R3)owrIeD&0w6=l&DcmuN2xd?5yXo&GL6+yN=Yn9jL%O? zD^4vb28tQz7#bMF*6Jwb;yinwbf6OvJ)?7wd35N sV<+Hp&DLV_R$Di@AGSWSb8QbS_ps~RywG-gx}e>IGjnWPj@3H=05Eh_kpKVy literal 0 HcmV?d00001 diff --git a/tests/data/save_policy_to_safetensors/xarm_tdmpc/param_stats.safetensors b/tests/data/save_policy_to_safetensors/xarm_tdmpc/param_stats.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..5e8a694703af7e2abee62891a64aefa55cd3b815 GIT binary patch literal 36312 zcmb`QYm8l06~_lCj}XKM4-JaZ@$rS@IOp7R&pl`AWKckDQWB6@NdzaiblOhZPTQH= zVj)eNC}>C;2^gZb7owsPe8d;bbRY#1N`j=Q5mHbLNK8Zs4@Hy@rTAadbN5|)pS|zB zYeD%iy`8zgwf0))?En9qJ7;m@H-?t}TsypJ^O~uRBa@fTjf~>I)zi(n$xTzunc=Z( zhu5@rY?&G!8~$u98IFeM);HV5*ECzr$<1rm&P}!E@GqlLdgac@N1AJ`k$}=D zuY#_gnqIfQB~B`j;v@(Y<`pMVoVl=ASFAXTlFozig0ISsBY(CPWfdyWr35F*u8&FZ~>Tf)v+|ED(tckalf+;Hp7I@AH!Fa;-fCA3hnQGd74x}h?mDU|EZC~>u#mRfc~S~*B{;!1U@-RD4x5?84WO_~~nI&p=XVA^92TAjFB&3NMU z&HZ*B!5bDGgYJzDi2dz$At!6xFdXVbGmFiTz&*6ePah2N8q^Uuu z6IZASrmY;by5?#%;|bFP3OHwHO11kONT4}elc9-I!!1=;s0pU599ZBv7uAd>O%GCC zv!r^Jc9R1JDBc8vk|qU-u2~XIByGVU(KSn=8BCfO-P5+@d6jl!1173j(ri%Dq#(;R zOO}bGtrldtX2~*xi4#NRElFOb-OPXiiXZg`B~1!aT(hK@NZM*aiffh>Gnh0n$Z*Y) z;Z^Dl3|GrFOM(qbniS->X2~y+wAF(A)-3sDFll0t-kK%7Yj(^uH%(tPr{2DxzBNmI zU7|Qebioo}2Go`iI$X1KxXP5K2`Nr3DK<#uM+~5W$c4Zq3R46OKrYA(sH`M-QEKUO zl_^aV(wth-Y>>)(a-c=2rOqxUbLfcbI+Zj+> zNvM2kseF|wO%qz5T3TWB!T4U)x18OS?2asA0pvsh{2_KMJK45C* zD*QUr?8x+{=DMj#yqetD+%Yw))^gAhfuBhIB1o42vyfV5p+^91<#7R@TK=Jb4Cyjp zCsNB!1VhBiUorzes$2G=ZwTQcKu3gunvF#$n}Glb!YxRzWt2h03&HRISe7IhBhl?R zpd$jmjOrIbx&#=Ox@A~;1kknu9;R-2nEo-O%Ydb+Tb3pmLg`09kLs4g=@&t|1Q?#W zWq5i7&~^eIsBU?n{xPJ>fF-J1H#dSIlzs+uL>TDIE+dGSfL2?EsmBtuoq&g`TOO)^ z4Cyjpsp^)c3Wg|@yAvE%-Evs{B1o42!&SEoSC0VNPT<~4-SS}lV@Q_)OIEimStrC? ztJ!)x{1fO=-Rsao5u{6iL92TWnkRs^6YywtuSW~V5HADG_FA+`2(4nnq1C+(Efhhz z1o*Se>(4v^l$`({F??81!I(1#%Kwptr%__WtI!#G-+zEJDFv70Mnk=@HLs`Yq~6HS}-t~Wnh+2 z+KR!gWR_duG;wMuzhz4RQ(n7(0~WuE?6Rb3!DwWb(O5!hD+X7QS+0W9q^ZF^WR`sZ zOnHp~PLx?bq05q{1w)WohF}S$tr*n5VW~f-2~z_IFuwQ9PF>xcU8CLo!2*x({x(mX z9-i>A1l-`1)dLMgej>O;X^N2Nh9%D>P^kuBf#>On?tvemfb%p&{p$vxMGZ@p&4SCG zNGk|oZdk%x0+s3jR@AVx+2%>pgFH7Zc{VuhF$k4zSSsxj#VMjCmQa^KrCNXmp64Vf zdD8SC*9}XqO?ui2LbV%~YP&>fiV*IGCEO)YsUBcO4NJRio-{qkcf*ozgVRZ|!k+00HgpUS6m;QM85$yUWxT6e8bXA|Jp?lZDvlOzdr{ zQeprEv@0=Qs4!9RzzlUtEjB<#IWqums%5jJ$-)HW%mmm}rR)G0<;)0pq0&TQ26AQw zT&D6^1rpd$v&^s7iIYXIm@%-ERX&gkAfR0-@yraGBbw!aU^6JOr@PWMLq3W*}^;c3*{w$eD@o zLdA)qQ_M)XOl?(RC~{^f0$6FXFcmp76*g77ufka50b>z&?jT7Mg|Em1zJi$As^XqO z9`Fe(DZ z!a${o!dDalUqMWz2LKXSzgjV@I9c>6;4I7t0r3F7aJ&CD~9rwiK=j|O~)!HScG?*KK_GxZHv zViGviHUpL?OkE4u4>R*XUR~G^U_(tSw{vl_@E;ho7dp|@Hw=hL;85EPSe!6i2)LoH zsrOyn;D|>9K14fifq+B}^~`LK@`HiQ2&CA|0On>yKY)Rd#PxK|j872f3LG WzYn zK>!+%J`cjiDaaEg55i|enxZnQI92i=d{!ibD(}V;j+ovq>3*4lXoU1O$?Sykijwc( zvm>p=m)9ZUijwExGb9;QYigIqNb)(7Ri-#i@)~@Wq=i&ogAtIZ-ae`KRPX@x`3y6v zLEd`u7<|4YTfWl8f(E3|U$D^)@q5|!+7cN?S z#FE3{lPG;js}Ec<8hkKi54bpS@)~?jWtFYoYRPW!k(EKTJZb8q&vBSOzJ-mKj0YcP z=}TLCY?Jrkvn{J^?KVtPE`jz4o2iM?=hDDSkUje*BWsUsntvJd0hqpuD60)Du{{>j zB(D5jIHCgWyEWpXrN=g)MDEqcRC^nexCHOjN&}ZCPM!4KC^02b{@xr>3Eiuax<@(* z3bOBJ2}@diY?F=QgEp(jcGhX7xY}f9_}tAZTRF{ws6hKHjj2hA7AH-{hEL=4C9SSD zSsXr`vj<$9I2j#2tJAPMPi($j6E7$Vh4P%D{X)qXMSb?Up&pUc-64a-2Y?PzLG8Xz zeu>Wq?H@}!6@$W1EYEfwEMg~?xL@R__*~I}mZfeO-PPf9MU zqTv6c;Jf`3Y*-mex+ofEib#?}Bk9P2_)?5!og$cI+c3f83&WwoXQB4*meyy{lvITB zD1We9y2lYH2qO6$U5`lGlZ!^IBADdRQ2R23p;(e5L+jHJ1)+QvFjzySZ$l7@BsngO z)smlEWD@y|*Z#-52_`E5xr*u#h3MDx(%24t}(Q)B(l)>Yo(C>s~GWm?z zK`N+p8VG|}zT0Y@g;gHM*WSBA6bjX2%Ls)McZ(b-pI}=lpeK@gC!||)e8#OHn0R62 zLHQKi{;{+!15psl_t{|Zz|gu3GN62d?jVa&cZ)12AFeA1Chis)P(F9Je=P02Gen_K zJ=COf#4GQmAqf3Hw>%#{29FE#(S%sHXnrq(Nwy3VOxi6P?Tc6*F~NiA+C7hE`^J2@ zuQ>#|P;sKo2flBXu@yINBnxR;$+Du@;Seps=Y4{9zp%BQho*s9GE`mhfeA5 z#e+y#&xy&g;;NFL<1>GGRkeEvcm(yFY)DnPTL4E)f2Yi;D&H6A1|J{&Yp-AFg#aX~ zzgODpKkxwc87x#)d8G#&G5wt~ms#?vl5OH+fO%C7R(!0IKjO21IaPa|1|C8Etx{f* z0SBhf@t{-Ya!6iPvNwDLu)Timu}VIM&;2#j@_~1?Vv%X#!+rx`@nJv?g-`gca@ER3 zmV{6C4Wgw<(?DO4JttaOWvznI5MO{j`=Sk&Cyeg#$-QnV^h!n(dx7?xawcWvu?#54 zz8hC1S*vJZ5;)vGrK$l*+;I2w%0|<8V?K`8ZJR?jQlg z3n2eePR{MipPo@HfXqxeICqc$;subaDd*;Ho9RZ_ysfomTkGxV0a=`KZ0=wo$zt@gm6mEX~c``62unD*wE5*_p+j6YJxh*F!_QC%S(h8hY2W zH)f~e`b`&Cxp$0R(&PQBo>-e7$KJnT?}OPJ>$~qiaA5xK z-}T6U{ni5u|6=)%t!UrTZ^54`P%&A zDfRK0RVx}Z58(C7yC$w%7Zv~gTzfv-d0Ua+clzQJ&%HE$(-&4O{QmKM#m&d zKJ@b6pZxrx+lq5mzFJ)V@XGPA7dPbJ|KGmiu^+tmp0oDeIlld+7aC{Ww6BO-w=X{X z(>uraT()B2O}zh-=MU^Z=_^~uk6du>-G8{HT|D!iLt{T)wtM{Mqh~LC_}+Fg{n#T# zbadDF9}({`e*R-8?4CI5o3|9niyN|EZ)z7G{q9o>C!bay-}t>@U;DZLjUMkJ@)6=@qMW|o*!)Ner<`r^zA{uj}@6=-#LEpY(YD zDeKSJ|EQ;*9p1jnZXWr3$ebIrR?LYU*t>*iOFFrIjf8uWQdQW<&_~B6ZwHt41{ Date: Thu, 9 May 2024 15:16:47 +0100 Subject: [PATCH 12/27] Fix stats override in ACT config (#161) --- lerobot/configs/policy/act.yaml | 12 ++++---- lerobot/configs/policy/diffusion.yaml | 28 +++++++++--------- .../aloha_act/actions.safetensors | Bin 5104 -> 5104 bytes .../aloha_act/grad_stats.safetensors | Bin 31688 -> 31688 bytes .../aloha_act/output_dict.safetensors | Bin 196 -> 196 bytes .../aloha_act/param_stats.safetensors | Bin 33408 -> 33408 bytes 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lerobot/configs/policy/act.yaml b/lerobot/configs/policy/act.yaml index a49a97f8..15efcce8 100644 --- a/lerobot/configs/policy/act.yaml +++ b/lerobot/configs/policy/act.yaml @@ -3,6 +3,12 @@ seed: 1000 dataset_repo_id: lerobot/aloha_sim_insertion_human +override_dataset_stats: + observation.images.top: + # stats from imagenet, since we use a pretrained vision model + mean: [[[0.485]], [[0.456]], [[0.406]]] # (c,1,1) + std: [[[0.229]], [[0.224]], [[0.225]]] # (c,1,1) + training: offline_steps: 80000 online_steps: 0 @@ -18,12 +24,6 @@ training: grad_clip_norm: 10 online_steps_between_rollouts: 1 - override_dataset_stats: - observation.images.top: - # stats from imagenet, since we use a pretrained vision model - mean: [[[0.485]], [[0.456]], [[0.406]]] # (c,1,1) - std: [[[0.229]], [[0.224]], [[0.225]]] # (c,1,1) - delta_timestamps: action: "[i / ${fps} for i in range(${policy.chunk_size})]" diff --git a/lerobot/configs/policy/diffusion.yaml b/lerobot/configs/policy/diffusion.yaml index 9a4aeb2a..7278985e 100644 --- a/lerobot/configs/policy/diffusion.yaml +++ b/lerobot/configs/policy/diffusion.yaml @@ -7,6 +7,20 @@ seed: 100000 dataset_repo_id: lerobot/pusht +override_dataset_stats: + # TODO(rcadene, alexander-soare): should we remove image stats as well? do we use a pretrained vision model? + observation.image: + mean: [[[0.5]], [[0.5]], [[0.5]]] # (c,1,1) + std: [[[0.5]], [[0.5]], [[0.5]]] # (c,1,1) + # TODO(rcadene, alexander-soare): we override state and action stats to use the same as the pretrained model + # from the original codebase, but we should remove these and train our own pretrained model + observation.state: + min: [13.456424, 32.938293] + max: [496.14618, 510.9579] + action: + min: [12.0, 25.0] + max: [511.0, 511.0] + training: offline_steps: 200000 online_steps: 0 @@ -34,20 +48,6 @@ eval: n_episodes: 50 batch_size: 50 -override_dataset_stats: - # TODO(rcadene, alexander-soare): should we remove image stats as well? do we use a pretrained vision model? - observation.image: - mean: [[[0.5]], [[0.5]], [[0.5]]] # (c,1,1) - std: [[[0.5]], [[0.5]], [[0.5]]] # (c,1,1) - # TODO(rcadene, alexander-soare): we override state and action stats to use the same as the pretrained model - # from the original codebase, but we should remove these and train our own pretrained model - observation.state: - min: [13.456424, 32.938293] - max: [496.14618, 510.9579] - action: - min: [12.0, 25.0] - max: [511.0, 511.0] - policy: name: diffusion diff --git a/tests/data/save_policy_to_safetensors/aloha_act/actions.safetensors b/tests/data/save_policy_to_safetensors/aloha_act/actions.safetensors index 70c9b6d811a396f7e554b424beb0b0ced73048d0..7e7ad8e1df015d0ff52d689b317b8d77b3f380fa 100644 GIT binary patch literal 5104 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 literal 5104 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 diff --git a/tests/data/save_policy_to_safetensors/aloha_act/grad_stats.safetensors b/tests/data/save_policy_to_safetensors/aloha_act/grad_stats.safetensors index 2e8451891e477a10a94c36901734822c69470a04..5188d8f428cdddf509da7f91f29950d9c80ad309 100644 GIT binary patch delta 1242 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 Date: Thu, 9 May 2024 17:58:39 +0100 Subject: [PATCH 13/27] Add context manager for seeding (#164) --- lerobot/common/utils/utils.py | 27 +++++++++++++++++++++++++ tests/test_utils.py | 38 +++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 tests/test_utils.py diff --git a/lerobot/common/utils/utils.py b/lerobot/common/utils/utils.py index 9d0ddd98..8fe621f4 100644 --- a/lerobot/common/utils/utils.py +++ b/lerobot/common/utils/utils.py @@ -1,8 +1,10 @@ import logging import os.path as osp import random +from contextlib import contextmanager from datetime import datetime from pathlib import Path +from typing import Generator import hydra import numpy as np @@ -39,6 +41,31 @@ def set_global_seed(seed): torch.cuda.manual_seed_all(seed) +@contextmanager +def seeded_context(seed: int) -> Generator[None, None, None]: + """Set the seed when entering a context, and restore the prior random state at exit. + + Example usage: + + ``` + a = random.random() # produces some random number + with seeded_context(1337): + b = random.random() # produces some other random number + c = random.random() # produces yet another random number, but the same it would have if we never made `b` + ``` + """ + random_state = random.getstate() + np_random_state = np.random.get_state() + torch_random_state = torch.random.get_rng_state() + torch_cuda_random_state = torch.cuda.random.get_rng_state() + set_global_seed(seed) + yield None + random.setstate(random_state) + np.random.set_state(np_random_state) + torch.random.set_rng_state(torch_random_state) + torch.cuda.random.set_rng_state(torch_cuda_random_state) + + def init_logging(): def custom_format(record): dt = datetime.now().strftime("%Y-%m-%d %H:%M:%S") diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 00000000..bcdd95b4 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,38 @@ +import random +from typing import Callable + +import numpy as np +import pytest +import torch + +from lerobot.common.utils.utils import seeded_context, set_global_seed + + +@pytest.mark.parametrize( + "rand_fn", + [ + random.random, + np.random.random, + lambda: torch.rand(1).item(), + ] + + [lambda: torch.rand(1, device="cuda")] + if torch.cuda.is_available() + else [], +) +def test_seeding(rand_fn: Callable[[], int]): + set_global_seed(0) + a = rand_fn() + with seeded_context(1337): + c = rand_fn() + b = rand_fn() + set_global_seed(0) + a_ = rand_fn() + b_ = rand_fn() + # Check that `set_global_seed` lets us reproduce a and b. + assert a_ == a + # Additionally, check that the `seeded_context` didn't interrupt the global RNG. + assert b_ == b + set_global_seed(1337) + c_ = rand_fn() + # Check that `seeded_context` and `global_seed` give the same reproducibility. + assert c_ == c From 1249aee3acdc12c6a9212f99df2a5c7a71f449e0 Mon Sep 17 00:00:00 2001 From: Alexander Soare Date: Fri, 10 May 2024 07:45:32 +0100 Subject: [PATCH 14/27] Enable logging all the information returned by the `forward` methods of policies (#151) --- lerobot/common/logger.py | 5 +++++ lerobot/common/policies/act/modeling_act.py | 4 ++-- lerobot/common/policies/policy_protocol.py | 3 ++- lerobot/scripts/train.py | 4 +++- .../aloha_act/output_dict.safetensors | Bin 196 -> 68 bytes 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lerobot/common/logger.py b/lerobot/common/logger.py index 8e7fe7f2..7a3e6eac 100644 --- a/lerobot/common/logger.py +++ b/lerobot/common/logger.py @@ -114,6 +114,11 @@ class Logger: assert mode in {"train", "eval"} if self._wandb is not None: for k, v in d.items(): + if not isinstance(v, (int, float, str)): + logging.warning( + f'WandB logging of key "{k}" was ignored as its type is not handled by this wrapper.' + ) + continue self._wandb.log({f"{mode}/{k}": v}, step=step) def log_video(self, video_path: str, step: int, mode: str = "train"): diff --git a/lerobot/common/policies/act/modeling_act.py b/lerobot/common/policies/act/modeling_act.py index 5ff25fea..a795d87b 100644 --- a/lerobot/common/policies/act/modeling_act.py +++ b/lerobot/common/policies/act/modeling_act.py @@ -101,7 +101,7 @@ class ACTPolicy(nn.Module, PyTorchModelHubMixin): F.l1_loss(batch["action"], actions_hat, reduction="none") * ~batch["action_is_pad"].unsqueeze(-1) ).mean() - loss_dict = {"l1_loss": l1_loss} + loss_dict = {"l1_loss": l1_loss.item()} if self.config.use_vae: # Calculate Dโ‚–โ‚—(latent_pdf || standard_normal). Note: After computing the KL-divergence for # each dimension independently, we sum over the latent dimension to get the total @@ -110,7 +110,7 @@ class ACTPolicy(nn.Module, PyTorchModelHubMixin): mean_kld = ( (-0.5 * (1 + log_sigma_x2_hat - mu_hat.pow(2) - (log_sigma_x2_hat).exp())).sum(-1).mean() ) - loss_dict["kld_loss"] = mean_kld + loss_dict["kld_loss"] = mean_kld.item() loss_dict["loss"] = l1_loss + mean_kld * self.config.kl_weight else: loss_dict["loss"] = l1_loss diff --git a/lerobot/common/policies/policy_protocol.py b/lerobot/common/policies/policy_protocol.py index 5749c6a8..b00cff5c 100644 --- a/lerobot/common/policies/policy_protocol.py +++ b/lerobot/common/policies/policy_protocol.py @@ -38,7 +38,8 @@ class Policy(Protocol): def forward(self, batch: dict[str, Tensor]) -> dict: """Run the batch through the model and compute the loss for training or validation. - Returns a dictionary with "loss" and maybe other information. + Returns a dictionary with "loss" and potentially other information. Apart from "loss" which is a Tensor, all + other items should be logging-friendly, native Python types. """ def select_action(self, batch: dict[str, Tensor]): diff --git a/lerobot/scripts/train.py b/lerobot/scripts/train.py index d5fedc84..7319e03f 100644 --- a/lerobot/scripts/train.py +++ b/lerobot/scripts/train.py @@ -72,6 +72,7 @@ def make_optimizer_and_scheduler(cfg, policy): def update_policy(policy, batch, optimizer, grad_clip_norm, lr_scheduler=None): + """Returns a dictionary of items for logging.""" start_time = time.time() policy.train() output_dict = policy.forward(batch) @@ -99,6 +100,7 @@ def update_policy(policy, batch, optimizer, grad_clip_norm, lr_scheduler=None): "grad_norm": float(grad_norm), "lr": optimizer.param_groups[0]["lr"], "update_s": time.time() - start_time, + **{k: v for k, v in output_dict.items() if k != "loss"}, } return info @@ -122,7 +124,7 @@ def train_notebook(out_dir=None, job_name=None, config_name="default", config_pa train(cfg, out_dir=out_dir, job_name=job_name) -def log_train_info(logger, info, step, cfg, dataset, is_offline): +def log_train_info(logger: Logger, info, step, cfg, dataset, is_offline): loss = info["loss"] grad_norm = info["grad_norm"] lr = info["lr"] diff --git a/tests/data/save_policy_to_safetensors/aloha_act/output_dict.safetensors b/tests/data/save_policy_to_safetensors/aloha_act/output_dict.safetensors index 02235e1713c7e9442a9432fe2ded6759864ae4ef..4c738f3972e7298fa60f0b4299365f62064da75a 100644 GIT binary patch delta 27 ecmX@Y=)!5i00Gq#>kPRJbWCDvYiE5gaRLBM6$d^5 delta 62 zcmZ=c!pOIQ0RpO(vU5`6Cvusx>L}$H0vQHuCOQ_ewK@|y4Mi<<42@!IYZVmCN)I?3 MThwDe>wAe40M Date: Sat, 11 May 2024 12:45:51 +0100 Subject: [PATCH 15/27] Remove torchrl acknowledgement (#177) --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index a305dbff..a936ecfe 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,6 @@ - Thanks to Tony Zaho, Zipeng Fu and colleagues for open sourcing ACT policy, ALOHA environments and datasets. Ours are adapted from [ALOHA](https://tonyzhaozh.github.io/aloha) and [Mobile ALOHA](https://mobile-aloha.github.io). - Thanks to Cheng Chi, Zhenjia Xu and colleagues for open sourcing Diffusion policy, Pusht environment and datasets, as well as UMI datasets. Ours are adapted from [Diffusion Policy](https://diffusion-policy.cs.columbia.edu) and [UMI Gripper](https://umi-gripper.github.io). - Thanks to Nicklas Hansen, Yunhai Feng and colleagues for open sourcing TDMPC policy, Simxarm environments and datasets. Ours are adapted from [TDMPC](https://github.com/nicklashansen/tdmpc) and [FOWM](https://www.yunhaifeng.com/FOWM). -- Thanks to Vincent Moens and colleagues for open sourcing [TorchRL](https://github.com/pytorch/rl). It allowed for quick experimentations on the design of `LeRobot`. - Thanks to Antonio Loquercio and Ashish Kumar for their early support. From ced3de4c94f4fa1996246095d973de42c037fa29 Mon Sep 17 00:00:00 2001 From: Remi Date: Sat, 11 May 2024 19:28:22 +0300 Subject: [PATCH 16/27] Fix hanging in visualize_dataset.py when num_workers > 0 (#165) --- lerobot/scripts/visualize_dataset.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lerobot/scripts/visualize_dataset.py b/lerobot/scripts/visualize_dataset.py index 1835e90c..d4fafe67 100644 --- a/lerobot/scripts/visualize_dataset.py +++ b/lerobot/scripts/visualize_dataset.py @@ -47,6 +47,7 @@ local$ rerun ws://localhost:9087 """ import argparse +import gc import logging import time from pathlib import Path @@ -115,15 +116,17 @@ def visualize_dataset( spawn_local_viewer = mode == "local" and not save rr.init(f"{repo_id}/episode_{episode_index}", spawn=spawn_local_viewer) + + # Manually call python garbage collector after `rr.init` to avoid hanging in a blocking flush + # when iterating on a dataloader with `num_workers` > 0 + # TODO(rcadene): remove `gc.collect` when rerun version 0.16 is out, which includes a fix + gc.collect() + if mode == "distant": rr.serve(open_browser=False, web_port=web_port, ws_port=ws_port) logging.info("Logging to Rerun") - if num_workers > 0: - # TODO(rcadene): fix data workers hanging when `rr.init` is called - logging.warning("If data loader is hanging, try `--num-workers 0`.") - for batch in tqdm.tqdm(dataloader, total=len(dataloader)): # iterate over the batch for i in range(len(batch["index"])): @@ -196,7 +199,7 @@ def main(): parser.add_argument( "--num-workers", type=int, - default=0, + default=4, help="Number of processes of Dataloader for loading the data.", ) parser.add_argument( From 29a196c5dd38bb526a232300c83bbcddd2851186 Mon Sep 17 00:00:00 2001 From: Simon Alibert <75076266+aliberts@users.noreply.github.com> Date: Sun, 12 May 2024 08:08:59 +0200 Subject: [PATCH 17/27] Fix #173 - Require gym-pusht to be installed for test_examples_3_and_2 (#174) --- .github/workflows/test.yml | 32 ++++++++++++++++++++++++++++++++ tests/test_examples.py | 3 +++ tests/utils.py | 19 ++++++++++++++++++- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f86e4f8e..45feabdc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -57,6 +57,38 @@ jobs: && rm -rf tests/outputs outputs + pytest-minimal: + name: Pytest (minimal install) + runs-on: ubuntu-latest + env: + DATA_DIR: tests/data + MUJOCO_GL: egl + steps: + - uses: actions/checkout@v4 + + - name: Install poetry + run: | + pipx install poetry && poetry config virtualenvs.in-project true + echo "${{ github.workspace }}/.venv/bin" >> $GITHUB_PATH + + - name: Set up Python 3.10 + uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Install poetry dependencies + run: | + poetry install --extras "test" + + - name: Test with pytest + run: | + pytest tests -v --cov=./lerobot --durations=0 \ + -W ignore::DeprecationWarning:imageio_ffmpeg._utils:7 \ + -W ignore::UserWarning:torch.utils.data.dataloader:558 \ + -W ignore::UserWarning:gymnasium.utils.env_checker:247 \ + && rm -rf tests/outputs outputs + + end-to-end: name: End-to-end runs-on: ubuntu-latest diff --git a/tests/test_examples.py b/tests/test_examples.py index c1f3c1dc..543eb022 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -3,6 +3,8 @@ import subprocess import sys from pathlib import Path +from tests.utils import require_package + def _find_and_replace(text: str, finds_and_replaces: list[tuple[str, str]]) -> str: for f, r in finds_and_replaces: @@ -21,6 +23,7 @@ def test_example_1(): assert Path("outputs/examples/1_load_lerobot_dataset/episode_0.mp4").exists() +@require_package("gym_pusht") def test_examples_3_and_2(): """ Train a model with example 3, check the outputs. diff --git a/tests/utils.py b/tests/utils.py index 6a706694..74e3ba8f 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,4 +1,5 @@ import platform +from functools import wraps import pytest import torch @@ -61,7 +62,6 @@ def require_env(func): Decorator that skips the test if the required environment package is not installed. As it need 'env_name' in args, it also checks whether it is provided as an argument. """ - from functools import wraps @wraps(func) def wrapper(*args, **kwargs): @@ -82,3 +82,20 @@ def require_env(func): return func(*args, **kwargs) return wrapper + + +def require_package(package_name): + """ + Decorator that skips the test if the specified package is not installed. + """ + + def decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + if not is_package_available(package_name): + pytest.skip(f"{package_name} not installed") + return func(*args, **kwargs) + + return wrapper + + return decorator From fc5cf3d84a33683bcb4c3c0491ef20d9ea4a2af1 Mon Sep 17 00:00:00 2001 From: AshisGhosh Date: Sat, 11 May 2024 23:13:12 -0700 Subject: [PATCH 18/27] Fixes issue #152 - error with creating wandb artifact (#172) Co-authored-by: Ashis Ghosh Co-authored-by: Simon Alibert <75076266+aliberts@users.noreply.github.com> --- lerobot/common/logger.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lerobot/common/logger.py b/lerobot/common/logger.py index 7a3e6eac..ea8db050 100644 --- a/lerobot/common/logger.py +++ b/lerobot/common/logger.py @@ -82,9 +82,9 @@ class Logger: # Also save the full Hydra config for the env configuration. OmegaConf.save(self._cfg, save_dir / "config.yaml") if self._wandb and not self._disable_wandb_artifact: - # note wandb artifact does not accept ":" in its name + # note wandb artifact does not accept ":" or "/" in its name artifact = self._wandb.Artifact( - self._group.replace(":", "_") + "-" + str(self._seed) + "-" + str(identifier), + f"{self._group.replace(':', '_').replace('/', '_')}-{self._seed}-{identifier}", type="model", ) artifact.add_file(save_dir / SAFETENSORS_SINGLE_FILE) @@ -94,9 +94,10 @@ class Logger: self._buffer_dir.mkdir(parents=True, exist_ok=True) fp = self._buffer_dir / f"{str(identifier)}.pkl" buffer.save(fp) - if self._wandb: + if self._wandb and not self._disable_wandb_artifact: + # note wandb artifact does not accept ":" or "/" in its name artifact = self._wandb.Artifact( - self._group + "-" + str(self._seed) + "-" + str(identifier), + f"{self._group.replace(':', '_').replace('/', '_')}-{self._seed}-{identifier}", type="buffer", ) artifact.add_file(fp) From 89c6be84caf5a628c04adcba05821d70b054f25a Mon Sep 17 00:00:00 2001 From: Simon Alibert <75076266+aliberts@users.noreply.github.com> Date: Sun, 12 May 2024 08:15:07 +0200 Subject: [PATCH 19/27] Limit datasets major update (#176) Co-authored-by: Quentin Lhoest <42851186+lhoestq@users.noreply.github.com> Co-authored-by: Quentin Lhoest --- poetry.lock | 288 ++++++++++++++++++++++++------------------------- pyproject.toml | 2 +- 2 files changed, 145 insertions(+), 145 deletions(-) diff --git a/poetry.lock b/poetry.lock index 89676fab..388e03f4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2606,13 +2606,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "3.7.0" +version = "3.7.1" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = true python-versions = ">=3.9" files = [ - {file = "pre_commit-3.7.0-py2.py3-none-any.whl", hash = "sha256:5eae9e10c2b5ac51577c3452ec0a490455c45a0533f7960f993a0d01e59decab"}, - {file = "pre_commit-3.7.0.tar.gz", hash = "sha256:e209d61b8acdcf742404408531f0c37d49d2c734fd7cff2d6076083d191cb060"}, + {file = "pre_commit-3.7.1-py2.py3-none-any.whl", hash = "sha256:fae36fd1d7ad7d6a5a1c0b0d5adb2ed1a3bda5a21bf6c3e5372073d7a11cd4c5"}, + {file = "pre_commit-3.7.1.tar.gz", hash = "sha256:8ca3ad567bc78a4972a3f1a477e94a79d4597e8140a6e0b651c5e33899c3654a"}, ] [package.dependencies] @@ -2860,67 +2860,67 @@ files = [ [[package]] name = "pymunk" -version = "6.7.0" +version = "6.8.0" description = "Pymunk is a easy-to-use pythonic 2D physics library" optional = false python-versions = ">=3.7" files = [ - {file = "pymunk-6.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4378774daf5cf2603c0558562221ba5a2ba9c6d7e4d830f4da9e1d6a00e6f3cd"}, - {file = "pymunk-6.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:badbdbf499f79c3e937ba7044c3ce3a665d6ae76c2a7df2408994e07fd78b34b"}, - {file = "pymunk-6.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46835d63bdcc579a488d2dfbc7cbec52bfc34a4ceb15086820d1372f70cb8695"}, - {file = "pymunk-6.7.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c63f0153bcb4080cd83f3d40cec4f525773ac0f4ac2bf9b9506c2fa8af7b4e41"}, - {file = "pymunk-6.7.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:72596e57997856817202580557a4f4b46a0b1ddf0fbbbadf978f46778d5aa642"}, - {file = "pymunk-6.7.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:43099a916c2bbd9740a740f259bb26341e8cb54fb0c06192ea0cc27606552596"}, - {file = "pymunk-6.7.0-cp310-cp310-win32.whl", hash = "sha256:2cf770c8ae5d14c51b7021768bf73b7c8c62d786d703dd9f6e1ec3ea12966f91"}, - {file = "pymunk-6.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:e0ea3a7cab752bc5078c202e40bf4db81435fd1d121190e851a960a1b9a070df"}, - {file = "pymunk-6.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:803c0dfb8be18a8fac5d37732d7db29589d6157594a22608fa5e34ee87a5ff8e"}, - {file = "pymunk-6.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e82f817cdddd3b9babebc1ce964eed55f8d5686475b92e3e6d3d22dca5b93f3c"}, - {file = "pymunk-6.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3693a1aeb4ce8a68574b3b7557c6a1e15ce420820b850f95f34ab24663fdcb11"}, - {file = "pymunk-6.7.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f32b352a87ad1705bfedef133253da697e9a0eeff764e125414a63231bfb06e"}, - {file = "pymunk-6.7.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7ec996c4305666336c3e2908b59e0644f4095a526ed2f96f0f8d35bdc41a4575"}, - {file = "pymunk-6.7.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7e54923293dfa51c41f222d967cb3b79872f35a4a892ae0bd31bad9cefd1b8a6"}, - {file = "pymunk-6.7.0-cp311-cp311-win32.whl", hash = "sha256:d4622c2927789d7bc834763569fb4a947c266702eb9e5f12f815bd841c49f669"}, - {file = "pymunk-6.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:031c74ed42e49474ca4fcdc11a9521c2084514d2213cb8b7df7cb50a66b66686"}, - {file = "pymunk-6.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c2316d188a9fc6d0661afc30fbb164a546b939faf359e98f082641ca41c924e2"}, - {file = "pymunk-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5f494effad0dbd873851b52b22c1a812fe36f1fb1e29d28759066cee1afca1e9"}, - {file = "pymunk-6.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:895deeae5a9c2ef3bbb842ef5d37e750160c8ba956a4149fbb89304eb7b4808e"}, - {file = "pymunk-6.7.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f672762c176ba51c2327f7a66db10c0adfb5f3caaa4f586098c62c169b311f87"}, - {file = "pymunk-6.7.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9f0e26d53cb5aaf22042de97638c356d25c1062198594390a18810f2992cd4b5"}, - {file = "pymunk-6.7.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c4985590a95d419a7684f2c01b33fc61e939debaae7b12d1cf0946070c1644f9"}, - {file = "pymunk-6.7.0-cp312-cp312-win32.whl", hash = "sha256:b63875005eee0126a0be32cfd9179be520a2f73235ae98408af2ba39255f8e07"}, - {file = "pymunk-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:4a9438d29c1f0397b45b328f74eaed097593de03d8d0546fa84c20c3a5f158e6"}, - {file = "pymunk-6.7.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:630ddc4a03f4ac9d5dfd13bb99e20146d804683212defb8d0633fbf4844035b4"}, - {file = "pymunk-6.7.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca0c565e7c8ff8bc2ee477ed712973609a77a229e813a7a18c499ff5b96415a7"}, - {file = "pymunk-6.7.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f0d79e89fc3ccee6007380a9df493017c178a606446a1382fc0e351bd48622d"}, - {file = "pymunk-6.7.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:827180ee032b3237be2980712cdfe1446c2f7aeeb7f13518ebb4cc022995d235"}, - {file = "pymunk-6.7.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c401a6068b376dcd3d25948b498cea410e15a93108c4d8e03c94f9b61767593b"}, - {file = "pymunk-6.7.0-cp37-cp37m-win32.whl", hash = "sha256:a38d8b70c6a7198fc0e746ab8dfedd70f9bf26579b6cd11789f3232f27d247fb"}, - {file = "pymunk-6.7.0-cp37-cp37m-win_amd64.whl", hash = "sha256:283746a11658288903af182605f1034bc5cffbb5de49fd4d8bea43330778ddfb"}, - {file = "pymunk-6.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8376aad8169a13a5368c597cf54b492f6dd6ef4c9273385af461b6f416f0205a"}, - {file = "pymunk-6.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0bf0ec5142ae387789eca6210a315508943a0af14faf337154c1c6b2e20abaad"}, - {file = "pymunk-6.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e5469182821d23e43e1fe50b21a313f798eefafc59b0f25dd69a7b579cdbbbc"}, - {file = "pymunk-6.7.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cee5c5da3f624c1b4f10e566f6322f354f0925dc081c1d6dfdb56fa94ff6b2b7"}, - {file = "pymunk-6.7.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:130234abfb503a9d3aba57161bf7520eb57c27278ad6f47888f862a2808b1f8d"}, - {file = "pymunk-6.7.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3532965ba0048057ce00eccbafca818586acabf77c4453d36e9be5f614dab260"}, - {file = "pymunk-6.7.0-cp38-cp38-win32.whl", hash = "sha256:3dca5b72c34f4957c039ced8bd58ca484b929f0f6c4fc4f8a2268d89999d3b13"}, - {file = "pymunk-6.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:aaac3b0a2446575cf0fa90745ef6b99cd786837e1baaf2f530febf2824d07276"}, - {file = "pymunk-6.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6ee13324c8fdfdab03069eef00aadfe06d353d9d6c5e4a93e190c9b214166f8b"}, - {file = "pymunk-6.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1fd1069c95061feebf7dfbbb32a2150e019d06001a0c8281442d27366d2a6f21"}, - {file = "pymunk-6.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7aeac2ba24977aae4e602a993c17c265f168374b018d09e13536c1df61cf4d5"}, - {file = "pymunk-6.7.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e78eb9f6b6a7656837698ea9a6ceea00d84959de3126e625de41cf240084dba6"}, - {file = "pymunk-6.7.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:927fa4262c62f409e79806ef282a3bee1dab5a69e680e5cf2ba26b58c850e9be"}, - {file = "pymunk-6.7.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c127f39bd23c93e82f0ee0adc1edbd8ebdda441d12f9d09987372be9852edb74"}, - {file = "pymunk-6.7.0-cp39-cp39-win32.whl", hash = "sha256:ce582ae06e6fe8e8d1ad10dc061fe5716b360ea04b79925532d96848741a5452"}, - {file = "pymunk-6.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:04874a4063270db73bd2e6b3522d2e6ffb193a183d06872bb1270385475412f8"}, - {file = "pymunk-6.7.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:032daa41f9219749e52b1ff3312cdff3eab24c31ec8495777da89003667137ad"}, - {file = "pymunk-6.7.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210e067b29fda70a8c21f09a9a900d0b917d425e6d47209426e5b88388bd2a06"}, - {file = "pymunk-6.7.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:046e510d76976c41cd92b3d5b985c930f0a568c2fb4f0632e40aaab4619ad481"}, - {file = "pymunk-6.7.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:27a4104a51ae690fc0feb2a567279234307decaf86214382a1dce89527365422"}, - {file = "pymunk-6.7.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8ac7b714a8fc83325519254c6734baa9dd1498210c6d5e51facfd829a6b2de09"}, - {file = "pymunk-6.7.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09b22ce73222c5f7cf061f6cd71097c94f57c89b6364acfc30f707ca1d3c67e2"}, - {file = "pymunk-6.7.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3313c5531e6678f249bc1cf84cb5c4993745e8652853f1962919678f6a0b4ec3"}, - {file = "pymunk-6.7.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d8aaaebdd546b9b76d4905039835910a5965fff816261ce2b9558a7607206f52"}, - {file = "pymunk-6.7.0.tar.gz", hash = "sha256:7b3bff3852c46a87b497a1a73bb36bb2b2f7e38be2e7c232498b857e79197560"}, + {file = "pymunk-6.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:96b363241569e616bea1d62346552e3503f2b58d6715b5bda20a13ba2522cea2"}, + {file = "pymunk-6.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:91aab5c0640cddaf100eaaf6df8578aa3b97b70c5e5e0c1d26f6826eefec8e96"}, + {file = "pymunk-6.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78973d4ef0fa715e127ca408f6063c82722b883d98cf216dddd906aa00debf4e"}, + {file = "pymunk-6.8.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7944db455d81bc552fc1b2edadbf82a6b91b11ee75193552ef629d0b8106975b"}, + {file = "pymunk-6.8.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3ec2a1c2a3b2b0eac97ebd2b84dfd51bd98b2b753a33dce81f4f26fa9e1a8974"}, + {file = "pymunk-6.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3134ba935921e0e888d9013258f1de111bc2da05a02ec2a7d520a8c580f28fba"}, + {file = "pymunk-6.8.0-cp310-cp310-win32.whl", hash = "sha256:a3222cb84481408faf6236f4cea6a17045881e5780a4dccc170344a7a4ad160a"}, + {file = "pymunk-6.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:7f13bffe06634f23e0453b0a5e388142cdbaa06f54a243aae98e2b9c2793ebb0"}, + {file = "pymunk-6.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0db72af65205c80d15403e6784bdd7c559e620411394449356dc869b90ade1c"}, + {file = "pymunk-6.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6e5cc30d15eba4bc33e00b9fb8c366255dac47fe486f5276f6334e8a8c34754"}, + {file = "pymunk-6.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3752e8486a4b8bfaa988be59a9773f0371d0cd52a7901fe7ba9caed1ea5b6129"}, + {file = "pymunk-6.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f20b3dfc56aee57cc910ce65505286e184e045c9169bd8d5eff50974b6a1e97"}, + {file = "pymunk-6.8.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6d807bba8fd7bae35754c29c2cb8809f0cf7817541c8cb4d134872e102899724"}, + {file = "pymunk-6.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ac39afd90800061b353cbeb71171109ef7411cc88f5607b10447b2906e4cde97"}, + {file = "pymunk-6.8.0-cp311-cp311-win32.whl", hash = "sha256:4de7683f832c694b82dbe7c20469765663f06ee82f8b711bd72731684b452889"}, + {file = "pymunk-6.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:6620fc590290c37e58c8495fb74e5eb433f24b7c7d46c8a7b4b54c56ca9990ab"}, + {file = "pymunk-6.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6eee05919e1e8f63b64a75362e82691365918b0ea33af11d2b3aab1d81402a3d"}, + {file = "pymunk-6.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b99fa28a8fa5242560a7f2d59604b9e55eed865d8308dd5f93af97ad2605f84"}, + {file = "pymunk-6.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d9be0614a4c0eaaff209656df464e9eb5653dc171a15230dd4d307a3f3564e6"}, + {file = "pymunk-6.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c22598b75ef99dd70fb2c6b8989c55ab00fac379555ebf68cfe7adfa65fd94e"}, + {file = "pymunk-6.8.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:533bb7555df1c904f1056ac9149e59ab039ee195fa22c69500843ef7e3f57062"}, + {file = "pymunk-6.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9de831180f7650c47fcfcadadf5d295e72065c8500a4c9a78f6d37229c2ca58b"}, + {file = "pymunk-6.8.0-cp312-cp312-win32.whl", hash = "sha256:8bbc9189c71a6c51825f8246e94c6642823ef42a4b3ed9c2afa7f8ec48425929"}, + {file = "pymunk-6.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:e3b61a162153dfdd0ebbab82eddb417da812085b3587ebf92a225d33df8e044d"}, + {file = "pymunk-6.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8a4fa8e3672a3b49850adf71b0eabacabb73db0514cbece0649bc77e1a124924"}, + {file = "pymunk-6.8.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ada172ee87296fdfdf5ac0d88c43502b482697185ce9b6d03d0f0d4b5b11532"}, + {file = "pymunk-6.8.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c0c9d881ca7d9a9375ce248e90f24efb298d41e4abf8e16f5c7e78c66983c34"}, + {file = "pymunk-6.8.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e5a6e2a7ff652b2977e24b4ed2d33fc7d628bd4e54ddeb488515b1475f715d91"}, + {file = "pymunk-6.8.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12f0af3417a95c5ab97207a5e54fbc91a54c801b4560283532f5582401a1f36e"}, + {file = "pymunk-6.8.0-cp37-cp37m-win32.whl", hash = "sha256:382aaa71d7615ded7cfc644a091391cf0fd3ecf7bc556e0145d0f6982c942ee7"}, + {file = "pymunk-6.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c40361a2b017107303568ace3e506d87ab46d67d31484f656ba7792901d20abd"}, + {file = "pymunk-6.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54167f0f9b65a49f35fbde56746ce7020b74b39b86ef8cec8804ef9422d258c9"}, + {file = "pymunk-6.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3e32c520ba2729c97fd5031cc0caa99de20a9b6dda85b8468cf769afa7a4a85c"}, + {file = "pymunk-6.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93c86daf68fb0785722cbea3fc36afcf9830af156de9ed99cbf2b6d6475240ab"}, + {file = "pymunk-6.8.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:269576ad7d4241c75611df0f0e3ff0b19de436f4facabb21185e579a573c91d0"}, + {file = "pymunk-6.8.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a4c90c82e6dfd35930ad779287859c3a867518065fce97fee6eeaf81a1754ea6"}, + {file = "pymunk-6.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06b5ce0a26a26b3490107c962632f4dd53137df14e11b0e55c9816005509dea1"}, + {file = "pymunk-6.8.0-cp38-cp38-win32.whl", hash = "sha256:ff3b4d086f47f4fee9980977ec4f1121909b5456ed05fcad3c0f2f6e224e1fef"}, + {file = "pymunk-6.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d8f7124ab9e5c69ab698d3836dc0d84e1a31d47b5e7ce6477cf5205d701887"}, + {file = "pymunk-6.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:47803f8229b95e9ae56cada9566e1b92b2789affe2229ed623d3a871fd307982"}, + {file = "pymunk-6.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:194cf34146b7393ebdd2e37cb50d5579e737baf378f900a50ff477c909a163c9"}, + {file = "pymunk-6.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af8d9d0a26dc4d504ac881407ac9d7689b0c89bf8c0535717c15583773eb965"}, + {file = "pymunk-6.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79c50449c12120d05fdf515e4c937220580f945ed1eda8c374734a3418fc18e6"}, + {file = "pymunk-6.8.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:45197c7fcebff6bc3d4b7f3ccef150a6c4c43f71860e03503e851c8ecc0af861"}, + {file = "pymunk-6.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:183ecbbafffe8a071ffb0efb6a5daa21f05d2b9a36c0538b47fbd15b6e6fa6e5"}, + {file = "pymunk-6.8.0-cp39-cp39-win32.whl", hash = "sha256:2453eff73e474c1f282088e70a5dfd970ebc9f565c1b39b1da69df1b43dee47f"}, + {file = "pymunk-6.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:769aae66d3918fa7d9ac33fca4e693a53aba1ed801050450c1a42b4c8ecc7250"}, + {file = "pymunk-6.8.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:22153b93074e8f397e245aad2811e50ccc94502616341a1420c2a3a7332c1db0"}, + {file = "pymunk-6.8.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b6d5d62b1f8ad3b8626be64817bed709edbbd03b578e33ae3e39ab7f9301055"}, + {file = "pymunk-6.8.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50d9ff9e7caa3a7f432f4c6da4d1acd0dd1208ca22fc4cea3d48d845ac4111b3"}, + {file = "pymunk-6.8.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b0688613c641c5a018091ba9285a38cb6e53a64daa9ec3bc80006ea6c4531a32"}, + {file = "pymunk-6.8.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:42cf265d55dd90ab3441c9e0a1596094372b063713760d2a5489321d1b9beddb"}, + {file = "pymunk-6.8.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f199f1f291f7ad8ec3c00d529c6207bb7a67497b6ecd79ffb27df1aabe973d7"}, + {file = "pymunk-6.8.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79fe51090090f4dd4e41603bbc46926be4bae3c3f554664b907fc3fda65019f8"}, + {file = "pymunk-6.8.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:03100f749d276742244d560e12ae125cbcf13606d24fd60455b52d5b9a9f7a17"}, + {file = "pymunk-6.8.0.tar.gz", hash = "sha256:882929eac3cc5107bec13da7bbe9b6a3868df87ecc373475d0d1aae82d2f5dda"}, ] [package.dependencies] @@ -3092,90 +3092,90 @@ files = [ [[package]] name = "regex" -version = "2024.4.28" +version = "2024.5.10" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.8" files = [ - {file = "regex-2024.4.28-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd196d056b40af073d95a2879678585f0b74ad35190fac04ca67954c582c6b61"}, - {file = "regex-2024.4.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8bb381f777351bd534462f63e1c6afb10a7caa9fa2a421ae22c26e796fe31b1f"}, - {file = "regex-2024.4.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:47af45b6153522733aa6e92543938e97a70ce0900649ba626cf5aad290b737b6"}, - {file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99d6a550425cc51c656331af0e2b1651e90eaaa23fb4acde577cf15068e2e20f"}, - {file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bf29304a8011feb58913c382902fde3395957a47645bf848eea695839aa101b7"}, - {file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:92da587eee39a52c91aebea8b850e4e4f095fe5928d415cb7ed656b3460ae79a"}, - {file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6277d426e2f31bdbacb377d17a7475e32b2d7d1f02faaecc48d8e370c6a3ff31"}, - {file = "regex-2024.4.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28e1f28d07220c0f3da0e8fcd5a115bbb53f8b55cecf9bec0c946eb9a059a94c"}, - {file = "regex-2024.4.28-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:aaa179975a64790c1f2701ac562b5eeb733946eeb036b5bcca05c8d928a62f10"}, - {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6f435946b7bf7a1b438b4e6b149b947c837cb23c704e780c19ba3e6855dbbdd3"}, - {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:19d6c11bf35a6ad077eb23852827f91c804eeb71ecb85db4ee1386825b9dc4db"}, - {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:fdae0120cddc839eb8e3c15faa8ad541cc6d906d3eb24d82fb041cfe2807bc1e"}, - {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e672cf9caaf669053121f1766d659a8813bd547edef6e009205378faf45c67b8"}, - {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f57515750d07e14743db55d59759893fdb21d2668f39e549a7d6cad5d70f9fea"}, - {file = "regex-2024.4.28-cp310-cp310-win32.whl", hash = "sha256:a1409c4eccb6981c7baabc8888d3550df518add6e06fe74fa1d9312c1838652d"}, - {file = "regex-2024.4.28-cp310-cp310-win_amd64.whl", hash = "sha256:1f687a28640f763f23f8a9801fe9e1b37338bb1ca5d564ddd41619458f1f22d1"}, - {file = "regex-2024.4.28-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:84077821c85f222362b72fdc44f7a3a13587a013a45cf14534df1cbbdc9a6796"}, - {file = "regex-2024.4.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b45d4503de8f4f3dc02f1d28a9b039e5504a02cc18906cfe744c11def942e9eb"}, - {file = "regex-2024.4.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:457c2cd5a646dd4ed536c92b535d73548fb8e216ebee602aa9f48e068fc393f3"}, - {file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b51739ddfd013c6f657b55a508de8b9ea78b56d22b236052c3a85a675102dc6"}, - {file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:459226445c7d7454981c4c0ce0ad1a72e1e751c3e417f305722bbcee6697e06a"}, - {file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:670fa596984b08a4a769491cbdf22350431970d0112e03d7e4eeaecaafcd0fec"}, - {file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe00f4fe11c8a521b173e6324d862ee7ee3412bf7107570c9b564fe1119b56fb"}, - {file = "regex-2024.4.28-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:36f392dc7763fe7924575475736bddf9ab9f7a66b920932d0ea50c2ded2f5636"}, - {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:23a412b7b1a7063f81a742463f38821097b6a37ce1e5b89dd8e871d14dbfd86b"}, - {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f1d6e4b7b2ae3a6a9df53efbf199e4bfcff0959dbdb5fd9ced34d4407348e39a"}, - {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:499334ad139557de97cbc4347ee921c0e2b5e9c0f009859e74f3f77918339257"}, - {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:0940038bec2fe9e26b203d636c44d31dd8766abc1fe66262da6484bd82461ccf"}, - {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:66372c2a01782c5fe8e04bff4a2a0121a9897e19223d9eab30c54c50b2ebeb7f"}, - {file = "regex-2024.4.28-cp311-cp311-win32.whl", hash = "sha256:c77d10ec3c1cf328b2f501ca32583625987ea0f23a0c2a49b37a39ee5c4c4630"}, - {file = "regex-2024.4.28-cp311-cp311-win_amd64.whl", hash = "sha256:fc0916c4295c64d6890a46e02d4482bb5ccf33bf1a824c0eaa9e83b148291f90"}, - {file = "regex-2024.4.28-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:08a1749f04fee2811c7617fdd46d2e46d09106fa8f475c884b65c01326eb15c5"}, - {file = "regex-2024.4.28-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b8eb28995771c087a73338f695a08c9abfdf723d185e57b97f6175c5051ff1ae"}, - {file = "regex-2024.4.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dd7ef715ccb8040954d44cfeff17e6b8e9f79c8019daae2fd30a8806ef5435c0"}, - {file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb0315a2b26fde4005a7c401707c5352df274460f2f85b209cf6024271373013"}, - {file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f2fc053228a6bd3a17a9b0a3f15c3ab3cf95727b00557e92e1cfe094b88cc662"}, - {file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fe9739a686dc44733d52d6e4f7b9c77b285e49edf8570754b322bca6b85b4cc"}, - {file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74fcf77d979364f9b69fcf8200849ca29a374973dc193a7317698aa37d8b01c"}, - {file = "regex-2024.4.28-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:965fd0cf4694d76f6564896b422724ec7b959ef927a7cb187fc6b3f4e4f59833"}, - {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2fef0b38c34ae675fcbb1b5db760d40c3fc3612cfa186e9e50df5782cac02bcd"}, - {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bc365ce25f6c7c5ed70e4bc674f9137f52b7dd6a125037f9132a7be52b8a252f"}, - {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:ac69b394764bb857429b031d29d9604842bc4cbfd964d764b1af1868eeebc4f0"}, - {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:144a1fc54765f5c5c36d6d4b073299832aa1ec6a746a6452c3ee7b46b3d3b11d"}, - {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2630ca4e152c221072fd4a56d4622b5ada876f668ecd24d5ab62544ae6793ed6"}, - {file = "regex-2024.4.28-cp312-cp312-win32.whl", hash = "sha256:7f3502f03b4da52bbe8ba962621daa846f38489cae5c4a7b5d738f15f6443d17"}, - {file = "regex-2024.4.28-cp312-cp312-win_amd64.whl", hash = "sha256:0dd3f69098511e71880fb00f5815db9ed0ef62c05775395968299cb400aeab82"}, - {file = "regex-2024.4.28-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:374f690e1dd0dbdcddea4a5c9bdd97632cf656c69113f7cd6a361f2a67221cb6"}, - {file = "regex-2024.4.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f87ae6b96374db20f180eab083aafe419b194e96e4f282c40191e71980c666"}, - {file = "regex-2024.4.28-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5dbc1bcc7413eebe5f18196e22804a3be1bfdfc7e2afd415e12c068624d48247"}, - {file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f85151ec5a232335f1be022b09fbbe459042ea1951d8a48fef251223fc67eee1"}, - {file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57ba112e5530530fd175ed550373eb263db4ca98b5f00694d73b18b9a02e7185"}, - {file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:224803b74aab56aa7be313f92a8d9911dcade37e5f167db62a738d0c85fdac4b"}, - {file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a54a047b607fd2d2d52a05e6ad294602f1e0dec2291152b745870afc47c1397"}, - {file = "regex-2024.4.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a2a512d623f1f2d01d881513af9fc6a7c46e5cfffb7dc50c38ce959f9246c94"}, - {file = "regex-2024.4.28-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c06bf3f38f0707592898428636cbb75d0a846651b053a1cf748763e3063a6925"}, - {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1031a5e7b048ee371ab3653aad3030ecfad6ee9ecdc85f0242c57751a05b0ac4"}, - {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d7a353ebfa7154c871a35caca7bfd8f9e18666829a1dc187115b80e35a29393e"}, - {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:7e76b9cfbf5ced1aca15a0e5b6f229344d9b3123439ffce552b11faab0114a02"}, - {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5ce479ecc068bc2a74cb98dd8dba99e070d1b2f4a8371a7dfe631f85db70fe6e"}, - {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7d77b6f63f806578c604dca209280e4c54f0fa9a8128bb8d2cc5fb6f99da4150"}, - {file = "regex-2024.4.28-cp38-cp38-win32.whl", hash = "sha256:d84308f097d7a513359757c69707ad339da799e53b7393819ec2ea36bc4beb58"}, - {file = "regex-2024.4.28-cp38-cp38-win_amd64.whl", hash = "sha256:2cc1b87bba1dd1a898e664a31012725e48af826bf3971e786c53e32e02adae6c"}, - {file = "regex-2024.4.28-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7413167c507a768eafb5424413c5b2f515c606be5bb4ef8c5dee43925aa5718b"}, - {file = "regex-2024.4.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:108e2dcf0b53a7c4ab8986842a8edcb8ab2e59919a74ff51c296772e8e74d0ae"}, - {file = "regex-2024.4.28-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f1c5742c31ba7d72f2dedf7968998730664b45e38827637e0f04a2ac7de2f5f1"}, - {file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecc6148228c9ae25ce403eade13a0961de1cb016bdb35c6eafd8e7b87ad028b1"}, - {file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7d893c8cf0e2429b823ef1a1d360a25950ed11f0e2a9df2b5198821832e1947"}, - {file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4290035b169578ffbbfa50d904d26bec16a94526071ebec3dadbebf67a26b25e"}, - {file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44a22ae1cfd82e4ffa2066eb3390777dc79468f866f0625261a93e44cdf6482b"}, - {file = "regex-2024.4.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd24fd140b69f0b0bcc9165c397e9b2e89ecbeda83303abf2a072609f60239e2"}, - {file = "regex-2024.4.28-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:39fb166d2196413bead229cd64a2ffd6ec78ebab83fff7d2701103cf9f4dfd26"}, - {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9301cc6db4d83d2c0719f7fcda37229691745168bf6ae849bea2e85fc769175d"}, - {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7c3d389e8d76a49923683123730c33e9553063d9041658f23897f0b396b2386f"}, - {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:99ef6289b62042500d581170d06e17f5353b111a15aa6b25b05b91c6886df8fc"}, - {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:b91d529b47798c016d4b4c1d06cc826ac40d196da54f0de3c519f5a297c5076a"}, - {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:43548ad74ea50456e1c68d3c67fff3de64c6edb85bcd511d1136f9b5376fc9d1"}, - {file = "regex-2024.4.28-cp39-cp39-win32.whl", hash = "sha256:05d9b6578a22db7dedb4df81451f360395828b04f4513980b6bd7a1412c679cc"}, - {file = "regex-2024.4.28-cp39-cp39-win_amd64.whl", hash = "sha256:3986217ec830c2109875be740531feb8ddafe0dfa49767cdcd072ed7e8927962"}, - {file = "regex-2024.4.28.tar.gz", hash = "sha256:83ab366777ea45d58f72593adf35d36ca911ea8bd838483c1823b883a121b0e4"}, + {file = "regex-2024.5.10-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:eda3dd46df535da787ffb9036b5140f941ecb91701717df91c9daf64cabef953"}, + {file = "regex-2024.5.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1d5bd666466c8f00a06886ce1397ba8b12371c1f1c6d1bef11013e9e0a1464a8"}, + {file = "regex-2024.5.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:32e5f3b8e32918bfbdd12eca62e49ab3031125c454b507127ad6ecbd86e62fca"}, + {file = "regex-2024.5.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:534efd2653ebc4f26fc0e47234e53bf0cb4715bb61f98c64d2774a278b58c846"}, + {file = "regex-2024.5.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:193b7c6834a06f722f0ce1ba685efe80881de7c3de31415513862f601097648c"}, + {file = "regex-2024.5.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:160ba087232c5c6e2a1e7ad08bd3a3f49b58c815be0504d8c8aacfb064491cd8"}, + {file = "regex-2024.5.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:951be1eae7b47660412dc4938777a975ebc41936d64e28081bf2e584b47ec246"}, + {file = "regex-2024.5.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8a0f0ab5453e409586b11ebe91c672040bc804ca98d03a656825f7890cbdf88"}, + {file = "regex-2024.5.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9e6d4d6ae1827b2f8c7200aaf7501c37cf3f3896c86a6aaf2566448397c823dd"}, + {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:161a206c8f3511e2f5fafc9142a2cc25d7fe9a1ec5ad9b4ad2496a7c33e1c5d2"}, + {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:44b3267cea873684af022822195298501568ed44d542f9a2d9bebc0212e99069"}, + {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:560278c9975694e1f0bc50da187abf2cdc1e4890739ea33df2bc4a85eeef143e"}, + {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:70364a097437dd0a90b31cd77f09f7387ad9ac60ef57590971f43b7fca3082a5"}, + {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:42be5de7cc8c1edac55db92d82b68dc8e683b204d6f5414c5a51997a323d7081"}, + {file = "regex-2024.5.10-cp310-cp310-win32.whl", hash = "sha256:9a8625849387b9d558d528e263ecc9c0fbde86cfa5c2f0eef43fff480ae24d71"}, + {file = "regex-2024.5.10-cp310-cp310-win_amd64.whl", hash = "sha256:903350bf44d7e4116b4d5898b30b15755d61dcd3161e3413a49c7db76f0bee5a"}, + {file = "regex-2024.5.10-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bf9596cba92ce7b1fd32c7b07c6e3212c7eed0edc271757e48bfcd2b54646452"}, + {file = "regex-2024.5.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:45cc13d398b6359a7708986386f72bd156ae781c3e83a68a6d4cee5af04b1ce9"}, + {file = "regex-2024.5.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ad45f3bccfcb00868f2871dce02a755529838d2b86163ab8a246115e80cfb7d6"}, + {file = "regex-2024.5.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33d19f0cde6838c81acffff25c7708e4adc7dd02896c9ec25c3939b1500a1778"}, + {file = "regex-2024.5.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0a9f89d7db5ef6bdf53e5cc8e6199a493d0f1374b3171796b464a74ebe8e508a"}, + {file = "regex-2024.5.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c6c71cf92b09e5faa72ea2c68aa1f61c9ce11cb66fdc5069d712f4392ddfd00"}, + {file = "regex-2024.5.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7467ad8b0eac0b28e52679e972b9b234b3de0ea5cee12eb50091d2b68145fe36"}, + {file = "regex-2024.5.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc0db93ad039fc2fe32ccd3dd0e0e70c4f3d6e37ae83f0a487e1aba939bd2fbd"}, + {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fa9335674d7c819674467c7b46154196c51efbaf5f5715187fd366814ba3fa39"}, + {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7dda3091838206969c2b286f9832dff41e2da545b99d1cfaea9ebd8584d02708"}, + {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:504b5116e2bd1821efd815941edff7535e93372a098e156bb9dffde30264e798"}, + {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:91b53dea84415e8115506cc62e441a2b54537359c63d856d73cb1abe05af4c9a"}, + {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1a3903128f9e17a500618e80c68165c78c741ebb17dd1a0b44575f92c3c68b02"}, + {file = "regex-2024.5.10-cp311-cp311-win32.whl", hash = "sha256:236cace6c1903effd647ed46ce6dd5d76d54985fc36dafc5256032886736c85d"}, + {file = "regex-2024.5.10-cp311-cp311-win_amd64.whl", hash = "sha256:12446827f43c7881decf2c126762e11425de5eb93b3b0d8b581344c16db7047a"}, + {file = "regex-2024.5.10-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:14905ed75c7a6edf423eb46c213ed3f4507c38115f1ed3c00f4ec9eafba50e58"}, + {file = "regex-2024.5.10-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4fad420b14ae1970a1f322e8ae84a1d9d89375eb71e1b504060ab2d1bfe68f3c"}, + {file = "regex-2024.5.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c46a76a599fcbf95f98755275c5527304cc4f1bb69919434c1e15544d7052910"}, + {file = "regex-2024.5.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0faecb6d5779753a6066a3c7a0471a8d29fe25d9981ca9e552d6d1b8f8b6a594"}, + {file = "regex-2024.5.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aab65121229c2ecdf4a31b793d99a6a0501225bd39b616e653c87b219ed34a49"}, + {file = "regex-2024.5.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:50e7e96a527488334379e05755b210b7da4a60fc5d6481938c1fa053e0c92184"}, + {file = "regex-2024.5.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba034c8db4b264ef1601eb33cd23d87c5013b8fb48b8161debe2e5d3bd9156b0"}, + {file = "regex-2024.5.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:031219782d97550c2098d9a68ce9e9eaefe67d2d81d8ff84c8354f9c009e720c"}, + {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:62b5f7910b639f3c1d122d408421317c351e213ca39c964ad4121f27916631c6"}, + {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cd832bd9b6120d6074f39bdfbb3c80e416848b07ac72910f1c7f03131a6debc3"}, + {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:e91b1976358e17197157b405cab408a5f4e33310cda211c49fc6da7cffd0b2f0"}, + {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:571452362d552de508c37191b6abbbb660028b8b418e2d68c20779e0bc8eaaa8"}, + {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5253dcb0bfda7214523de58b002eb0090cb530d7c55993ce5f6d17faf953ece7"}, + {file = "regex-2024.5.10-cp312-cp312-win32.whl", hash = "sha256:2f30a5ab8902f93930dc6f627c4dd5da2703333287081c85cace0fc6e21c25af"}, + {file = "regex-2024.5.10-cp312-cp312-win_amd64.whl", hash = "sha256:3799e36d60a35162bb35b2246d8bb012192b7437dff807ef79c14e7352706306"}, + {file = "regex-2024.5.10-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bbdc5db2c98ac2bf1971ffa1410c87ca7a15800415f788971e8ba8520fc0fda9"}, + {file = "regex-2024.5.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6ccdeef4584450b6f0bddd5135354908dacad95425fcb629fe36d13e48b60f32"}, + {file = "regex-2024.5.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:29d839829209f3c53f004e1de8c3113efce6d98029f044fa5cfee666253ee7e6"}, + {file = "regex-2024.5.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0709ba544cf50bd5cb843df4b8bb6701bae2b70a8e88da9add8386cbca5c1385"}, + {file = "regex-2024.5.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:972b49f2fe1047b9249c958ec4fa1bdd2cf8ce305dc19d27546d5a38e57732d8"}, + {file = "regex-2024.5.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cdbb1998da94607d5eec02566b9586f0e70d6438abf1b690261aac0edda7ab6"}, + {file = "regex-2024.5.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf7c8ee4861d9ef5b1120abb75846828c811f932d63311596ad25fa168053e00"}, + {file = "regex-2024.5.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d35d4cc9270944e95f9c88af757b0c9fc43f396917e143a5756608462c5223b"}, + {file = "regex-2024.5.10-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8722f72068b3e1156a4b2e1afde6810f1fc67155a9fa30a4b9d5b4bc46f18fb0"}, + {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:696639a73ca78a380acfaa0a1f6dd8220616a99074c05bba9ba8bb916914b224"}, + {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea057306ab469130167014b662643cfaed84651c792948891d003cf0039223a5"}, + {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b43b78f9386d3d932a6ce5af4b45f393d2e93693ee18dc4800d30a8909df700e"}, + {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c43395a3b7cc9862801a65c6994678484f186ce13c929abab44fb8a9e473a55a"}, + {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0bc94873ba11e34837bffd7e5006703abeffc4514e2f482022f46ce05bd25e67"}, + {file = "regex-2024.5.10-cp38-cp38-win32.whl", hash = "sha256:1118ba9def608250250f4b3e3f48c62f4562ba16ca58ede491b6e7554bfa09ff"}, + {file = "regex-2024.5.10-cp38-cp38-win_amd64.whl", hash = "sha256:458d68d34fb74b906709735c927c029e62f7d06437a98af1b5b6258025223210"}, + {file = "regex-2024.5.10-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:15e593386ec6331e0ab4ac0795b7593f02ab2f4b30a698beb89fbdc34f92386a"}, + {file = "regex-2024.5.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ca23b41355ba95929e9505ee04e55495726aa2282003ed9b012d86f857d3e49b"}, + {file = "regex-2024.5.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c8982ee19ccecabbaeac1ba687bfef085a6352a8c64f821ce2f43e6d76a9298"}, + {file = "regex-2024.5.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7117cb7d6ac7f2e985f3d18aa8a1728864097da1a677ffa69e970ca215baebf1"}, + {file = "regex-2024.5.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b66421f8878a0c82fc0c272a43e2121c8d4c67cb37429b764f0d5ad70b82993b"}, + {file = "regex-2024.5.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:224a9269f133564109ce668213ef3cb32bc72ccf040b0b51c72a50e569e9dc9e"}, + {file = "regex-2024.5.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab98016541543692a37905871a5ffca59b16e08aacc3d7d10a27297b443f572d"}, + {file = "regex-2024.5.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:51d27844763c273a122e08a3e86e7aefa54ee09fb672d96a645ece0454d8425e"}, + {file = "regex-2024.5.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:853cc36e756ff673bf984e9044ccc8fad60b95a748915dddeab9488aea974c73"}, + {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4e7eaf9df15423d07b6050fb91f86c66307171b95ea53e2d87a7993b6d02c7f7"}, + {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:169fd0acd7a259f58f417e492e93d0e15fc87592cd1e971c8c533ad5703b5830"}, + {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:334b79ce9c08f26b4659a53f42892793948a613c46f1b583e985fd5a6bf1c149"}, + {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:f03b1dbd4d9596dd84955bb40f7d885204d6aac0d56a919bb1e0ff2fb7e1735a"}, + {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cfa6d61a76c77610ba9274c1a90a453062bdf6887858afbe214d18ad41cf6bde"}, + {file = "regex-2024.5.10-cp39-cp39-win32.whl", hash = "sha256:249fbcee0a277c32a3ce36d8e36d50c27c968fdf969e0fbe342658d4e010fbc8"}, + {file = "regex-2024.5.10-cp39-cp39-win_amd64.whl", hash = "sha256:0ce56a923f4c01d7568811bfdffe156268c0a7aae8a94c902b92fe34c4bde785"}, + {file = "regex-2024.5.10.tar.gz", hash = "sha256:304e7e2418146ae4d0ef0e9ffa28f881f7874b45b4994cc2279b21b6e7ae50c8"}, ] [[package]] @@ -3803,13 +3803,13 @@ tests = ["pytest", "pytest-cov"] [[package]] name = "tifffile" -version = "2024.5.3" +version = "2024.5.10" description = "Read and write TIFF files" optional = true python-versions = ">=3.9" files = [ - {file = "tifffile-2024.5.3-py3-none-any.whl", hash = "sha256:cac4d939156ff7f16d65fd689637808a7b5b3ad58f9c73327fc009b0aa32c7d5"}, - {file = "tifffile-2024.5.3.tar.gz", hash = "sha256:44521508ecc51ebaf0e47e9748913e9c7331a4e32fb571ff4dfc05cb8f4d8896"}, + {file = "tifffile-2024.5.10-py3-none-any.whl", hash = "sha256:4154f091aa24d4e75bfad9ab2d5424a68c70e67b8220188066dc61946d4551bd"}, + {file = "tifffile-2024.5.10.tar.gz", hash = "sha256:aa1e1b12be952ab20717d6848bd6d4a5ee88d2aa319f1152bff4354ad728ec86"}, ] [package.dependencies] @@ -4348,4 +4348,4 @@ xarm = ["gym-xarm"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.13" -content-hash = "21dd1d7404ac774bd1139e8cda44ea8e3ed97c30e524f2ed862de431d3d5fa87" +content-hash = "2f0d2cbf4a2dec546e25b29b9b108ff1f97b4c278b718360b3f7f6a2bf9dcef8" diff --git a/pyproject.toml b/pyproject.toml index 56c84416..24d9452d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,7 +54,7 @@ pre-commit = {version = ">=3.7.0", optional = true} debugpy = {version = ">=1.8.1", optional = true} pytest = {version = ">=8.1.0", optional = true} pytest-cov = {version = ">=5.0.0", optional = true} -datasets = ">=2.19.0" +datasets = "^2.19.0" imagecodecs = { version = ">=2024.1.1", optional = true } pyav = ">=12.0.5" moviepy = ">=1.0.3" From f52f4f2cd2975686f8f8037d8396544712231475 Mon Sep 17 00:00:00 2001 From: Simon Alibert <75076266+aliberts@users.noreply.github.com> Date: Wed, 15 May 2024 12:13:09 +0200 Subject: [PATCH 20/27] Add copyrights (#157) --- lerobot/__init__.py | 15 +++++++++++++++ lerobot/__version__.py | 15 +++++++++++++++ .../_video_benchmark/run_video_benchmark.py | 15 +++++++++++++++ lerobot/common/datasets/factory.py | 15 +++++++++++++++ lerobot/common/datasets/lerobot_dataset.py | 15 +++++++++++++++ .../_diffusion_policy_replay_buffer.py | 15 +++++++++++++++ .../push_dataset_to_hub/_download_raw.py | 15 +++++++++++++++ .../_umi_imagecodecs_numcodecs.py | 15 +++++++++++++++ .../push_dataset_to_hub/aloha_hdf5_format.py | 15 +++++++++++++++ .../push_dataset_to_hub/compute_stats.py | 15 +++++++++++++++ .../push_dataset_to_hub/pusht_zarr_format.py | 15 +++++++++++++++ .../push_dataset_to_hub/umi_zarr_format.py | 15 +++++++++++++++ .../common/datasets/push_dataset_to_hub/utils.py | 15 +++++++++++++++ .../push_dataset_to_hub/xarm_pkl_format.py | 15 +++++++++++++++ lerobot/common/datasets/utils.py | 15 +++++++++++++++ lerobot/common/datasets/video_utils.py | 15 +++++++++++++++ lerobot/common/envs/factory.py | 15 +++++++++++++++ lerobot/common/envs/utils.py | 15 +++++++++++++++ lerobot/common/logger.py | 15 +++++++++++++++ lerobot/common/policies/act/configuration_act.py | 15 +++++++++++++++ lerobot/common/policies/act/modeling_act.py | 15 +++++++++++++++ .../diffusion/configuration_diffusion.py | 16 ++++++++++++++++ .../policies/diffusion/modeling_diffusion.py | 16 ++++++++++++++++ lerobot/common/policies/factory.py | 15 +++++++++++++++ lerobot/common/policies/normalize.py | 15 +++++++++++++++ lerobot/common/policies/policy_protocol.py | 15 +++++++++++++++ .../common/policies/tdmpc/configuration_tdmpc.py | 16 ++++++++++++++++ lerobot/common/policies/tdmpc/modeling_tdmpc.py | 16 ++++++++++++++++ lerobot/common/policies/utils.py | 15 +++++++++++++++ lerobot/common/utils/import_utils.py | 15 +++++++++++++++ lerobot/common/utils/io_utils.py | 15 +++++++++++++++ lerobot/common/utils/utils.py | 15 +++++++++++++++ lerobot/scripts/display_sys_info.py | 15 +++++++++++++++ lerobot/scripts/eval.py | 15 +++++++++++++++ lerobot/scripts/push_dataset_to_hub.py | 15 +++++++++++++++ lerobot/scripts/train.py | 15 +++++++++++++++ lerobot/scripts/visualize_dataset.py | 15 +++++++++++++++ tests/conftest.py | 15 +++++++++++++++ tests/scripts/save_dataset_to_safetensors.py | 15 +++++++++++++++ tests/scripts/save_policy_to_safetensor.py | 15 +++++++++++++++ tests/test_available.py | 15 +++++++++++++++ tests/test_datasets.py | 15 +++++++++++++++ tests/test_envs.py | 15 +++++++++++++++ tests/test_examples.py | 15 +++++++++++++++ tests/test_policies.py | 15 +++++++++++++++ tests/test_visualize_dataset.py | 15 +++++++++++++++ tests/utils.py | 15 +++++++++++++++ 47 files changed, 709 insertions(+) diff --git a/lerobot/__init__.py b/lerobot/__init__.py index 072f4bc7..e188bc52 100644 --- a/lerobot/__init__.py +++ b/lerobot/__init__.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """ This file contains lists of available environments, dataset and policies to reflect the current state of LeRobot library. We do not want to import all the dependencies, but instead we keep it lightweight to ensure fast access to these variables. diff --git a/lerobot/__version__.py b/lerobot/__version__.py index 6232b699..d12aafaa 100644 --- a/lerobot/__version__.py +++ b/lerobot/__version__.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """To enable `lerobot.__version__`""" from importlib.metadata import PackageNotFoundError, version diff --git a/lerobot/common/datasets/_video_benchmark/run_video_benchmark.py b/lerobot/common/datasets/_video_benchmark/run_video_benchmark.py index 85d48fcf..8be251dc 100644 --- a/lerobot/common/datasets/_video_benchmark/run_video_benchmark.py +++ b/lerobot/common/datasets/_video_benchmark/run_video_benchmark.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import json import random import shutil diff --git a/lerobot/common/datasets/factory.py b/lerobot/common/datasets/factory.py index 22dd1789..78967db6 100644 --- a/lerobot/common/datasets/factory.py +++ b/lerobot/common/datasets/factory.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import logging import torch diff --git a/lerobot/common/datasets/lerobot_dataset.py b/lerobot/common/datasets/lerobot_dataset.py index f7bc5bd2..21d09879 100644 --- a/lerobot/common/datasets/lerobot_dataset.py +++ b/lerobot/common/datasets/lerobot_dataset.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import os from pathlib import Path diff --git a/lerobot/common/datasets/push_dataset_to_hub/_diffusion_policy_replay_buffer.py b/lerobot/common/datasets/push_dataset_to_hub/_diffusion_policy_replay_buffer.py index 2f532650..33b4c974 100644 --- a/lerobot/common/datasets/push_dataset_to_hub/_diffusion_policy_replay_buffer.py +++ b/lerobot/common/datasets/push_dataset_to_hub/_diffusion_policy_replay_buffer.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """Helper code for loading PushT dataset from Diffusion Policy (https://diffusion-policy.cs.columbia.edu/) Copied from the original Diffusion Policy repository and used in our `download_and_upload_dataset.py` script. diff --git a/lerobot/common/datasets/push_dataset_to_hub/_download_raw.py b/lerobot/common/datasets/push_dataset_to_hub/_download_raw.py index d26f3d23..232fd055 100644 --- a/lerobot/common/datasets/push_dataset_to_hub/_download_raw.py +++ b/lerobot/common/datasets/push_dataset_to_hub/_download_raw.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """ This file contains all obsolete download scripts. They are centralized here to not have to load useless dependencies when using datasets. diff --git a/lerobot/common/datasets/push_dataset_to_hub/_umi_imagecodecs_numcodecs.py b/lerobot/common/datasets/push_dataset_to_hub/_umi_imagecodecs_numcodecs.py index 1561fb88..a118b7e7 100644 --- a/lerobot/common/datasets/push_dataset_to_hub/_umi_imagecodecs_numcodecs.py +++ b/lerobot/common/datasets/push_dataset_to_hub/_umi_imagecodecs_numcodecs.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # imagecodecs/numcodecs.py # Copyright (c) 2021-2022, Christoph Gohlke diff --git a/lerobot/common/datasets/push_dataset_to_hub/aloha_hdf5_format.py b/lerobot/common/datasets/push_dataset_to_hub/aloha_hdf5_format.py index f51a59cd..4efadc9e 100644 --- a/lerobot/common/datasets/push_dataset_to_hub/aloha_hdf5_format.py +++ b/lerobot/common/datasets/push_dataset_to_hub/aloha_hdf5_format.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """ Contains utilities to process raw data format of HDF5 files like in: https://github.com/tonyzhaozh/act """ diff --git a/lerobot/common/datasets/push_dataset_to_hub/compute_stats.py b/lerobot/common/datasets/push_dataset_to_hub/compute_stats.py index a7a952fb..ec296658 100644 --- a/lerobot/common/datasets/push_dataset_to_hub/compute_stats.py +++ b/lerobot/common/datasets/push_dataset_to_hub/compute_stats.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from copy import deepcopy from math import ceil diff --git a/lerobot/common/datasets/push_dataset_to_hub/pusht_zarr_format.py b/lerobot/common/datasets/push_dataset_to_hub/pusht_zarr_format.py index 0c3a8d19..8133a36a 100644 --- a/lerobot/common/datasets/push_dataset_to_hub/pusht_zarr_format.py +++ b/lerobot/common/datasets/push_dataset_to_hub/pusht_zarr_format.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """Process zarr files formatted like in: https://github.com/real-stanford/diffusion_policy""" import shutil diff --git a/lerobot/common/datasets/push_dataset_to_hub/umi_zarr_format.py b/lerobot/common/datasets/push_dataset_to_hub/umi_zarr_format.py index 00828750..cab2bdc5 100644 --- a/lerobot/common/datasets/push_dataset_to_hub/umi_zarr_format.py +++ b/lerobot/common/datasets/push_dataset_to_hub/umi_zarr_format.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """Process UMI (Universal Manipulation Interface) data stored in Zarr format like in: https://github.com/real-stanford/universal_manipulation_interface""" import logging diff --git a/lerobot/common/datasets/push_dataset_to_hub/utils.py b/lerobot/common/datasets/push_dataset_to_hub/utils.py index 1b12c0b7..4feb1dcf 100644 --- a/lerobot/common/datasets/push_dataset_to_hub/utils.py +++ b/lerobot/common/datasets/push_dataset_to_hub/utils.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from concurrent.futures import ThreadPoolExecutor from pathlib import Path diff --git a/lerobot/common/datasets/push_dataset_to_hub/xarm_pkl_format.py b/lerobot/common/datasets/push_dataset_to_hub/xarm_pkl_format.py index 686edf4c..899ebdde 100644 --- a/lerobot/common/datasets/push_dataset_to_hub/xarm_pkl_format.py +++ b/lerobot/common/datasets/push_dataset_to_hub/xarm_pkl_format.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """Process pickle files formatted like in: https://github.com/fyhMer/fowm""" import pickle diff --git a/lerobot/common/datasets/utils.py b/lerobot/common/datasets/utils.py index 96b8fbbc..5cdd5f7c 100644 --- a/lerobot/common/datasets/utils.py +++ b/lerobot/common/datasets/utils.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import json from pathlib import Path diff --git a/lerobot/common/datasets/video_utils.py b/lerobot/common/datasets/video_utils.py index 0252be2e..edfca918 100644 --- a/lerobot/common/datasets/video_utils.py +++ b/lerobot/common/datasets/video_utils.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import logging import subprocess import warnings diff --git a/lerobot/common/envs/factory.py b/lerobot/common/envs/factory.py index c5fd4671..83f94cfe 100644 --- a/lerobot/common/envs/factory.py +++ b/lerobot/common/envs/factory.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import importlib import gymnasium as gym diff --git a/lerobot/common/envs/utils.py b/lerobot/common/envs/utils.py index 5370d385..8fce0369 100644 --- a/lerobot/common/envs/utils.py +++ b/lerobot/common/envs/utils.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import einops import numpy as np import torch diff --git a/lerobot/common/logger.py b/lerobot/common/logger.py index ea8db050..109f6951 100644 --- a/lerobot/common/logger.py +++ b/lerobot/common/logger.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # TODO(rcadene, alexander-soare): clean this file """Borrowed from https://github.com/fyhMer/fowm/blob/main/src/logger.py""" diff --git a/lerobot/common/policies/act/configuration_act.py b/lerobot/common/policies/act/configuration_act.py index a3980b14..95f443da 100644 --- a/lerobot/common/policies/act/configuration_act.py +++ b/lerobot/common/policies/act/configuration_act.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 Tony Z. Zhao and The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from dataclasses import dataclass, field diff --git a/lerobot/common/policies/act/modeling_act.py b/lerobot/common/policies/act/modeling_act.py index a795d87b..e85a3736 100644 --- a/lerobot/common/policies/act/modeling_act.py +++ b/lerobot/common/policies/act/modeling_act.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 Tony Z. Zhao and The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """Action Chunking Transformer Policy As per Learning Fine-Grained Bimanual Manipulation with Low-Cost Hardware (https://arxiv.org/abs/2304.13705). diff --git a/lerobot/common/policies/diffusion/configuration_diffusion.py b/lerobot/common/policies/diffusion/configuration_diffusion.py index 28a514ab..d0554942 100644 --- a/lerobot/common/policies/diffusion/configuration_diffusion.py +++ b/lerobot/common/policies/diffusion/configuration_diffusion.py @@ -1,3 +1,19 @@ +#!/usr/bin/env python + +# Copyright 2024 Columbia Artificial Intelligence, Robotics Lab, +# and The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from dataclasses import dataclass, field diff --git a/lerobot/common/policies/diffusion/modeling_diffusion.py b/lerobot/common/policies/diffusion/modeling_diffusion.py index 3115160f..c67040b6 100644 --- a/lerobot/common/policies/diffusion/modeling_diffusion.py +++ b/lerobot/common/policies/diffusion/modeling_diffusion.py @@ -1,3 +1,19 @@ +#!/usr/bin/env python + +# Copyright 2024 Columbia Artificial Intelligence, Robotics Lab, +# and The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """Diffusion Policy as per "Diffusion Policy: Visuomotor Policy Learning via Action Diffusion" TODO(alexander-soare): diff --git a/lerobot/common/policies/factory.py b/lerobot/common/policies/factory.py index a819d18f..4c124b61 100644 --- a/lerobot/common/policies/factory.py +++ b/lerobot/common/policies/factory.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import inspect import logging diff --git a/lerobot/common/policies/normalize.py b/lerobot/common/policies/normalize.py index ab57c8ba..d638c541 100644 --- a/lerobot/common/policies/normalize.py +++ b/lerobot/common/policies/normalize.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import torch from torch import Tensor, nn diff --git a/lerobot/common/policies/policy_protocol.py b/lerobot/common/policies/policy_protocol.py index b00cff5c..38738a90 100644 --- a/lerobot/common/policies/policy_protocol.py +++ b/lerobot/common/policies/policy_protocol.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """A protocol that all policies should follow. This provides a mechanism for type-hinting and isinstance checks without requiring the policies classes diff --git a/lerobot/common/policies/tdmpc/configuration_tdmpc.py b/lerobot/common/policies/tdmpc/configuration_tdmpc.py index 00d00913..ddf52248 100644 --- a/lerobot/common/policies/tdmpc/configuration_tdmpc.py +++ b/lerobot/common/policies/tdmpc/configuration_tdmpc.py @@ -1,3 +1,19 @@ +#!/usr/bin/env python + +# Copyright 2024 Nicklas Hansen, Xiaolong Wang, Hao Su, +# and The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from dataclasses import dataclass, field diff --git a/lerobot/common/policies/tdmpc/modeling_tdmpc.py b/lerobot/common/policies/tdmpc/modeling_tdmpc.py index 1fba43d0..70e78c98 100644 --- a/lerobot/common/policies/tdmpc/modeling_tdmpc.py +++ b/lerobot/common/policies/tdmpc/modeling_tdmpc.py @@ -1,3 +1,19 @@ +#!/usr/bin/env python + +# Copyright 2024 Nicklas Hansen, Xiaolong Wang, Hao Su, +# and The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """Implementation of Finetuning Offline World Models in the Real World. The comments in this code may sometimes refer to these references: diff --git a/lerobot/common/policies/utils.py b/lerobot/common/policies/utils.py index b23c1336..8f7b6eec 100644 --- a/lerobot/common/policies/utils.py +++ b/lerobot/common/policies/utils.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import torch from torch import nn diff --git a/lerobot/common/utils/import_utils.py b/lerobot/common/utils/import_utils.py index 642e0ff1..cd5f8245 100644 --- a/lerobot/common/utils/import_utils.py +++ b/lerobot/common/utils/import_utils.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import importlib import logging diff --git a/lerobot/common/utils/io_utils.py b/lerobot/common/utils/io_utils.py index 5d727bd7..b85f17c7 100644 --- a/lerobot/common/utils/io_utils.py +++ b/lerobot/common/utils/io_utils.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import warnings import imageio diff --git a/lerobot/common/utils/utils.py b/lerobot/common/utils/utils.py index 8fe621f4..d62507b5 100644 --- a/lerobot/common/utils/utils.py +++ b/lerobot/common/utils/utils.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import logging import os.path as osp import random diff --git a/lerobot/scripts/display_sys_info.py b/lerobot/scripts/display_sys_info.py index e4ea4260..4d8b4850 100644 --- a/lerobot/scripts/display_sys_info.py +++ b/lerobot/scripts/display_sys_info.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import platform import huggingface_hub diff --git a/lerobot/scripts/eval.py b/lerobot/scripts/eval.py index e4a9bfef..9c95633a 100644 --- a/lerobot/scripts/eval.py +++ b/lerobot/scripts/eval.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """Evaluate a policy on an environment by running rollouts and computing metrics. Usage examples: diff --git a/lerobot/scripts/push_dataset_to_hub.py b/lerobot/scripts/push_dataset_to_hub.py index dfac410b..16d890a7 100644 --- a/lerobot/scripts/push_dataset_to_hub.py +++ b/lerobot/scripts/push_dataset_to_hub.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """ Use this script to convert your dataset into LeRobot dataset format and upload it to the Hugging Face hub, or store it locally. LeRobot dataset format is lightweight, fast to load from, and does not require any diff --git a/lerobot/scripts/train.py b/lerobot/scripts/train.py index 7319e03f..ab07695b 100644 --- a/lerobot/scripts/train.py +++ b/lerobot/scripts/train.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import logging import time from copy import deepcopy diff --git a/lerobot/scripts/visualize_dataset.py b/lerobot/scripts/visualize_dataset.py index d4fafe67..58da6a47 100644 --- a/lerobot/scripts/visualize_dataset.py +++ b/lerobot/scripts/visualize_dataset.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """ Visualize data of **all** frames of any episode of a dataset of type LeRobotDataset. Note: The last frame of the episode doesnt always correspond to a final state. diff --git a/tests/conftest.py b/tests/conftest.py index 856ca455..62f831aa 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from .utils import DEVICE diff --git a/tests/scripts/save_dataset_to_safetensors.py b/tests/scripts/save_dataset_to_safetensors.py index 17cf2b38..554efe75 100644 --- a/tests/scripts/save_dataset_to_safetensors.py +++ b/tests/scripts/save_dataset_to_safetensors.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """ This script provides a utility for saving a dataset as safetensors files for the purpose of testing backward compatibility when updating the data format. It uses the `PushtDataset` to create a DataLoader and saves selected frame from the diff --git a/tests/scripts/save_policy_to_safetensor.py b/tests/scripts/save_policy_to_safetensor.py index 29e9a34f..e79a94ff 100644 --- a/tests/scripts/save_policy_to_safetensor.py +++ b/tests/scripts/save_policy_to_safetensor.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import shutil from pathlib import Path diff --git a/tests/test_available.py b/tests/test_available.py index ead9296a..db5bd520 100644 --- a/tests/test_available.py +++ b/tests/test_available.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import importlib import gymnasium as gym diff --git a/tests/test_datasets.py b/tests/test_datasets.py index 1d93d48f..afea16a5 100644 --- a/tests/test_datasets.py +++ b/tests/test_datasets.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import json import logging from copy import deepcopy diff --git a/tests/test_envs.py b/tests/test_envs.py index f172a645..aec9999d 100644 --- a/tests/test_envs.py +++ b/tests/test_envs.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import importlib import gymnasium as gym diff --git a/tests/test_examples.py b/tests/test_examples.py index 543eb022..de95a991 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # TODO(aliberts): Mute logging for these tests import subprocess import sys diff --git a/tests/test_policies.py b/tests/test_policies.py index f0fa7c56..c8457854 100644 --- a/tests/test_policies.py +++ b/tests/test_policies.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import inspect from pathlib import Path diff --git a/tests/test_visualize_dataset.py b/tests/test_visualize_dataset.py index 0124afd3..99954040 100644 --- a/tests/test_visualize_dataset.py +++ b/tests/test_visualize_dataset.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import pytest from lerobot.scripts.visualize_dataset import visualize_dataset diff --git a/tests/utils.py b/tests/utils.py index 74e3ba8f..ba49ee70 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,3 +1,18 @@ +#!/usr/bin/env python + +# Copyright 2024 The HuggingFace Inc. team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import platform from functools import wraps From 68c1b13406068b9d88afbfcb2366f927141514f3 Mon Sep 17 00:00:00 2001 From: Alexander Soare Date: Thu, 16 May 2024 13:51:53 +0100 Subject: [PATCH 21/27] Make policies compatible with other/multiple image keys (#149) --- .../common/policies/act/configuration_act.py | 7 --- lerobot/common/policies/act/modeling_act.py | 46 +++++++------------ .../diffusion/configuration_diffusion.py | 17 +++++-- .../policies/diffusion/modeling_diffusion.py | 34 +++++++++----- .../policies/tdmpc/configuration_tdmpc.py | 12 +++-- .../common/policies/tdmpc/modeling_tdmpc.py | 20 ++++---- lerobot/common/policies/utils.py | 4 ++ lerobot/scripts/train.py | 3 +- tests/test_policies.py | 33 +++++++++++++ 9 files changed, 107 insertions(+), 69 deletions(-) diff --git a/lerobot/common/policies/act/configuration_act.py b/lerobot/common/policies/act/configuration_act.py index 95f443da..be444b06 100644 --- a/lerobot/common/policies/act/configuration_act.py +++ b/lerobot/common/policies/act/configuration_act.py @@ -145,10 +145,3 @@ class ACTConfig: raise ValueError( f"Multiple observation steps not handled yet. Got `nobs_steps={self.n_obs_steps}`" ) - # Check that there is only one image. - # TODO(alexander-soare): generalize this to multiple images. - if ( - sum(k.startswith("observation.images.") for k in self.input_shapes) != 1 - or "observation.images.top" not in self.input_shapes - ): - raise ValueError('For now, only "observation.images.top" is accepted for an image input.') diff --git a/lerobot/common/policies/act/modeling_act.py b/lerobot/common/policies/act/modeling_act.py index e85a3736..4a8df1ce 100644 --- a/lerobot/common/policies/act/modeling_act.py +++ b/lerobot/common/policies/act/modeling_act.py @@ -62,6 +62,7 @@ class ACTPolicy(nn.Module, PyTorchModelHubMixin): if config is None: config = ACTConfig() self.config = config + self.normalize_inputs = Normalize( config.input_shapes, config.input_normalization_modes, dataset_stats ) @@ -71,8 +72,13 @@ class ACTPolicy(nn.Module, PyTorchModelHubMixin): self.unnormalize_outputs = Unnormalize( config.output_shapes, config.output_normalization_modes, dataset_stats ) + self.model = ACT(config) + self.expected_image_keys = [k for k in config.input_shapes if k.startswith("observation.image")] + + self.reset() + def reset(self): """This should be called whenever the environment is reset.""" if self.config.n_action_steps is not None: @@ -86,13 +92,10 @@ class ACTPolicy(nn.Module, PyTorchModelHubMixin): environment. It works by managing the actions in a queue and only calling `select_actions` when the queue is empty. """ - assert "observation.images.top" in batch - assert "observation.state" in batch - self.eval() batch = self.normalize_inputs(batch) - self._stack_images(batch) + batch["observation.images"] = torch.stack([batch[k] for k in self.expected_image_keys], dim=-4) if len(self._action_queue) == 0: # `self.model.forward` returns a (batch_size, n_action_steps, action_dim) tensor, but the queue @@ -108,8 +111,8 @@ class ACTPolicy(nn.Module, PyTorchModelHubMixin): def forward(self, batch: dict[str, Tensor]) -> dict[str, Tensor]: """Run the batch through the model and compute the loss for training or validation.""" batch = self.normalize_inputs(batch) + batch["observation.images"] = torch.stack([batch[k] for k in self.expected_image_keys], dim=-4) batch = self.normalize_targets(batch) - self._stack_images(batch) actions_hat, (mu_hat, log_sigma_x2_hat) = self.model(batch) l1_loss = ( @@ -132,21 +135,6 @@ class ACTPolicy(nn.Module, PyTorchModelHubMixin): return loss_dict - def _stack_images(self, batch: dict[str, Tensor]) -> dict[str, Tensor]: - """Stacks all the images in a batch and puts them in a new key: "observation.images". - - This function expects `batch` to have (at least): - { - "observation.state": (B, state_dim) batch of robot states. - "observation.images.{name}": (B, C, H, W) tensor of images. - } - """ - # Stack images in the order dictated by input_shapes. - batch["observation.images"] = torch.stack( - [batch[k] for k in self.config.input_shapes if k.startswith("observation.images.")], - dim=-4, - ) - class ACT(nn.Module): """Action Chunking Transformer: The underlying neural network for ACTPolicy. @@ -176,10 +164,10 @@ class ACT(nn.Module): โ”‚ encoder โ”‚ โ”‚ โ”‚ โ”‚Transf.โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚encoderโ”‚ โ”‚ โ””โ”€โ”€โ”€โ–ฒโ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ - โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ–ฒโ”€โ”€โ”€โ”˜ โ”‚ - โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ - inputs โ””โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ - โ”‚ โ”‚ + โ”‚ โ”‚ โ”‚ โ””โ–ฒโ”€โ”€โ–ฒโ”€โ–ฒโ”€โ”˜ โ”‚ + โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ + inputs โ””โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”˜ โ”‚ image emb. โ”‚ + โ”‚ state emb. โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ """ @@ -321,18 +309,18 @@ class ACT(nn.Module): all_cam_features.append(cam_features) all_cam_pos_embeds.append(cam_pos_embed) # Concatenate camera observation feature maps and positional embeddings along the width dimension. - encoder_in = torch.cat(all_cam_features, axis=3) - cam_pos_embed = torch.cat(all_cam_pos_embeds, axis=3) + encoder_in = torch.cat(all_cam_features, axis=-1) + cam_pos_embed = torch.cat(all_cam_pos_embeds, axis=-1) # Get positional embeddings for robot state and latent. - robot_state_embed = self.encoder_robot_state_input_proj(batch["observation.state"]) - latent_embed = self.encoder_latent_input_proj(latent_sample) + robot_state_embed = self.encoder_robot_state_input_proj(batch["observation.state"]) # (B, C) + latent_embed = self.encoder_latent_input_proj(latent_sample) # (B, C) # Stack encoder input and positional embeddings moving to (S, B, C). encoder_in = torch.cat( [ torch.stack([latent_embed, robot_state_embed], axis=0), - encoder_in.flatten(2).permute(2, 0, 1), + einops.rearrange(encoder_in, "b c h w -> (h w) b c"), ] ) pos_embed = torch.cat( diff --git a/lerobot/common/policies/diffusion/configuration_diffusion.py b/lerobot/common/policies/diffusion/configuration_diffusion.py index d0554942..632f6cd6 100644 --- a/lerobot/common/policies/diffusion/configuration_diffusion.py +++ b/lerobot/common/policies/diffusion/configuration_diffusion.py @@ -148,14 +148,21 @@ class DiffusionConfig: raise ValueError( f"`vision_backbone` must be one of the ResNet variants. Got {self.vision_backbone}." ) + # There should only be one image key. + image_keys = {k for k in self.input_shapes if k.startswith("observation.image")} + if len(image_keys) != 1: + raise ValueError( + f"{self.__class__.__name__} only handles one image for now. Got image keys {image_keys}." + ) + image_key = next(iter(image_keys)) if ( - self.crop_shape[0] > self.input_shapes["observation.image"][1] - or self.crop_shape[1] > self.input_shapes["observation.image"][2] + self.crop_shape[0] > self.input_shapes[image_key][1] + or self.crop_shape[1] > self.input_shapes[image_key][2] ): raise ValueError( - f'`crop_shape` should fit within `input_shapes["observation.image"]`. Got {self.crop_shape} ' - f'for `crop_shape` and {self.input_shapes["observation.image"]} for ' - '`input_shapes["observation.image"]`.' + f"`crop_shape` should fit within `input_shapes[{image_key}]`. Got {self.crop_shape} " + f"for `crop_shape` and {self.input_shapes[image_key]} for " + "`input_shapes[{image_key}]`." ) supported_prediction_types = ["epsilon", "sample"] if self.prediction_type not in supported_prediction_types: diff --git a/lerobot/common/policies/diffusion/modeling_diffusion.py b/lerobot/common/policies/diffusion/modeling_diffusion.py index c67040b6..1659b68e 100644 --- a/lerobot/common/policies/diffusion/modeling_diffusion.py +++ b/lerobot/common/policies/diffusion/modeling_diffusion.py @@ -19,6 +19,7 @@ TODO(alexander-soare): - Remove reliance on Robomimic for SpatialSoftmax. - Remove reliance on diffusers for DDPMScheduler and LR scheduler. + - Make compatible with multiple image keys. """ import math @@ -83,10 +84,18 @@ class DiffusionPolicy(nn.Module, PyTorchModelHubMixin): self.diffusion = DiffusionModel(config) + image_keys = [k for k in config.input_shapes if k.startswith("observation.image")] + # Note: This check is covered in the post-init of the config but have a sanity check just in case. + if len(image_keys) != 1: + raise NotImplementedError( + f"{self.__class__.__name__} only handles one image for now. Got image keys {image_keys}." + ) + self.input_image_key = image_keys[0] + + self.reset() + def reset(self): - """ - Clear observation and action queues. Should be called on `env.reset()` - """ + """Clear observation and action queues. Should be called on `env.reset()`""" self._queues = { "observation.image": deque(maxlen=self.config.n_obs_steps), "observation.state": deque(maxlen=self.config.n_obs_steps), @@ -115,16 +124,14 @@ class DiffusionPolicy(nn.Module, PyTorchModelHubMixin): "horizon" may not the best name to describe what the variable actually means, because this period is actually measured from the first observation which (if `n_obs_steps` > 1) happened in the past. """ - assert "observation.image" in batch - assert "observation.state" in batch - batch = self.normalize_inputs(batch) + batch["observation.image"] = batch[self.input_image_key] self._queues = populate_queues(self._queues, batch) if len(self._queues["action"]) == 0: # stack n latest observations from the queue - batch = {key: torch.stack(list(self._queues[key]), dim=1) for key in batch} + batch = {k: torch.stack(list(self._queues[k]), dim=1) for k in batch if k in self._queues} actions = self.diffusion.generate_actions(batch) # TODO(rcadene): make above methods return output dictionary? @@ -138,6 +145,7 @@ class DiffusionPolicy(nn.Module, PyTorchModelHubMixin): def forward(self, batch: dict[str, Tensor]) -> dict[str, Tensor]: """Run the batch through the model and compute the loss for training or validation.""" batch = self.normalize_inputs(batch) + batch["observation.image"] = batch[self.input_image_key] batch = self.normalize_targets(batch) loss = self.diffusion.compute_loss(batch) return {"loss": loss} @@ -215,13 +223,12 @@ class DiffusionModel(nn.Module): def generate_actions(self, batch: dict[str, Tensor]) -> Tensor: """ - This function expects `batch` to have (at least): + This function expects `batch` to have: { "observation.state": (B, n_obs_steps, state_dim) "observation.image": (B, n_obs_steps, C, H, W) } """ - assert set(batch).issuperset({"observation.state", "observation.image"}) batch_size, n_obs_steps = batch["observation.state"].shape[:2] assert n_obs_steps == self.config.n_obs_steps @@ -345,9 +352,12 @@ class DiffusionRgbEncoder(nn.Module): # Set up pooling and final layers. # Use a dry run to get the feature map shape. - # The dummy input should take the number of image channels from `config.input_shapes` and it should use the - # height and width from `config.crop_shape`. - dummy_input = torch.zeros(size=(1, config.input_shapes["observation.image"][0], *config.crop_shape)) + # The dummy input should take the number of image channels from `config.input_shapes` and it should + # use the height and width from `config.crop_shape`. + image_keys = [k for k in config.input_shapes if k.startswith("observation.image")] + assert len(image_keys) == 1 + image_key = image_keys[0] + dummy_input = torch.zeros(size=(1, config.input_shapes[image_key][0], *config.crop_shape)) with torch.inference_mode(): dummy_feature_map = self.backbone(dummy_input) feature_map_shape = tuple(dummy_feature_map.shape[1:]) diff --git a/lerobot/common/policies/tdmpc/configuration_tdmpc.py b/lerobot/common/policies/tdmpc/configuration_tdmpc.py index ddf52248..cf76fb08 100644 --- a/lerobot/common/policies/tdmpc/configuration_tdmpc.py +++ b/lerobot/common/policies/tdmpc/configuration_tdmpc.py @@ -147,12 +147,18 @@ class TDMPCConfig: def __post_init__(self): """Input validation (not exhaustive).""" - if self.input_shapes["observation.image"][-2] != self.input_shapes["observation.image"][-1]: + # There should only be one image key. + image_keys = {k for k in self.input_shapes if k.startswith("observation.image")} + if len(image_keys) != 1: + raise ValueError( + f"{self.__class__.__name__} only handles one image for now. Got image keys {image_keys}." + ) + image_key = next(iter(image_keys)) + if self.input_shapes[image_key][-2] != self.input_shapes[image_key][-1]: # TODO(alexander-soare): This limitation is solely because of code in the random shift # augmentation. It should be able to be removed. raise ValueError( - "Only square images are handled now. Got image shape " - f"{self.input_shapes['observation.image']}." + f"Only square images are handled now. Got image shape {self.input_shapes[image_key]}." ) if self.n_gaussian_samples <= 0: raise ValueError( diff --git a/lerobot/common/policies/tdmpc/modeling_tdmpc.py b/lerobot/common/policies/tdmpc/modeling_tdmpc.py index 70e78c98..7c873bf2 100644 --- a/lerobot/common/policies/tdmpc/modeling_tdmpc.py +++ b/lerobot/common/policies/tdmpc/modeling_tdmpc.py @@ -112,13 +112,12 @@ class TDMPCPolicy(nn.Module, PyTorchModelHubMixin): config.output_shapes, config.output_normalization_modes, dataset_stats ) - def save(self, fp): - """Save state dict of TOLD model to filepath.""" - torch.save(self.state_dict(), fp) + image_keys = [k for k in config.input_shapes if k.startswith("observation.image")] + # Note: This check is covered in the post-init of the config but have a sanity check just in case. + assert len(image_keys) == 1 + self.input_image_key = image_keys[0] - def load(self, fp): - """Load a saved state dict from filepath into current agent.""" - self.load_state_dict(torch.load(fp)) + self.reset() def reset(self): """ @@ -137,10 +136,8 @@ class TDMPCPolicy(nn.Module, PyTorchModelHubMixin): @torch.no_grad() def select_action(self, batch: dict[str, Tensor]): """Select a single action given environment observations.""" - assert "observation.image" in batch - assert "observation.state" in batch - batch = self.normalize_inputs(batch) + batch["observation.image"] = batch[self.input_image_key] self._queues = populate_queues(self._queues, batch) @@ -319,13 +316,11 @@ class TDMPCPolicy(nn.Module, PyTorchModelHubMixin): device = get_device_from_parameters(self) batch = self.normalize_inputs(batch) + batch["observation.image"] = batch[self.input_image_key] batch = self.normalize_targets(batch) info = {} - # TODO(alexander-soare): Refactor TDMPC and make it comply with the policy interface documentation. - batch_size = batch["index"].shape[0] - # (b, t) -> (t, b) for key in batch: if batch[key].ndim > 1: @@ -353,6 +348,7 @@ class TDMPCPolicy(nn.Module, PyTorchModelHubMixin): # Run latent rollout using the latent dynamics model and policy model. # Note this has shape `horizon+1` because there are `horizon` actions and a current `z`. Each action # gives us a next `z`. + batch_size = batch["index"].shape[0] z_preds = torch.empty(horizon + 1, batch_size, self.config.latent_dim, device=device) z_preds[0] = self.model.encode(current_observation) reward_preds = torch.empty_like(reward, device=device) diff --git a/lerobot/common/policies/utils.py b/lerobot/common/policies/utils.py index 8f7b6eec..5a62daa2 100644 --- a/lerobot/common/policies/utils.py +++ b/lerobot/common/policies/utils.py @@ -19,6 +19,10 @@ from torch import nn def populate_queues(queues, batch): for key in batch: + # Ignore keys not in the queues already (leaving the responsibility to the caller to make sure the + # queues have the keys they want). + if key not in queues: + continue if len(queues[key]) != queues[key].maxlen: # initialize by copying the first observation several times until the queue is full while len(queues[key]) != queues[key].maxlen: diff --git a/lerobot/scripts/train.py b/lerobot/scripts/train.py index ab07695b..7ca7a0b3 100644 --- a/lerobot/scripts/train.py +++ b/lerobot/scripts/train.py @@ -23,6 +23,7 @@ import hydra import torch from datasets import concatenate_datasets from datasets.utils import disable_progress_bars, enable_progress_bars +from omegaconf import DictConfig from lerobot.common.datasets.factory import make_dataset from lerobot.common.datasets.utils import cycle @@ -307,7 +308,7 @@ def add_episodes_inplace( sampler.num_samples = len(concat_dataset) -def train(cfg: dict, out_dir=None, job_name=None): +def train(cfg: DictConfig, out_dir: str | None = None, job_name: str | None = None): if out_dir is None: raise NotImplementedError() if job_name is None: diff --git a/tests/test_policies.py b/tests/test_policies.py index c8457854..75633fe6 100644 --- a/tests/test_policies.py +++ b/tests/test_policies.py @@ -64,6 +64,14 @@ def test_get_policy_and_config_classes(policy_name: str): "act", ["env.task=AlohaTransferCube-v0", "dataset_repo_id=lerobot/aloha_sim_transfer_cube_scripted"], ), + # Note: these parameters also need custom logic in the test function for overriding the Hydra config. + ( + "aloha", + "diffusion", + ["env.task=AlohaInsertion-v0", "dataset_repo_id=lerobot/aloha_sim_insertion_human"], + ), + # Note: these parameters also need custom logic in the test function for overriding the Hydra config. + ("pusht", "act", ["env.task=PushT-v0", "dataset_repo_id=lerobot/pusht"]), ], ) @require_env @@ -87,6 +95,31 @@ def test_policy(env_name, policy_name, extra_overrides): + extra_overrides, ) + # Additional config override logic. + if env_name == "aloha" and policy_name == "diffusion": + for keys in [ + ("training", "delta_timestamps"), + ("policy", "input_shapes"), + ("policy", "input_normalization_modes"), + ]: + dct = dict(cfg[keys[0]][keys[1]]) + dct["observation.images.top"] = dct["observation.image"] + del dct["observation.image"] + cfg[keys[0]][keys[1]] = dct + cfg.override_dataset_stats = None + + # Additional config override logic. + if env_name == "pusht" and policy_name == "act": + for keys in [ + ("policy", "input_shapes"), + ("policy", "input_normalization_modes"), + ]: + dct = dict(cfg[keys[0]][keys[1]]) + dct["observation.image"] = dct["observation.images.top"] + del dct["observation.images.top"] + cfg[keys[0]][keys[1]] = dct + cfg.override_dataset_stats = None + # Check that we can make the policy object. dataset = make_dataset(cfg) policy = make_policy(hydra_cfg=cfg, dataset_stats=dataset.stats) From c9069df9f1e09a98f193eacc7241adead2d10553 Mon Sep 17 00:00:00 2001 From: Akshay Kashyap Date: Thu, 16 May 2024 10:34:10 -0400 Subject: [PATCH 22/27] Port SpatialSoftmax and remove Robomimic dependency (#182) Co-authored-by: Alexander Soare --- .../policies/diffusion/modeling_diffusion.py | 74 +++++++- poetry.lock | 179 +----------------- pyproject.toml | 1 - .../pusht_diffusion/actions.safetensors | Bin 4600 -> 4600 bytes .../pusht_diffusion/grad_stats.safetensors | Bin 47424 -> 47424 bytes .../pusht_diffusion/output_dict.safetensors | Bin 68 -> 68 bytes .../pusht_diffusion/param_stats.safetensors | Bin 49120 -> 49120 bytes 7 files changed, 75 insertions(+), 179 deletions(-) diff --git a/lerobot/common/policies/diffusion/modeling_diffusion.py b/lerobot/common/policies/diffusion/modeling_diffusion.py index 1659b68e..2ae03f22 100644 --- a/lerobot/common/policies/diffusion/modeling_diffusion.py +++ b/lerobot/common/policies/diffusion/modeling_diffusion.py @@ -17,7 +17,6 @@ """Diffusion Policy as per "Diffusion Policy: Visuomotor Policy Learning via Action Diffusion" TODO(alexander-soare): - - Remove reliance on Robomimic for SpatialSoftmax. - Remove reliance on diffusers for DDPMScheduler and LR scheduler. - Make compatible with multiple image keys. """ @@ -27,13 +26,13 @@ from collections import deque from typing import Callable import einops +import numpy as np import torch import torch.nn.functional as F # noqa: N812 import torchvision from diffusers.schedulers.scheduling_ddim import DDIMScheduler from diffusers.schedulers.scheduling_ddpm import DDPMScheduler from huggingface_hub import PyTorchModelHubMixin -from robomimic.models.base_nets import SpatialSoftmax from torch import Tensor, nn from lerobot.common.policies.diffusion.configuration_diffusion import DiffusionConfig @@ -312,6 +311,77 @@ class DiffusionModel(nn.Module): return loss.mean() +class SpatialSoftmax(nn.Module): + """ + Spatial Soft Argmax operation described in "Deep Spatial Autoencoders for Visuomotor Learning" by Finn et al. + (https://arxiv.org/pdf/1509.06113). A minimal port of the robomimic implementation. + + At a high level, this takes 2D feature maps (from a convnet/ViT) and returns the "center of mass" + of activations of each channel, i.e., keypoints in the image space for the policy to focus on. + + Example: take feature maps of size (512x10x12). We generate a grid of normalized coordinates (10x12x2): + ----------------------------------------------------- + | (-1., -1.) | (-0.82, -1.) | ... | (1., -1.) | + | (-1., -0.78) | (-0.82, -0.78) | ... | (1., -0.78) | + | ... | ... | ... | ... | + | (-1., 1.) | (-0.82, 1.) | ... | (1., 1.) | + ----------------------------------------------------- + This is achieved by applying channel-wise softmax over the activations (512x120) and computing the dot + product with the coordinates (120x2) to get expected points of maximal activation (512x2). + + The example above results in 512 keypoints (corresponding to the 512 input channels). We can optionally + provide num_kp != None to control the number of keypoints. This is achieved by a first applying a learnable + linear mapping (in_channels, H, W) -> (num_kp, H, W). + """ + + def __init__(self, input_shape, num_kp=None): + """ + Args: + input_shape (list): (C, H, W) input feature map shape. + num_kp (int): number of keypoints in output. If None, output will have the same number of channels as input. + """ + super().__init__() + + assert len(input_shape) == 3 + self._in_c, self._in_h, self._in_w = input_shape + + if num_kp is not None: + self.nets = torch.nn.Conv2d(self._in_c, num_kp, kernel_size=1) + self._out_c = num_kp + else: + self.nets = None + self._out_c = self._in_c + + # we could use torch.linspace directly but that seems to behave slightly differently than numpy + # and causes a small degradation in pc_success of pre-trained models. + pos_x, pos_y = np.meshgrid(np.linspace(-1.0, 1.0, self._in_w), np.linspace(-1.0, 1.0, self._in_h)) + pos_x = torch.from_numpy(pos_x.reshape(self._in_h * self._in_w, 1)).float() + pos_y = torch.from_numpy(pos_y.reshape(self._in_h * self._in_w, 1)).float() + # register as buffer so it's moved to the correct device. + self.register_buffer("pos_grid", torch.cat([pos_x, pos_y], dim=1)) + + def forward(self, features: Tensor) -> Tensor: + """ + Args: + features: (B, C, H, W) input feature maps. + Returns: + (B, K, 2) image-space coordinates of keypoints. + """ + if self.nets is not None: + features = self.nets(features) + + # [B, K, H, W] -> [B * K, H * W] where K is number of keypoints + features = features.reshape(-1, self._in_h * self._in_w) + # 2d softmax normalization + attention = F.softmax(features, dim=-1) + # [B * K, H * W] x [H * W, 2] -> [B * K, 2] for spatial coordinate mean in x and y dimensions + expected_xy = attention @ self.pos_grid + # reshape to [B, K, 2] + feature_keypoints = expected_xy.view(-1, self._out_c, 2) + + return feature_keypoints + + class DiffusionRgbEncoder(nn.Module): """Encoder an RGB image into a 1D feature vector. diff --git a/poetry.lock b/poetry.lock index 388e03f4..e0b27f15 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4,7 +4,7 @@ name = "absl-py" version = "2.1.0" description = "Abseil Python Common Libraries, see https://github.com/abseil/abseil-py." -optional = false +optional = true python-versions = ">=3.7" files = [ {file = "absl-py-2.1.0.tar.gz", hash = "sha256:7820790efbb316739cde8b4e19357243fc3608a152024288513dd968d7d959ff"}, @@ -767,16 +767,6 @@ files = [ [package.dependencies] six = ">=1.4.0" -[[package]] -name = "egl-probe" -version = "1.0.2" -description = "" -optional = false -python-versions = "*" -files = [ - {file = "egl_probe-1.0.2.tar.gz", hash = "sha256:29bdca7b08da1e060cfb42cd46af8300a7ac4f3b1b2eeb16e545ea16d9a5ac93"}, -] - [[package]] name = "einops" version = "0.8.0" @@ -1037,64 +1027,6 @@ files = [ [package.extras] preview = ["glfw-preview"] -[[package]] -name = "grpcio" -version = "1.63.0" -description = "HTTP/2-based RPC framework" -optional = false -python-versions = ">=3.8" -files = [ - {file = "grpcio-1.63.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:2e93aca840c29d4ab5db93f94ed0a0ca899e241f2e8aec6334ab3575dc46125c"}, - {file = "grpcio-1.63.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:91b73d3f1340fefa1e1716c8c1ec9930c676d6b10a3513ab6c26004cb02d8b3f"}, - {file = "grpcio-1.63.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:b3afbd9d6827fa6f475a4f91db55e441113f6d3eb9b7ebb8fb806e5bb6d6bd0d"}, - {file = "grpcio-1.63.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8f3f6883ce54a7a5f47db43289a0a4c776487912de1a0e2cc83fdaec9685cc9f"}, - {file = "grpcio-1.63.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf8dae9cc0412cb86c8de5a8f3be395c5119a370f3ce2e69c8b7d46bb9872c8d"}, - {file = "grpcio-1.63.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:08e1559fd3b3b4468486b26b0af64a3904a8dbc78d8d936af9c1cf9636eb3e8b"}, - {file = "grpcio-1.63.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5c039ef01516039fa39da8a8a43a95b64e288f79f42a17e6c2904a02a319b357"}, - {file = "grpcio-1.63.0-cp310-cp310-win32.whl", hash = "sha256:ad2ac8903b2eae071055a927ef74121ed52d69468e91d9bcbd028bd0e554be6d"}, - {file = "grpcio-1.63.0-cp310-cp310-win_amd64.whl", hash = "sha256:b2e44f59316716532a993ca2966636df6fbe7be4ab6f099de6815570ebe4383a"}, - {file = "grpcio-1.63.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:f28f8b2db7b86c77916829d64ab21ff49a9d8289ea1564a2b2a3a8ed9ffcccd3"}, - {file = "grpcio-1.63.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:65bf975639a1f93bee63ca60d2e4951f1b543f498d581869922910a476ead2f5"}, - {file = "grpcio-1.63.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:b5194775fec7dc3dbd6a935102bb156cd2c35efe1685b0a46c67b927c74f0cfb"}, - {file = "grpcio-1.63.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4cbb2100ee46d024c45920d16e888ee5d3cf47c66e316210bc236d5bebc42b3"}, - {file = "grpcio-1.63.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ff737cf29b5b801619f10e59b581869e32f400159e8b12d7a97e7e3bdeee6a2"}, - {file = "grpcio-1.63.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cd1e68776262dd44dedd7381b1a0ad09d9930ffb405f737d64f505eb7f77d6c7"}, - {file = "grpcio-1.63.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:93f45f27f516548e23e4ec3fbab21b060416007dbe768a111fc4611464cc773f"}, - {file = "grpcio-1.63.0-cp311-cp311-win32.whl", hash = "sha256:878b1d88d0137df60e6b09b74cdb73db123f9579232c8456f53e9abc4f62eb3c"}, - {file = "grpcio-1.63.0-cp311-cp311-win_amd64.whl", hash = "sha256:756fed02dacd24e8f488f295a913f250b56b98fb793f41d5b2de6c44fb762434"}, - {file = "grpcio-1.63.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:93a46794cc96c3a674cdfb59ef9ce84d46185fe9421baf2268ccb556f8f81f57"}, - {file = "grpcio-1.63.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a7b19dfc74d0be7032ca1eda0ed545e582ee46cd65c162f9e9fc6b26ef827dc6"}, - {file = "grpcio-1.63.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:8064d986d3a64ba21e498b9a376cbc5d6ab2e8ab0e288d39f266f0fca169b90d"}, - {file = "grpcio-1.63.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:219bb1848cd2c90348c79ed0a6b0ea51866bc7e72fa6e205e459fedab5770172"}, - {file = "grpcio-1.63.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2d60cd1d58817bc5985fae6168d8b5655c4981d448d0f5b6194bbcc038090d2"}, - {file = "grpcio-1.63.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9e350cb096e5c67832e9b6e018cf8a0d2a53b2a958f6251615173165269a91b0"}, - {file = "grpcio-1.63.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:56cdf96ff82e3cc90dbe8bac260352993f23e8e256e063c327b6cf9c88daf7a9"}, - {file = "grpcio-1.63.0-cp312-cp312-win32.whl", hash = "sha256:3a6d1f9ea965e750db7b4ee6f9fdef5fdf135abe8a249e75d84b0a3e0c668a1b"}, - {file = "grpcio-1.63.0-cp312-cp312-win_amd64.whl", hash = "sha256:d2497769895bb03efe3187fb1888fc20e98a5f18b3d14b606167dacda5789434"}, - {file = "grpcio-1.63.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:fdf348ae69c6ff484402cfdb14e18c1b0054ac2420079d575c53a60b9b2853ae"}, - {file = "grpcio-1.63.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a3abfe0b0f6798dedd2e9e92e881d9acd0fdb62ae27dcbbfa7654a57e24060c0"}, - {file = "grpcio-1.63.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:6ef0ad92873672a2a3767cb827b64741c363ebaa27e7f21659e4e31f4d750280"}, - {file = "grpcio-1.63.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b416252ac5588d9dfb8a30a191451adbf534e9ce5f56bb02cd193f12d8845b7f"}, - {file = "grpcio-1.63.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3b77eaefc74d7eb861d3ffbdf91b50a1bb1639514ebe764c47773b833fa2d91"}, - {file = "grpcio-1.63.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b005292369d9c1f80bf70c1db1c17c6c342da7576f1c689e8eee4fb0c256af85"}, - {file = "grpcio-1.63.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cdcda1156dcc41e042d1e899ba1f5c2e9f3cd7625b3d6ebfa619806a4c1aadda"}, - {file = "grpcio-1.63.0-cp38-cp38-win32.whl", hash = "sha256:01799e8649f9e94ba7db1aeb3452188048b0019dc37696b0f5ce212c87c560c3"}, - {file = "grpcio-1.63.0-cp38-cp38-win_amd64.whl", hash = "sha256:6a1a3642d76f887aa4009d92f71eb37809abceb3b7b5a1eec9c554a246f20e3a"}, - {file = "grpcio-1.63.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:75f701ff645858a2b16bc8c9fc68af215a8bb2d5a9b647448129de6e85d52bce"}, - {file = "grpcio-1.63.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cacdef0348a08e475a721967f48206a2254a1b26ee7637638d9e081761a5ba86"}, - {file = "grpcio-1.63.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:0697563d1d84d6985e40ec5ec596ff41b52abb3fd91ec240e8cb44a63b895094"}, - {file = "grpcio-1.63.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6426e1fb92d006e47476d42b8f240c1d916a6d4423c5258ccc5b105e43438f61"}, - {file = "grpcio-1.63.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e48cee31bc5f5a31fb2f3b573764bd563aaa5472342860edcc7039525b53e46a"}, - {file = "grpcio-1.63.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:50344663068041b34a992c19c600236e7abb42d6ec32567916b87b4c8b8833b3"}, - {file = "grpcio-1.63.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:259e11932230d70ef24a21b9fb5bb947eb4703f57865a404054400ee92f42f5d"}, - {file = "grpcio-1.63.0-cp39-cp39-win32.whl", hash = "sha256:a44624aad77bf8ca198c55af811fd28f2b3eaf0a50ec5b57b06c034416ef2d0a"}, - {file = "grpcio-1.63.0-cp39-cp39-win_amd64.whl", hash = "sha256:166e5c460e5d7d4656ff9e63b13e1f6029b122104c1633d5f37eaea348d7356d"}, - {file = "grpcio-1.63.0.tar.gz", hash = "sha256:f3023e14805c61bc439fb40ca545ac3d5740ce66120a678a3c6c2c55b70343d1"}, -] - -[package.extras] -protobuf = ["grpcio-tools (>=1.63.0)"] - [[package]] name = "gym-aloha" version = "0.1.1" @@ -1668,7 +1600,6 @@ files = [ {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:9e2addd2d1866fe112bc6f80117bcc6bc25191c5ed1bfbcf9f1386a884252ae8"}, {file = "lxml-5.2.1-cp37-cp37m-win32.whl", hash = "sha256:f51969bac61441fd31f028d7b3b45962f3ecebf691a510495e5d2cd8c8092dbd"}, {file = "lxml-5.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:b0b58fbfa1bf7367dde8a557994e3b1637294be6cf2169810375caf8571a085c"}, - {file = "lxml-5.2.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3e183c6e3298a2ed5af9d7a356ea823bccaab4ec2349dc9ed83999fd289d14d5"}, {file = "lxml-5.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:804f74efe22b6a227306dd890eecc4f8c59ff25ca35f1f14e7482bbce96ef10b"}, {file = "lxml-5.2.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:08802f0c56ed150cc6885ae0788a321b73505d2263ee56dad84d200cab11c07a"}, {file = "lxml-5.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f8c09ed18ecb4ebf23e02b8e7a22a05d6411911e6fabef3a36e4f371f4f2585"}, @@ -1740,21 +1671,6 @@ html5 = ["html5lib"] htmlsoup = ["BeautifulSoup4"] source = ["Cython (>=3.0.10)"] -[[package]] -name = "markdown" -version = "3.6" -description = "Python implementation of John Gruber's Markdown." -optional = false -python-versions = ">=3.8" -files = [ - {file = "Markdown-3.6-py3-none-any.whl", hash = "sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f"}, - {file = "Markdown-3.6.tar.gz", hash = "sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224"}, -] - -[package.extras] -docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] -testing = ["coverage", "pyyaml"] - [[package]] name = "markupsafe" version = "2.1.5" @@ -3056,6 +2972,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -3224,30 +3141,6 @@ typing-extensions = ">=4.5" [package.extras] tests = ["pytest (==7.1.2)"] -[[package]] -name = "robomimic" -version = "0.2.0" -description = "robomimic: A Modular Framework for Robot Learning from Demonstration" -optional = false -python-versions = ">=3" -files = [ - {file = "robomimic-0.2.0.tar.gz", hash = "sha256:ee3bb5cf9c3e1feead6b57b43c5db738fd0a8e0c015fdf6419808af8fffdc463"}, -] - -[package.dependencies] -egl_probe = ">=1.0.1" -h5py = "*" -imageio = "*" -imageio-ffmpeg = "*" -numpy = ">=1.13.3" -psutil = "*" -tensorboard = "*" -tensorboardX = "*" -termcolor = "*" -torch = "*" -torchvision = "*" -tqdm = "*" - [[package]] name = "safetensors" version = "0.4.3" @@ -3738,55 +3631,6 @@ files = [ {file = "tbb-2021.12.0-py3-none-win_amd64.whl", hash = "sha256:fc2772d850229f2f3df85f1109c4844c495a2db7433d38200959ee9265b34789"}, ] -[[package]] -name = "tensorboard" -version = "2.16.2" -description = "TensorBoard lets you watch Tensors Flow" -optional = false -python-versions = ">=3.9" -files = [ - {file = "tensorboard-2.16.2-py3-none-any.whl", hash = "sha256:9f2b4e7dad86667615c0e5cd072f1ea8403fc032a299f0072d6f74855775cc45"}, -] - -[package.dependencies] -absl-py = ">=0.4" -grpcio = ">=1.48.2" -markdown = ">=2.6.8" -numpy = ">=1.12.0" -protobuf = ">=3.19.6,<4.24.0 || >4.24.0" -setuptools = ">=41.0.0" -six = ">1.9" -tensorboard-data-server = ">=0.7.0,<0.8.0" -werkzeug = ">=1.0.1" - -[[package]] -name = "tensorboard-data-server" -version = "0.7.2" -description = "Fast data loading for TensorBoard" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tensorboard_data_server-0.7.2-py3-none-any.whl", hash = "sha256:7e0610d205889588983836ec05dc098e80f97b7e7bbff7e994ebb78f578d0ddb"}, - {file = "tensorboard_data_server-0.7.2-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:9fe5d24221b29625dbc7328b0436ca7fc1c23de4acf4d272f1180856e32f9f60"}, - {file = "tensorboard_data_server-0.7.2-py3-none-manylinux_2_31_x86_64.whl", hash = "sha256:ef687163c24185ae9754ed5650eb5bc4d84ff257aabdc33f0cc6f74d8ba54530"}, -] - -[[package]] -name = "tensorboardx" -version = "2.6.2.2" -description = "TensorBoardX lets you watch Tensors Flow without Tensorflow" -optional = false -python-versions = "*" -files = [ - {file = "tensorboardX-2.6.2.2-py2.py3-none-any.whl", hash = "sha256:160025acbf759ede23fd3526ae9d9bfbfd8b68eb16c38a010ebe326dc6395db8"}, - {file = "tensorboardX-2.6.2.2.tar.gz", hash = "sha256:c6476d7cd0d529b0b72f4acadb1269f9ed8b22f441e87a84f2a3b940bb87b666"}, -] - -[package.dependencies] -numpy = "*" -packaging = "*" -protobuf = ">=3.20" - [[package]] name = "termcolor" version = "2.4.0" @@ -4064,23 +3908,6 @@ perf = ["orjson"] reports = ["pydantic (>=2.0.0)"] sweeps = ["sweeps (>=0.2.0)"] -[[package]] -name = "werkzeug" -version = "3.0.3" -description = "The comprehensive WSGI web application library." -optional = false -python-versions = ">=3.8" -files = [ - {file = "werkzeug-3.0.3-py3-none-any.whl", hash = "sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8"}, - {file = "werkzeug-3.0.3.tar.gz", hash = "sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18"}, -] - -[package.dependencies] -MarkupSafe = ">=2.1.1" - -[package.extras] -watchdog = ["watchdog (>=2.3)"] - [[package]] name = "xxhash" version = "3.4.1" @@ -4348,4 +4175,4 @@ xarm = ["gym-xarm"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.13" -content-hash = "2f0d2cbf4a2dec546e25b29b9b108ff1f97b4c278b718360b3f7f6a2bf9dcef8" +content-hash = "e3e3c306a5519e4f716a1ac086ad9b734efedcac077a0ec71e5bc16349a1e559" diff --git a/pyproject.toml b/pyproject.toml index 24d9452d..5b80d06f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,6 @@ diffusers = "^0.27.2" torchvision = ">=0.18.0" h5py = ">=3.10.0" huggingface-hub = ">=0.21.4" -robomimic = "0.2.0" gymnasium = ">=0.29.1" cmake = ">=3.29.0.1" gym-pusht = { version = ">=0.1.3", optional = true} diff --git a/tests/data/save_policy_to_safetensors/pusht_diffusion/actions.safetensors b/tests/data/save_policy_to_safetensors/pusht_diffusion/actions.safetensors index 730f5b2bc2a801d15b4ade3593c90f95650f5472..8f03990351292611f702c163ee387b3d7248b5f0 100644 GIT binary patch literal 4600 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 literal 4600 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 N2@G4MTx_#u{sckZ-xdG> delta 1719 zcmX|=FZ%Ts}s(r%@ctUTNxBoQ++_csHpQSn$ri!Pw3z@mVGB2_pdT1l!1 zU6hxAgg|)&L6k=zl4Js+0TB@jg-RbrWZ8<}bPE3k%456~IhJuLO}3ZrYK@q>Y-c2To)`eb)(AExJpp-iABym}58q@p zq6POSU>Ypd7V#Tkg~e`7*ScDWzIU4#3)2HONwpk16kIq4Qr@nBpa-`! z6L$OIqwb&ZCySzBWNIHnM~K;B2Hpn-$qA^mM`SK15l-)QC%eSi5V!t}W@r3ia0tJS zPp+rHbjOmYERp`r#V;nAVE1^K^gKcazrTeoN>Fw}1lW9+Q9CcRTuqJEAw0-u|PizIPi$CDAS&q<-S&>IS5i>T1lB2<{~L`4Pv1mWN9 zp^u$^PHY}ZWcxqxJ=Hx8(oTu9-}I>jxUn^ckvw#UxgYYF<(C{;K+5NEEd1|oYi=Kl znSz2OXKnpt10BBfuf^EH)t{pBKCYmv-w#$ z#1sswGmU`|IA_D~?#!UD%LxqMbA}xd&BIIQ=?Tdcca^bl9Nzi8pV(w-fT44qWUuyH z_@c?1oZom3nI;N}3nDpM{oi|Jp{qGH7Hy5&uC-wcMplG0Hle_8y8Lc_XNOvjtMN^e z4)S~MA)&EEN3t*E`?*&YrMhTT#h*+=sdXFiNQVIQWhkck#ZiQ2FN+C#$VHOgI(v1} zNozEDB2gQnz6;$}mVR-wKeGiG7SI)h=KtgBH9$4W0nZA}EsIlZUeVIz zSwwO4;?6{nX^ae`u=h}VwgjBes&znt|n4BL<4Ny zb&gU557X1H#wB#@rY-bttjhoN@Mi7T9~Z-pTTFZTfl5~3*0}gcKRN$m!=-^;3Nm5Q zM0?HN&E&DX?uD#D_M9N2A!|7}_D@Rpp>z|^SojpW7-HQTac*N4;0n}SkLWE01Z-F`~f*5aI3D<3( zGkMXO)K`6rG^;QEpDmDjE1ZhZk4O6j?!0|yRm10M(GUMbGV3s5>4@K-0-s-LU;1!h znBT#zHgI-lCy_NijLwcZllage$~p9i6flp$9F&CpS9$Q8y{xl4L*RcpLc!?51r&y5 zDJ5p1$yAi+gy!am8#R=oVp5VP!P59xdu`be`-?vnG^A?%Q=W;{${7V!-g-gzGCqTf zm{?$P#xkhLH{a^u;4M^j(h}Xhb}99*g{IDybSwWg8GTH?(2f;Y@j|i%)bY2S2vemA z<~9?C>( Pt?Bc-gS6{CoasLR6e#%s diff --git a/tests/data/save_policy_to_safetensors/pusht_diffusion/output_dict.safetensors b/tests/data/save_policy_to_safetensors/pusht_diffusion/output_dict.safetensors index 5f33535d5ad316f4cef55925a215428643ed2f52..a9f61b36ed2735850072768de10a153ef1aea7aa 100644 GIT binary patch delta 9 QcmZ>9nc%?kuA##o01%i1k^lez delta 9 QcmZ>9nc%>3p0ULq01lS|@Bjb+ diff --git a/tests/data/save_policy_to_safetensors/pusht_diffusion/param_stats.safetensors b/tests/data/save_policy_to_safetensors/pusht_diffusion/param_stats.safetensors index ade6a9e03118ac410f6f0ff9357b6779074437b6..a9f4608f6c1c544e8324803f154f57cb9f6acd96 100644 GIT binary patch delta 173 zcmV;e08;h_}JR*~kx<3gn zoKLrTs;WFyv)Q_T0RcFZS-c+sB9nQ%F9A%Gsk~niIFjc#(xDPP0|sZgbL}@g8j~5l z9|3BUIlWI30y9E5VzClEsMYT|bOt~?3VxHCy*?4GIj%Q@a}qt!tyH;GpgcShlj*%r b0gsb8z8?W&lUcq$0dSLlVQ3i2|LL%w>h_}JS&rtx<3gr zoKLrTs;WFIv)Q_T0RcCYS-c+sAd`8#F9A)Hsk~niIg;l$(xDPP0|sZgbL}@g9+Mfp z9|3NYIlWI3{4zo~VzClEsMYT|bOt~?|9z91y*?4RIj%Q@a}qt!tyH;GpgcSalj*%r b0g;nAz8?W%lUcq$0d$j@zFz?!lli{q5xGhY From 4d7d41cdee1e2406746ff38739fda2c58586e811 Mon Sep 17 00:00:00 2001 From: Alexander Soare Date: Thu, 16 May 2024 15:43:25 +0100 Subject: [PATCH 23/27] Fix act action queue (#185) --- lerobot/common/policies/act/modeling_act.py | 6 +++--- .../aloha_act/actions.safetensors | Bin 5104 -> 5104 bytes .../aloha_act/grad_stats.safetensors | Bin 31688 -> 31688 bytes 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lerobot/common/policies/act/modeling_act.py b/lerobot/common/policies/act/modeling_act.py index 4a8df1ce..3aab03cf 100644 --- a/lerobot/common/policies/act/modeling_act.py +++ b/lerobot/common/policies/act/modeling_act.py @@ -98,13 +98,13 @@ class ACTPolicy(nn.Module, PyTorchModelHubMixin): batch["observation.images"] = torch.stack([batch[k] for k in self.expected_image_keys], dim=-4) if len(self._action_queue) == 0: - # `self.model.forward` returns a (batch_size, n_action_steps, action_dim) tensor, but the queue - # effectively has shape (n_action_steps, batch_size, *), hence the transpose. - actions = self.model(batch)[0][: self.config.n_action_steps] + actions = self.model(batch)[0][:, : self.config.n_action_steps] # TODO(rcadene): make _forward return output dictionary? actions = self.unnormalize_outputs({"action": actions})["action"] + # `self.model.forward` returns a (batch_size, n_action_steps, action_dim) tensor, but the queue + # effectively has shape (n_action_steps, batch_size, *), hence the transpose. self._action_queue.extend(actions.transpose(0, 1)) return self._action_queue.popleft() diff --git a/tests/data/save_policy_to_safetensors/aloha_act/actions.safetensors b/tests/data/save_policy_to_safetensors/aloha_act/actions.safetensors index 7e7ad8e1df015d0ff52d689b317b8d77b3f380fa..3c9447d7fa0b68143216f21c4d9cf5c075253fe4 100644 GIT binary patch literal 5104 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 literal 5104 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 diff --git a/tests/data/save_policy_to_safetensors/aloha_act/grad_stats.safetensors b/tests/data/save_policy_to_safetensors/aloha_act/grad_stats.safetensors index 5188d8f428cdddf509da7f91f29950d9c80ad309..7dfbc3b35cc394e87cd77018d4f427928b9aa637 100644 GIT binary patch delta 110 zcmV-!0FnR5_W{WF0k9BvQS|F*yWiJSJZkQmIefA!Jk{F(xgs{;JMQ7>IWSb)JK|an zIg=~7I~5V|xpws>JPm4_xc^&QI}Rt-xeTT(Je8;;IfRu%JHo>fxUd`sI~9{*cNYn| QUje!FRLwdIWJV(JKkCj zIg=~7I}{P{xpws>JPvA`xc^&QI}az;xeTT(Je8;;IfRu%JHo>fxUd`sI}(#&cNYn` QUje!FRLwd=vw?R<1in}@TmS$7 From 625f0557ef9d2fc6b57604dafb99820d89d1d02e Mon Sep 17 00:00:00 2001 From: Alexander Soare Date: Fri, 17 May 2024 14:57:49 +0100 Subject: [PATCH 24/27] Act temporal ensembling (#186) --- .../common/policies/act/configuration_act.py | 17 +++++++---- lerobot/common/policies/act/modeling_act.py | 28 +++++++++++++++++-- lerobot/configs/policy/act.yaml | 2 +- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/lerobot/common/policies/act/configuration_act.py b/lerobot/common/policies/act/configuration_act.py index be444b06..cc072083 100644 --- a/lerobot/common/policies/act/configuration_act.py +++ b/lerobot/common/policies/act/configuration_act.py @@ -66,8 +66,12 @@ class ACTConfig: documentation in the policy class). latent_dim: The VAE's latent dimension. n_vae_encoder_layers: The number of transformer layers to use for the VAE's encoder. - use_temporal_aggregation: Whether to blend the actions of multiple policy invocations for any given - environment step. + temporal_ensemble_momentum: Exponential moving average (EMA) momentum parameter (ฮฑ) for ensembling + actions for a given time step over multiple policy invocations. Updates are calculated as: + xโปโ‚™ = ฮฑxโปโ‚™โ‚‹โ‚ + (1-ฮฑ)xโ‚™. Note that the ACT paper and original ACT code describes a different + parameter here: they refer to a weighting scheme wแตข = exp(-mโ‹…i) and set m = 0.01. With our + formulation, this is equivalent to ฮฑ = exp(-0.01) โ‰ˆ 0.99. When this parameter is provided, we + require `n_action_steps == 1` (since we need to query the policy every step anyway). dropout: Dropout to use in the transformer layers (see code for details). kl_weight: The weight to use for the KL-divergence component of the loss if the variational objective is enabled. Loss is then calculated as: `reconstruction_loss + kl_weight * kld_loss`. @@ -122,7 +126,7 @@ class ACTConfig: n_vae_encoder_layers: int = 4 # Inference. - use_temporal_aggregation: bool = False + temporal_ensemble_momentum: float | None = None # Training and loss computation. dropout: float = 0.1 @@ -134,8 +138,11 @@ class ACTConfig: raise ValueError( f"`vision_backbone` must be one of the ResNet variants. Got {self.vision_backbone}." ) - if self.use_temporal_aggregation: - raise NotImplementedError("Temporal aggregation is not yet implemented.") + if self.temporal_ensemble_momentum is not None and self.n_action_steps > 1: + raise NotImplementedError( + "`n_action_steps` must be 1 when using temporal ensembling. This is " + "because the policy needs to be queried every step to compute the ensembled action." + ) if self.n_action_steps > self.chunk_size: raise ValueError( f"The chunk size is the upper bound for the number of action steps per model invocation. Got " diff --git a/lerobot/common/policies/act/modeling_act.py b/lerobot/common/policies/act/modeling_act.py index 3aab03cf..72ebdd7a 100644 --- a/lerobot/common/policies/act/modeling_act.py +++ b/lerobot/common/policies/act/modeling_act.py @@ -61,7 +61,7 @@ class ACTPolicy(nn.Module, PyTorchModelHubMixin): super().__init__() if config is None: config = ACTConfig() - self.config = config + self.config: ACTConfig = config self.normalize_inputs = Normalize( config.input_shapes, config.input_normalization_modes, dataset_stats @@ -81,7 +81,9 @@ class ACTPolicy(nn.Module, PyTorchModelHubMixin): def reset(self): """This should be called whenever the environment is reset.""" - if self.config.n_action_steps is not None: + if self.config.temporal_ensemble_momentum is not None: + self._ensembled_actions = None + else: self._action_queue = deque([], maxlen=self.config.n_action_steps) @torch.no_grad @@ -97,6 +99,28 @@ class ACTPolicy(nn.Module, PyTorchModelHubMixin): batch = self.normalize_inputs(batch) batch["observation.images"] = torch.stack([batch[k] for k in self.expected_image_keys], dim=-4) + # If we are doing temporal ensembling, keep track of the exponential moving average (EMA), and return + # the first action. + if self.config.temporal_ensemble_momentum is not None: + actions = self.model(batch)[0] # (batch_size, chunk_size, action_dim) + actions = self.unnormalize_outputs({"action": actions})["action"] + if self._ensembled_actions is None: + # Initializes `self._ensembled_action` to the sequence of actions predicted during the first + # time step of the episode. + self._ensembled_actions = actions.clone() + else: + # self._ensembled_actions will have shape (batch_size, chunk_size - 1, action_dim). Compute + # the EMA update for those entries. + alpha = self.config.temporal_ensemble_momentum + self._ensembled_actions = alpha * self._ensembled_actions + (1 - alpha) * actions[:, :-1] + # The last action, which has no prior moving average, needs to get concatenated onto the end. + self._ensembled_actions = torch.cat([self._ensembled_actions, actions[:, -1:]], dim=1) + # "Consume" the first action. + action, self._ensembled_actions = self._ensembled_actions[:, 0], self._ensembled_actions[:, 1:] + return action + + # Action queue logic for n_action_steps > 1. When the action_queue is depleted, populate it by + # querying the policy. if len(self._action_queue) == 0: actions = self.model(batch)[0][:, : self.config.n_action_steps] diff --git a/lerobot/configs/policy/act.yaml b/lerobot/configs/policy/act.yaml index 15efcce8..f09e6a12 100644 --- a/lerobot/configs/policy/act.yaml +++ b/lerobot/configs/policy/act.yaml @@ -73,7 +73,7 @@ policy: n_vae_encoder_layers: 4 # Inference. - use_temporal_aggregation: false + temporal_ensemble_momentum: null # Training and loss computation. dropout: 0.1 From 5ec0af62c62de6c6f7ae4dad498d9dbcf676b062 Mon Sep 17 00:00:00 2001 From: Alexander Soare Date: Fri, 17 May 2024 15:05:40 +0100 Subject: [PATCH 25/27] Explain why n_encoder_layers=1 (#193) --- lerobot/common/policies/act/configuration_act.py | 3 +++ lerobot/configs/policy/act.yaml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/lerobot/common/policies/act/configuration_act.py b/lerobot/common/policies/act/configuration_act.py index cc072083..95374f4d 100644 --- a/lerobot/common/policies/act/configuration_act.py +++ b/lerobot/common/policies/act/configuration_act.py @@ -119,6 +119,9 @@ class ACTConfig: dim_feedforward: int = 3200 feedforward_activation: str = "relu" n_encoder_layers: int = 4 + # Note: Although the original ACT implementation has 7 for `n_decoder_layers`, there is a bug in the code + # that means only the first layer is used. Here we match the original implementation by setting this to 1. + # See this issue https://github.com/tonyzhaozh/act/issues/25#issue-2258740521. n_decoder_layers: int = 1 # VAE. use_vae: bool = True diff --git a/lerobot/configs/policy/act.yaml b/lerobot/configs/policy/act.yaml index f09e6a12..7a12dcc2 100644 --- a/lerobot/configs/policy/act.yaml +++ b/lerobot/configs/policy/act.yaml @@ -66,6 +66,9 @@ policy: dim_feedforward: 3200 feedforward_activation: relu n_encoder_layers: 4 + # Note: Although the original ACT implementation has 7 for `n_decoder_layers`, there is a bug in the code + # that means only the first layer is used. Here we match the original implementation by setting this to 1. + # See this issue https://github.com/tonyzhaozh/act/issues/25#issue-2258740521. n_decoder_layers: 1 # VAE. use_vae: true From 096149b118863fb9e6213c6663614d24c97c6735 Mon Sep 17 00:00:00 2001 From: Alexander Soare Date: Fri, 17 May 2024 18:01:39 +0100 Subject: [PATCH 26/27] Disable wandb by default (#195) --- lerobot/configs/default.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerobot/configs/default.yaml b/lerobot/configs/default.yaml index 7cad0a1a..ae36b3e2 100644 --- a/lerobot/configs/default.yaml +++ b/lerobot/configs/default.yaml @@ -35,7 +35,7 @@ eval: use_async_envs: false wandb: - enable: true + enable: false # Set to true to disable saving an artifact despite save_model == True disable_artifact: false project: lerobot From 19dfb9144ad679975f17a1f6c9fee7913dbde366 Mon Sep 17 00:00:00 2001 From: Alexander Soare Date: Mon, 20 May 2024 09:02:24 +0100 Subject: [PATCH 27/27] Update the README to reflect WandB disabled by default (#198) --- README.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a936ecfe..b1c441cb 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,8 @@ To use [Weights and Biases](https://docs.wandb.ai/quickstart) for experiment tra wandb login ``` +(note: you will also need to enable WandB in the configuration. See below.) + ## Walkthrough ``` @@ -158,13 +160,13 @@ See `python lerobot/scripts/eval.py --help` for more instructions. Check out [example 3](./examples/3_train_policy.py) that illustrates how to start training a model. -In general, you can use our training script to easily train any policy. To use wandb for logging training and evaluation curves, make sure you ran `wandb login`. Here is an example of training the ACT policy on trajectories collected by humans on the Aloha simulation environment for the insertion task: +In general, you can use our training script to easily train any policy. Here is an example of training the ACT policy on trajectories collected by humans on the Aloha simulation environment for the insertion task: ```bash python lerobot/scripts/train.py \ policy=act \ env=aloha \ env.task=AlohaInsertion-v0 \ - dataset_repo_id=lerobot/aloha_sim_insertion_human + dataset_repo_id=lerobot/aloha_sim_insertion_human \ ``` The experiment directory is automatically generated and will show up in yellow in your terminal. It looks like `outputs/train/2024-05-05/20-21-12_aloha_act_default`. You can manually specify an experiment directory by adding this argument to the `train.py` python command: @@ -172,17 +174,17 @@ The experiment directory is automatically generated and will show up in yellow i hydra.run.dir=your/new/experiment/dir ``` -A link to the wandb logs for the run will also show up in yellow in your terminal. Here is an example of logs from wandb: -![](media/wandb.png) +To use wandb for logging training and evaluation curves, make sure you've run `wandb login` as a one-time setup step. Then, when running the training command above, enable WandB in the configuration by adding: -You can deactivate wandb by adding these arguments to the `train.py` python command: ```bash - wandb.disable_artifact=true \ - wandb.enable=false + wandb.enable=true ``` -Note: For efficiency, during training every checkpoint is evaluated on a low number of episodes. After training, you may want to re-evaluate your best checkpoints on more episodes or change the evaluation settings. See `python lerobot/scripts/eval.py --help` for more instructions. +A link to the wandb logs for the run will also show up in yellow in your terminal. Here is an example of what they look like in your browser: +![](media/wandb.png) + +Note: For efficiency, during training every checkpoint is evaluated on a low number of episodes. After training, you may want to re-evaluate your best checkpoints on more episodes or change the evaluation settings. See `python lerobot/scripts/eval.py --help` for more instructions. ## Contribute

@_Fl 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