position_difference.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 """
3 ==============================================================================
4 
5  This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
6 
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
10  any later version.
11 
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.
16 
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
20 
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
24 
25 ==============================================================================
26 
27 ==============================================================================
28 
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.
33 
34  Pursuant to DoD Directive 523024
35 
36  DISTRIBUTION STATEMENT A: This software has been approved for public
37  release, distribution is unlimited.
38 
39 ==============================================================================
40 """
41 import argparse
42 import gnsstk
43 import matplotlib.pyplot as plt
44 import numpy as np
45 import sys
46 
47 
48 valid_types = ['rinexnav', 'rinex3nav', 'yuma', 'sp3', 'fic', 'sem']
49 
50 
52  return gnsstk.Position(x[0], x[1], x[2])
53 
54 
55 # All data read functions should obey this contract:
56 # 1. Take filename and prn as parameters
57 # 2. Return an object that has a position function ((CommonTime) -> numpy.array)
58 # 3. Return an object that has a first_time function (() -> CommonTime)
59 # 4. Return an object that has a last_time (() -> CommonTime)
60 def rinexnav_data(filename, prn):
61  header, data = gnsstk.readRinexNav(filename)
62  sat = gnsstk.SatID(prn, gnsstk.SatelliteSystem.GPS)
63  g = gnsstk.GPSEphemerisStore()
64  for d in data:
65  if prn == d.PRNID:
66  ephem = d.toEngEphemeris()
67  g.addEphemeris(ephem)
68 
69  class rinexnav_holder:
70  def __init__(self, gpsStore, satStore):
71  self.gpsStore = gpsStore
72  self.satStore = satStore
73  def first_time(self):
74  return self.gpsStore.getInitialTime()
75  def last_time(self):
76  return self.gpsStore.getFinalTime()
77  def position(self, t):
78  triple = self.gpsStore.getXvt(self.satStore, t).getPos()
79  return triple2Position(triple)
80  return rinexnav_holder(g, sat)
81 
82 
83 def rinex3nav_data(filename, prn):
84  header, data = gnsstk.readRinex3Nav(filename)
85  sat = gnsstk.SatID(prn, gnsstk.SatelliteSystem.GPS)
86  g = gnsstk.GPSEphemerisStore()
87  for d in data:
88  if prn == d.PRNID:
89  ephem = d.toEngEphemeris()
90  g.addEphemeris(ephem)
91 
92  class rinex3nav_holder:
93  def __init__(self, gpsStore, satStore):
94  self.gpsStore = gpsStore
95  self.satStore = satStore
96  def first_time(self):
97  return self.gpsStore.getInitialTime()
98  def last_time(self):
99  return self.gpsStore.getFinalTime()
100  def position(self, t):
101  triple = self.gpsStore.getXvt(self.satStore, t).getPos()
102  return triple2Position(triple)
103  return rinex3nav_holder(g, sat)
104 
105 
106 def sp3_data(filename, prn):
107  store = gnsstk.SP3EphemerisStore()
108  store.loadFile(filename)
109  sat = gnsstk.SatID(prn)
110 
111  class sp3_holder:
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)
117  def last_time(self):
118  return self.sp3Store.getPositionFinalTime(self.satStore)
119  def position(self, t):
120  triple = self.sp3Store.getPosition(self.satStore, t)
121  return triple2Position(triple)
122  return sp3_holder(store, sat)
123 
124 
125 def yuma_data(filename, prn):
126  header, data = gnsstk.readYuma(filename)
127  sat = gnsstk.SatID(prn, gnsstk.SatelliteSystem.GPS)
128  almanac = gnsstk.GPSAlmanacStore()
129  for d in data:
130  if prn == d.PRN:
131  orbit = d.toAlmOrbit()
132  almanac.addAlmanac(orbit)
133 
134  class yuma_holder:
135  def __init__(self, almanacStore, satStore):
136  self.almanacStore = almanacStore
137  self.satStore = satStore
138  def first_time(self):
139  return self.almanacStore.getInitialTime()
140  def last_time(self):
141  return self.almanacStore.getFinalTime()
142  def position(self, t):
143  triple = self.almanacStore.getXvt(self.satStore, t).getPos()
144  return triple2Position(triple)
145  return yuma_holder(almanac, sat)
146 
147 
148 def sem_data(filename, prn):
149  header, data = gnsstk.readSEM(filename)
150  sat = gnsstk.SatID(prn, gnsstk.SatelliteSystem.GPS)
151  almanac = gnsstk.GPSAlmanacStore()
152  for d in data:
153  if prn == d.PRN:
154  orbit = d.toAlmOrbit()
155  almanac.addAlmanac(orbit)
156 
157  class sem_holder:
158  def __init__(self, almanacStore, satStore):
159  self.almanacStore = almanacStore
160  self.satStore = satStore
161  def first_time(self):
162  return self.almanacStore.getInitialTime()
163  def last_time(self):
164  return self.almanacStore.getFinalTime()
165  def position(self, t):
166  triple = self.almanacStore.getXvt(self.satStore, t).getPos()
167  return triple2Position(triple)
168  return sem_holder(almanac, sat)
169 
170 
171 # Director function for data reading:
172 def read_data(filetype, filename, prn):
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)
178  if func is None:
179  raise NotImplementedError(func + ' is not an implemented function.')
180  return func(filename, prn)
181 
182 
183 def main(args=sys.argv[1:]):
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) + '.')
188 
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.')
208 
209  args = parser.parse_args(args)
210 
211 
212  def timestr(t):
213  return str(gnsstk.CivilTime(t))
214 
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'
220  sys.exit()
221  try:
222  with open('filename'): pass
223  except IOError as e:
224  print e
225  sys.exit(filename, 'cannot be read.\n')
226 
227  check(args.filetype1, args.filename1)
228  check(args.filetype2, args.filename2)
229 
230  pos1 = read_data(args.filetype1, args.filename1, args.prn_id)
231  pos2 = read_data(args.filetype2, args.filename2, args.prn_id)
232 
233  X = [] # list of x plot values
234  Y = [] # list of y plot values
235 
236  starttime = max(pos1.first_time(), pos2.first_time())
237  endtime = min(pos1.last_time(), pos2.last_time())
238 
239  if args.verbose:
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'
246 
247  sumErr = 0.0
248  sumErrSq = 0.0
249  n = 0
250  maxErr = 0.0
251 
252  for t in gnsstk.times(starttime, endtime, seconds=args.timestep):
253  try:
254  p1 = pos1.position(t)
255  p2 = pos2.position(t)
256  error = gnsstk.range(p1, p2)
257  maxErr = max(maxErr, error)
258  X.append(t.getDays())
259  Y.append(error)
260  if args.verbose:
261  sumErr += error
262  sumErrSq += error*error
263  n += 1
264  print 'Time:', timestr(t)
265  print '\tPosition 1:', p1
266  print '\tPosition 2:', p2
267  print '\tError:', error
268  except gnsstk.exceptions.InvalidRequest:
269  if args.verbose:
270  print 'Can\'t use data at:', timestr(t)
271 
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'
275 
276  fig = plt.figure()
277  title = ('Error for PRN ' + str(args.prn_id) + ' starting '
278  + gnsstk.CivilTime(starttime).printf('%02m/%02d/%04Y %02H:%02M:%02S'))
279 
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)')
288  if args.drawdots:
289  plt.plot(X, Y, 'ro')
290  else:
291  plt.plot(X, Y, 'r')
292 
293  # sets the y scale
294  plt.ylim([0, 2.0 * maxErr])
295 
296  # converts common time day (float) -> string
297  def daytostring(x):
298  t = gnsstk.CommonTime()
299  t.set(x)
300  return gnsstk.CivilTime(t).printf(args.format)
301 
302  # sets the text shown per-pixel when viewed interactively
303  def format_coord(x, y):
304  return 'x=' + daytostring(x) + ', y=%1.4f'%(y)
305  ax.format_coord = format_coord
306 
307  # sets x ticks to use the daytostring text
308  locs, labels = plt.xticks()
309  for i in range(len(locs)):
310  labels[i] = daytostring(locs[i])
311  ax.set_xticklabels(labels)
312 
313  if not args.noplot:
314  plt.show()
315 
316  if args.save is not None:
317  fig.savefig(args.save)
318 
319 
320 def run(prn, filetype1, filename1, filetype2, filename2,
321  verbose=False, noplot=False, savelocation=None,
322  drawdots=False, timestep=300, format='%02H:%02M'):
323  """
324  Functional interface to the position_difference script for easier
325  calling. See help on the script (python position_difference.py -h) for more.
326  """
327  commands = [str(prn), filetype1, filename1, filetype2, filename2,
328  '-t', str(timestep), '-f', format]
329  if verbose:
330  commands.append('-v')
331  if noplot:
332  commands.append('-n')
333  if savelocation is not None:
334  commands.append('-s')
335  commands.append(savelocation)
336  if drawdots:
337  commands.append('-d')
338  main(commands)
339 
340 
341 if __name__ == '__main__':
342  main()
position_difference.sem_data
def sem_data(filename, prn)
Definition: position_difference.py:148
position_difference.rinex3nav_data
def rinex3nav_data(filename, prn)
Definition: position_difference.py:83
gnsstk::max
T max(const SparseMatrix< T > &SM)
Maximum element - return 0 if empty.
Definition: SparseMatrix.hpp:881
gnsstk::SatID
Definition: SatID.hpp:89
position_difference.rinexnav_data
def rinexnav_data(filename, prn)
Definition: position_difference.py:60
position_difference.yuma_data
def yuma_data(filename, prn)
Definition: position_difference.py:125
position_difference.run
def run(prn, filetype1, filename1, filetype2, filename2, verbose=False, noplot=False, savelocation=None, drawdots=False, timestep=300, format='%02H:%02M')
Definition: position_difference.py:320
position_difference.sp3_data
def sp3_data(filename, prn)
Definition: position_difference.py:106
position_difference.read_data
def read_data(filetype, filename, prn)
Definition: position_difference.py:172
gnsstk::CommonTime
Definition: CommonTime.hpp:84
position_difference.triple2Position
def triple2Position(x)
Definition: position_difference.py:51
gnsstk::min
T min(const SparseMatrix< T > &SM)
Maximum element - return 0 if empty.
Definition: SparseMatrix.hpp:858
gnsstk::CivilTime
Definition: CivilTime.hpp:55
position_difference.main
def main(args=sys.argv[1:])
Definition: position_difference.py:183
gnsstk::range
double range(const Position &A, const Position &B)
Definition: Position.cpp:1273
gnsstk::Position
Definition: Position.hpp:136


gnsstk
Author(s):
autogenerated on Wed Oct 25 2023 02:40:40