I've to create an UDP connection between two computers. The computer A have to send each 4 milisec. a packet to the computer B, telling B where and how to move a robotic arm. The B computer will send back the arm position velocity and acceleration and the error between the consign and the position...
The A computer works fine, it has C code program that I can't see but it doesn't matter because of the robot i'm working with only accept python code. I've been trying to do so in the B computer with a multithread program where one thread has the only function of sending back the error and position.
In this little thread where I've tried to determine the time that takes sending a UDP package ( teledirigido.fbk.send(... )) and then making a sleep substracting the time of the code execution from 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)
The first problem is that the sleep method doesn't lie the "(0.004-(self.acaba-self.empieza))" argument, python interpreter says:
Exception in thread Thread-3:
Traceback (most recent call last):
File "/usr/lib/python2.6/threading.py", line 532, in __bootstrap_inner
self.run()
File "./conclase.py", line 210, in run
time.sleep(0.004-(self.acaba-self.empieza))
IOError: [Errno 22] Invalid argument
If I uses decsec. instead of miliseconds the program gives no error.
The second and last problem I found is that the timing is not quite deterministic. 开发者_JAVA技巧Is there any way to make a timed event in python that run this little piece of code and exits?
I've lots of issues, I know, I hope somebody answer this question and also it result useful to other people.
Thanks to everybody! stackoverflow and all the people that uses are fantastic!
You get errno 22 when you pass a negative argument to time.sleep.
What are the values of self.acaba and self.empieza ? If the time elapsed between the two calls is over 4ms this will fail.
Getting a periodic callback depends on your OS. You can get that on Unix systems with a SIGALRM. See http://docs.python.org/library/signal.html for more on this. Carefull, though: signals and threads don't mix well.
You can also look at the sched module from stdlib which integrates well in multithreaded code.
time.sleep(max(0, <your time formula>)) # protect from negative time
It may be hard to reach stable 4ms unless your kernel is compiled with HZ at least 1000. Also make sure your program leaves enough idle cpu to schedule your "realtime" thread properly, say if your program uses over 90% cpu, you won't get timely wakeups.
If you get your UDP queries every 4ms reliably, you can base your timing off that. If you don't have a source of timing, you could do something like this:
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`
This will not skip sending data, but of course a single datum could be delayed, that is it will have correct frequency, but may have some jitter.
精彩评论