破坏性变更:LeRobot policy 不再在权重中内嵌归一化层。归一化现在由外部的 PolicyProcessorPipeline 组件处理。
| PR #1452 之前 | PR #1452 之后 | |
|---|---|---|
| 归一化位置 | 嵌入在模型权重中(normalize_inputs.*) | 外部的 PolicyProcessorPipeline 组件 |
| 模型 state 字典 | 包含归一化统计 | 仅含干净权重 - 无归一化参数 |
| 用法 | policy(batch) 处理一切 | preprocessor(batch) → policy(...) → postprocessor(...) |
PolicyProcessorPipeline 系统配合使用使用迁移脚本转换带有内嵌归一化的模型:
python src/lerobot/processor/migrate_policy_normalization.py \
--pretrained-path lerobot/act_aloha_sim_transfer_cube_human \
--push-to-hub \
--branch migrated该脚本:
# New usage pattern (after migration)
from lerobot.policies import make_policy, make_pre_post_processors
# Load model and processors separately
policy = make_policy(config, ds_meta=dataset.meta)
preprocessor, postprocessor = make_pre_post_processors(
policy_cfg=config,
dataset_stats=dataset.meta.stats
)
# Process data through pipeline
processed_batch = preprocessor(raw_batch)
action = policy.select_action(processed_batch)
final_action = postprocessor(action)PR #777 改进了 LeRobot 的 calibration,但不向后兼容。下面概述了有哪些变化,以及你如何继续使用在此拉取请求之前创建的 dataset。
| PR #777 之前 | PR #777 之后 | |
|---|---|---|
| 关节范围 | 度数 -180...180° | 归一化范围 关节:–100...100 gripper:0...100 |
| 零位(SO100 / SO101) | 机械臂水平完全伸展 | 位于每个关节范围的中部 |
| 边界处理 | 用于检测 ±180 ° 回绕的软件保护 | 由于零位在范围中部,无需回绕逻辑 |
我们在这里提供了一个迁移示例脚本,用于回放使用旧 calibration 录制的 episode:examples/backward_compatibility/replay.py。
下面我们带你了解示例脚本中所做的修改,以使旧的 calibration dataset 能够正常使用。
+ key = f"{name.removeprefix('main_')}.pos"
action[key] = action_array[i].item()
+ action["shoulder_lift.pos"] = -(action["shoulder_lift.pos"] - 90)
+ action["elbow_flex.pos"] -= 90我们来逐项分析。
新代码库对位置 observation 使用 .pos 后缀,并且我们已移除 main_ 前缀:
key = f"{name.removeprefix('main_')}.pos"对于 "shoulder_lift"(id = 2),与旧 calibration/代码相比,0 位置偏移了 -90 度,且方向反转。
action["shoulder_lift.pos"] = -(action["shoulder_lift.pos"] - 90)对于 "elbow_flex"(id = 3),与旧 calibration/代码相比,0 位置偏移了 -90 度。
action["elbow_flex.pos"] -= 90要使用度数归一化,我们将 --robot.use_degrees 选项设置为 true。
python examples/backward_compatibility/replay.py \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem5A460814411 \
--robot.id=blue \
+ --robot.use_degrees=true \
--dataset.repo_id=my_dataset_id \
--dataset.episode=0policy 输出的 action 与 dataset(torch.Tensors)格式相同。因此,应应用相同的变换。
要找到这些变换,我们建议先用上面一节的方法,回放你的 policy 所训练 dataset 中的一个 episode。
然后,在 inference 脚本中(如 record.py 脚本所示)添加这些相同的变换:
action_values = predict_action(
observation_frame,
policy,
get_safe_torch_device(policy.config.device),
policy.config.use_amp,
task=single_task,
robot_type=robot.robot_type,
)
action = {key: action_values[i].item() for i, key in enumerate(robot.action_features)}
+ action["shoulder_lift.pos"] = -(action["shoulder_lift.pos"] - 90)
+ action["elbow_flex.pos"] -= 90
robot.send_action(action)如果你有疑问或遇到迁移问题,欢迎在 Discord 上提问
在 GitHub 上更新