通过OpenClaw接入机械臂,实现自然语言控制机械臂 保姆教程
最近OpenClaw实在是太火啦,所以花了一下午来实现了一个简单OpenClaw的项目
本文参考上述大大的文章实现使用openclaw控制机械臂运动,做一个我的技术的分享
首个用openclaw跑通七轴臂控制教学!_openclaw 机械臂-CSDN博客
实现效果如下:
演示
我的演示设备如下:
1. Ubutun 20.4的虚拟机
2. 6轴自由度的机械臂
3. 串口线
整个步骤如下:
一、OpenClaw配置
1. 进入OpenClaw — Personal AI Assistant网址
复制命令
关于Ubutun如何配置node.js,参考这个网址Ubuntu 20.04 下 OpenClaw(龙虾)本地化部署保姆级教程_ubuntu安装龙虾-CSDN博客
npm i -g openclaw
安装之后输入这个命令
openclaw onboard
Yes

QuickStart

Use existing values

这里选择模型的API,我这里使用的是Kimi,因为注册送10块钱
大家可以跟我一起去创建一个api,Kimi API 开放平台

得到你的API号,粘贴过来就行了
在这里输入你的API号码

选择现有模型

跳过选择

继续跳过
后面一连串都选择NO

继续跳过hooks

Restart
用网页端
这里有一个坑,就是Ubutun原生的火狐浏览器可能打不开,建议下载一个微软浏览器,粘贴网址过来即可。
进来时下述画面,openclaw就配置好了。
二、配置机械臂的SDK
这一部分根据你自己的机械臂的不同可以不同使用
我以我的丐版6轴机械臂为例
我的机械臂是以STM32单片机做一个控制,然后用使用串口线跟虚拟机做一个通信,串口线是USB转CH340。

