public bool C2isP2 = false; // "Mask" L2C-derived pseudoranges as P-code derived pseudorange public void Add(Epoch e) { if (e == null) { return; } if (C2isP2) { e.ForEach(s => { if (s.L2 != null && s.L2.trackstat.SignalType == 17) { s.L2.trackstat.SignalType = 5; } }); } var re = new RINEX211Epoch(e); // Record all sats seen re.ForEach(s => { if (!SatList.Contains(s.Name)) { SatList.Add(s.Name); } }); // Infer sampling interval, once if (this.Count == 1) { interval = (re.timestamp - this.First().timestamp).Seconds; } this.Add(re); // Record all observation-types seen if (!ObsTypeList.Contains(RINEX211ObsType.C1)) // Only look for L1 observations if not already seen { if (e.Exists(a => a.L1 != null)) { ObsTypeList.AddRange(new[] { RINEX211ObsType.C1, RINEX211ObsType.L1, RINEX211ObsType.D1, RINEX211ObsType.S1 }); } } if (!ObsTypeList.Contains(RINEX211ObsType.C5)) { if (e.Exists(a => a.L5 != null)) { ObsTypeList.AddRange(new[] { RINEX211ObsType.C5, RINEX211ObsType.L5, RINEX211ObsType.D5, RINEX211ObsType.S5 }); } } if (!ObsTypeList.Contains(RINEX211ObsType.L2)) { if (e.Exists(a => a.L2 != null)) { ObsTypeList.AddRange(new[] { RINEX211ObsType.L2, RINEX211ObsType.D2, RINEX211ObsType.S2 }); } } // L2 will have P2 or C2, in addition to L2, D2 and S2 - some sats may track C2 if configured (L2C) if (!ObsTypeList.Contains(RINEX211ObsType.P2)) { if (e.Exists(a => a.L2 != null && (a.L2.trackstat.SignalType == 5 || a.L2.trackstat.SignalType == 9))) { ObsTypeList.Add(RINEX211ObsType.P2); } } if (!ObsTypeList.Contains(RINEX211ObsType.C2)) { if (e.Exists(a => a.L2 != null && a.L2.trackstat.SignalType == 17)) { ObsTypeList.Add(RINEX211ObsType.C2); } } ObsTypeList.Sort(); }
public bool ParseSBAS = true; // Parse or ignore SBAS observations //Parse a #RANGEA message. Return Epoch public Epoch Parse(string line) { if (!line.StartsWith("#RANGEA")) { return(null); } // Check CRC of message if (!CRCok(line)) { Console.Error.WriteLine("CRC failed."); return(null); } string header = line.Split(';')[0]; string[] fields = header.Split(','); Epoch e = new Epoch(int.Parse(fields[5]), double.Parse(fields[6])); string data = line.Split(new char[] { ';', '*' })[1]; fields = data.Split(','); int i = 1; // Skip "number of observations to follow" while (fields.Length - i > 9) { int prn = int.Parse(fields[i++]); int glofreq = short.Parse(fields[i++]) - 7; Obs o = new Obs { psr = double.Parse(fields[i++]), psr_std = double.Parse(fields[i++]), adr = Math.Abs(double.Parse(fields[i++])), adr_std = double.Parse(fields[i++]), dopp = double.Parse(fields[i++]), snr = double.Parse(fields[i++]), locktime = float.Parse(fields[i++]), trackstat = new TrackStat(int.Parse(fields[i++], NumberStyles.HexNumber)) }; // Accept GPS, GLONASS, SBAS if (o.trackstat.SatelliteSystem > 2) { continue; } if (!ParseGLO && o.trackstat.SatelliteSystem == 1) { continue; } if (!ParseSBAS && o.trackstat.SatelliteSystem == 2) { continue; } if (!ParseL5 && o.trackstat.SignalType == 14) { continue; } // Throw out observations where parity is unknown if (!o.trackstat.ParityKnown) { continue; } // o.trackstat.SatelliteSystem: 0 = GPS, 1 = GLONASS, 2 = WAAS, 7 = Other char system = 'G'; // Default to GPS if (o.trackstat.SatelliteSystem == 1) { prn -= 37; // GLONASS PRN's are shown +37; fix. system = 'R'; } else if (o.trackstat.SatelliteSystem == 2) { prn -= 100; // SBAS should be reported -100, according to spec system = 'S'; } // Add observation to Sat, if already exists. Else create new Sat sat = e.Find(s => (s.PRN == prn && s.System == system)); if (sat == null) { sat = new Sat(system, prn); e.Add(sat); } if (o.trackstat.PrimaryL1) { if (o.trackstat.SignalType == 14) { sat.L5 = o; } else { // If a sat is manually assigned to a channel, we might see more than one observation of each type for the same sat. if (sat.L1 != null) { Console.Error.WriteLine("Observation on L1 for PRN {0} already parsed!", prn); } sat.L1 = o; } } else { if (sat.L2 != null) { Console.Error.WriteLine("Observation on L2 for PRN {0} already parsed!", prn); } sat.L2 = o; } } return(e); }