机器人项目实战(5):从单次抓取,到接收指令连续做事

53 阅读7分钟

机器人项目实战(5):从单次抓取,到接收指令连续做事

前面几篇,我分别整理了相机、识别、抓取参考、灵巧手求解和实机动作适配。

最后这一篇,把它们放回完整任务里。

任务目标仍然是橙子、苹果、香蕉、柠檬,以及锤子和螺丝刀。不过,程序除了完成一次抓取,还要处理目标挤在一起、连续搬运,以及小智发来的新指令。

我把这一阶段的流程组织成:接收任务、观察桌面、准备目标、抓取放置,再更新场景。

1. 先让指令变成明确的任务

接入小智后,机器人侧通过串口接收结构化指令。

我把串口解析和机器人任务执行分开。解析层负责从字节流中找出完整指令,检查帧头、帧尾和校验值;任务层再根据功能码和参数,决定调用哪个任务。

当前指令帧长度是 10 字节:

帧头|功能码|6 字节参数|校验值|帧尾

对应到抓取相关任务,主要有:

  • 抓取指定类别并放置;
  • 按给定类别顺序抓取;
  • 按配置顺序循环搬运;
  • 将指定物体递到交接位置。

这样,机器人侧拿到的是确定的任务名称和参数。上层输入方式变化时,底层抓取流程仍然可以复用。

2. 抓之前,先看目标周围有没有其他东西

如果目标单独放着,可以继续计算抓取。目标附近还有其他物体时,我在流程中加入了抓前打散。

这里先检测当前配置中的全部类别,再根据水平检测框是否相交进行分组。框的边或角接触,也归入相交关系。

分组还包含间接连接。例如:

苹果与香蕉的框相交
香蕉与柠檬的框相交
    ↓
三者归为同一组

判断依据是图像中的检测框关系。程序随后只处理当前目标所在的组,不去打散其他独立区域。

如果目标所在组只有它自己,就直接进入抓取准备。

3. 从哪边拨开?

确定目标所在组后,我先计算一个包住整组物体的水平矩形,并取它的中心 C。

接着,在矩形四个角里选择起点 P。

选择时,我计算每个角到各成员检测框的距离,取其中最小值,再选择这个最小值最大的角。直观上,就是优先从相对空一些的角进入。

拨动方向从 P 指向 C,并继续越过中心,终点设为:

终点 = 2C - P

也就是把中心作为中点,沿这条线拨到另一侧。

得到图像中的起点和中心后,我用组内有效深度的中位数,将它们还原到三维空间,再转换到机器人基坐标系,生成水平方向的拨动路径。

这样,拨动距离会随分组范围变化,而不是每组都使用同一个固定长度。

4. 拨完以后,重新拍照

拨动执行分成转手、移动到预位置、下探、水平拨动和抬升几个阶段,随后返回观察位置。

回到观察位之后,我重新拍照、重新识别,再为目标分组。

这一轮使用的是更新后的检测结果。物体已经被拨动,前一张图里的位置也就完成了它的作用。

整个过程形成一个循环:

观察与分组
    ↓
目标独立 → 进入抓取
    ↓ 否
规划并执行拨动
    ↓
返回观察位,重新识别

当前最多尝试 5 次拨动。达到次数后仍处于相交组,就结束这次准备流程并返回原因。

5. 把一次抓取接成完整动作

目标准备完成后,复用前面几篇的流程:

生成抓取参考
    ↓
灵巧手求解与 TCP 换算
    ↓
准备手形、到达预抓取位置
    ↓
接近、闭合、等待、抬升
    ↓
移动到放置位置、松手
    ↓
返回观察位

在当前搬运任务中,我使用镜像方式生成另一侧的放置位姿,并为放置轨迹增加基坐标系 Z 方向的偏移。

顺序抓取时,每个物体走完抓取和放置,再回到观察位处理下一个。

我没有在开始时一次算完所有物体的位置,而是让每轮抓取使用当时的场景数据。前一个物体被拿走,或者打散动作改变了布局,后面的目标位置就跟着更新。

6. 抓完之后,再看一次来源区域

顺序任务中,我还加入了抓取后的复拍检查。

完成抓取、放置并返回来源侧观察位后,程序重新检测当前类别。如果仍然检测到该类别,就按配置重新执行这轮流程;没有检测到,再推进到下一个类别。

这里采用的是类别级判断,适合当前按类别组织的任务。

目标没有识别到时,我也保留了跳过、重试和中止三种策略。当前默认使用跳过,让任务继续处理后面的类别;重试则有次数上限。

这样,任务列表与实际桌面之间就有了衔接:每一步既知道接下来要找什么,也会根据当前画面决定怎样继续。

7. 连续搬运,需要管理这一轮的目标

循环搬运建立在顺序抓取上,两侧分别配置观察位置。

每个搬运方向开始时,我先拍一张图,确定这一方向中实际出现的目标类别,并保留配置中的顺序。

这张图用于确定本方向的任务名单,后续每次抓取仍会更新目标位置。等这一方向完成后,再根据完成列表组织反向搬运。

我把“这一轮处理哪些类别”和“某个物体当前在哪里”分开管理:

  • 类别列表决定任务顺序;
  • 每轮识别提供当前的位置和抓取数据。

这样,连续任务既有明确进度,也能跟随桌面变化更新动作。

8. 正在搬运,又收到新指令怎么办?

小智接入以后,串口监听需要在任务运行期间继续接收数据。

因此,我让串口接收和任务执行分开运行。新指令到来时,先保存为待执行任务,不在当前动作中间直接启动另一套动作。

对于循环搬运这类持续任务,新指令会提出切换请求,等当前物体完成放置等阶段后,再交给下一个任务。

待执行位置只保留最新的一条指令。当前任务结束后,有新任务就继续执行;没有待执行任务,则返回初始观察位。

我希望这里的行为尽量清楚:收到指令、正在执行、等待切换和执行结束,是几个独立状态。

写在最后

从最初选相机,到接入深度、完成标定,再到识别目标、求解手形和组织任务,这个项目逐步从单个功能变成了相互配合的流程。

最后这部分,我主要做了三件事:目标挤在一起时先打散,动作改变场景后重新观察,再通过任务层连接连续搬运和外部指令。

回头看,各模块之间的数据衔接和执行顺序,占了很大一部分工作。相机提供当前场景,感知给出目标,求解生成姿态,设备执行动作,任务层决定下一步。

到这里,这个系列从设备选型写到了任务执行。后续继续调整时,我会优先记录那些有具体问题、实际改动和运行结果的部分,再围绕它们补充新的文章。