对不好的头衔感到抱歉,我真的不知道如何描述这一点......
我的情况是,对于机器人应用程序,我们需要一个实时循环来每1ms控制一次电机。同时我们可能想要做一些没有实时要求的事情,例如路径规划,图像处理,对象识别等。此外,非实时任务的一些结果将被发送到实时电机控制循环来控制机器人。
对于实时部分,我使用Ubuntu和RT-Preempt Patch。因此,我可以在while循环中运行实时控制循环,就像示例代码here。
一样但是,我不知道非实时部分。在我看来,我会在同一个进程中创建一个线程并在该线程中运行非实时任务。
由于我对实时编程非常陌生,我不知道我的设计会出现什么问题。此外,我想知道是否有任何设计此类程序的范例?
--- --- EDIT
有关我的申请的更多详情。
更具体地说,机器人是机器人手臂。
对于实时部分,它计算正向运动学,反向运动学和雅可比。然后使用简单的PID控制器计算正确的输出命令。最后,使用EtherCAT将电机命令发送到每个电机。
对于非实时部分,例如,可以从kinect获取PointCloud流,进行一些预处理,计算场景中对象的姿势,确定机器人手臂的良好抓握姿势,最后发送每个马达到达实时部分的目标,以便机器人手臂实际上移动到目标并抓住物体。整个过程可能需要10秒左右。然而,同时实时循环应该继续运行并发送适当的力命令或位置命令,以使机器人手臂保持其原始姿势并保持静止。
对于这两个部分之间的通信,在大多数情况下,命令是由非实时部分的新算法生成的,并将其发送到实时部分以使机器人手臂移动。然而,有时非实时部分中的算法将需要知道例如末端执行器的当前姿势。因此,非实时部分需要从正向运动学中获取信息,这些信息位于实时部分。
答案 0 :(得分:2)
什么是实时循环?我猜(因为你提到“每1毫秒做一些电机控制”)做一些非常短的计算,并输出几个字节到电机设备。
非实时部分在做什么?我想象一些用户界面???
什么样的机器人?
路径规划可能需要很强的实时性,特别是在机器人快速移动的情况下。巡航导弹或Google Car与robocup的小型机器人不同。失去几毫秒的通信可能会在巡航导弹或谷歌车上杀死人类,但在机器人上是可以接受的 - 你只会松开一个游戏并且可能会轻微损害你的机器人。
速度为40米/秒(144公里/小时,略高于法国130公里/小时的高速公路限速),2毫秒意味着8厘米,如果那8厘米是人肉,则可能意味着杀死某人。
两部分如何互动?实时部分是否向其他部分发送了一些信息?
也许这两个部分可能是一些不同的进程(而不是线程)与某些通信?也许使用带信号量的共享内存进行同步。然后查看sem_overview(7)和shm_overview(7)。
请注意,在实时和“非实时”部分之间的接口处,非实时部分实际上也可能变为“实时”。
重点是定义两个(实时与非实时)部分之间的概念界面,并决定是否可以承受丢失一些数据和一些同步(两部分之间的通信)。 / p>
如果非实时部分的角色只是显示或设置速度(即某些低和高阈值),您可能有时会丢失一些数据或同步。但细节就是邪恶(如果机器人是一辆真正的自动驾驶汽车,在谷歌汽车的某些高速公路上驾驶,你可能不应该失去一些交换,然后这两个部分都变成了实时!)。
答案 1 :(得分:1)
正如@Basile Starynkevitch强调的那样,如何将整个系统划分为实时与常规部分非常重要。
在RT-Linux中实现时,系统中具有实时要求的部分将被制作成在内核中运行的实时线程。这允许它们无阻碍地运行,但是有一个巨大的缺点:没有人在用户空间中期待的保护。实时线程崩溃意味着系统崩溃了。出于这个原因(和其他人),你应该尽可能地限制实时组件。
系统的非实时组件将作为常规Linux进程运行。他们可以随意使用您想要的任何昂贵的计划算法,实时线程将抢占它们并根据需要运行。棘手的部分是通信,为此提供了两种机制:FIFO和共享内存。
FIFO是最简单的,并且允许单向通信(如果你想要双向,则使用两个)。它们是角色设备,您不必担心读/写重叠。更多来自tldp.org。
为了传递大量数据,最好使用共享内存。有了它,两个进程将同一部分映射到内存中。但是你必须在进程/线程之间进行协调,以确保不会在另一个写入的中间读取,反之亦然。当其中一方是实时线程时,这实际上稍微容易一些,因为您知道实时线程不会被抢占。更多来自drdobbs.com。
您还需要了解优先级倒置(例如,当高优先级线程必须等待低优先级线程才能释放共享资源时)。