作为一个学生项目,我们正在建造一个机器人,它应该通过一个确定的路线并拿起一个木制立方体。它的核心是一台运行debian的单板计算机,ARM9的频率为250MHz。因此控制器有足够的处理能力。此外,它还进行了一些图像处理(不是在驱动时,只在停止时),这就是为什么我们不使用没有操作系统的简单微控制器。
此刻整个过程非常好,但有一个问题:主控制循环执行没有任何延迟,并实现超过1kHz的循环频率。这绰绰有余,100Hz就足够了。但是每隔一段时间,就有一个循环需要100ms甚至更长时间,这可能会严重干扰控制器。
我怀疑还有一些其他任务会导致这种延迟,因为调度程序可能会检测到他们在很长一段时间内没有任何CPU时间。
所以我最喜欢的是以下内容:在控制器的主循环中可能只有5ms的短暂睡眠,它实际上只需要5ms但是给系统的其余部分一些处理器时间。我可以包括例如延迟500us使用nanosleep,但执行时间总是超过10ms,因此它不是真正的替代品。我更喜欢像自愿睡眠一样让等待任务有机会做某事,但尽快回来。
否则系统会被卸载,因此很长一段时间内都没有真正需要大量处理的东西。
有没有办法在用户空间中这样做,即不必坚持像RTAI这样的东西?
谢谢, 菲利普
答案 0 :(得分:0)
我建议您在进行电机控制时坚持使用实时接口;我看到一个1000公斤的卡车在演示期间撞到墙上,因为操作系统决定一次考虑别的东西......: - )
如果你想远离RTAI(但你不应该);一个(也许)快速解决方案是拍一个Arduino板用于实际驾驶,并保持linux板的高级处理。
要修复“墙壁问题”,请在驱动板上实现一个看门狗,如果暂时没有命令就停止了...
答案 1 :(得分:0)
实时问题需要实时操作系统。
因为实时操作系统是可预测的。您可以设置任务优先级,以便需要在指定时间生成结果的任务优先级不会被需要处理能力但没有时间限制的任务抢占。
答案 2 :(得分:0)
好的,我找到了一个让它更好的解决方案,尽管不完美。还有另一个thread解释了sched_setscheduler()函数。我的初始化代码现在看起来像这样:
// Lock memory to reduce probability of high latency due to swapping
int rtres = mlockall(MCL_CURRENT | MCL_FUTURE);
if (rtres) {
cerr << "WARNING: mlockall() failed: " << rtres << endl;
}
// Set real-time scheduler policy to get more time deterministic behaviour
struct sched_param rtparams;
rtparams.sched_priority = sched_get_priority_max(SCHED_FIFO);
rtres = sched_setscheduler(0, SCHED_FIFO, &rtparams);
if (rtres) {
cerr << "WARNING: sched_setscheduler() failed: " << rtres << endl;
}
另外,我已经从主循环中移除了短暂的睡眠。该过程现在消耗所有可用的处理能力,并且(显然)对来自外部世界的任何动作(例如控制台按键等)没有响应,但是这对于手头的任务是可以的。 主循环统计显示大多数迭代完成所需的时间不到一毫秒,但仍有少数(每1000个左右)需要大约。 100毫秒。这仍然不好,但至少没有更长的延迟。
由于它“仅”是一个学生项目,我们可以忍受这一点,并将其作为进一步改进的候选人。
无论如何,感谢您的建议。下次,我会更好地了解如何应对实时要求并从一开始就使用RT操作系统。
此致 菲利普
答案 3 :(得分:0)
我们正在使用带有RT patch的标准Linux在ARM7板上运行100 Hz循环,这允许(几乎)内核中的所有锁被抢占。将它与高优先级线程相结合,可以在内核和用户空间中提供必要的性能。
您唯一需要做的就是应用补丁并配置内核以使用完全抢占,它也很容易使用 - 无需更改软件架构中的任何内容,尽管我对此不够熟悉Debian说这个补丁是否会干净利落。