#!/usr/bin/env ruby require 'gps_pvt' require 'uri' # runnable quick example to solve PVT by using RINEX NAV/OBS or u-blox ubx $stderr.puts <<__STRING__ Usage: #{__FILE__} GPS_file1 GPS_file2 ... As GPS_file, rinex_nav(*.YYn, *.YYh, *.YYq, *.YYg), rinex_obs(*.YYo), ubx(*.ubx), SP3(*.sp3), and ANTEX(*.atx) format are currently supported. (YY = last two digit of year) File format is automatically determined based on its extention described in above parentheses. If you want to specify its format manually, command options like --rinex_nav=file_name are available. Other than --rinex_nav, --rinex_obs, -rinex_clk, --ubx, --sp3 or --antex are supported. Supported RINEX versions are 2 and 3. A file having additional ".gz" or ".Z" extension is recognized as a compressed file. Major URL such as http(s)://... or ftp://..., and serial port (COMn for Windows, /dev/tty* for *NIX) is acceptable as an input file name. __STRING__ options = [] misc_options = {} # check options and file format files = ARGV.collect{|arg| next [arg, nil] unless arg =~ /^--([^=]+)=?/ k, v = [$1.downcase.to_sym, $'] next [v, k] if [:rinex_nav, :rinex_obs, :ubx, :sp3, :antex, :rinex_clk].include?(k) # file type options << [$1.to_sym, $'] nil }.compact options.reject!{|opt| case opt[0] when :start_time, :end_time require 'time' gpst_type = GPS_PVT::GPS::Time t = nil if opt[1] =~ /^(?:(\d+):)??(\d+(?:\.\d*)?)$/ then t = [$1 && $1.to_i, $2.to_f] t = gpst_type::new(*t) if t[0] elsif t = (Time::parse(opt[1]) rescue nil) then # leap second handling in Ruby Time is system dependent, thus #t = gpst_type::new(0, t - Time::parse("1980-01-06 00:00:00 +0000")) # is inappropriate. subsec = t.subsec.to_f t = gpst_type::new(t.to_a[0..5].reverse) t += (subsec + gpst_type::guess_leap_seconds(t)) else raise "Unknown time format: #{opt[1]}" end case t when gpst_type $stderr.puts( "#{opt[0]}: %d week %f (a.k.a %04d/%02d/%02d %02d:%02d:%02.1f)" \ %(t.to_a + t.utc)) when Array $stderr.puts("#{opt[0]}: #{t[0] || '(current)'} week #{t[1]}") end misc_options[opt[0]] = t true when :online_ephemeris misc_options[opt[0]] = opt[1] true else false end } # Check file existence and extension files.collect!{|fname, ftype| ftype ||= case fname when /\.\d{2}[nhqg](?:\.gz)?$/; :rinex_nav when /\.\d{2}o(?:\.gz)?$/; :rinex_obs when /\.ubx$/; :ubx when /\.sp3(?:\.Z)?$/; :sp3 when /\.atx(?:\.Z)?$/; :antex when /\.clk$/; :rinex_clk else raise "Format cannot be guessed, use --(format, ex. rinex_nav)=#{fname}" end fname = proc{ next fname if File::exist?(fname) next fname if ((fname =~ Serial::SPEC) rescue false) if uri = URI::parse(fname) and !uri.instance_of?(URI::Generic) then next uri end raise "File not found: #{fname}" }.call [fname, ftype] } rcv = GPS_PVT::Receiver::new(options) proc{|src| next unless src loader = proc{|t_meas| utc = Time::utc(*t_meas.c_tm) y, yday = [:year, :yday].collect{|f| utc.send(f)} uri = URI::parse( "ftp://gssc.esa.int/gnss/data/daily/" + "%04d/brdc/BRDC00IGS_R_%04d%03d0000_01D_MN.rnx.gz"%[y, y, yday]) rcv.parse_rinex_nav(uri) uri } run_orig = rcv.method(:run) eph_list = {} rcv.define_singleton_method(:run){|meas, t_meas, *args| w_d = [t_meas.week, (t_meas.seconds.to_i / 86400)] eph_list[w_d] ||= loader.call(t_meas) run_orig.call(meas, t_meas, *args) } }.call(misc_options[:online_ephemeris]) proc{ run_orig = rcv.method(:run) t_start, t_end = [nil, nil] tasks = [] task = proc{|meas, t_meas, *args| t_start, t_end = [:start_time, :end_time].collect{|k| res = misc_options[k] res.kind_of?(Array) \ ? GPS_PVT::GPS::Time::new(t_meas.week, res[1]) \ : res } task = tasks.shift task.call(*([meas, t_meas] + args)) } tasks << proc{|meas, t_meas, *args| next nil if t_start && (t_start > t_meas) task = tasks.shift task.call(*([meas, t_meas] + args)) } tasks << proc{|meas, t_meas, *args| next nil if t_end && (t_end < t_meas) run_orig.call(*([meas, t_meas] + args)) } rcv.define_singleton_method(:run){|*args| task.call(*args) } }.call if [:start_time, :end_time].any?{|k| misc_options[k]} puts rcv.header # parse RINEX NAV files.each{|fname, ftype| case ftype when :rinex_nav; rcv.parse_rinex_nav(fname) when :sp3; rcv.attach_sp3(fname) when :antex; rcv.attach_antex(fname) when :rinex_clk; rcv.attach_rinex_clk(fname) end } # other files files.each{|fname, ftype| case ftype when :ubx; rcv.parse_ubx(fname) when :rinex_obs; rcv.parse_rinex_obs(fname) end }