469,909 Members | 1,809 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,909 developers. It's quick & easy.

How do I run routines where timing is critical?

Hello All!
I am new to Python, and wanted to know if I might ask you a question
regarding timing.

I want a main loop which takes photos from 8 different web-cams, each can
be addressed by http://ip-addr/image.jpg. That's the easy part, but I want
to have 2 cameras poll 3-times a second, 4 cameras poll 2 times a second,
and the remaining 2 cameras poll once a second. I have found lots of info
suggesting the use of threads for this, all using sleep to have a single
event fire every second or so. But, what I'd like to do is have a loop
which does not need to 'sleep' but can rather evaluate where I am in the
second and then have that logic trigger the event.

In otherwords,

While 1
if second >1.00 and <1.25
Camera 1 & camera 2
Camera 5 & camera 6 & camera 7 & camera 8

if second >1.25 and < 1.50
Camera 1 & camera 2

if second >1.50 and <1.75
Camera 1 & camera 2
Camera 5 & camera 6 & camera 7 & camera 8

if second >1.75 and < 2.0
Camera 1 & camera 2

if second >1.00 and < 1.334
Camera 3 & camera 4

if second > 1.334 and < 1.667
Camera 3 & camera 4

if second > 1.667 and < 2.000
Camera 3 & camera 4

Please don't be too harsh with me. I'm still new, and am still quite
actively learning, but I've searched a bit on this and can't seem to find
it on my own.

Thank you in advance!
Dave Rose
Stamford, CT - USA
Jul 18 '05 #1
6 1647
"S. David Rose" <ph****@conversent.net> writes:
I want a main loop which takes photos from 8 different web-cams,
each can be addressed by http://ip-addr/image.jpg. That's the easy
part, but I want to have 2 cameras poll 3-times a second, 4 cameras
poll 2 times a second, and the remaining 2 cameras poll once a
second. I have found lots of info suggesting the use of threads for
this, all using sleep to have a single event fire every second or
so. But, what I'd like to do is have a loop which does not need to
'sleep' but can rather evaluate where I am in the second and then
have that logic trigger the event.


You have to do some pretty advanced stuff if you want to make sure of
accurate timing. But if you just want to sleep for 1/4 of a second and
can tolerate some slop, you can say

import time
time.sleep(0.25)

I.e. you don't have to sleep an integer number of seconds.
Jul 18 '05 #2
On Mon, 21 Jun 2004 02:06:30 GMT, "S. David Rose"
<ph****@conversent.net> declaimed the following in comp.lang.python:
Hello All!
I am new to Python, and wanted to know if I might ask you a question
regarding timing.
First off, based on your subject line: Define "critical".
Remember, Python is a byte-coded interpreted language, not something
running at machine-code level.

I want a main loop which takes photos from 8 different web-cams, each can
be addressed by http://ip-addr/image.jpg. That's the easy part, but I want
to have 2 cameras poll 3-times a second, 4 cameras poll 2 times a second,
and the remaining 2 cameras poll once a second. I have found lots of info
suggesting the use of threads for this, all using sleep to have a single
event fire every second or so. But, what I'd like to do is have a loop
which does not need to 'sleep' but can rather evaluate where I am in the
second and then have that logic trigger the event.

I hope you intend to dedicate most of the CPU time to this
polling loop. sleep() maps directly to an OS service call, taking
practically no CPU.

The traditional polling loop normal relies on testing an
externally set "address" -- IE, a keyboard status register that goes
"high" when a key has been pressed; when the loop reads the high state,
it reads the data register, then resets (if the data read doesn't
automatically reset) the status register.

Your timing loop, to work as a poll, will require you to
constantly ask the OS for the current system time, compute the
difference from a base time, and perform the capture on certain values
of the difference.