所以需要在虚拟机上面先编写一个CH341的驱动,参考这篇帖子
CH340 CH341 Linux驱动最完整使用教程(永久解决/dev/ttyUSB0 permission denied问题,USB设备读写C++实现)_ttych341usb0: ch341 usb device-CSDN博客
驱动编译完了挂载之后,会发现驱动节点和设备节点,如下
接下来就是自己定义通信的舵机协议,可以参考我的C代码,fasong.c 如下:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include <stdlib.h>
// 角度转PWM值 (0-270度 -> 500-2500)
int angle_to_pwm(int angle) {
// 确保角度在有效范围内
if (angle < -135) angle = -135;
if (angle > 135) angle = 135;
// 线性映射:-135度->500,0度->1500,135度->2500
float pwm = 1500 + (angle * (1000.0 / 135.0));
return (int)(pwm + 0.5); // 四舍五入到最接近的整数
}
// 生成所有舵机指令的复合字符串
char *generate_compound_command(int angles[], int servo_count, int move_time) {
// 计算需要的缓冲区大小 (每个指令15字节 * 舵机数量 + 3{}+1)
int buf_size = 15 * servo_count + 4;
char *command = (char *)malloc(buf_size * sizeof(char));
if (command == NULL) {
perror("内存分配失败");
exit(1);
}
// 添加起始大括号
strcpy(command, "{");
for (int i = 0; i < servo_count; i++) {
int pwm = angle_to_pwm(angles[i]);
// 确保PWM值在有效范围内
if (pwm < 500) pwm = 500;
if (pwm > 2500) pwm = 2500;
// 追加单个舵机指令到复合字符串
char temp[16];
snprintf(temp, sizeof(temp), "#%03dP%04dT%04d!", i, pwm, move_time);
strcat(command, temp);
}
// 添加结束大括号
strcat(command, "}");
return command;
}
int main(int argc, char *argv[]) {
int fd;
const char *device = "/dev/ttyCH341USB0";
int angles[6]; // 存储6个舵机的角度值
int move_time = 1000; // 默认移动时间(ms)
// 检查命令行参数数量
if (argc < 7 || argc > 8) {
printf("用法: %s <角度1> <角度2> <角度3> <角度4> <角度5> <角度6> [时间(ms)]\n", argv[0]);
printf("例如: %s 90 45 0 45 90 135 1000\n", argv[0]);
printf("注意: 角度范围0-270度, 时间范围0-9999ms\n");
return 1;
}
// 将命令行参数转换为整数并存储到 angles 数组
for (int i = 0; i < 6; i++) {
angles[i] = atoi(argv[i + 1]);
if (angles[i] < -135 || angles[i] > 135) {
printf("错误: 角度值必须在 -135 到 135 之间\n");
return 1;
}
}
// 如果有时间参数,则使用
if (argc == 8) {
move_time = atoi(argv[7]);
if (move_time < 0 || move_time > 9999) {
printf("错误: 时间值必须在 0 到 9999 之间\n");
return 1;
}
}
// 生成复合指令字符串
char *compound_command = generate_compound_command(angles, 6, move_time);
printf("Generated compound command: %s\n", compound_command);
// 打开串口设备
fd = open(device, O_WRONLY | O_NOCTTY);
if (fd < 0) {
perror("无法打开设备");
free(compound_command);
return 1;
}
// 配置串口参数
struct termios tty;
if (tcgetattr(fd, &tty) != 0) {
perror("无法获取串口属性");
close(fd);
free(compound_command);
return 1;
}
// 设置波特率为115200
cfsetospeed(&tty, B115200);
cfsetispeed(&tty, B115200);
// 8N1 (8数据位, 无奇偶校验, 1停止位)
tty.c_cflag &= ~PARENB;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
// 禁用硬件流控制
tty.c_cflag &= ~CRTSCTS;
// 禁用软件流控制
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
// 设置为原始模式
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tty.c_oflag &= ~OPOST;
// 应用配置
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
perror("无法设置串口属性");
close(fd);
free(compound_command);
return 1;
}
// 发送复合指令
ssize_t written = write(fd, compound_command, strlen(compound_command));
if (written < 0) {
perror("写入数据失败");
} else {
printf("成功写入 %zd 字节指令: %s\n", written, compound_command);
}
// 释放内存
free(compound_command);
// 清空串口缓冲区
if (tcflush(fd, TCIOFLUSH) == 0) {
printf("串口缓冲区已清空\n");
} else {
perror("清空串口缓冲区失败");
}
// 关闭设备
close(fd);
return 0;
}
编写接口python jiekou.py
import subprocess
def control_arm(angles):
# 确保传入的角度列表长度为 6
if len(angles) != 6:
raise ValueError("角度列表必须包含 6 个值")
# 将角度值转换为字符串列表
angle_str = [str(angle) for angle in angles]
# 调用 C 可执行文件
try:
result = subprocess.run(
["./fasong"] + angle_str, # 可执行文件路径 + 参数
check=True, # 检查返回值
text=True, # 以文本模式捕获输出
capture_output=True # 捕获标准输出和标准错误
)
print(result.stdout) # 打印 C 程序的输出
except subprocess.CalledProcessError as e:
print(f"程序执行失败: {e}")
print(f"错误输出: {e.stderr}")
# 示例调用
#angles = [0, 0, 0, 0, 0, 0]
#control_arm(angles)
再往下就是机械臂的正逆运动学
理论可以参考这篇帖子:机器人学基础(1)-位置运动学-正运动学、逆运动学方程建立及其求解-CSDN博客
我这里图方便,就直接使用的python的roboticstoolbox的包,参考如下:
GitHub - petercorke/robotics-toolbox-python: Robotics Toolbox for Python · GitHub
定义好机械臂的DH矩阵(这个根据你自己的机械臂来),正逆运动学之后就可以定义一些基本的运动函数了
我的代码 dfbot_controller.py如下:
from roboticstoolbox import *
from spatialmath import *
import numpy as np
import time
from jiekou import control_arm
# =========================
# 1. 建立机械臂模型(前5轴参与运动学,最后一个是夹爪)
# =========================
DFbot = DHRobot(
[
RevoluteMDH(d=0.04145, qlim=np.array([-np.pi * 3 / 4, np.pi * 3 / 4])), # J1 底座左右
RevoluteMDH(alpha=np.pi / 2, qlim=np.array([-np.pi / 2, np.pi / 2])), # J2 大臂
RevoluteMDH(a=-0.08285, qlim=np.array([-np.pi * 3 / 4, np.pi * 3 / 4])), # J3 小臂
RevoluteMDH(a=-0.08285, qlim=np.array([-np.pi * 3 / 4, np.pi * 3 / 4])), # J4 手肘/腕部
RevoluteMDH(alpha=-np.pi / 2, d=0.11, qlim=np.array([0, np.pi])), # J5 末端左右转
],
name="DFbot",
)
# =========================
# 2. 角度转换
# =========================
def convert_deg(deg, gripper=0):
d1 = deg[0]
d2 = -90 - deg[1]
d3 = deg[2]
d4 = deg[3] - 90
d5 = deg[4]
return [d1, d2, d3, d4, d5, gripper]
def rad_to_deg(state):
return [float(x) / np.pi * 180 for x in state]
def deg_to_rad(deg):
return np.array([x / 180 * np.pi for x in deg], dtype=float)
# =========================
# 3. 关节限位处理
# =========================
def clip_to_joint_limits(q):
q_new = np.array(q, dtype=float).copy()
for i, link in enumerate(DFbot.links):
if link.qlim is not None:
qmin, qmax = link.qlim
q_new[i] = np.clip(q_new[i], qmin, qmax)
return q_new
def within_joint_limits(q):
for i, link in enumerate(DFbot.links):
if link.qlim is not None:
qmin, qmax = link.qlim
if q[i] < qmin or q[i] > qmax:
return False
return True
# =========================
# 4. 基础控制
# =========================
def move_joint_rad(state, delay=1, gripper=0):
state = clip_to_joint_limits(state)
deg = rad_to_deg(state)
cmd = convert_deg(deg, gripper=gripper)
print("关节角(弧度):", state)
print("关节角(角度):", deg)
print("发送给机械臂:", cmd)
control_arm(cmd)
time.sleep(delay)
return state
def move_joint_deg(deg, delay=1, gripper=0):
cmd = convert_deg(deg, gripper=gripper)
print("输入角度:", deg)
print("发送给机械臂:", cmd)
control_arm(cmd)
time.sleep(delay)
# =========================
# 5. 单关节增量控制
# =========================
def move_joint_delta(state_now, joint_index, delta_rad, delay=1, gripper=0):
"""
joint_index: 0~4
delta_rad: 该关节增量(弧度)
"""
state_new = np.array(state_now, dtype=float).copy()
state_new[joint_index] += delta_rad
state_new = clip_to_joint_limits(state_new)
print(f"\n--- 第 {joint_index+1} 关节增量运动 {np.degrees(delta_rad):.2f} 度 ---")
return move_joint_rad(state_new, delay=delay, gripper=gripper)
# =========================
# 6. 逆运动学:只优先约束位置
# =========================
def solve_ik_position_only(T_target, q0, mask=None, ilimit=200, slimit=200):
if mask is None:
mask = [1, 1, 1, 0, 0, 0]
sol = DFbot.ikine_LM(
T_target,
q0=q0,
ilimit=ilimit,
slimit=slimit,
joint_limits=True,
mask=mask
)
return sol
# =========================
# 7. 单步笛卡尔相对移动
# =========================
def move_cartesian_relative_once(state_now, dx=0, dy=0, dz=0, delay=1, show_result=True):
T_now = DFbot.fkine(state_now).A
T_target = T_now.copy()
T_target[0, 3] += dx
T_target[1, 3] += dy
T_target[2, 3] += dz
print("当前末端位姿 T_now =\n", T_now)
print("目标末端位姿 T_target =\n", T_target)
sol = solve_ik_position_only(T_target, q0=state_now)
if not sol.success:
print("逆运动学求解失败!")
print("失败原因:", sol.reason)
return False, state_now
state_new = clip_to_joint_limits(sol.q)
if not within_joint_limits(state_new):
print("逆解结果超出关节限制")
return False, state_now
if show_result:
print("逆解成功,新的关节角(弧度):", state_new)
print("新的关节角(角度):", rad_to_deg(state_new))
state_new = move_joint_rad(state_new, delay=delay)
return True, state_new
# =========================
# 8. 带缩步重试的笛卡尔移动
# =========================
def move_cartesian_relative(state_now, dx=0, dy=0, dz=0, delay=1, show_result=True, retry=5):
scale = 1.0
for k in range(retry):
dx_try = dx * scale
dy_try = dy * scale
dz_try = dz * scale
print(f"\n第 {k+1} 次尝试: dx={dx_try:.4f}, dy={dy_try:.4f}, dz={dz_try:.4f}")
ok, state_new = move_cartesian_relative_once(
state_now,
dx=dx_try,
dy=dy_try,
dz=dz_try,
delay=delay,
show_result=show_result
)
if ok:
return state_new
scale *= 0.5
print("本次失败,自动缩小步长后重试...")
print("多次尝试后仍然失败,保持原状态不动。")
return state_now
# =========================
# 9. 分步平滑移动
# =========================
def move_cartesian_smooth(state_now, dx=0, dy=0, dz=0, steps=5, delay=0.5):
dx_step = dx / steps
dy_step = dy / steps
dz_step = dz / steps
for i in range(steps):
print(f"\n===== 平滑移动第 {i+1}/{steps} 步 =====")
state_now = move_cartesian_relative(
state_now,
dx=dx_step,
dy=dy_step,
dz=dz_step,
delay=delay,
show_result=True,
retry=5
)
return state_now
# =========================
# 10. 末端上下动作(保留逆运动学)
# =========================
def move_up(state_now, step=0.02, delay=1, smooth=True):
print("\n--- 执行动作:向上移动 ---")
if smooth:
return move_cartesian_smooth(state_now, dz=step, steps=5, delay=delay)
else:
return move_cartesian_relative(state_now, dz=step, delay=delay)
def move_down(state_now, step=0.02, delay=1, smooth=True):
print("\n--- 执行动作:向下移动 ---")
if smooth:
return move_cartesian_smooth(state_now, dz=-step, steps=5, delay=delay)
else:
return move_cartesian_relative(state_now, dz=-step, delay=delay)
# =========================
# 11. 重新定义左右动作:直接控制第1关节
# =========================
def move_left(state_now, step_deg=5, delay=1):
"""
向左:底座(第1关节)左转
"""
print("\n--- 执行动作:向左(底座左转) ---")
return move_joint_delta(state_now, joint_index=0, delta_rad=np.deg2rad(step_deg), delay=delay)
def move_right(state_now, step_deg=5, delay=1):
"""
向右:底座(第1关节)右转
"""
print("\n--- 执行动作:向右(底座右转) ---")
return move_joint_delta(state_now, joint_index=0, delta_rad=np.deg2rad(-step_deg), delay=delay)
# =========================
# 12. 重新定义旋转动作:直接控制第5关节
# =========================
def rotate_left(state_now, step_deg=5, delay=1):
"""
向左旋转:第5关节左转
"""
print("\n--- 执行动作:向左旋转(末端左转) ---")
return move_joint_delta(state_now, joint_index=4, delta_rad=np.deg2rad(step_deg), delay=delay)
def rotate_right(state_now, step_deg=5, delay=1):
"""
向右旋转:第5关节右转
"""
print("\n--- 执行动作:向右旋转(末端右转) ---")
return move_joint_delta(state_now, joint_index=4, delta_rad=np.deg2rad(-step_deg), delay=delay)
# =========================
# 13. 夹爪控制(第6通道)
# =========================
def gripper_open(state_now, gripper_deg=30, delay=1):
print("\n--- 执行动作:夹爪打开 ---")
return move_joint_rad(state_now, delay=delay, gripper=gripper_deg)
def gripper_close(state_now, gripper_deg=0, delay=1):
print("\n--- 执行动作:夹爪闭合 ---")
return move_joint_rad(state_now, delay=delay, gripper=gripper_deg)
# =========================
# 14. 组合动作封装
# =========================
def action_up_down(state_now, step=0.02, delay=1):
print("\n=== 组合动作:上 -> 下 ===")
state_now = move_up(state_now, step=step, delay=delay, smooth=True)
state_now = move_down(state_now, step=step, delay=delay, smooth=True)
return state_now
def action_left_right(state_now, step_deg=10, delay=1):
print("\n=== 组合动作:左 -> 右 ===")
state_now = move_left(state_now, step_deg=step_deg, delay=delay)
state_now = move_right(state_now, step_deg=step_deg, delay=delay)
return state_now
def action_rotate_lr(state_now, step_deg=10, delay=1):
print("\n=== 组合动作:左旋 -> 右旋 ===")
state_now = rotate_left(state_now, step_deg=step_deg, delay=delay)
state_now = rotate_right(state_now, step_deg=step_deg, delay=delay)
return state_now
# =========================
# 15. 推荐姿态
# =========================
state0 = np.array([0, 0, 0, 0, 0], dtype=float)
state_ready = np.array([0, -0.4, 0.5, 0.6, 0.2], dtype=float)
deg0 = [0, 0, 0, 0, 0]
# =========================
# 16. 可视化
# =========================
DFbot.plot(state0, block=False)
# =========================
# 17. 主程序
# =========================
if __name__ == "__main__":
print("\n===== 到初始位置 =====")
current_state = move_joint_deg(deg0, delay=2)
print("\n===== 到 ready 姿态 =====")
current_state = move_joint_rad(state_ready, delay=2)
#print("\n===== 测试:向上 =====")
#current_state = move_up(current_state, step=0.03, delay=0.6, smooth=True)
#print("\n===== 测试:向下 =====")
#current_state = move_down(current_state, step=0.06, delay=0.6, smooth=True)
print("\n===== 测试:向左 =====")
current_state = move_left(current_state, step_deg=50, delay=1)
print("\n===== 测试:向右 =====")
current_state = move_right(current_state, step_deg=50, delay=1)
#print("\n===== 测试:向左旋转 =====")
#current_state = rotate_left(current_state, step_deg=50, delay=1)
#print("\n===== 测试:向右旋转 =====")
#current_state = rotate_right(current_state, step_deg=50, delay=1)
#print("\n===== 测试:夹爪打开/闭合 =====")
#gripper_open(current_state, gripper_deg=30, delay=1)
#gripper_close(current_state, gripper_deg=0, delay=1)
print("\n===== 动作执行完成 =====")
到此,其实已经可以直接在虚拟机上面控制机械臂运动了
三、配置OpenClaw的skill
我们上面已经定义好机械臂的运动代码了,现在想直接使用自然语言进行一个机械臂运动的控制,OpenClaw刚好可以实现上述功能,本质上就是根据你事先配置好的skill.md进行学习
首先我们需要找到OpenClaw的目录我的如下:
进入skills目录下,创建一个新的目录dfbot-arm-codegen,再在此目录下创建一个新的文件夹references

