在 Ubuntu 22.04 虚拟机中调试宇树 A1 电机
- 相关文献
Ubuntu22.04虚拟机平台环境搭建教程见链接
juejin.cn/post/756722…
阶段 1:硬件连接与虚拟机设置
1.1 硬件连接
-
电源:确保 A1 电机已连接到 24V 直流电源。
-
通信:使用一个 USB-to-RS485 适配器。
-
接线:将 USB-to-RS485 适配器的
A和B端连接到 A1 电机的 RS485A和B端口。 -
隔离:确保在这条 RS485 总线上只连接了这一个电机。
1.2 虚拟机环境准备
-
启动 Ubuntu 22.04 虚拟机。
-
在虚拟机菜单(通常是顶部或底部的 “虚拟机” -> “可移动设备” 或 USB 图标)中,找到你的 USB-to-RS485 适配器(例如 "FTDI" 或 "CH340"),并选择 “连接到此虚拟机”。
-
打开 Ubuntu 终端,安装编译所需的依赖:
sudo apt update sudo apt install build-essential cmake
1.3 查找串口设备
-
在 Ubuntu 终端中,运行以下命令来查找你的适配器被分配到的设备名:
ls /dev/ttyUSB* -
你应该会看到输出,例如:
/dev/ttyUSB0
请记住这个名称,这就是你的串口路径。
(故障排除:如果提示 没有那个文件或目录,说明你的 USB 适配器没有被虚拟机正确“直通”。请返回步骤 1.2,拔插 USB 设备,并确保在虚拟机菜单中选中了它。)
阶段 2:编译官方 SDK 工具
-
将你拥有的
unitree_actuator_sdk文件夹(在本次调试中为unitree_actuator_sdk-A1B1) 放置到你的主目录(例如~/Downloads)下。 -
进入该目录,并创建
build文件夹来编译项目:# cd 到 SDK 根目录 cd ~/Downloads/unitree_actuator_sdk # 创建并进入 build 文件夹 mkdir build cd build # 运行 cmake cmake .. # 编译 make -
编译完成后,你会在
build文件夹内看到changeID和example_a1_motor两个可执行文件。
阶段 3:使用 changeID 设置电机 ID
此步骤将电机的 ID 设置为一个已知值(例如 2),以便后续程序可以调用它。
-
确保你仍在
build目录中。 -
使用
sudo权限运行changeID程序:sudo ./changeID -
程序会提示输入串口名称:
Please input the name of serial port.(e.g. Linux:/dev/ttyUSB0, Windows:\\.\COM3) -
输入你在步骤 1.3 中找到的名称,然后按 Enter 键:
/dev/ttyUSB0
5. 程序会尝试发送广播命令。你可能会看到警告,这是正常的:
[WARNING] SerialPort::recv, unblock version, wait time out [WARNING] motor id=187 does not reply
(解释:id=187 是 0xBB 的十进制,即广播ID。电机收到广播命令时不需要回复,所以此警告可忽略。)
- 程序会显示提示,表示已进入“ID修改模式”:
Please turn the motor. One time: id=0; Two times: id=1, Three times: id=2 ID can only be 0, 1, 2 Once finished, press 'a`
-
执行操作:
-
用手转动A1电机的输出轴。你会感觉到它在“咔-咔”地跳动(电子拨轮模式)。
-
根据提示,为了将 ID 设置为
2,你需要转动电机直到感觉到 3 次“咔”的跳动。 -
完成后,停止转动。
-
-
保存ID:
-
在终端中,按下
a键,然后按 Enter 键。 -
程序会发送“保存ID”的命令并退出。
-
至此,你的电机 ID 已被设置为
2。
-
阶段 4:使用 example_a1_motor 测试电机
此步骤用于验证 ID 是否设置成功,并测试电机的实际转动和数据反馈。
-
修改示例代码以匹配 ID:
-
example_a1_motor默认控制的 ID 可能不是2。我们需要修改它。 -
回到 SDK 根目录,编辑
example_a1_motor.cpp文件:cd ~/Downloads/unitree_actuator_sdk gedit example/example_a1_motor.cpp -
在文件中找到设置 ID 的行(例如
cmd.id = 0;或cmd.id = 1;),将其修改为你刚刚设置的 ID2:cmd.id = 2; -
保存文件并退出 (按
Ctrl+O,Enter,Ctrl+X)。
-
-
重新编译:
-
回到
build目录并重新运行make:cd build make
-
-
运行测试:
-
确保电机已固定好,防止转动时跳动。
-
运行修改后的程序:
sudo ./example_a1_motor
-
阶段 5:测试位置控制 (伺服模式)
这是 STM32 项目的核心目标:控制电机转到特定圈数(位置)。我们将修改 example_a1_motor.cpp 来实现“转动1圈并保持”。
-
重要概念:转子端 vs 输出端
-
宇树A1电机使用手册.pdf和宇树A1电机数据手册.pdf明确指出,A1 电机的减速比约为 9.1 (或 9)。 -
所有的控制指令(
Pos,W,K_P,K_W)都是发送给减速器前的电机转子的,而不是最终的输出轴 4。 -
因此,要让输出轴转 1 圈 (6.28 弧度),你需要命令电机转子转
6.28 * 9.1弧度 5。
-
-
修改示例代码 (位置模式):
-
打开
example_a1_motor.cpp文件:cd ~/Downloads/unitree_actuator_sdk gedit example/example_a1_motor.cpp -
将其
while(true)循环中的命令部分修改为如下内容。我们使用mode = 10(FOC伺服模式) 6666,并设置kp和kd:#include <unistd.h> #include "serialPort/SerialPort.h" #include "unitreeMotor/unitreeMotor.h" #define circle -2 //A1电机目标圈数 int main() { SerialPort serial("/dev/ttyUSB0"); MotorCmd cmd; MotorData data; while(true) { cmd.motorType = MotorType::A1; data.motorType = MotorType::A1; cmd.mode = queryMotorMode(MotorType::A1,MotorMode::FOC); // 模式10:闭环伺服 cmd.id = 0; // 你设置好的 ID cmd.kp = 0.007; // 位置刚度 Kp (一个示例值) cmd.kd = 0.7; // 速度刚度 Kd (一个示例值) // 目标:输出轴转 1 圈 (6.28 弧度) // 减速比为 9.1 (来自手册) cmd.q = 6.28 * 9.1*circle; // 目标位置 (转子端) cmd.dq = 0.0; // 目标速度 0 cmd.tau = 0.0; // 前馈力矩 0 serial.sendRecv(&cmd,&data); std::cout << std::endl; std::cout << "motor.q: " << data.q << std::endl; std::cout << "motor.temp: " << data.temp << std::endl; std::cout << "motor.W: " << data.dq << std::endl; std::cout << "motor.merror: " << data.merror << std::endl; std::cout << std::endl; usleep(200); } }
保存文件并退出 (按
Ctrl+O,Enter,Ctrl+X)。 -
-
重新编译:
cd build make -
运行测试 (位置模式):
-
安全警告:确保电机已固定。此命令会使电机立即转动circle圈(2圈)并强力锁止。
-
cmd.kp & cmd.kd调参:
cmd.kp从很小的值(0.001开始),如果刚开始扭矩太大导致电机响应太快,则减小cmd.kp,如果电机转速太慢,则增大cmd.kp
cmd.kd大致为cmd.kp的10倍,如果最后到达目标圈数的时候存在震荡,则增大cmd.kd -
运行程序:
sudo ./example_a1_motor -
预期结果:
-
电机快速转动 circle圈(circle*360度)。
-
电机强力地保持在 circle圈的位置,你用手无法转动它。
-
终端会打印
merror: 0,并且motor.q的值会稳定在-111.496附近 (即 6.28 * 9.1*circle)。
-
-
阶段 6:测试阻尼模式(待完善)
阻尼模式让电机变得“粘稠”,它会抵抗运动,但不会锁定位置。这在机器人腿部落地时非常有用。
-
修改示例代码 (阻尼模式):
-
根据手册,阻尼模式是速度模式的一种特例,设置
W=07。 -
终端输入
gedit example/example_a1_motor.cpp打开文件,并修改while(true)循环:// ... (while(true) 循环内部) cmd.mode = queryMotorMode(MotorType::A1,MotorMode::FOC); // 模式10 cmd.id = 2; cmd.kp = 0.0; // Kp 设为 0 cmd.kd = 3.0; // 仅设置 Kd (阻尼) cmd.q = 0.0; // 目标位置 0 cmd.dq = 0.0; // 目标速度 0 cmd.tau = 0.0; // ...
-
-
重新编译并运行:
cd build make sudo ./example_a1_motor -
预期结果:
-
电机不会主动转动。
-
用手转动电机输出轴:你会感觉到一股与你转动速度成正比的阻力,就像在转动一个粘稠的旋钮。
-
松手:电机会停在当前位置,而不是返回原点。
-
阶段 7:测试力矩模式(待完善)
此模式让电机输出恒定的力矩,这对于模拟弹簧或施加恒定压力很有用。
-
修改示例代码 (力矩模式):
-
根据手册,力矩模式需要将
Kp和Kd都设为 0 8。 -
终端
gedit example/example_a1_motor.cpp打开文件,并修改while(true)循环:// ... (while(true) 循环内部) cmd.mode = queryMotorMode(MotorType::A1,MotorMode::FOC); // 模式10 cmd.id = 2; cmd.kp = 0.0; // Kp 设为 0 cmd.kd = 0.0; // Kd 设为 0 cmd.q = 0.0; cmd.dq = 0.0; cmd.tau = 0.5; // 设置一个较小的前馈力矩 (单位 N.m) // ...
-
-
重新编译并运行:
cd build make sudo ./example_a1_motor -
预期结果:
-
电机开始以一个恒定的(较小的)力矩转动。
-
注意:由于没有负载,电机会持续加速直到达到最大速度 9。
-
你可以用手感觉到它在"使劲",但你可以轻易地阻止它。
-