I should ask -- how long does it take to transfer the image?
You are asking for two cameras at 0.333sec intervals... That means each
camera can only consume 0.1667sec for a transfer (this is also ignoring
that the other cameras may also be involved. 8 cameras at 0.125sec each,
processed in sequence, will require a full second. BUT... by your specs,
2@0.333 means 6 images per second, 4@0.5sec is another 8 images, and
2@1.0sec is 2 images... Or a total of 16 images to be transferred EVERY
second -- or one image every 0.0625 seconds. Include the overhead needed
to calculate the current time fraction for each test.
Pseudo-code:

t0 = int(time.clock() * 1000) # floating seconds -> integer millisec
loop
diff = int(time.clock() * 1000) - t0
if (diff % 333) < some_slop_parameter:
capture the 3/second cameras
if (diff % 500) < some_slop_parameter:
capture the 2/second cameras
if (diff % 1000) < some_slop_parameter:
capture the 1/second cameras
Where "some_slop_parameter" is a value to allow for non-exact intervals
(better hope it is smaller than the empty loop time)... Normally you'd
be looking for the modulo to be 0.0 to signal that the interval has been
reached, but since you can't ensure the loop will hit that tightly, use
something like 10 milliseconds (experiment to ensure it doesn't hit a
single camera capture twice).
Threads make it much simpler... Though you still risk a bit of
drift by the time a capture takes (unless you've allowed for capture
time when setting the sleep interval). Two approaches: one thread per
camera, where you initialize each thread by that camera's sleep
interval; or one thread per sleep interval, where you initialize with
both the interval AND a list of the cameras to be captured.

-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <
Home Page: <http://www.dm.net/~wulfraed/> <
Overflow Page: <http://wlfraed.home.netcom.com/> <

Jul 18 '05 #3
You can do something like this. I am assuming you can poll with 2
cameras every 0.3 seconds instead of 0.33333333... seconds.

# start of code
class Camera():
def __init__(self, clickInterval):
self.clickInterval = clickInterval
#
#

# List of camera objects with their periodicity
cameraList = [Camera(0.3), Camera(0.3), Camera(0.5), Camera(0.5), \
Camera(0.5), Camera(0.5), Camera(1), Camera(1)]

globalTime = 0.0 # counter to keep track of current time
import time

while True:
time.sleep(0.1) # 0.1 seconds is the granularity
globalTime += 0.1
# examine each camera if it needs to capture at this moment
for camera in cameraList:
if globalTime % camera.clickInterval == 0.0:
click(camera) # capture image from this camera
#
#
#
# end of code

You have to add additional parameters to the Camera class to define
it's
address, etc. Every 0.1 second you determine which of the cameras to
be clicked and then capture images from those cameras.

--Hemanth P.S.

"S. David Rose" <ph****@conversent.net> wrote in message news:<Go**********************@news4.srv.hcvlny.cv .net>...
Hello All!
I am new to Python, and wanted to know if I might ask you a question
regarding timing.

I want a main loop which takes photos from 8 different web-cams, each can
be addressed by http://ip-addr/image.jpg. That's the easy part, but I want
to have 2 cameras poll 3-times a second, 4 cameras poll 2 times a second,
and the remaining 2 cameras poll once a second. I have found lots of info
suggesting the use of threads for this, all using sleep to have a single
event fire every second or so. But, what I'd like to do is have a loop
which does not need to 'sleep' but can rather evaluate where I am in the
second and then have that logic trigger the event.

In otherwords,

While 1
if second >1.00 and <1.25
Camera 1 & camera 2
Camera 5 & camera 6 & camera 7 & camera 8

if second >1.25 and < 1.50
Camera 1 & camera 2

if second >1.50 and <1.75
Camera 1 & camera 2
Camera 5 & camera 6 & camera 7 & camera 8

if second >1.75 and < 2.0
Camera 1 & camera 2

if second >1.00 and < 1.334
Camera 3 & camera 4

if second > 1.334 and < 1.667
Camera 3 & camera 4

if second > 1.667 and < 2.000
Camera 3 & camera 4

Please don't be too harsh with me. I'm still new, and am still quite
actively learning, but I've searched a bit on this and can't seem to find
it on my own.

Thank you in advance!
Dave Rose
Stamford, CT - USA

Jul 18 '05 #4
IMO you want an event-driven structure.

import heapq, math, time

events = []

The event loop looks something like this: (all untested)
def sleep_until(when):
now = time.time()
if when > now:
time.sleep(when-now)

def add_event(when, callback):
heapq.heappush(events, (when, callback))

def eventloop():
while events:
when, callback = heapq.heappop(events)
sleep_until(when)
callback()

A camera might be something like this: (again, all untested)
class Camera:
def __init__(self, number, frequency):
self.number = number
self.frequency = frequency
self.reschedule()

def __repr__(self):
return "<Camera %d (frequency %d/sec)>" % (self.number, self.frequency)

def take_photo(self):
print "Taking photo from", self, "at", time.time() % 60

def reschedule(self):
now = time.time()
f = self.frequency
next = math.floor(now * f + 1) / f
add_event(next, self.callback)

def callback(self):
self.take_photo()
self.reschedule()

The main program would create 8 cameras and run the event loop:
def main():
frequency = [3, 3, 2, 2, 2, 2, 1, 1]
cameras = [Camera(i, f) for (i, f) in enumerate(frequency)]
eventloop()

if __name__ == '__main__':
main()

The calculation of the "next" in reschedule is intended to find the next
"1/frequency" time. This means that if a camera has frequency=2, and
fires at time 1.6, it will next fire at time 2.0---even if the last time
it schedule itself, it was scheduled for time 1.0 and was delayed by 0.6
seconds. I suspect that if the system can't keep up with all the
cameras, that this will result in the cameras being serviced
"round-robin" with equal frequency, which may or may not be acceptable.
It also means that after a temporary slowdown (background disk activity)
clears up, the cameras will immediately return to their given speed in
Hz, rather than trying to take the appropriate number of photos to the
number of seconds that have passed, in quick succession.

Jeff

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)