在dfbot-arm-codegen目录下创建一个skill.md的脚本文件,用来教会OpenClaw如何使用你编译好的代码
脚本内容如下:
---
name: dfbot-arm-codegen
description: 引导 OpenClaw 生成基于 DFbot 机械臂的控制代码。支持笛卡尔空间位移、关节控制和夹爪操作。
metadata:
{
"openclaw":
{
"emoji": "🤖",
"requires": { "bins": ["python3"] },
},
}
---
## 功能概览
- 本技能根据用户指令生成 Python 脚本。
- 依赖用户本地的 `dfbot_controller.py` 模块。
## 生成代码的硬性规则 (CRITICAL)
1. **指定运行与存放目录**:
- CRITICAL: 所有生成的 Python 脚本必须明确说明或默认在以下目录下运行:
`/home/rlk/.nvm/versions/node/v22.22.1/lib/node_modules/openclaw/workspace`
- 提醒用户确保 `dfbot_controller.py` 和 `jiekou.py` 已放置在该目录下,否则脚本将无法导入依赖。
2. **状态追踪**:
- 机械臂所有移动函数(如 `move_up`, `move_left`)都必须接收 `state_now` 并在执行后返回新的 `current_state`。
- 必须链式更新状态:`current_state = move_up(current_state, ...)`。
3. **导入与初始化**:
- 必须从 `dfbot_controller` 导入 `deg0`, `state_ready` 以及各种 `move_*` 函数。
- 脚本开头通常先执行 `current_state = move_joint_deg(deg0)` 初始化。
4. **单位规范**:
- 笛卡尔移动 (`move_up/down/smooth`) 单位是 **米 (m)**。
- 关节转动 (`move_left/right`, `rotate_left/right`) 单位是 **度 (°)**。
- 夹爪开合单位是 **度 (°)** (30度为开,0度为关)。
## 使用本技能生成代码
- 根据用户需求,结合 `references/robot-api.md` 生成完整脚本。
- 生成后告知用户:脚本已针对 `/home/rlk/.nvm/versions/node/v22.22.1/lib/node_modules/openclaw/workspace` 路径优化,请在该目录下执行 `python3 <生成的脚本名>.py`。
## 参考资料
- 详细 API 见 `references/robot-api.md`。
再references目录创建robot-api.md教会它如何使用我们定义好的函数
# DFbot API 速查与最小可运行模板
供 OpenClaw 根据用户自然语言生成机械臂控制代码时参考。所有底层逻辑已在 `dfbot_controller.py` 中封装完成。
## 1. 预设状态与基础控制
从 `dfbot_controller.py` 中导入。机械臂控制的核心逻辑是**状态更新**,所有的动作函数都会返回最新的关节状态数组(弧度),必须用变量接收并传递给下一次动作!
```python
from dfbot_controller import deg0, state_ready, move_joint_deg, move_joint_rad
# 1. 移动到零位(使用角度),返回初始化的弧度状态
current_state = move_joint_deg(deg0, delay=2)
# 2. 移动到准备姿态(使用弧度)
current_state = move_joint_rad(state_ready, delay=2)
```
## 2. 常用动作接口
|动作类型|函数签名|说明|
|------|------|------|------|
|向上移动|move_up(state_now, step=0.02, delay=1, smooth=True)|笛卡尔Z轴增加,step单位:米 (m)|
向下移动|move_down(state_now, step=0.02, delay=1, smooth=True)|笛卡尔Z轴减少,step单位:米 (m)|
底座向左|move_left(state_now, step_deg=5, delay=1)|第1关节左转,单位:角度 (°)|
底座向右|move_right(state_now, step_deg=5, delay=1)|第1关节右转,单位:角度 (°)|
末端左旋|rotate_left(state_now, step_deg=5, delay=1)|第5关节左旋,单位:角度 (°)|
末端右旋|rotate_right(state_now, step_deg=5, delay=1)|第5关节右旋,单位:角度 (°)|
任意平滑|ove_cartesian_smooth(state_now, dx=0, dy=0, dz=0, steps=5, delay=0.5)|对当前位姿平滑移动|
## 3.夹爪控制
夹爪单独控制,不改变主要机械臂的5轴运动学状态,但同样需要传递和返回状态:
```python
from dfbot_controller import gripper_open, gripper_close
# 30度为打开
current_state = gripper_open(current_state, gripper_deg=30, delay=1)
# 0度为闭合
current_state = gripper_close(current_state, gripper_deg=0, delay=1)
```
## 4.最小可运行模板(生成代码时基于此扩展)
```python
#!/usr/bin/env python3
import time
# 导入用户封装好的 DFbot 模块
from dfbot_controller import (
deg0, state_ready,
move_joint_deg, move_joint_rad,
move_up, move_down, move_left, move_right,
rotate_left, rotate_right,
gripper_open, gripper_close
)
def main():
print("===== 开始执行 DFbot 控制任务 =====")
# 1. 初始化到零位并获取初始状态
current_state = move_joint_deg(deg0, delay=2)
# 2. 移动到工作准备姿态
current_state = move_joint_rad(state_ready, delay=2)
# 3. 夹爪打开准备
current_state = gripper_open(current_state, gripper_deg=30, delay=1)
# --- 根据用户需求在这里插入具体动作 ---
# 示例:向左转动 20 度
current_state = move_left(current_state, step_deg=20, delay=1.5)
# 示例:向下移动 3 厘米 (0.03米) 准备抓取
current_state = move_down(current_state, step=0.03, delay=1, smooth=True)
# 示例:闭合夹爪
current_state = gripper_close(current_state, gripper_deg=0, delay=1)
# 示例:向上提起 5 厘米 (0.05米)
current_state = move_up(current_state, step=0.05, delay=1.5, smooth=True)
# -----------------------------------
# 4. 任务结束,返回零位
print("===== 任务完成,复位 =====")
current_state = move_joint_deg(deg0, delay=2)
if __name__ == "__main__":
main()
```
生成代码时请根据用户描述替换或增加运动步骤
这两部分其实可以让AI给你生成
配置好skill之后重新启动一下OpenClaw,然后进行一些配置的提示
我的提示词如下:

最后就可以用你的语言直接控制机械臂啦
综上,这个项目只是一个简单的尝试,机械臂也只能做一些简单的运动,希望能给一些人帮助
更多推荐


所有评论(0)