3 ==============================================================================
5 This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
7 The GNSSTk is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 3.0 of the License, or
12 The GNSSTk is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with GNSSTk; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
21 This software was developed by Applied Research Laboratories at the
22 University of Texas at Austin.
23 Copyright 2004-2022, The Board of Regents of The University of Texas System
25 ==============================================================================
27 ==============================================================================
29 This software was developed by Applied Research Laboratories at the
30 University of Texas at Austin, under contract to an agency or agencies
31 within the U.S. Department of Defense. The U.S. Government retains all
32 rights to use, duplicate, distribute, disclose, or release this software.
34 Pursuant to DoD Directive 523024
36 DISTRIBUTION STATEMENT A: This software has been approved for public
37 release, distribution is unlimited.
39 ==============================================================================
43 import matplotlib.pyplot
as plt
48 valid_types = [
'rinexnav',
'rinex3nav',
'yuma',
'sp3',
'fic',
'sem']
61 header, data = gnsstk.readRinexNav(filename)
63 g = gnsstk.GPSEphemerisStore()
66 ephem = d.toEngEphemeris()
69 class rinexnav_holder:
70 def __init__(self, gpsStore, satStore):
71 self.gpsStore = gpsStore
72 self.satStore = satStore
74 return self.gpsStore.getInitialTime()
76 return self.gpsStore.getFinalTime()
77 def position(self, t):
78 triple = self.gpsStore.getXvt(self.satStore, t).getPos()
80 return rinexnav_holder(g, sat)
84 header, data = gnsstk.readRinex3Nav(filename)
86 g = gnsstk.GPSEphemerisStore()
89 ephem = d.toEngEphemeris()
92 class rinex3nav_holder:
93 def __init__(self, gpsStore, satStore):
94 self.gpsStore = gpsStore
95 self.satStore = satStore
97 return self.gpsStore.getInitialTime()
99 return self.gpsStore.getFinalTime()
100 def position(self, t):
101 triple = self.gpsStore.getXvt(self.satStore, t).getPos()
103 return rinex3nav_holder(g, sat)
107 store = gnsstk.SP3EphemerisStore()
108 store.loadFile(filename)
112 def __init__(self, sp3Store, satStore):
113 self.sp3Store = sp3Store
114 self.satStore = satStore
115 def first_time(self):
116 return self.sp3Store.getPositionInitialTime(self.satStore)
118 return self.sp3Store.getPositionFinalTime(self.satStore)
119 def position(self, t):
120 triple = self.sp3Store.getPosition(self.satStore, t)
122 return sp3_holder(store, sat)
126 header, data = gnsstk.readYuma(filename)
128 almanac = gnsstk.GPSAlmanacStore()
131 orbit = d.toAlmOrbit()
132 almanac.addAlmanac(orbit)
135 def __init__(self, almanacStore, satStore):
136 self.almanacStore = almanacStore
137 self.satStore = satStore
138 def first_time(self):
139 return self.almanacStore.getInitialTime()
141 return self.almanacStore.getFinalTime()
142 def position(self, t):
143 triple = self.almanacStore.getXvt(self.satStore, t).getPos()
145 return yuma_holder(almanac, sat)
149 header, data = gnsstk.readSEM(filename)
151 almanac = gnsstk.GPSAlmanacStore()
154 orbit = d.toAlmOrbit()
155 almanac.addAlmanac(orbit)
158 def __init__(self, almanacStore, satStore):
159 self.almanacStore = almanacStore
160 self.satStore = satStore
161 def first_time(self):
162 return self.almanacStore.getInitialTime()
164 return self.almanacStore.getFinalTime()
165 def position(self, t):
166 triple = self.almanacStore.getXvt(self.satStore, t).getPos()
168 return sem_holder(almanac, sat)
173 """Calls the appropriate position reader function based on the filetype."""
174 func_name = filetype +
'_data'
175 possibles = globals().copy()
176 possibles.update(locals())
177 func = possibles.get(func_name)
179 raise NotImplementedError(func +
' is not an implemented function.')
180 return func(filename, prn)
184 program_description = (
'This program takes 2 nav files and '
185 'provides a plot of the magnitude of '
186 'the difference of a given PRN ID.'
187 'Valid file types are ' + str(valid_types) +
'.')
189 parser = argparse.ArgumentParser(description=program_description)
190 parser.add_argument(
'prn_id', type=int,
191 help=
'The integer PRN ID you are interested in.')
192 parser.add_argument(
'filetype1', help=
'Type for the first file.')
193 parser.add_argument(
'filename1', help=
'File name for the first file.')
194 parser.add_argument(
'filetype2', help=
'Type for the second file.')
195 parser.add_argument(
'filename2', help=
'File name for the second file.')
196 parser.add_argument(
'-v',
'--verbose', action=
"store_true",
197 help=
'Print output locations and error.')
198 parser.add_argument(
'-n',
'--noplot', action=
"store_true",
199 help=
'Don\'t plot the file.')
200 parser.add_argument(
'-d',
'--drawdots', action=
"store_true",
201 help=
'Matplotlib will not connect calculated data '
202 'points in the plot')
203 parser.add_argument(
'-t',
'--timestep', type=int, default=300,
204 help=
'Timestep, in seconds, between plot points.')
205 parser.add_argument(
'-s',
'--save', help=
'Save the image to <file>.')
206 parser.add_argument(
'-f',
'--format', default=
'%02H:%02M',
207 help=
'Format for x time ticks.')
209 args = parser.parse_args(args)
215 def check(filetype, filename):
216 if not filetype
in valid_types:
217 print 'Invalid filetype:', filetype
218 print 'Valid choices are:' + str(valid_types)
219 print 'Use the -h or --help flags for more information.\n'
222 with open(
'filename'):
pass
225 sys.exit(filename,
'cannot be read.\n')
227 check(args.filetype1, args.filename1)
228 check(args.filetype2, args.filename2)
230 pos1 =
read_data(args.filetype1, args.filename1, args.prn_id)
231 pos2 =
read_data(args.filetype2, args.filename2, args.prn_id)
236 starttime =
max(pos1.first_time(), pos2.first_time())
237 endtime =
min(pos1.last_time(), pos2.last_time())
240 print (args.filename1 +
' ranges from ' + timestr(pos1.first_time())
241 +
' to ' + timestr(pos1.last_time()))
242 print (args.filename2 +
' ranges from ' + timestr(pos2.first_time())
243 +
' to ' + timestr(pos2.last_time()))
244 print 'Earliest time computable:', timestr(starttime)
245 print 'Latest time computable:', timestr(endtime),
'\n'
252 for t
in gnsstk.times(starttime, endtime, seconds=args.timestep):
254 p1 = pos1.position(t)
255 p2 = pos2.position(t)
257 maxErr =
max(maxErr, error)
258 X.append(t.getDays())
262 sumErrSq += error*error
264 print 'Time:', timestr(t)
265 print '\tPosition 1:', p1
266 print '\tPosition 2:', p2
267 print '\tError:', error
268 except gnsstk.exceptions.InvalidRequest:
270 print 'Can\'t use data at:', timestr(t)
272 if args.verbose
and n > 0:
273 print 'Arithmetic mean of error values: ', sumErr / n,
'm'
274 print 'Root mean square of error values:', np.sqrt(sumErrSq / n),
'm'
277 title = (
'Error for PRN ' + str(args.prn_id) +
' starting '
280 fig.suptitle(title, fontsize=14, fontweight=
'bold')
281 ax = fig.add_subplot(111)
282 ax.text(0.90, 0.90, args.filetype1 +
': ' + args.filename1
283 +
'\n' + args.filetype2 +
': ' + args.filename2,
284 verticalalignment=
'bottom', horizontalalignment=
'right',
285 transform=ax.transAxes)
286 ax.set_xlabel(
'Time')
287 ax.set_ylabel(
'Error (meters)')
294 plt.ylim([0, 2.0 * maxErr])
303 def format_coord(x, y):
304 return 'x=' + daytostring(x) +
', y=%1.4f'%(y)
305 ax.format_coord = format_coord
308 locs, labels = plt.xticks()
309 for i
in range(len(locs)):
310 labels[i] = daytostring(locs[i])
311 ax.set_xticklabels(labels)
316 if args.save
is not None:
317 fig.savefig(args.save)
320 def run(prn, filetype1, filename1, filetype2, filename2,
321 verbose=False, noplot=False, savelocation=None,
322 drawdots=False, timestep=300, format='%02H:%02M
'):
324 Functional interface to the position_difference script for easier
325 calling. See help on the script (python position_difference.py -h) for more.
327 commands = [str(prn), filetype1, filename1, filetype2, filename2,
328 '-t', str(timestep),
'-f', format]
330 commands.append(
'-v')
332 commands.append(
'-n')
333 if savelocation
is not None:
334 commands.append(
'-s')
335 commands.append(savelocation)
337 commands.append(
'-d')
341 if __name__ ==
'__main__':