-
Notifications
You must be signed in to change notification settings - Fork 0
/
soaring.py
131 lines (108 loc) · 3.93 KB
/
soaring.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#
# Connect thermal soaring code with either the Pixhawk or Piccolo
#
import sys
import argparse
from collections import deque
import multiprocessing
from multiprocessing.managers import SyncManager
from processing import processingProcess
# For debugging
# Trigger with: Tracer()()
# From: http://stackoverflow.com/a/35773311
from IPython.core.debugger import Tracer
#
# Allow working with a deque between threads
# http://stackoverflow.com/a/27345949
#
SyncManager.register('deque', deque)
#
# Work with data and commands
#
class NetworkData:
def __init__(self, data, commands, cond):
self.data = data
self.commands = commands
self.commandCondition = cond
# Add data/commands
def addData(self, d):
self.data.append(d)
def addCommand(self, c):
with self.commandCondition:
self.commands.append(c)
self.commandCondition.notify()
# Get one and pop off that we've used this data
def getData(self):
# Must copy since AutoProxy[deque] doesn't allow indexing
c = self.data.copy()
if c:
d = c[0]
self.data.popleft()
return d
return None
# Just get *all* the data, so we can just keep on running the thermal
# identification on the last so many data points
def getAllData(self):
return self.data.copy()
# Get one and pop off that we've sent this command
def getCommand(self):
c = self.commands.copy()
if c:
d = c[0]
self.commands.popleft()
return d
return None
# If we have a command available, return it. Otherwise, wait for one to be
# added, and then return that
def getCommandWait(self):
with self.commandCondition:
while True:
c = self.getCommand()
if c:
return c
self.commandCondition.wait()
if __name__ == "__main__":
# Parse command-line arguments
parser = argparse.ArgumentParser()
parser.add_argument('-s', dest='server', type=str, default="127.0.0.1:2050",
help='address of MAVProxy or the C++/Python interface server if for Piccolo')
parser.add_argument('-d', dest='debug', action='store_true',
help='debugging information')
parser.add_argument('-p', dest='piccolo', action='store_true',
help='Connect to Piccolo autopilot rather than the Pixhawk')
args = parser.parse_args()
# Get the server and port number from the input arguments
try:
server, port = args.server.split(":")
port = int(port)
except ValueError:
print("Error: invalid server address, example: localhost:2050")
sys.exit(1)
# Import either the mavlink or Piccolo networking
if args.piccolo:
from networking_piccolo import networkingProcess
else:
from networking_mavlink import networkingProcess
# Max length of data to keep
maxLength = 750
with SyncManager() as syncManager:
# Data to be passed back and forth between processes
data = syncManager.deque(maxlen=maxLength)
commands = syncManager.deque(maxlen=maxLength)
# When we add another command to send to the autopilot, wake up the
# sending thread to send this new data. This is to keep the sending
# thread from using 100% of the CPU since the select() will wake up
# continuously when we're done sending data and don't have any more to
# send yet.
commandCondition = multiprocessing.Condition()
# Functions to operate on these deques
nd = NetworkData(data, commands, commandCondition)
# Start the processes
n = multiprocessing.Process(target=networkingProcess,
args=[server, port, nd, args.debug])
p = multiprocessing.Process(target=processingProcess,
args=[nd, args.debug])
n.start()
p.start()
p.join()
n.join()