root/points/trunk/points.py

Revision 59 (checked in by cbc, 12 years ago)

Attempt to fix timing/process issue with copying backup goto list.

Line 
1 #!/usr/bin/env python
2
3 """
4 Generate glider goto list.
5
6 Warning: This script has only been tested for operations in
7          the Northwestern hemispheric quadrant. It will most
8          certainly fail for operations crossing quadrants.
9
10 Usage:
11
12     python points.py glider_name \\
13                      glider_lat glider_lon \\
14                      bearing \\
15                      heading [distance [steps [no_copy]]]
16
17     where glider_name is the whoru response from the glider,
18
19     where glider_lat and glider_lon are the present glider
20         latitude and longitude in ISO format (+/-ddmm.mmmm),
21
22     where bearing is the literal token bearing,
23
24     where heading is the direction of movement in degrees
25         clockwise from north,
26
27     where the optional distance is the spherical distance of       
28         movement in kilometers per step, defaulting to 2km,
29
30     where the optional steps are the number of waypoints to
31         generate with distance between each step, defaulting
32         to 20,
33
34     and where if the optional no_copy is present, suppress
35         writing a goto list to the to-glider folder
36         (archive only);
37
38     or
39
40     python points.py glider_name \\
41                      glider_lat glider_lon \\
42                      target \\
43                      target_lat target_lon \\
44                      [steps [no_copy]]
45
46     where glider_name is the whoru response from the glider,
47
48     where glider_lat and glider_lon are the present glider
49         latitude and longitude in ISO format (+/-ddmm.mmmm),
50
51     where target is the literal token target,
52
53     where target_lat and target_lon are the desired glider
54         latitude and longitude in ISO format (+/-ddmm.mmmm),
55
56     where the optional steps are the number of waypoints to
57         generate between present and desired glider positions,
58         defaulting to 20.
59
60     and where if the optional no_copy is present, suppress
61         writing a goto list to the to-glider folder
62         (archive only).
63 """
64
65 import sys
66 import os
67 import math
68 import shutil
69 import time
70 from datetime import datetime
71
72 months = {1: 'Jan',
73           2: 'Feb',
74           3: 'Mar',
75           4: 'Apr',
76           5: 'May',
77           6: 'Jun',
78           7: 'Jul',
79           8: 'Aug',
80           9: 'Sep',
81           10: 'Oct',
82           11: 'Nov',
83           12: 'Dec'}
84
85 LB1MOOR = [3310.353, -7819.800]
86 LB1ADCP = [3310.172, -7820.007]
87 LB2MOOR = [3256.491, -7805.667]
88 LB2ADCP = [3256.419, -7805.926]
89 LB3MOOR = [3251.142, -7800.793]
90 LB3ADCP = [3251.142, -7800.793]
91
92 glider_dir = '/var/opt/gmc/gliders'
93
94 goto_names = {"ramses": "goto_l10.ma",
95               "pelagia": "goto_l20.ma",}
96
97 first_template = \
98 """#
99 # Filename: %s
100 # File creation time: %s
101 # Generated by: %s
102 #
103
104 behavior_name=goto_list
105
106 <start:b_arg>
107         b_arg: num_legs_to_run(nodim) -2 # -1 loop, -2 run once, > 0 = this m$
108         b_arg: start_when(enum) 0       # 0 baw_immediately
109         b_arg: list_stop_when(enum) 7   # BAW_WHEN_WPT_DIST
110
111         # SATISFYING RADIUS
112         b_arg: list_when_wpt_dist(m) 100
113
114         # LIST PARAMETERS
115         b_arg: initial_wpt(enum) 0      # 0 to n-1, -1 first after last, -2 c$
116         b_arg: num_waypoints(nodim) %u
117 <end:b_arg>
118
119 <start:waypoints>
120 """
121
122 last_template = \
123 """<end:waypoints>
124
125 """
126
127 nmperrad = 360.0 * 60.0 / (2 * math.pi)  # 1 nautical mile per minute lat
128 kmperrad = nmperrad * 1.852              # mean at 48 degrees
129 kmperdeg = kmperrad * math.pi / 180.0
130
131 def ddmm2decdeg(ddmm):
132     sign = ddmm < 0
133     ddmm = abs(ddmm)
134     dd = (ddmm // 100)
135     mm = ddmm - (dd * 100)
136     dm = mm / 60
137     if sign:
138         decdeg = -(dd + dm)
139     else:
140         decdeg = dd + dm
141     return decdeg
142
143 def decdeg2ddmm(decdeg):
144     dd = int(decdeg)
145     dm = decdeg - dd
146     mm = dm * 60
147     ddmm = (dd * 100) + mm
148     return ddmm
149
150 def latlondict(latlonlist):
151     return {'lat': latlonlist[0],
152             'lon': latlonlist[1]}
153
154 def latlonlist(latlondict):
155     return [latlondict['lat'], latlondict['lon']]
156
157 def line(origin, target, steps):
158     vector = {'lat': target['lat'] - origin['lat'],
159               'lon': target['lon'] - origin['lon']}
160     divs = {'lat': vector['lat'] / steps,
161             'lon': vector['lon'] / steps}
162     points = [{'lat': origin['lat'] + (x * divs['lat']),
163                'lon': origin['lon'] + (x * divs['lon'])}
164               for x in range(1, steps + 1)]
165     return points
166
167 def swap(seq):
168     return [seq[1], seq[0]]
169
170 def _target(glider_name, glider_pos, target, steps, copy=False):
171     goto_name = goto_names[glider_name]
172     glider_pos = map(ddmm2decdeg, glider_pos)
173     target = map(ddmm2decdeg, target)
174
175     glider_pos = latlondict(glider_pos)
176     target = latlondict(target)
177
178     points = line(glider_pos, target, steps)
179     points = [latlonlist(point) for point in points]
180     points = [map(decdeg2ddmm, point) for point in points]
181
182     points = [swap(point) for point in points]
183
184     now = datetime.now()
185     now_string = "%02d-%s-%04d %02d:%02d:%02d UTC" % (now.day,
186                                                       months[now.month],
187                                                       now.year,
188                                                       now.hour,
189                                                       now.minute,
190                                                       now.second,
191                                                      )
192     now_stamp = "%04d%02d%02dT%02d%02d%02d" % (now.year,
193                                                now.month,
194                                                now.day,
195                                                now.hour,
196                                                now.minute,
197                                                now.second)
198
199     backup_dir = os.path.join(os.path.dirname(
200                                   os.path.abspath(__file__)),
201                               "archive",
202                               glider_name)
203     backup_name = "%s_%s_%s" % (glider_name,
204                                 goto_name,
205                                 now_stamp)
206     goto_path = os.path.join(glider_dir,
207                              glider_name,
208                              "to-glider",
209                              goto_name)
210     try:
211         os.makedirs(backup_dir)
212     except:
213         pass
214     backup_path = os.path.join(backup_dir,
215                                backup_name)
216
217     command_line = "%s %s" % (sys.executable,
218                               " ".join(sys.argv))
219     if copy:
220         dest = goto_path
221         dupe = backup_path
222     else:
223         dest = backup_path
224         dupe = None
225
226     handle = open(dest, "w")
227     handle.write(first_template % (goto_name,
228                                    now_string,
229                                    command_line,
230                                    steps))
231     handle.writelines(["\t%.3f\t%.3f\n" % tuple(point) for point in points])
232     handle.write(last_template)
233     handle.close()
234
235     if dupe:
236         shutil.copy2(dest, dupe)
237         print "\nCopied from %s to %s." % (dest, dupe),
238         sys.stdout.flush()
239
240     time.sleep(1)
241     return points
242
243 def _bearing(glider_name, glider_pos, heading, distance, steps, copy=False):
244     glider_pos = map(ddmm2decdeg, glider_pos)
245     glider_pos = map(math.radians, glider_pos)
246     glider_pos = latlondict(glider_pos)
247     heading = math.radians(heading)
248     distance = distance / kmperrad
249     dlat = distance * math.cos(heading)
250     dlon = distance * math.sin(heading) / math.cos(glider_pos['lat'])
251     target = {}
252     target['lon'] = glider_pos['lon'] + (steps * dlon)
253     target['lat'] = glider_pos['lat'] + (steps * dlat)
254     target = latlonlist(target)
255     target = map(math.degrees, target)
256     target = map(decdeg2ddmm, target)
257     glider_pos = latlonlist(glider_pos)
258     glider_pos = map(math.degrees, glider_pos)
259     glider_pos = map(decdeg2ddmm, glider_pos)
260     return _target(glider_name, glider_pos, target, steps, copy)
261
262 if __name__ == "__main__":
263     num_args = len(sys.argv) - 1
264     if not (num_args == 5 or
265             num_args == 6 or
266             num_args == 7 or
267             num_args == 8):
268         sys.exit(__doc__)
269
270     try:
271         glider_name = sys.argv[1]
272         glider_pos = [float(sys.argv[2]), float(sys.argv[3])]
273         method = sys.argv[4].lower()
274         if method == "bearing":
275             heading = target = float(sys.argv[5])
276             if num_args > 5:
277                 distance = float(sys.argv[6])
278             else:
279                 distance = 2
280             if num_args > 6:
281                 steps = int(sys.argv[7])
282             else:
283                 steps = 20
284             if num_args > 7:
285                 copy = False
286             else:
287                 copy = True
288             _bearing(glider_name, glider_pos, heading, distance, steps, copy)
289         elif method == "target":
290             target = [float(sys.argv[5]), float(sys.argv[6])]
291             if num_args > 6:
292                 steps = int(sys.argv[7])
293             else:
294                 steps = 20
295             if num_args > 7:
296                 copy = False
297             else:
298                 copy = True
299             _target(glider_name, glider_pos, target, steps, copy)
300         else:
301             raise Exception("Incorrect points method type.")
302     except:
303         sys.exit(__doc__)
304
Note: See TracBrowser for help on using the browser.