/// <summary> /// 获取卫星在指定时刻,相对于测站的信息 /// </summary> /// <param name="service"></param> /// <param name="prn"></param> /// <param name="time"></param> /// <returns></returns> public StationSatInfo GetInstantSatInfo(IEphemerisService service, SatelliteNumber prn, Time time) { Geo.Coordinates.XYZ satPos = service.Get(prn, time).XYZ; GeoCoord coord = CoordTransformer.XyzToGeoCoord(satPos); Geo.Coordinates.Polar p = CoordTransformer.XyzToGeoPolar(satPos, StationPos); if (p.Elevation < EleAngle) { return(null); } this.LonLats.Add(new Vector(coord.Lon, coord.Lat) { Tag = prn.ToString() }); //显示到表格 return(new StationSatInfo() { PRN = prn, Time = time, Azimuth = p.Azimuth, ElevatAngle = p.Elevation, Distance = p.Range, Lat = coord.Lat, Lon = coord.Lon, Height = coord.Height, X = satPos.X, Y = satPos.Y, Z = satPos.Z }); }
public Ephemeris GetEphemerisInfo(Time gpsTime, XYZ staXyz, bool IsDualFreq = false) { double dt, dtr, clockOffSet; //*** correct satellite time dt = SatSvClock_NonRelative(gpsTime.SecondsOfWeek); //*** icd-200 20.3.3.3.3.1 dtr = SatSvClock_Relative(gpsTime.SecondsOfWeek, dt); clockOffSet = dt + dtr; //*** icd-200 20.3.3.3.3.2 (not dual freq) //*** old version below //*** if( (!myModes.IsDualFreq()) && (!myModes.IsIon())) svClock = svClock - tgd; //*** 2006july28 notes //*** DOD does NOT apply sat P1P2 DCB correction (Tgd) to broadcast clocks //*** IGS does NOT apply sat P1P2 DCB corrections to their clocks "by agreed convention" //*** thus, sat P1P2 DCB must be applied to DoD/IGS clocks if single freq. //*** this is same convention as icd-200 20.3.3.3.3.2 //*** this has NOTHING to do with use of any kind of normals ionosphere model //*** its purpose is undoing the disseminated svClock biases by means of //*** uncorrected (by DCB's) pseudorange ionosphere estimates if (!IsDualFreq) { clockOffSet = clockOffSet - TGD; } //*** compute broadcast position at corrected time Geo.Coordinates.XYZ xyz = GetSatXyz(gpsTime.SecondsOfWeek - clockOffSet, this.Prn); var state = OrbitUtil.GetPosXYZ(this, gpsTime.SecondsOfWeek - clockOffSet); return(new Ephemeris { XYZ = state.Value, ClockBias = clockOffSet, RelativeCorrection = dtr, Prn = this.Prn, Time = gpsTime, ClockDrift = ClockDrift, XyzDot = state.Rms }); }
/// <summary> /// 构造函数 /// </summary> public Ephemeris() { XYZ = new Geo.Coordinates.XYZ(); XyzDot = new Geo.Coordinates.XYZ(); }
/// <summary> /// 获取插值后的 EphemerisInfo。 /// 注意:不对钟差相对论误差进行改正,此处时间是卫星钟时间,没有相对信息。2014.09.08 /// 失败,如超过时间,则返回null /// 由于一般没有卫星速度的数据,必须通过插值坐标计算速度。2015.03. /// 如果有速度信息,以下的方法就不合适了。 /// </summary> /// <param name="gpsTime">时间</param> /// <returns></returns> public Ephemeris GetEphemerisInfo(Time gpsTime) { SatelliteNumber PRN = sortedRecords[0].Prn; Time min = sortedRecords[0].Time; Time max = sortedRecords[sortedRecords.Count - 1].Time; double span = (double)(max - min); double gpsSecond = (gpsTime - min); //减去序列中第一个数 //老是在这里出问题,宽限一点呢??16分钟 double expand = 60 * 16; if (gpsSecond + expand < 0 || gpsSecond - expand > span) { //return null; throw new ArgumentException("历元在给定的时间段外,不可进行插值。"); } //计算位置 double x = 0, y = 0, z = 0; double dtime = 0; double dx = 0, dy = 0, dz = 0; double ddtime = 0; int count = sortedRecords.Count; int order = 10; order = Math.Min(order, count); //czs // List<int> indexes = GetNearstIndexes(sortedRecords, gpsSecond, order); //cy List <int> indexes = GetNearstIndexes(sortedRecords, gpsTime, order); double[] t = new double[order + 1]; double[] tList = new double[order + 1]; double[] xList = new double[order + 1]; double[] yList = new double[order + 1]; double[] zList = new double[order + 1]; double[] clockList = new double[order + 1]; int i = 0; foreach (var item in indexes) { Ephemeris record = sortedRecords[item]; t[i] = (record.Time - gpsTime); //秒。 #region 方案1:顾及地球自转效应 //correction for earth rotation double sinl = Math.Sin(SunMoonPosition.OMGE * t[i]); double cosl = Math.Cos(SunMoonPosition.OMGE * t[i]); xList[i] = cosl * record.XYZ.X - sinl * record.XYZ.Y; yList[i] = sinl * record.XYZ.X + cosl * record.XYZ.Y; zList[i] = record.XYZ.Z; #endregion #region 方案2:不顾及地球自转效应 //xList[time] = record.XYZ.X; //yList[time] = record.XYZ.Y; //zList[time] = record.XYZ.Z; #endregion tList[i] = (record.Time - sortedRecords[0].Time); //秒。 clockList[i] = record.ClockBias; i++; } Lagrange(tList, xList, gpsSecond, ref x, ref dx); Lagrange(tList, yList, gpsSecond, ref y, ref dy); Lagrange(tList, zList, gpsSecond, ref z, ref dz); Lagrange(tList, clockList, gpsSecond, ref dtime, ref ddtime); int Nhalf = (int)(order / 2) - 1; int Nmatch = indexes[Nhalf]; //fitX.GetYdY(gpsSecond, ref x, ref dx); //fitY.GetYdY(gpsSecond, ref y, ref dy); //fitZ.GetYdY(gpsSecond, ref z, ref dz); //fitClock.GetYdY(gpsSecond, ref dtime, ref ddtime); XYZ SatXyz = new XYZ(x, y, z); if (!SatXyz.IsValid) { throw new Exception("插值失败!"); } //精度赋值 XYZ SatXyzSig = sortedRecords[Nmatch].Rms; double clockSig = sortedRecords[Nmatch].ClockBiasRms; XYZ SatXyzDotSig = new Geo.Coordinates.XYZ(0); //计算速度 //double nextSecond = gpsSecond + 0.001; //XYZ xyzNext = new XYZ(fitX.GetY(nextSecond), fitY.GetY(nextSecond), fitZ.GetY(nextSecond)); //XYZ speed = (xyzNext-xyz) / 0.001; XYZ SatSpeed = new XYZ(dx, dy, dz); //Add relativity correction to dtime //This only for consistency with GPSEphemerisInter //dtr=-2*dot(R,V)/(C*C) //dtime +=EphemerisUtil.GetRelativeCorrection(SatXyz, SatSpeed); return(new Ephemeris() { Prn = PRN, XYZ = SatXyz, Rms = SatXyzSig, // Clock = fitClock.GetY(gpsSecond), ClockBias = dtime, ClockBiasRms = clockSig, ClockDrift = ddtime, Time = gpsTime, XyzDot = SatSpeed, XyzDotRms = SatXyzDotSig }); }
/// <summary> /// Creates an instance of the class with the given position, velocity, and time. /// </summary> /// <param name="pos">The position vector.</param> /// <param name="vel">The velocity vector.</param> /// <param name="date">The time associated with the position.</param> public TimedMotionState(XYZ pos, XYZ vel, Julian date) : base(pos, vel) { Date = date; }
/// <summary> /// 指定时段内,可以看见的卫星。 /// </summary> /// <returns></returns> public List <VisibilityOfSat> GetPeriodSatAppearTimes() { this.LonLats.Clear(); List <VisibilityOfSat> sats = new List <VisibilityOfSat>(); List <StationSatInfo> infos = new List <StationSatInfo>(); List <SatelliteNumber> prns = new List <SatelliteNumber>(); // EphemerisService.EphemerisDataSource.GetEphemerisInfos( foreach (SatelliteNumber rec in EphemerisService.Prns)//卫星一颗一颗的算 { if (prns.Contains(rec)) { continue; } prns.Add(rec); VisibilityOfSat satA = new VisibilityOfSat() { PRN = rec, VisibleTimes = new List <BufferedTimePeriod>() }; sats.Add(satA); Polar lastP = null; DateTime f = DateTime.MinValue; for (int i = 0; i < Count; i++) { DateTime time = From + TimeSpan.FromMinutes(i * SpanMinutes); Time g = new Time(time); Geo.Coordinates.XYZ xyz = EphemerisService.Get(rec, g).XYZ; GeoCoord coord = CoordTransformer.XyzToGeoCoord(xyz); Polar p = CoordTransformer.XyzToGeoPolar(xyz, StationPos); if (lastP == null) { lastP = p; continue; } if (p.Elevation >= EleAngle) { if (f.Equals(DateTime.MinValue) || lastP.Elevation < EleAngle) { f = time; lastP = p; continue; } } if (p.Elevation < EleAngle || i == Count - 1) //当前小于指定高度角 { if (!f.Equals(DateTime.MinValue) && lastP.Elevation > EleAngle) //且上一个时刻是大于的,则终端出现了。 { BufferedTimePeriod s = new BufferedTimePeriod(f, time); satA.VisibleTimes.Add(s); this.LonLats.Add(new Vector(coord.Lon, coord.Lat) { Tag = rec.PRN.ToString() }); } } lastP = p; } } sats.Sort(); return(sats); }
/// <summary> /// 默认构造函数 /// </summary> /// <param name="Offset"></param> /// <param name="RotationAngleSecond"></param> /// <param name="ScaleFactorPpm"></param> public XyzFrameConvertParam(XYZ Offset, XYZ RotationAngleSecond, double ScaleFactorPpm) { this.Offset = Offset; this.RotationAngleSecond = RotationAngleSecond; this.ScaleFactorPpm = ScaleFactorPpm; }
/// <summary> /// 转换 /// </summary> /// <param name="old"></param> /// <returns></returns> public XYZ Convert(XYZ old) { return(CoordinateTransform(old, ConvertParam)); }