使用Python建立确定性的时间套接字连接

时间:2011-07-18 10:10:02

标签: python multithreading sockets timing

我要在两台计算机之间创建UDP连接。 计算机A必须发送每4个milisec。一个包到计算机B,告诉B在哪里以及如何移动机器人手臂。 B计算机将发回手臂位置速度和加速度以及托运和位置之间的误差......

A计算机工作正常,它有C代码程序,我看不到,但它没关系,因为我只使用接受python代码的机器人。 我一直试图在B计算机上使用多线程程序,其中一个线程具有发回错误和位置的唯一功能。

在这个小线程中,我试图确定发送UDP包(teledirigido.fbk.send(...))然后从4 milisec减去代码执行时间的时间。

class enviaDeterministico(threading.Thread):
    def __init__(self,teledirigido):
        self.teledirigido = teledirigido
        # thanks to mordi
        threading.Thread.__init__(self)
        self.t = timeit.time
    def run(self):
        while 1:
            self.empieza0 = self.t.time()
            self.empieza = self.t.time()
            self.teledirigido.cond.acquire()
            self.teledirigido.fbk.send(self.teledirigido.lectura.enviarAmpliado())
            self.acaba = self.t.time()
            time.sleep((0.004-(self.acaba-self.empieza)))
            self.teledirigido.cond.release()
            self.acaba0 = self.t.time()
            print 'tiempo entre envios %.6f'% (self.acaba0-self.empieza0)

第一个问题是睡眠方法不是“(0.004-(self.acaba-self.empieza))”参数,python解释器说:

  

线程Thread-3中的异常:

     

追踪(最近一次呼叫最后一次):

     

文件“/usr/lib/python2.6/threading.py”,第532行,__ bootstrap_inner

self.run()
     

文件“./conclase.py”,第210行,在运行中

time.sleep(0.004-(self.acaba-self.empieza))
     

IOError:[Errno 22]参数无效

如果我使用decsec。而不是毫秒,程序没有错误。

我发现的第二个也是最后一个问题是时机不是很确定。有没有办法在python中创建一个运行这段代码并退出的定时事件?

我有很多问题,我知道,我希望有人回答这个问题,结果也会对其他人有用。

感谢大家! stackoverflow和所有使用的人都太棒了!

2 个答案:

答案 0 :(得分:2)

当你将负参数传递给time.sleep时,你会得到错误22。

self.acaba和self.empieza有什么价值?如果两次呼叫之间经过的时间超过4ms,则会失败。

定期回调取决于您的操作系统。您可以使用SIGALRM在Unix系统上实现。有关详情,请参阅http://docs.python.org/library/signal.html。但要小心:信号和线程混合不好。

您还可以查看stdlib中的sched模块,该模块可以很好地集成在多线程代码中。

答案 1 :(得分:1)

time.sleep(max(0, <your time formula>))  # protect from negative time

除非您的内核使用至少1000的HZ编译,否则可能很难达到稳定的4ms。还要确保您的程序保留足够的空闲cpu以正确安排“实时”线程,比如说您的程序使用超过90%的cpu,你不会及时醒来。

如果您可靠地每4毫秒获得一次UDP查询,那么您可以将时间基准关闭。如果你没有时间来源,你可以这样做:

class Timer(threading.Thread):
    def run(self):
        started = time.time()
        counter = 0
        while True:
            counter += 1
            now = time.time()
            if started + counter * 0.040 - now > 0:
                time.sleep(started + counter * 0.040 - now)
            # send datum number `counter`

这不会跳过发送数据,但当然可以延迟单个数据,即它具有正确的频率,但可能会有一些抖动。