4

抱歉标题不好,我真的不知道如何简短地描述它......

我的场景是,对于机器人应用程序,我们需要一个实时循环来每 1ms 控制一次电机。同时我们可能想做一些没有实时要求的事情,例如路径规划、图像处理、对象识别等。此外,非实时任务的一些结果将被发送到实时电机控制循环来控制机器人。

对于实时部分,我使用带有 RT-Preempt Patch 的 Ubuntu。因此,我可以像这里的示例代码一样在 while 循环中运行实时控制循环。

但是,我不知道非实时部分。以我的拙见,我会在同一进程中新建一个线程并在该线程中运行非实时任务。

由于我对实时编程非常陌生,所以我不知道我的设计会出现什么问题。此外,我想知道是否有设计这种程序的范式?

- -编辑 - -

有关我的应用程序的更多详细信息。

机器人,更具体地说,是机械臂。

对于实时部分,它计算正向运动学、逆向运动学和雅可比。然后使用简单的 PID 控制器计算正确的输出命令。最后,使用 EtherCAT 向每个电机发送电机命令。

对于非实时部分,比如可以从kinect获取PointCloud流,做一些预处理,计算场景中物体的位姿,为机械臂确定一个好的抓握位姿,最后发送每个人的目标电机到实时部分,这样机器人手臂就会真正移动到目标并抓住物体。整个过程可能需要 10 秒左右。但同时实时循环应保持运行并发送适当的力命令或位置命令,以使机器人手臂保持其原始姿势并静止不动。

对于这两个部分之间的通信,在大多数情况下,命令是通过一种新颖的算法从非实时部分生成的,并将其发送到实时部分,以使机械臂运动。然而,有时非实时部分的算法需要知道,例如,末端执行器的当前姿势。因此,非实时部分需要从位于实时部分的正向运动学中获取信息。

4

2 回答 2

2

实时循环到底在做什么?我猜(因为你提到“每 1 毫秒做一些电机控制”)做一些非常短的计算,并向电机设备输出几个字节。

非实时部分在做什么?我想象一些用户界面???

什么样的机器人?

路径规划可能需要很强的实时性,尤其是在机器人快速移动的情况下。巡航导弹或 Google Car 与用于robocup的小型机器人不同。失去几毫秒的通信可能会在巡航导弹或谷歌汽车上杀死人类,但在 Robocup 上是可以接受的——你只会失去一场比赛,可能会对你的机器人造成轻微伤害。

在 40 米/秒(144 公里/小时,略高于法国 130 公里/小时的高速公路限速)时,两毫秒意味着 8 厘米,如果这 8 厘米是人肉,那可能意味着杀人。

这两个部分是如何相互作用的?实时部分是否正在向另一部分发送一些信息?

也许这两个部分可能是一些不同的进程(不是线程),有一些通信?也许使用带有信号量的共享内存进行同步。然后看看sem_overview(7)shm_overview(7)

请注意,在实时和“非实时”部分之间的接口处,非实时部分实际上也可能变为“实时”。

要点是定义两个(实时与非实时)部分之间的概念接口,并决定是否可以承受丢失一些数据和一些同步(两个部分之间的通信)的损失。

如果非实时部分的作用只是显示或设置速度(即一些低阈值和高阈值),您可能有时会丢失一些数据或同步。但邪恶在于细节(如果机器人是真正的自动驾驶汽车,在某条高速公路上行驶 à la 谷歌汽车,你可能不应该失去一些交换,然后这两个部分都变得实时!)。

于 2014-08-07T16:22:01.417 回答
1

正如@Basile Starynkevitch 所强调的那样,如何将整个系统划分为实时部分和常规部分非常重要。

在 RT-Linux 中实现时,系统中具有实时要求的部分将被制成实时线程,在内核内部运行。这允许它们不受抢占地运行,但有一个巨大的缺点:在用户空间中没有人们期望的保护。实时线程崩溃意味着系统已经崩溃。出于这个原因(和其他原因),您应该尽可能地限制实时组件。

系统的非实时组件将作为常规 Linux 进程运行。它们可以与您想要的任何昂贵的规划算法一起突飞猛进,实时线程将抢占它们并根据需要运行。棘手的部分是通信,为此提供了两种机制:FIFO 和共享内存。

FIFO 是最简单的,并且允许单向通信(如果需要双向通信,请使用两个)。它们是字符设备,您不必担心读/写重叠。更多来自tldp.org

对于传递大量数据,共享内存更可取。有了它,两个进程将同一部分映射到内存中。但是您必须在进程/线程之间进行协调,以确保一个不会在另一个写入中间读取,反之亦然。当其中一方是实时线程时,这实际上稍微容易一些,因为您知道实时线程不会被抢占。更多来自drdobbs.com

您还需要注意优先级反转(例如,当高优先级线程必须等待低优先级线程释放共享资源时)。

于 2014-08-09T12:07:22.150 回答