-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.py
114 lines (91 loc) · 3.83 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from config.configuration import componentDic, rootTopic,componentsSamplingIntevalInSeconds
from componentClass import Component
import threading
import signal
import sys
import time
import math
# CTRl+C handler to exit the program properly
def signal_handler(sig, frame):
print('Bye Bye')
sys.exit(0)
# Get components from the config file
def get_components():
my_components = {}
for key in componentDic:
# Imports the name of the class and creates an object
mod = __import__(key, fromlist=[componentDic.get(key)])
klass = getattr(mod, componentDic.get(key))
aux_component = klass(rootTopic)
# Ignores objects which are not Components
if isinstance(aux_component, Component):
my_components[key] = aux_component
my_components[key].setup(componentsSamplingIntevalInSeconds.get(key))
# The use of threads here is mainly in the case of components that
# should run in a parallel loop, such as the camera, and they can
# do so by implementing the run function. This shouldn't be
# the used for components such as sensors, since their data
# acquisition is done in the main loop
p = threading.Thread(
target=my_components[key].run)
p.daemon = True
p.start()
else:
print("It's not a valid component")
return my_components
# Get the slowest and fastest poll rates in order to define
# the cycle speed and the maximum number of cycles before resetting
# the counter
def get_max_min_sampling_interval(my_components):
max_interval = -1.0
min_interval = 1000.0
for component in my_components:
if my_components[component].sampInterval <= min_interval:
min_interval = my_components[component].sampInterval
if my_components[component].sampInterval >= max_interval:
max_interval = my_components[component].sampInterval
return max_interval, min_interval
# Update the number of cycles between measurements for
# each component based on the loop speed
def update_loop_cycles(my_components, loop_speed, timestamp):
for _, component in my_components.iteritems():
component.calculate_loop_cycles(loop_speed, timestamp)
# Main behavior
def main():
# Get components and setup CTRL+C handling
signal.signal(signal.SIGINT, signal_handler)
my_components = get_components()
# Get the sampling ratios of all components in order to
# define the cycle speed, the number of cycles
# in between measurements for each component as well as
# the number of cycles of the slowest component in order
# to reset the counter
max_rate, min_rate = get_max_min_sampling_interval(my_components)
max_loops = math.ceil((max_rate / min_rate))
update_loop_cycles(my_components, min_rate, time.time() * 1000000)
print "Loop speed: {} || Maximum number of cycles {} ".format(
min_rate, max_loops)
loopcount = 1
# Get timestamp, call handle data for each component
# sleep the rate - time_spent_on_loop
while True:
begin = time.time()
timestamp = int(begin * 1000000) # microseconds
for _, component in my_components.iteritems():
if loopcount % component.loopCycles == 0:
# component.handleData(timestamp)
p = threading.Thread(
target=component.handleData, args=(timestamp,))
p.daemon = True
p.start()
loopcount += 1
end = time.time()
# Prevents errors in case the loop takes too long
# Loop time is around 2ms with 2 components
if (end - begin) < min_rate:
time.sleep(min_rate - (end - begin))
if loopcount > max_loops:
loopcount = 1
sys.exit(0)
if __name__ == "__main__":
main()