root/points/trunk/points.py

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

Fix spelling error in docstring.

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 from datetime import datetime
70
71 months = {1: 'Jan',
72           2: 'Feb',
73           3: 'Mar',
74           4: 'Apr',
75           5: 'May',
76           6: 'Jun',
77           7: 'Jul',
78           8: 'Aug',
79           9: 'Sep',
80           10: 'Oct',
81           11: 'Nov',
82           12: 'Dec'}
83
84 LB1MOOR = [3310.353, -7819.800]
85 LB1ADCP = [3310.172, -7820.007]
86 LB2MOOR = [3256.491, -7805.667]
87 LB2ADCP = [3256.419, -7805.926]
88 LB3MOOR = [3251.142, -7800.793]
89 LB3ADCP = [3251.142, -7800.793]
90
91 glider_dir = '/var/opt/gmc/gliders'
92
93 goto_names = {"ramses": "goto_l10.ma",
94               "pelagia": "goto_l20.ma",}
95
96 first_template = \
97 """#
98 # Filename: %s
99 # File creation time: %s
100 # Generated by: %s
101 #
102
103 behavior_name=goto_list
104
105 <start:b_arg>
106         b_arg: num_legs_to_run(nodim) -2 # -1 loop, -2 run once, > 0 = this m$
107         b_arg: start_when(enum) 0       # 0 baw_immediately
108         b_arg: list_stop_when(enum) 7   # BAW_WHEN_WPT_DIST
109
110         # SATISFYING RADIUS
111         b_arg: list_when_wpt_dist(m) 100
112
113         # LIST PARAMETERS
114         b_arg: initial_wpt(enum) 0      # 0 to n-1, -1 first after last, -2 c$
115         b_arg: num_waypoints(nodim) %u
116 <end:b_arg>
117
118 <start:waypoints>
119 """
120
121 last_template = \
122 """<end:waypoints>
123
124 """
125
126 nmperrad = 360.0 * 60.0 / (2 * math.pi)  # 1 nautical mile per minute lat
127 kmperrad = nmperrad * 1.852              # mean at 48 degrees
128 kmperdeg = kmperrad * math.pi / 180.0
129
130 def ddmm2decdeg(ddmm):
131     sign = ddmm < 0
132     ddmm = abs(ddmm)
133     dd = (ddmm // 100)
134     mm = ddmm - (dd * 100)
135     dm = mm / 60
136     if sign:
137         decdeg = -(dd + dm)
138     else:
139         decdeg = dd + dm
140     return decdeg
141
142 def decdeg2ddmm(decdeg):
143     dd = int(decdeg)
144     dm = decdeg - dd
145     mm = dm * 60
146     ddmm = (dd * 100) + mm
147     return ddmm
148
149 def latlondict(latlonlist):
150     return {'lat': latlonlist[0],
151             'lon': latlonlist[1]}
152
153 def latlonlist(latlondict):
154     return [latlondict['lat'], latlondict['lon']]
155
156 def line(origin, target, steps):
157     vector = {'lat': target['lat'] - origin['lat'],
158               'lon': target['lon'] - origin['lon']}
159     divs = {'lat': vector['lat'] / steps,
160             'lon': vector['lon'] / steps}
161     points = [{'lat': origin['lat'] + (x * divs['lat']),
162                'lon': origin['lon'] + (x * divs['lon'])}
163               for x in range(1, steps + 1)]
164     return points
165
166 def swap(seq):
167     return [seq[1], seq[0]]
168
169 def _target(glider_name, glider_pos, target, steps, copy=False):
170     goto_name = goto_names[glider_name]
171     glider_pos = map(ddmm2decdeg, glider_pos)
172     target = map(ddmm2decdeg, target)
173
174     glider_pos = latlondict(glider_pos)
175     target = latlondict(target)
176
177     points = line(glider_pos, target, steps)
178     points = [latlonlist(point) for point in points]
179     points = [map(decdeg2ddmm, point) for point in points]
180
181     points = [swap(point) for point in points]
182
183     now = datetime.now()
184     now_string = "%02d-%s-%04d %02d:%02d:%02d UTC" % (now.day,
185                                                       months[now.month],
186                                                       now.year,
187                                                       now.hour,
188                                                       now.minute,
189                                                       now.second,
190                                                      )
191     now_stamp = "%04d%02d%02dT%02d%02d%02d" % (now.year,
192                                                now.month,
193                                                now.day,
194                                                now.hour,
195                                                now.minute,
196                                                now.second)
197
198     backup_dir = os.path.join(os.path.dirname(
199                                   os.path.abspath(__file__)),
200                               "archive",
201                               glider_name)
202     backup_name = "%s_%s_%s" % (glider_name,
203                                 goto_name,
204                                 now_stamp)
205     goto_path = os.path.join(glider_dir,
206                              glider_name,
207                              "to-glider",
208                              goto_name)
209     try:
210         os.makedirs(backup_dir)
211     except:
212         pass
213     backup_path = os.path.join(backup_dir,
214                                backup_name)
215
216     command_line = "%s %s" % (sys.executable,
217                               " ".join(sys.argv))
218     handle = open(backup_path, "w")
219     handle.write(first_template % (goto_name,
220                                    now_string,
221                                    command_line,
222                                    steps))
223     handle.writelines(["\t%.3f\t%.3f\n" % tuple(point) for point in points])
224     handle.write(last_template)
225     handle.close()
226
227     if copy:
228         shutil.copy2(backup_path, goto_path)
229     return points
230
231 def _bearing(glider_name, glider_pos, heading, distance, steps, copy=False):
232     glider_pos = map(ddmm2decdeg, glider_pos)
233     glider_pos = map(math.radians, glider_pos)
234     glider_pos = latlondict(glider_pos)
235     heading = math.radians(heading)
236     distance = distance / kmperrad
237     dlat = distance * math.cos(heading)
238     dlon = distance * math.sin(heading) / math.cos(glider_pos['lat'])
239     target = {}
240     target['lon'] = glider_pos['lon'] + (steps * dlon)
241     target['lat'] = glider_pos['lat'] + (steps * dlat)
242     target = latlonlist(target)
243     target = map(math.degrees, target)
244     target = map(decdeg2ddmm, target)
245     glider_pos = latlonlist(glider_pos)
246     glider_pos = map(math.degrees, glider_pos)
247     glider_pos = map(decdeg2ddmm, glider_pos)
248     return _target(glider_name, glider_pos, target, steps, copy)
249
250 if __name__ == "__main__":
251     num_args = len(sys.argv) - 1
252     if not (num_args == 5 or
253             num_args == 6 or
254             num_args == 7 or
255             num_args == 8):
256         sys.exit(__doc__)
257
258     try:
259         glider_name = sys.argv[1]
260         glider_pos = [float(sys.argv[2]), float(sys.argv[3])]
261         method = sys.argv[4].lower()
262         if method == "bearing":
263             heading = target = float(sys.argv[5])
264             if num_args > 5:
265                 distance = float(sys.argv[6])
266             else:
267                 distance = 2
268             if num_args > 6:
269                 steps = int(sys.argv[7])
270             else:
271                 steps = 20
272             if num_args > 7:
273                 copy = False
274             else:
275                 copy = True
276             _bearing(glider_name, glider_pos, heading, distance, steps, copy)
277         elif method == "target":
278             target = [float(sys.argv[5]), float(sys.argv[6])]
279             if num_args > 6:
280                 steps = int(sys.argv[7])
281             else:
282                 steps = 20
283             if num_args > 7:
284                 copy = False
285             else:
286                 copy = True
287             _target(glider_name, glider_pos, target, steps, copy)
288         else:
289             raise Exception("Incorrect points method type.")
290     except:
291         sys.exit(__doc__)
292
Note: See TracBrowser for help on using the browser.