博主最近想要学习一下robot learning相关内容,找到一个挺著名的由hugging face开源的框架lerobot。网上关于这个框架有用介绍比较少,就想自己来写一下。
lerobot是干什么的?
LeRobot 旨在为 PyTorch 中的真实世界机器人技术提供模型、数据集和工具。目标是降低进入机器人技术领域的门槛,以便每个人都能通过共享数据集和预训练模型做出贡献并从中受益。
lerobot的部署
git clone 项目
git clone https://github.com/huggingface/lerobot.git
cd lerobot
创建虚拟环境
conda create -y -n lerobot python=3.10
conda activate lerobot
安装ffmpeg库
conda install ffmpeg
安装其他依赖 [linux]
如果是下面这样最基本的形式,就代表装基本的依赖
pip install .
这行命令代表安装aloha所需的额外依赖
pip install --no-binary=av -e ".[aloha,]"
其中[ ]内的是额外选项
查看根目录下的pyproject.toml中的[project.optional-dependencies]要啥装啥
aloha = ["gym-aloha>=0.1.1 ; python_version < '4.0'"]
dev = ["pre-commit>=3.7.0", "debugpy>=1.8.1"]
dora = [
"gym-dora @ git+https://github.com/dora-rs/dora-lerobot.git#subdirectory=gym_dora ; python_version < '4.0'",
]
dynamixel = ["dynamixel-sdk>=3.7.31", "pynput>=1.7.7"]
feetech = ["feetech-servo-sdk>=1.0.0", "pynput>=1.7.7"]
intelrealsense = ["pyrealsense2>=2.55.1.6486 ; sys_platform != 'darwin'"]
pi0 = ["transformers>=4.48.0"]
pusht = ["gym-pusht>=0.1.5 ; python_version < '4.0'"]
stretch = [
"hello-robot-stretch-body>=0.7.27 ; python_version < '4.0' and sys_platform == 'linux'",
"pyrender @ git+https://github.com/mmatl/pyrender.git ; sys_platform == 'linux'",
"pyrealsense2>=2.55.1.6486 ; sys_platform != 'darwin'",
"pynput>=1.7.7",
]
test = ["pytest>=8.1.0", "pytest-cov>=5.0.0", "pyserial>=3.5"]
umi = ["imagecodecs>=2024.1.1"]
video_benchmark = ["scikit-image>=0.23.2", "pandas>=2.2.2"]
xarm = ["gym-xarm>=0.1.1 ; python_version < '4.0'"]
[windows]系统下使用这行命令会报错
原因: PyAV的库中要求使用这条命令的前提是posix env windows不符合
解决方案就是直接先pip安装即可 “av>=12.0.5,<13.0.0”
pip install av==12.2.0
pip install --no-binary=av -e ".[aloha, pusht, feetech]"
–no-binary=av
- 作用:强制对
av
包从源码构建,而非使用预编译的二进制轮子(.whl
)。 - 原因:
- 系统依赖适配:
av
是 FFmpeg 的 Python 绑定库,依赖系统级库(如 FFmpeg)。预编译的二进制文件可能与用户系统不兼容。 - 定制化需求:需要针对特定环境(如 CUDA 支持)编译
av
,或修改其源码。
- 系统依赖适配:
- 代价:编译耗时较长,且需确保系统已安装编译工具链(如
gcc
,ffmpeg-dev
)。
-e
或 --editable
- 作用:以可编辑模式(开发模式)安装包。
- 原理:
- 符号链接(Symlink):将包的源代码目录直接链接到 Python 的
site-packages
目录中,而非复制文件。 - 实时生效:修改源码后无需重新安装,修改立即生效。
- 符号链接(Symlink):将包的源代码目录直接链接到 Python 的
- 典型场景:开发调试自己的包或依赖库时使用。
利用元数据集查看数据集信息
元数据:元数据是关于数据的数据,它提供了对数据的描述、解释和上下文信息,有助于人们更好地理解、管理和使用数据
你可以通过repo_id(仓库ID) 来载入huggingface社区的数据集 和元数据
查看现有的repo_id
from huggingface_hub import HfApi
hub_api = HfApi()
repo_ids = [info.id for info in hub_api.list_datasets(task_categories="robotics", tags=["LeRobot"])]
pprint(repo_ids)
通过repo_id来加载元数据
通过LeRobotDatasetMetadata这个类可以查看数据集的元数据,这样的好处在于你不用下载整个数据集就能知道这个数据集的内容
from lerobot.common.datasets.lerobot_dataset import LeRobotDataset, LeRobotDatasetMetadata
repo_id = "lerobot/aloha_mobile_cabinet"
ds_meta = LeRobotDatasetMetadata(repo_id)
然后利用这个实例化的类就可以打印相关的信息
print(f"Total number of episodes: {ds_meta.total_episodes}")
print(f"Average number of frames per episode: {ds_meta.total_frames / ds_meta.total_episodes:.3f}")
print(f"Frames per second used during data collection: {ds_meta.fps}")
print(f"Robot type: {ds_meta.robot_type}")
print(f"keys to access images from cameras: {ds_meta.camera_keys=}\n")
print("Tasks:")
print(ds_meta.tasks)
print("Features:")
pprint(ds_meta.features)
输出为
还有一些其他的属性如data_path,shapes
等可以到这个类中具体去看
直接打印这个实例能获得简单的概况
print(ds_meta)
加载数据集
加载数据的方式和[[利用元数据集查看数据集信息]]类似,都是使用repo_id,不过 LeRobotDataset提供了下载子集的选项
dataset = LeRobotDataset(repo_id, episodes=[0, 10, 11, 23])
# And see how many frames you have:
print(f"Selected episodes: {dataset.episodes}")
print(f"Number of episodes selected: {dataset.num_episodes}")
print(f"Number of frames selected: {dataset.num_frames}")
当然也可以下载完整数据集
dataset = LeRobotDataset(repo_id)
print(f"Number of episodes selected: {dataset.num_episodes}")
print(f"Number of frames selected: {dataset.num_frames}")
输出为
遍历数据
LeRobotDataset是PyTorch dataset的子集 调用方式基本一致
获取第一个epsiode的数据
episode_index = 0
from_idx = dataset.episode_data_index["from"][episode_index].item()
to_idx = dataset.episode_data_index["to"][episode_index].item()
from 和 to存放着每个epsiode的开始和结束index,这边的from[1]和to[0]一样 但是其实结束index是1499 由于需要使用 range(左闭右开)来遍历所以这边to的值会比实际多1
获取第一帧的数据,方式和Pytorch dataset获取方式一样
camera_key = dataset.meta.camera_keys[0]
print(f"{camera_key}")
frames = [dataset[idx][camera_key] for idx in range(from_idx, to_idx)]
print(type(frames[0]))
print(frames[0].shape)
输出为
LeRobotDataset还提供了输出当前状态时附加过去,未来状态的参数
delta_timestamps = {
# loads 4 images: 1 second before current frame, 500 ms before, 200 ms before, and current frame
camera_key: [-1, -0.5, -0.20, 0],
# loads 6 state vectors: 1.5 seconds before, 1 second before, ... 200 ms, 100 ms, and current frame
"observation.state": [-1.5, -1, -0.5, -0.20, -0.10, 0],
# loads 64 action vectors: current frame, 1 frame in the future, 2 frames, ... 63 frames in the future
"action": [t / dataset.fps for t in range(64)],
}
dataset = LeRobotDataset(repo_id, delta_timestamps=delta_timestamps)
print(f"\n{dataset[0][camera_key].shape=}")
print(f"{dataset[0]['observation.state'].shape=}")
print(f"{dataset[0]['action'].shape=}\n")
输出
dataloader
由于LeRobotDataset是Pytorch Dataset的子类所以实现dataloader的方式非常简单
dataloader = torch.utils.data.DataLoader(
dataset,
num_workers=0,
batch_size=32,
shuffle=True,
)
for batch in dataloader:
print(f"{batch[camera_key].shape=}")
print(f"{batch['observation.state'].shape=}")
print(f"{batch['action'].shape=}")
break
输出
参考资料
https://huggingface.co/lerobot
后续
lerobot[评估策略,训练策略]