以机械臂替代人工签到,单通道人力成本降低 50% 以上;机械臂本身的科技互动属性为主办方创造差异化营销触点,形成自然流量入口,间接降低获客成本。
用开源遥操作训练替代传统人工签到,核验与发证全程自动化,为展会签到处打造可复现、自带科技营销属性的服务机器人。
王天琪
触发延迟 <2 s(含扫码解码、数据库查询、指令生成)
# **01 实验前置流程 —— 详细说明**
# **步骤 1:硬件组装**
### **1.1 机械臂组装**
1\. 使用螺丝刀套件,按照 SO-ARM101 打印件的结构,将 6 个飞特 C047 舵机安装到从臂(Follower)的 6 个关节位置:shoulder_pan、shoulder_lift、elbow_flex、wrist_flex、wrist_roll、gripper。
2\. 将飞特 C001 舵机安装到主臂(Leader)第 2 号关节,C044 舵机安装到主臂第 1 号和第 3 号关节,C046 舵机安装到主臂第 4 号、第 5 号关节及第 6 号夹爪。
3\. 将舵机控制板固定在机械臂底座上,连接舵机线缆。
### **1.2 电源与通信连接**
| 连接项 | 规格 | 操作 |
| --- | --- | --- |
| 从臂电源 | DC 12V/2A(5.5mm x 2.1mm) | 将 12V 电源适配器接入从臂舵机控制板 |
| 主臂电源 | DC 5V/4A(5.5mm x 2.1mm) | 将 5V 电源适配器接入主臂舵机控制板 |
| 从臂通信 | Type-C 数据线 | 连接从臂控制板 Type-C 口与电脑 USB,务必使用带数据传输功能的线 |
| 主臂通信 | Type-C 数据线 | 连接主臂控制板 Type-C 口与电脑 USB |
| 摄像头 0(ACT 俯视) | USB 免驱 200 万像素 | 接入电脑 USB 拓展坞,安装在机械臂上方俯视位置 |
| 摄像头 1(ACT 手腕) | USB 免驱 200 万像素 | 安装在机械臂手腕处,跟随手腕运动 |
| 摄像头 2(二维码扫描) | USB 免驱摄像头 | 安装在签到台面,对准嘉宾出示二维码的位置 |
## **步骤 2:上电自检**
### **2.1 机械臂上电顺序**
1\. 先连接从臂 12V 电源,确认从臂控制板电源指示灯亮起。
2\. 再连接主臂 5V 电源,确认主臂控制板电源指示灯亮起。
3\. 用 Type-C 数据线分别连接从臂、主臂到电脑 USB 口。
4\. 打开 Windows 设备管理器 → 端口(COM 和 LPT),确认两个舵机控制板分别分配到不同 COM 端口。记录端口号(本项目从臂为 COM5,主臂为 COM6)。
### **2.2 摄像头自检**
**摄像头明细:**
本项目使用 3 路 USB 摄像头,各有不同用途。摄像头 index 可能因 USB 插拔顺序变化,首次使用需通过 lerobot-find-cameras 确认。
\# 激活 LeRobot 虚拟环境
D:/Lerobot/Lelab/venv/Scripts/activate
| 摄像头 | 用途 | index | 分辨率 | 帧率 | 安装位置 | 线材要求 |
| --- | --- | --- | --- | --- | --- | --- |
| 俯视摄像头[hardBreak](top) | ACT 模型训\[hardBreak\]练/推理的顶部视角 | 0 | 640x480 | 30fps | 机械臂正上方俯\[hardBreak\]拍,覆盖抓取区域 | USB 线长约 1\[hardBreak\]米 |
| 手腕摄像头[hardBreak](wan) | ACT 模型训\[hardBreak\]练/推理的手腕视角 | 1 | 640x480 | 30fps | 安装在机械臂腕部,跟随手腕运动 | USB 线需柔韧耐弯折 |
| 扫码摄像头(qr) | 扫描嘉宾出\[hardBreak\]示的二维码 | 2 | 640x480 | 30fps | 签到台面正面,对准鸾幟示嘉宾出示位置 | USB 线长约 1米 |
三路摄像头均为 USB 免驱 200 万像素高清摄像头。分辨率在代码中统一设置为 640x480@30fps,与 LeRobot 录制/训练/部署链路保持一致。
\# 列出所有摄像头,确认 index 编号
lerobot-find-cameras
\# 预期输出:列出 index=0, 1, 2 三个摄像头
\# 检查测试帧图片是否正常(保存在 lerobot/outputs/captured_images)
\# 如果 index 编号不对(如换过 USB 口),拔插摄像头后重新运行此命令确认
**摄像头 index 重要性**
三路摄像头的 index 必须与代码配置一致:index=0 是 ACT 俯视摄像头,index=1 是 ACT 手腕摄像头,index=2 是二维码扫描摄像头。如果 USB 接口变更导致 index 变化,需同步修改 act_handover\_[adapter.py](http://adapter.py) 中的 ACT_TOP_CAMERA_INDEX、ACT_WAN_CAMERA_INDEX 和 qr\_[handover.py](http://handover.py) 中的 CAMERA_INDEX。
## **步骤 3:机械臂校准**
首次使用必须校准,校准数据保存在 LeRobot 配置目录,后续录制/训练/部署链路中保持一致。
### **3.1 校准从臂(Follower)**
\# 校准从臂(本项目 robot_id = Gigi,串口 = COM5)
lerobot-calibrate \\
--robot.type=so101_follower \\
--robot.port=COM5 \\
--[robot.id](http://robot.id)=Gigi
\# 按照终端提示操作:
\# 1. 将机械臂各关节移动到第一个校准位置(通常是完全伸直或归零位)
\# 2. 按回车确认
\# 3. 移动到第二个校准位置
\# 4. 按回车确认
\# 5. 校准完成后,终端输出 "Calibration done" 表示成功
**3.2 校准主臂(Leader)**
\# 校准主臂(遥操作设备)
lerobot-calibrate \\
--robot.type=so101_leader \\
--robot.port=COM6 \\
--[robot.id](http://robot.id)=Gigi_leader
**校准说明**
校准只需执行一次。校准后 [robot.id](http://robot.id)(Gigi)在后续录制、训练、部署中必须保持一致。如果更换舵机或拆卸重组,需要重新校准。
## **步骤 4:软件环境部署**
### **4.1 创建 LeRobot 虚拟环境**
\# 1. 安装 Python 3.12(从 [python.org](http://python.org) 下载,勾选 "Add Python to PATH")
\# 2. 创建虚拟环境
python -m venv D:/Lerobot/Lelab/venv
\# 3. 激活虚拟环境
D:/Lerobot/Lelab/venv/Scripts/activate
\# 4. 安装 LeRobot 及依赖
pip install --upgrade pip
pip install lerobot
pip install 'lerobot\[core_scripts,training\]'
pip install huggingface_hub
\# 5. 验证安装
lerobot-info
\# 预期输出:LeRobot 版本号、已安装依赖列表、可用策略类型
### **4.2 安装扫码依赖**
\# 在同一虚拟环境中安装
pip install opencv-python pyzbar pillow
\# pyzbar 需要系统级 ZBar 库:
\# Windows: 从 <https://zbar.osdn.io/> 下载安装 ZBar Windows installer
### **4.3 部署项目代码**
\# 项目目录结构
robot_qr_demo/
├── qr\_[handover.py](http://handover.py) # 主程序:扫码核验 + 触发递证
├── act_handover\_[adapter.py](http://adapter.py) # ACT 模型适配器
└── guest_database.xlsx # 嘉宾数据库(首次运行自动生成)
\# 将项目文件放到任意目录,例如:
cd C:/Users/sulei/Documents/Codex/2026-08-23/new-chat-2/outputs/robot_qr_demo
### **4.4 关键配置参数确认**
act_handover\_[adapter.py](http://adapter.py) 中以下参数需与实际硬件一致:
| 参数名 | 本项目实际值 | 如何确认 |
| --- | --- | --- |
| MODEL_PATH | C:/Users/sulei/.cache/.../005000/pretrained_model | 训练完成后从 HuggingFace Hub 下载或本地输出路径 |
| SO101_ROBOT_ID | Gigi | 校准时设定的 [robot.id](http://robot.id) |
| SO101_SERIAL_PORT | COM5 | 设备管理器中从臂的 COM 端口 |
| ACT_TOP_CAMERA_INDEX | 0 | lerobot-find-cameras 输出的俯视摄像头 index |
| ACT_WAN_CAMERA_INDEX | 1 | lerobot-find-cameras 输出的手腕摄像头 index |
| CAMERA_INDEX (qr_handover) | 2 | lerobot-find-cameras 输出的扫码摄像头 index |
| LELAB_VENV_PYTHON | D:/Lerobot/Lelab/venv/Scripts/python.exe | 虚拟环境 Python 路径 |
| LELAB_ROLLOUT_EXE | D:/Lerobot/Lelab/venv/Scripts/lerobot-rollout.exe | 虚拟环境中 lerobot-rollout 路径 |
### **4.5 验证 LeRobot 环境**
\# 完整验证流程
D:/Lerobot/Lelab/venv/Scripts/activate
\# 1. 验证 LeRobot 安装
lerobot-info
\# 2. 验证摄像头识别
lerobot-find-cameras
\# 3. 验证机械臂串口(需连接从臂 USB)
lerobot-find-port
\# 按提示:拔掉 USB → 回车 → 重新插入 → 回车
\# 确认输出端口为 COM5(与配置一致)
\# 4. 模拟模式验证扫码流程(SIMULATION_MODE=True)
cd C:/Users/sulei/Documents/Codex/2026-08-23/new-chat-2/outputs/robot_qr_demo
python qr\_[handover.py](http://handover.py)
\# 用手机展示二维码 → 终端输出 \[核验\] OK 成功 → \[ACT\] >>> \[模拟模式\] 就绪
\# 表示环境部署完成
1、核心场景:嘉宾出示二维码 → 系统扫码 → 数据库匹配 → 返回核验结果
2、核心功能:摄像头采集二维码 → 解码 → 查询数据库 → 匹配嘉宾信息与证件类型
3、输入:嘉宾二维码图像;输出:核验结果 + 证件类型
4、技术路径:
①环节:扫码与核验代码
②技术选型:AI Agent 辅助开发(Trae Work / Vibe Coding)
③实现方式:使用 Trae Work 的 AI Agent 生成二维码扫描、数据库查询、匹配逻辑代码,人工审核与调试
备注:技术选型说明:AI Agent(Trae Work):用于快速生成扫码识别、数据库交互、触发逻辑等标准化代码模块,显著降低开发门槛与编码耗时,开发者聚焦于逻辑设计与联调验证。
5、二维码扫描与数据核验代码:

扫码核验具体步骤:
## **步骤 1:数据库初始化**
本项目使用 Excel 文件(guest_database.xlsx)作为嘉宾数据库,首次运行程序时自动生成。
### **1.1 嘉宾数据结构**
嘉宾数据以 Python 列表形式硬编码在 qr\_[handover.py](http://handover.py) 中,程序启动时自动导出为 Excel 文件。数据结构如下:
\# qr\_[handover.py](http://handover.py) 中的嘉宾数据库定义
GUEST_DATABASE = \[
{"guest_id": "GUEST-001", "name": "张晨", "organization": "星河科技",
"certificate": "VIP 嘉宾证", "slot_id": 0, "status": "未领取"},
{"guest_id": "GUEST-002", "name": "李雅", "organization": "远景医疗",
"certificate": "演讲嘉宾证", "slot_id": 0, "status": "未领取"},
{"guest_id": "GUEST-003", "name": "王浩", "organization": "智联制造",
"certificate": "参会嘉宾证", "slot_id": 0, "status": "未领取"},
{"guest_id": "GUEST-004", "name": "陈敏", "organization": "新锐资本",
"certificate": "合作伙伴证", "slot_id": 0, "status": "未领取"},
\]
### **1.2 数据库自动生成与回读**
程序启动时执行以下流程:
1\. load_test_database():检查是否存在 guest_database.xlsx,如果存在则回读嘉宾领取状态(避免程序重启后状态清零)。
2\. export_test_database():将内存中的嘉宾数据(含最新状态)导出为 Excel 文件,生成 guest_database.xlsx。
3\. scan_from_camera():启动摄像头持续扫描二维码。
### **1.3 修改嘉宾数据**
如需新增或修改嘉宾信息,直接编辑 qr\_[handover.py](http://handover.py) 中的 GUEST_DATABASE 列表,重新运行程序即可自动生成更新后的 Excel 文件。也可直接修改 guest_database.xlsx 文件(程序关闭时),下次启动时会自动回读。
**状态说明**
嘉宾状态有三态:未领取(初始)、处理中(机械臂正在执行递证,防重入锁定)、已领取(递证完成)。如果递证失败,状态自动回滚为未领取,允许再次扫码。
## **步骤 2:启动二维码扫描程序**
### **2.1 安装依赖**
\# 激活 LeRobot 虚拟环境
D:/Lerobot/Lelab/venv/Scripts/activate
\# 安装扫码依赖(如尚未安装)
pip install opencv-python pyzbar pillow
### **2.2 启动程序**
\# 进入项目目录
cd C:/Users/sulei/Documents/Codex/2026-08-23/new-chat-2/outputs/robot_qr_demo
\# 启动扫码核验程序
python qr\_[handover.py](http://handover.py)
程序启动后会依次执行:
1\. 从 guest_database.xlsx 回读嘉宾状态(如果文件存在)
2\. 导出/更新 guest_database.xlsx
3\. 打开 index=2 的摄像头,开始持续扫描二维码
4\. 终端输出 \[扫码\] 摄像头(index=2)已打开,等待识别二维码...... 即表示启动成功
### **2.3 扫码核验逻辑**
程序使用 cv2.QRCodeDetector 进行二维码识别。当检测到二维码时,执行以下核验流程:
1\. decode 二维码内容(如 GUEST-001)
2\. find_guest():在 GUEST_DATABASE 中按嘉宾编号查找
3\. 检查状态:如果已领取则拒绝(防重复),如果处理中则跳过(防重入)
4\. 核验通过:将状态锁为处理中,调用 act_handover_adapter.hand_over_certificate(guest) 触发机械臂
5\. 递证成功:状态改为已领取,记录时间戳,更新 Excel
6\. 递证失败:状态回滚为未领取,允许再次扫码
### **2.4 防重复触发机制(三重保护)**
qr\_[handover.py](http://handover.py) 中实现了三重防重复触发策略,避免同一个二维码被反复触发:
### **2.5 退出程序**
\# 按 Ctrl+C 安全退出
\# 程序会释放摄像头资源并打印:
\# \[扫码\] 收到 Ctrl+C,停止扫描。
\# \[扫码\] 摄像头资源已释放。
1、核心场景:核验通过 → 机械臂从物料区抓取证件 → 递送至指定位置 → 复位
2、核心功能:接收核验结果 → 生成触发指令 → 调用机械臂控制接口启动递发动作
3、输入:核验信号;输出:机械臂动作触发指令
4、技术路径:
①环节:机械臂数据录制与训练
②技术选型:LeRobot 开源框架(Hugging Face 官方 CLI)
③实现方式:使用 LeRobot CLI 进行遥操作示教数据录制、ACT 策略模型训练、模型调用与推理
备注:技术选型说明:LeRobot(Hugging Face):提供机械臂遥操作数据录制、策略训练、模型部署的开源工具链,免去从零搭建训练框架的成本,示教数据与训练模型可开源共享。
# **LeRobot 命令**
## **步骤 1:LeRobot 安装与环境配置**
环境搭建文档中已说明 LeRobot 的安装(见前置文档),此处补充机械臂相关的校准步骤。
### **1.1 校准机械臂**
校准从臂(首次使用必须执行,校准数据保存在 LeRobot 配置目录)
lerobot-calibrate \\
--robot.type=so101_follower \\
--robot.port=COM5 \\
--[robot.id](http://robot.id)=Gigi
校准主臂(遥操作设备,用于录制示教数据)
lerobot-calibrate \\
--robot.type=so101_leader \\
--robot.port=COM6 \\
--[robot.id](http://robot.id)=Gigi_leader
[**robot.id**](http://robot.id) **一致性要求**
校准时设定的 [robot.id](http://robot.id)(Gigi)在后续录制、训练、部署链路中必须保持一致。act_handover\_[adapter.py](http://adapter.py) 中 SO101_ROBOT_ID = "Gigi" 即对应此校准 ID。
## **步骤 2:遥操作数据录制**
目标:通过主臂(Leader)遥控从臂(Follower),录制「抓取证件 -> 递送至嘉宾面前 -> 松开 -> 复位」的动作序列,生成训练数据集。
### **2.1.1 前置准备**
录制前需完成以下准备:
1\. 登录 Hugging Face 平台。在终端执行 huggingface-cli login,输入你的 HF Token(从 <https://huggingface.co/settings/tokens> 获取)。这一步是必须的,因为录制的数据集会自动上传到 HuggingFace Hub 用于后续训练。
2\. 设置 HF 用户名环境变量。在 Windows CMD 中执行 set HF_USER=你的用户名,后续命令中用 %HF_USER% 引用。
3\. 确认硬件已连接:从臂上电(12V),主臂上电(5V),两根 Type-C 数据线分别连接到电脑 USB 口,三路摄像头已插入。
4\. 确认已校准:从臂校准 ID 为 Gigi(COM5),主臂校准 ID 为 Gigi_leader(COM6)。
### **2.1.2 启动数据录制命令**
在 LeRobot 虚拟环境中执行以下命令,启动遥操作数据录制。该命令会同时打开从臂的两路摄像头(俯视 + 手腕),录制关节角度和摄像头画面:
lerobot-record \\
--robot.type=so101_follower \\
--robot.port=COM5 \\
--[robot.id](http://robot.id)=Gigi \\
--robot.cameras="{top: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, wan: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}}" \\
--teleop.type=so101_leader \\
--teleop.port=COM6 \\
--[teleop.id](http://teleop.id)=Gigi_leader \\
--dataset.repo_id=%HF_USER%/checkin_badge_handover \\
--dataset.num_episodes=50 \\
--dataset.single_task="Pick up the badge card and hand it to the guest"
### **2.1.3 命令参数逐项说明**
**2.1.4 摄像头 JSON 配置格式说明**
\--robot.cameras 参数接受 JSON 格式的摄像头配置。字段名必须使用 LeRobot 规定的名称,否则会报 RobotConfig 错误:
**2.1.5 录制操作流程**
执行录制命令后,从臂会进入跟随模式。操作者手持主臂进行遥控,从臂会实时跟随主臂的运动。具体操作步骤:
1\. 命令执行后,终端会显示 "Recording episode 0/50",从臂进入跟随模式。
2\. 操作者手持主臂,缓慢移动到证件放置区,从臂会跟随到达。
3\. 闭合主臂夹爪,从臂夹爪同步闭合,抓取证件。
4\. 移动主臂将证件递送到嘉宾面前的指定位置。
5\. 松开主臂夹爪,从臂释放证件。
6\. 移动主臂回到初始位置,从臂跟随复位。
7\. 按回车键确认本条录制完成,终端显示 "Recording episode 1/50"。
8\. 如果本次动作不理想(如抓取失败、轨迹偏移),输入 r 并回车,丢弃当前 episode 重新录制。
9\. 重复步骤 2-8,直到录满 50 条。录制完成后,数据集自动上传到 HuggingFace Hub。
### **2.1.6 验证录制数据**
录制完成后,执行以下命令验证数据集的完整性和质量:
查看数据集基本信息
python -c "from lerobot.common.datasets.lerobot_dataset import LeRobotDataset; ds = LeRobotDataset('$HF_USER/checkin_badge_handover'); print(f'Episodes: {ds.num_episodes}, Frames: {len(ds)}')"
预期输出:
Episodes: 50, Frames: 7500 (每条约 150 帧,具体取决于动作时长)
也可以通过可视化工具回放示教轨迹,确认录制质量:
回放示教轨迹(弹出可视化窗口)
lerobot-visualize-dataset --repo-id=$HF_USER/checkin_badge_handover
## **2.2 ACT 策略模型训练**
目标:使用录制的 50 条示教数据,训练一个 ACT(Action Chunking Transformer)策略模型,使机械臂能够自主完成递发证件动作。
### **2.2.1 启动训练命令**
在 LeRobot 虚拟环境中执行以下命令,使用 ACT(Action Chunking Transformer)策略对示教数据进行训练。ACT 是一种基于 Transformer 的模仿学习策略,每次推理预测未来多步动作(action chunk),减少累积误差,适合机械臂操作任务。
#激活 LeRobot 虚拟环境
D:/Lerobot/Lelab/venv/Scripts/activate
#启动 ACT 策略训练
lerobot-train \
--policy.type=act \
--dataset.repo_id=%HF_USER%/checkin_badge_handover \
--steps=20000 \
--batch_size=4 \
--output_dir=outputs/train/checkin_act \
--job_name=act_2026-08-30 \
--save_checkpoint=true \
--save_freq=5000 \
--policy.device=cpu \
--policy.push_to_hub=true
#训练前置条件
执行训练命令前,需确保以下条件已满足:
**2.2.2 训练参数逐项说明**
**2.2.3 训练监控**
训练过程中可以通过 TensorBoard 实时监控 loss 曲线和学习率变化。在另一个终端窗口执行:
\# 启动 TensorBoard
tensorboard --logdir=outputs/train/checkin_act --port=6006
\# 在浏览器打开 <http://localhost:6006>
\# 关注 loss 曲线:正常情况下 loss 应从初始值(约 1.0-5.0)逐渐下降到 0.1-0.5 范围
\# 如果 loss 不下降,检查数据集质量或调整学习率
### **2.2.4 训练输出结构**
训练完成后,输出目录结构如下。每个 checkpoint 子目录中的 pretrained_model 文件夹包含可直接部署的模型权重:
outputs/train/checkin_act/
checkpoints/
5000/pretrained_model/ # 第 5000 步 checkpoint
10000/pretrained_model/ # 第 10000 步 checkpoint
15000/pretrained_model/ # 第 15000 步 checkpoint
20000/pretrained_model/ # 第 20000 步 checkpoint
last/pretrained_model/ # 最终 checkpoint(同 20000)
config.yaml # 完整训练配置文件
train_logs/ # 训练日志
### **2.2.5 选择最优 checkpoint**
训练过程中会保存多个 checkpoint。通常选择 loss 最低的 checkpoint 进行部署,不一定是最后一个。可以通过 TensorBoard 对比各 checkpoint 的 loss 值。本项目实际使用的是第 5000 步 checkpoint(实验中发现 5000 步效果最佳,后续步数可能过拟合):
\# 本项目实际使用的模型路径
\# C:/Users/sulei/.cache/huggingface/hub/
\# models--shuren2--act_2026-08-30_08-46-05
\# /snapshots/4bce61c23728018a2f473cbbd79057a08ea482d7
\# /checkpoints/005000/pretrained_model
1、核心场景:扫码核验 → 自动触发 → 机械臂递发 → 签到完成
2、核心功能:LeRobot 训练模型推理 → 执行抓取-递送-复位轨迹 → 完成证件发放
3、输入:动作指令;输出:物理递发动作完成
4、技术路径:
①环节:全链路触发与联调
②实现方式:Python 脚本编排
③编写触发脚本串联扫码结果与机械臂动作调用,实现事件驱动的自动化流程
5、全流程编排代码:
## **任务1:扫码核验**
### **1.1、数据库初始化**
嘉宾数据以 Python 列表形式定义在 qr\_[handover.py](http://handover.py) 文件中,包含 4 条嘉宾记录。每条记录有 6 个字段:嘉宾编号(如 GUEST-001)、姓名、单位、证件类型、槽位编号、领取状态。程序启动时自动执行以下操作:
1\. 检查当前目录是否存在 guest_database.xlsx 文件。如果存在,读取该文件并恢复嘉宾的领取状态(避免程序重启后状态清零)。
2\. 将内存中的嘉宾数据(含恢复的状态)导出为 guest_database.xlsx 文件,覆盖旧文件。
3\. 打开 index=2 的摄像头,进入扫码等待状态。
如需新增嘉宾,直接编辑 qr\_[handover.py](http://handover.py) 中的 GUEST_DATABASE 列表,添加新的字典项,重新运行程序即可。也可直接编辑 Excel 文件(程序关闭时),下次启动自动回读。
### **1.2、 扫码核验流程**
摄像头持续采集画面,使用 OpenCV 的 QRCodeDetector 检测并解码二维码。当检测到有效二维码时:
1\. 解码二维码内容(如 GUEST-001)。
2\. 在嘉宾数据库中按编号查找匹配。如果未找到,打印拒绝信息,等待下一次扫码。
3\. 检查嘉宾状态:如果状态为「已领取」,拒绝发放(防止重复签到)。如果状态为「处理中」,跳过(防止重入)。
4\. 核验通过:将状态临时锁为「处理中」,然后调用 act_handover\_[adapter.py](http://adapter.py) 的 hand_over_certificate() 函数触发机械臂。
5\. 递证成功:状态改为「已领取」,记录当前时间戳,更新 Excel 文件。
6\. 递证失败:状态回滚为「未领取」,允许嘉宾重新扫码。
### **1.3、 防重复触发机制**
为防止同一个二维码在机械臂执行期间被反复触发,程序实现了四重保护机制:
**任务2:机械臂递发**
### **1.1 数据录制**
通过主臂遥控从臂完成示教动作。操作者手持主臂,从臂实时跟随主臂运动。每次完成一个完整的「抓取证件 -> 递送 -> 松开 -> 复位」动作序列后按回车确认,LeRobot 自动保存关节角度和双路摄像头画面为一条 episode。共录制 50 条,录制完成后数据集自动上传到 HuggingFace Hub。
### **1.2 策略训练**
使用 LeRobot 的 lerobot-train 命令,以 ACT 策略对 50 条示教数据进行训练,共训练 20000 步,每 5000 步保存一次 checkpoint。ACT 策略的核心原理是:每次推理不是只预测下一步动作,而是预测未来多步动作(action chunk),减少累积误差。训练在 CPU 上约需 1-2 小时。训练过程中可通过 TensorBoard 监控 loss 曲线。训练完成后选择 loss 最低的 checkpoint 部署(本项目使用第 5000 步 checkpoint)。
### **1.3 模型部署**
核验通过后,系统调用 lerobot-rollout CLI 将训练好的 ACT 模型部署到机械臂。rollout 命令会自动连接机械臂、打开双路摄像头、加载模型权重、进入推理循环。每 0.25 秒采集一次摄像头画面和关节角度,送入模型推理,模型输出关节目标角度,机械臂各关节向目标运动。60 秒后机械臂自动归位。推理在 CPU 上运行,延迟约 50-100ms,满足实时控制需求。
## **任务3:全流程联调**
### **1.1 系统架构**
系统由两个 Python 文件组成:qr\_[handover.py](http://handover.py) 是主程序,负责扫码核验和流程编排;act_handover\_[adapter.py](http://adapter.py) 是适配器,负责模型加载和机械臂控制。两个文件通过函数调用串联:qr\_[handover.py](http://handover.py) 在核验成功后调用 act_handover\_[adapter.py](http://adapter.py) 的 hand_over_certificate() 函数触发机械臂。
### **1.2 启动方式**
启动命令为 python qr\_[handover.py](http://handover.py) 程序启动后自动初始化数据库、打开摄像头、进入扫码等待状态。
### **1.3 运行日志说明**
程序运行时在终端输出结构化日志,每条日志以 \[模块名\] 前缀标识来源。典型运行流程:
\# 程序启动
\[数据库\] 已从 Excel 回读嘉宾领取状态。
\[数据库\] 已导出/更新:guest_database.xlsx
\[扫码\] 摄像头(index=2)已打开,等待识别二维码......
\# 嘉宾扫码(二维码内容为 GUEST-001)
\[核验\] OK 成功:张晨 | 星河科技 | VIP 嘉宾证 | 槽位 0
\[ACT\] 调用官方 lerobot-rollout CLI 执行递证动作......
\# 机械臂执行中(约 60 秒)
\[ACT\] OK 官方 rollout 完成(耗时 60.2s,exit=0)。
嘉宾=张晨 / 证件=VIP 嘉宾证 / 槽位=0
\[核验\] = 递证动作已完成,记录已更新。
\[扫码\] 冷却 62.0s 后继续接待下一位嘉宾。
\# 下一位嘉宾(二维码内容为 GUEST-002)
\[核验\] OK 成功:李雅 | 远景医疗 | 演讲嘉宾证 | 槽位 0
......
### **1.4 异常处理说明**

# **一、项目代码获取方式**
## **1.1 代码文件清单**
## **1.2 下载方式**
方式一:HuggingFace Hub 获取模型和数据集
\# 1. 安装 huggingface_hub
pip install huggingface_hub
\# 2. 下载训练好的 ACT 模型
huggingface-cli download shuren2/act_2026-08-30_08-46-05 \\
--local-dir ./pretrained_model
\# 3. 下载示教数据集(可选,用于重新训练)
huggingface-cli download shuren2/checkin_badge_handover \\
--repo-type dataset \\
--local-dir ./checkin_badge_handover
方式二:直接复制代码文件
本文档附带的代码文件可直接复制使用。将 qr\_[handover.py](http://handover.py) 和 act_handover\_[adapter.py](http://adapter.py) 放到同一目录,按以下结构组织:
robot_qr_demo/
|-- qr\_[handover.py](http://handover.py) # 主程序
|-- act_handover\_[adapter.py](http://adapter.py) # ACT 适配器
|-- guest_database.xlsx # 首次运行后自动生成
## **1.3 获取后验证**
\# 激活 LeRobot 虚拟环境
D:/Lerobot/Lelab/venv/Scripts/activate
\# 进入项目目录
cd robot_qr_demo
\# 模拟模式验证(SIMULATION_MODE=True)
python qr\_[handover.py](http://handover.py)
\# 出示二维码(GUEST-001),预期输出:
\# \[核验\] OK 成功:张晨 | 星河科技 | VIP 嘉宾证 | 槽位 0
\# \[ACT\] >>> \[模拟模式\] 就绪:向 张晨 递交 VIP 嘉宾证。未发送实际动作。
\# 表示代码获取成功,环境配置正确。
二、训练执行细节
以下是从示教数据到训练出可用模型的具体执行步骤。
## **2.1 训练命令**
\# 激活虚拟环境
D:/Lerobot/Lelab/venv/Scripts/activate
\# 执行训练(CPU 约 1-2 小时)
lerobot-train \\
--policy.type=act \\
--dataset.repo_id=%HF_USER%/checkin_badge_handover \\
--steps=20000 \\
--batch_size=4 \\
--output_dir=outputs/train/checkin_act \\
--job_name=act_2026-08-30 \\
--save_checkpoint=true \\
--save_freq=5000 \\
--policy.device=cpu \\
--policy.push_to_hub=true
## **2.2 参数说明**
| 参数 | 值 | 说明 |
| --- | --- | --- |
| \--policy.type | act | ACT 策略,每次预测多步动作减少累积误差 |
| \--dataset.repo_id | $HF_USER/checkin_badge_handover | 训练数据集(录制步骤上传到 HF Hub) |
| \--steps | 20000 | 训练总步数,50 条数据建议 10000-30000 |
| \--batch_size | 4 | 批量大小,CPU 建议 4,内存不足降为 2 |
| \--output_dir | outputs/train/checkin_act | 输出目录,checkpoint 保存在 checkpoints/ 下 |
| \--save_freq | 5000 | 每 5000 步保存一次 checkpoint |
| \--policy.device | cpu | CPU 训练,ACT 模型小可完成 |
| \--policy.push_to_hub | true | 训练完成后推送到 HuggingFace Hub |
## **2.3 训练输出与模型选择**
训练完成后,checkpoint 保存在以下目录:
outputs/train/checkin_act/checkpoints/
5000/pretrained_model/ <- 本项目实际使用此 checkpoint
10000/pretrained_model/
15000/pretrained_model/
20000/pretrained_model/
last/pretrained_model/
通过 TensorBoard(tensorboard --logdir=outputs/train/checkin_act)对比各 checkpoint 的 loss 值,选择 loss 最低的部署。本项目使用第 5000 步 checkpoint。
## **2.4 训练后验证**
\# 查看数据集信息
python -c "from lerobot.common.datasets.lerobot_dataset import LeRobotDataset; ds = LeRobotDataset('$HF_USER/checkin_badge_handover'); print(f'Episodes: {ds.num_episodes}, Frames: {len(ds)}')"
\# 预期输出:Episodes: 50, Frames: 7500
# **三、部署执行细节**
以下是将训练好的模型部署到机械臂的具体执行步骤。
## **3.1 配置模型路径**
编辑 act_handover\_[adapter.py](http://adapter.py),修改以下参数:
\# 关闭模拟模式,使用真实部署
SIMULATION_MODE = False
USE_LELAB_ROLLOUT = True
\# 修改为你的模型路径(正斜杠,等号格式)
MODEL_PATH = Path(
"outputs/train/checkin_act/checkpoints/005000/pretrained_model"
)
\# 确认硬件参数与校准时一致
SO101_ROBOT_ID = "Gigi"
SO101_SERIAL_PORT = "COM5"
ACT_TOP_CAMERA_INDEX = 0
ACT_WAN_CAMERA_INDEX = 1
## **3.2 lerobot-rollout 完整命令**
核验通过后,系统自动构造并执行以下命令:
D:/Lerobot/Lelab/venv/Scripts/lerobot-rollout.exe \\
--robot.type so101_follower \\
--[robot.id](http://robot.id) Gigi \\
--robot.port COM5 \\
--robot.use_degrees True \\
--robot.max_relative_target 20.00 \\
--robot.cameras {"top": {"type": "opencv", "index_or_path": 0, "width": 640, "height": 480, "fps": 30}, "wan": {"type": "opencv", "index_or_path": 1, "width": 640, "height": 480, "fps": 30}} \\
--policy.path=outputs/train/checkin_act/checkpoints/005000/pretrained_model \\
--strategy.type base \\
--duration 60 \\
--device cpu \\
--return_to_initial_position True \\
--task handover_cert:张晨:VIP嘉宾证:slot0
## **3.3 rollout 参数说明**
| 参数 | 值 | 说明 |
| --- | --- | --- |
| \--robot.port | COM5 | 从臂串口,字符串格式(不能用整数 5) |
| \--robot.max_relative_target | 20.00 | 每关节每步最大 20 度(默认 5 度太小) |
| \--robot.cameras | JSON | 双路摄像头配置,字段名:index_or_path/width/height/fps |
| \--policy.path=<路径> | 等号格式 | 必须用等号连接,不能拆分。路径用正斜杠 |
| \--strategy.type | base | 自主推理模式 |
| \--duration | 60 | 运行 60 秒后自动停止并归位 |
| \--device | cpu | CPU 推理,延迟约 50-100ms |
| \--return_to_initial_position | True | 结束后回到初始姿态 |
## **3.4 Python 调用方法**
act_handover\_[adapter.py](http://adapter.py) 通过 subprocess 调用 lerobot-rollout,核心代码如下:
\# 1. 构造命令参数
def *build*lerobot_rollout_argv(guest):
cameras_dict = {
"top": {"type": "opencv", "index_or_path": 0,
"width": 640, "height": 480, "fps": 30},
"wan": {"type": "opencv", "index_or_path": 1,
"width": 640, "height": 480, "fps": 30},
}
argv = \[
"--robot.type", "so101_follower",
"--[robot.id](http://robot.id)", "Gigi",
"--robot.port", "COM5",
"--robot.use_degrees", "True",
"--robot.max_relative_target", "20.00",
"--robot.cameras", json.dumps(cameras_dict),
"--policy.path=" + str(MODEL_PATH), # 等号格式
"--strategy.type", "base",
"--duration", "60",
"--device", "cpu",
"--return_to_initial_position", "True",
"--task", "handover_cert:%s:%s:slot%s" % (
guest\["name"\], guest\["certificate"\], guest\["slot_id"\]),
\]
return argv
\# 2. 启动子进程并等待完成
def *run*lerobot_rollout_episode(guest):
argv = *build*lerobot_rollout_argv(guest)
full_cmd = \[str(LELAB_ROLLOUT_EXE)\] + argv
proc = subprocess.Popen(full_cmd, stdout=None, stderr=None)
while True:
rc = proc.poll() # 检查是否结束
if rc is not None:
break
if *signal*interrupted: # Ctrl+C 中断
proc.terminate()
break
time.sleep(0.2)
return rc == 0 # 退出码 0 表示成功
## **3.5 部署执行流程**
核验通过后,系统按以下步骤自动执行:
1\. qr\_[handover.py](http://handover.py) 核验成功,嘉宾状态锁为「处理中」
2\. 调用 act_handover\_[adapter.py](http://adapter.py) 的 hand_over_certificate(guest)
3\. 构造 lerobot-rollout 命令参数列表
4\. subprocess.Popen 启动 lerobot-rollout 子进程
5\. 子进程内部:连接机械臂 -> 打开摄像头 -> 加载模型 -> 推理循环(每 0.25 秒采集画面+关节角度 -> 模型推理 -> 发送动作)
6\. 机械臂自主完成「抓取证件 -> 递送 -> 松开 -> 复位」
7\. 60 秒后子进程退出,退出码 0 表示成功
8\. 主程序将嘉宾状态改为「已领取」,更新 Excel
9\. 系统冷却约 60 秒后恢复扫码,等待下一位
## **3.6 单独测试部署(不经过扫码)**
可跳过扫码流程,直接测试模型部署是否正常:
\# 直接运行 lerobot-rollout 测试模型
lerobot-rollout \\
--robot.type so101_follower \\
--[robot.id](http://robot.id) Gigi \\
--robot.port COM5 \\
--robot.use_degrees True \\
--robot.max_relative_target 20.00 \\
--robot.cameras "{top: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, wan: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}}" \\
--policy.path=outputs/train/checkin_act/checkpoints/005000/pretrained_model \\
--strategy.type base \\
--duration 60 \\
--device cpu \\
--display_data True \\
--return_to_initial_position True
\# --display_data True 可看到实时关节角度和摄像头画面
\# 预期:机械臂自主运动,完成抓取-递送-复位
## **3.7 全流程启动**
\# 确认 act_handover\_[adapter.py](http://adapter.py) 中:
\# SIMULATION_MODE = False
\# USE_LELAB_ROLLOUT = True
\# MODEL_PATH = <你的模型路径>
cd robot_qr_demo
python qr\_[handover.py](http://handover.py)
\# 嘉宾出示二维码(GUEST-001)
\# 系统自动:扫码 -> 核验 -> 机械臂递证 -> 归位 -> 等待下一位
\# 按 Ctrl+C 退出
**复现成功标志**
终端输出 \[核验\] OK 成功 -> \[ACT\] OK 官方 rollout 完成 -> 机械臂自主抓取证件并递送给嘉宾 -> 复位等待下一位 -> guest_database.xlsx 中该嘉宾状态变为已领取。建议连续测试 4 位嘉宾验证稳定性。