微雪SO-ARM101机械臂

SO-ARM100/101 - Waveshare Wiki

https://wiki.seeedstudio.com/cn/lerobot_so100m_new

【SO-ARM机械臂Lerobot超详细上手教程:1序言】 https://www.bilibili.com/video/BV1H6UUBcErT/?share_source=copy_web&vd_source=9c987ed6ab5014f976c5bd5305300cc0

LeRobot SO-101 机械臂实践 · MyBlog

启用MuJoCo仿真

拉取官方lerobot仓库

1
git clone https://github.com/huggingface/lerobot.git ~/lerobot

使用UV安装GPU-Torch 和 MuJoCo

1
2
3
4
uv venv
uv pip install torch --torch-backend=auto
uv add mujoco
uv sync

配置舵机id

SO-ARM100/101 设置舵机的 ID - Waveshare Wiki
跟着教程,其实就是先电脑连接上控制板,使用命令查看端口号,因为使用uv虚拟环境,所以最好使用uv run

1
uv run lerobot-find-port

开始配置

1
uv run lerobot-setup-motors --robot.type=so101_follower --robot.port=COM13

其中robot.type指的是从臂:so101_follower
改成teleop.type就可以配置主臂,端口也要改成teleop.port

然后从爪子开始,每次只连接一个到控制板上面,然后按回车会依次进行编号

校准

1
uv run lerobot-calibrate  --teleop.type=so101_leader --teleop.port=COM12 --teleop.id=so101_leader

需要先把每个关节舵机调整成中间,然后在进行校准,扭动舵机,从最小到最大

进行测试

先去收录仓库下载MuJoCo的文件,选中的是scene.xml

如果在上面的步骤中使用uv add mujoco的话,那么把下面的代码在lerobot目录下创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import time
import mujoco
import mujoco.viewer
import numpy as np

# LeRobot 导入
from lerobot.teleoperators.so_leader.so_leader import SOLeader
from lerobot.teleoperators.so_leader.config_so_leader import SOLeaderTeleopConfig

# 配置
XML_PATH = r"D:\tempfolder\arm\101\scene.xml"
LEADER_PORT = "COM12" # 用户指定的端口

# 关节名称映射
# Mujoco XML 关节名称: shoulder_pan, shoulder_lift, elbow_flex, wrist_flex, wrist_roll, gripper
# SOLeader 电机名称: shoulder_pan, shoulder_lift, elbow_flex, wrist_flex, wrist_roll, gripper
# 名称完全匹配,所以我们可以直接映射。

JOINT_NAMES = [
"shoulder_pan",
"shoulder_lift",
"elbow_flex",
"wrist_flex",
"wrist_roll",
"gripper",
]

def main():
# 1. 初始化真实的 LeRobot 主臂 (Leader Arm)
print(f"正在初始化 SOLeader,端口: {LEADER_PORT}...")

# 配置使用角度 (degrees),方便后续转换为弧度 (radians)
leader_config = SOLeaderTeleopConfig(port=LEADER_PORT, use_degrees=True)
leader = SOLeader(leader_config)

try:
leader.connect()
print("主臂连接成功!")
except Exception as e:
print(f"主臂连接失败: {e}")
print("请检查端口和连接是否正常。")
return

# 2. 初始化 Mujoco 仿真环境
print(f"正在加载 Mujoco 模型: {XML_PATH}...")
try:
m = mujoco.MjModel.from_xml_path(XML_PATH)
d = mujoco.MjData(m)
except Exception as e:
print(f"Mujoco 模型加载失败: {e}")
leader.disconnect()
return

print("开始遥操作循环...")
print("按 Ctrl+C 停止。")

# 3. 遥操作循环 (Teleoperation Loop)
with mujoco.viewer.launch_passive(m, d) as viewer:
start_time = time.time()
try:
while viewer.is_running():
# 读取主臂动作
# 返回字典 {motor_name.pos: value},单位为角度 (因为设置了 use_degrees=True)
leader_action = leader.get_action()

# 应用到 Mujoco 仿真中
for i, name in enumerate(JOINT_NAMES):
motor_key = f"{name}.pos"
if motor_key in leader_action:
# 获取角度值
deg_val = leader_action[motor_key]

# 转换为弧度 (Mujoco 使用弧度)
rad_val = np.deg2rad(deg_val)

# 在 Mujoco 模型中查找关节 ID
joint_id = mujoco.mj_name2id(m, mujoco.mjtObj.mjOBJ_JOINT, name)
if joint_id != -1:
# 获取关节在 qpos 中的地址
qpos_adr = m.jnt_qposadr[joint_id]
# 设置关节位置
d.qpos[qpos_adr] = rad_val