iD8DBQFA2jqLJd01MZaTXX0RAia6AKCSIT2vPFjxX/Uv8B36dTXV74wTRACeNwCl
qO3MZ75g3u3Cwmurcei6gK8=
=Od1P
-----END PGP SIGNATURE-----

Jul 18 '05 #5

"S. David Rose" <ph****@conversent.net> wrote in message
news:Go**********************@news4.srv.hcvlny.cv. net...
I want a main loop which takes photos from 8 different web-cams, each can be addressed by http://ip-addr/image.jpg.
Public web cams generally update once every few seconds, or slower, so I
presume these are private cameras on a private net.
That's the easy part, but I want
to have 2 cameras poll 3-times a second, 4 cameras poll 2 times a second,
and the remaining 2 cameras poll once a second.
Your proto-code below shows the 'remaining 2' being polled 4 times a
second.

How long does it take to 'poll' a camera and process the data and be ready
for another? IOW,
I have found lots of info
suggesting the use of threads for this, all using sleep to have a single
event fire every second or so.
(Stackless tasklets might also be a possibility, but I have 0 experience
therewith).
Once a second will not get you several times a second. Unless cameras
respond 'immediately', you may need to make several requests and process
replies as they come.
But, what I'd like to do is have a loop
which does not need to 'sleep' but can rather evaluate where I am in the
second and then have that logic trigger the event.

In otherwords,

While 1
if second >1.00 and <1.25
Camera 1 & camera 2
Camera 5 & camera 6 & camera 7 & camera 8

if second >1.25 and < 1.50
Camera 1 & camera 2

if second >1.50 and <1.75
Camera 1 & camera 2
Camera 5 & camera 6 & camera 7 & camera 8

if second >1.75 and < 2.0
Camera 1 & camera 2

if second >1.00 and < 1.334
Camera 3 & camera 4

if second > 1.334 and < 1.667
Camera 3 & camera 4

if second > 1.667 and < 2.000
Camera 3 & camera 4


How critical is the timing? Above suggests some sloppiness is allowed. If
so, following schedule might work (where '3A' is first 3-time-a-second
camera, etc).

0.00 3A,3B
pause
0.25 2A,2B,2C,2D
0.33 3A,3B
pause
0.50 1A,1B
pause
0.66 3A,3B
0.75 2A,2B,2C,2D
pause
and repeat

pause periods could be used to process previously collected data.

Terry J. Reedy


Jul 18 '05 #6
"S. David Rose" <ph****@conversent.net> wrote in message news:<Go**********************@news4.srv.hcvlny.cv .net>...
But, what I'd like to do is have a loop
which does not need to 'sleep' but can rather evaluate where I am in the
second and then have that logic trigger the event.


Sounds like you're writing your own scheduler. You might want to look
into the 'sched' module.

--
Tim Lesher
ti*@lesher.ws
Jul 18 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

354 posts views Thread by Montrose... | last post: by
6 posts views Thread by MPH Computers | last post: by
2 posts views Thread by Oeyvind Brandtsegg | last post: by
2 posts views Thread by Steven D'Aprano | last post: by
15 posts views Thread by Jay | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.