Python 如何安排实时循环任务?
我们是一个由学士学生组成的团队,目前正致力于建造一个腿部机器人。目前,我们与机器人的接口是用python编写的,使用的是主板上的sdk 为了与主板sdk通信,我们需要每毫秒发送一个命令 为了允许我们定期发送任务,我们已经将rt抢占补丁应用到linux内核。(Ubuntu LTS 20.04,内核5.10.27-rt36) 我们对编写实时应用程序非常陌生,并且遇到了一些问题,我们的任务有时会比指定的时间步长小得多。在下图中,我们绘制了while循环的每个周期的时间,其中命令被发送到sdk。(x轴是以秒为单位的时间,y轴是迭代经过的时间,也以秒为单位) 从图中可以看出,一个步骤比其他步骤小得多。每次运行脚本时,这似乎都发生在同一个精确的时间标记上 我们使用以下方法设置整个脚本的优先级:Python 如何安排实时循环任务?,python,linux,posix,real-time,preempt-rt,Python,Linux,Posix,Real Time,Preempt Rt,我们是一个由学士学生组成的团队,目前正致力于建造一个腿部机器人。目前,我们与机器人的接口是用python编写的,使用的是主板上的sdk 为了与主板sdk通信,我们需要每毫秒发送一个命令 为了允许我们定期发送任务,我们已经将rt抢占补丁应用到linux内核。(Ubuntu LTS 20.04,内核5.10.27-rt36) 我们对编写实时应用程序非常陌生,并且遇到了一些问题,我们的任务有时会比指定的时间步长小得多。在下图中,我们绘制了while循环的每个周期的时间,其中命令被发送到sdk。(x轴是
pid = os.getpid()
sched = os.SCHED_FIFO
param = os.sched_param(98)
os.sched_setscheduler(pid, sched, param)
我们的循环任务如下所示:
dt设置为0.001
while(_running):
if direction:
q = q + 0.0025
if (q > np.pi/2).any():
direction = False
else:
q = q - 0.0025
if (q < -np.pi/2).any():
direction = True
master_board.track_reference(q, q_prime)
#Terminate if duration has passed
if (time.perf_counter() - program_start > duration):
_running = False
cycle_time = time.perf_counter() - cycle_start
time.sleep(dt - cycle_time)
cycle_start = time.perf_counter()
timestep_end = time.perf_counter()
time_per_timestep_array.append(timestep_end - timestep_start)
timestep_start = time.perf_counter()
(\u运行)时的:
如果指示:
q=q+0.0025
如果(q>np.pi/2).any():
方向=错误
其他:
q=q-0.0025
如果(q<-np.pi/2).any():
方向=真
主电路板。轨道参考(q,q素)
#如果持续时间已过,则终止
如果(time.perf_counter()-程序启动>持续时间):
_运行=错误
循环时间=时间。性能计数器()-循环开始
睡眠时间(dt-循环时间)
循环开始=时间。性能计数器()
timestep\u end=time.perf\u计数器()
每个时间步数组的时间步。追加(时间步结束-时间步开始)
timestep\u start=time.perf\u计数器()
我们怀疑这个问题与我们定义睡眠量的方式有关。Cycle_time是指上面time.sleep()的计算所花费的时间,因此:sleep time+Cycle time=1ms。然而,我们不知道如何正确地做到这一点,我们正在努力寻找关于这个主题的资源
如何为实时应用程序正确定义这样的任务
我们有非常松散的需求(几毫秒),但对我们来说,它是确定性的非常重要,因为这是我们论文的一部分,我们需要了解发生了什么
非常感谢您对我们问题的任何回答或相关资源
链接到完整代码:
您正在记录上一个周期的timestep\u start
和当前周期的timestep\u end
之间的时间。该间隔不能准确表示周期时间步长(即使我们假设没有发生任务抢占);它不包括数组附加函数所消耗的时间。由于异常值似乎在每次运行脚本时都发生在同一个精确的时间标记上,因此我们可能会怀疑此时数组超过了一定的大小,必须进行昂贵的内存重新分配。无论真正的原因是什么,您都应该通过记录循环开始之间的时间来消除此类计时不准确:
timestep_end = cycle_start
time_per_timestep_array.append(timestep_end - timestep_start)
timestep_start = cycle_start
timestep_end = cycle_start
time_per_timestep_array.append(timestep_end - timestep_start)
timestep_start = cycle_start