# 步进仿真
mujoco.mj_step(m, d)

# 同步视图
viewer.sync()

# 保持循环频率 (约 60Hz)
time.sleep(1.0/60.0)

except KeyboardInterrupt:
print("正在停止...")
finally:
leader.disconnect()
print("断开连接。")

if __name__ == "__main__":
main()

解释

为什么需要分配id

简单来说,舵机分配 ID 的过程就是通过串口通讯修改舵机内部芯片的“身份证号”(EEPROM 配置)

以下是这一过程的技术原理和操作逻辑拆解:

  1. 为什么需要分配 ID?

• 出厂默认 ID 都是 1:所有的 Feetech STS3215 舵机出厂时,内部存储器里的 ID 号都被写死为 1

• 总线通讯原理:这些舵机使用的是**串行总线(Serial Bus)**通信。这意味着所有舵机都挂在同一根通讯线上(Tx/Rx)。当电脑发送指令“ID 为 1 的舵机请转动”时,如果线上挂着 6 个 ID 都是 1 的舵机,它们会同时响应,或者返回的数据会互相干扰(总线冲突),导致通信失败。

• 区分关节:为了让电脑能单独指挥“手腕”或“底座”,我们必须给每个关节分配一个独一无二的数字(1 到 6)。

  1. 分配 ID 的核心逻辑(如何改写)

无论是使用 Python 脚本还是 Windows 软件,底层的操作步骤都是一样的:

1. 物理隔离(关键步骤)

    ◦ 因为所有新舵机 ID 都是 1,你不能把它们串联起来一次性改。如果串联了,电脑发“把 ID 1 改成 6”,所有舵机都会变成 6。

    ◦ 因此,必须只连接一个舵机到驱动板上,。

2. 发送改写指令

    ◦ 电脑通过 USB 转串口(驱动板)发送一串十六进制指令。

    ◦ 指令含义大致是:[广播/针对ID 1] [写入内存] [地址: ID寄存器] [新数值: 6]

    ◦ 这个新 ID 会被写入舵机的 EEPROM(非易失性存储器),这意味着断电后 ID 依然会保存,不需要每次开机都重设。

3. 验证

    ◦ 写入后,程序通常会尝试用新 ID(比如 6)去 ping 一下舵机。如果舵机有回应,说明修改成功。

  1. LeRobot 的分配策略(倒序法)

LeRobot 官方脚本采用了一种特定的顺序,为了防止混淆,通常建议您遵循这个映射表,:

关节名称 (Joint Name) 部位描述 分配 ID
Gripper 夹爪(最末端) 6
Wrist Roll 手腕旋转 5
Wrist Flex 手腕弯曲 4
Elbow 肘部 3
Shoulder Lift 肩部升降 2
Shoulder Pan 底座旋转 1

脚本的操作流程是这样的,:

1. 程序提示:Connect ... 'gripper' motor only

2. 您只插入夹爪舵机。

3. 程序扫描(通常扫描 ID 1),找到舵机。

4. 程序发送指令:将 ID 1 改为 6

5. 程序提示:Connect ... 'wrist_roll' motor only

6. 您拔掉夹爪舵机,换上第二个舵机(它是新的,ID 还是 1)。

7. 程序发送指令:将 ID 1 改为 5

8. ……以此类推,直到底座(ID 1)。

  1. 如果您使用 Windows GUI 工具 (Feetech/Hiwonder)

既然您在 Windows 上,且之前的脚本有报错,您也可以用“上帝视角”手动修改,原理更直观:

1. 打开 BusLinker 或 FD (Feetech Debugger) 软件。

2. 连接一个舵机。

3. 点击 “Search” (搜索) -> 软件会显示探测到 ID: 1

4. 在 ID 设置栏输入 6,点击 “Set” (设置/写入)

5. 此时软件再搜索,就会显示探测到 ID: 6

6. 拔掉它,贴上标签“6”,换下一个,重复步骤改为 5、4、3…

总结

这个过程本质上就是给每个刚出生的“克隆人”(ID 1)发一张不同的身份证(ID 1-6),这样以后它们坐在同一条船(总线)上时,电脑叫谁的名字,谁才会答应。

⚠️ 重要提示:一旦您把 ID 改乱了(比如两个舵机都设成了 3),把它们串联在一起时就会报错。解决方法是单独把其中一个连上电脑,重新把 ID 改掉。