public override void Correct(EpochInformation epochInformation) { Time gpsTime = epochInformation.ReceiverTime;//.CorrectedTime; XYZ reciverPosition = epochInformation.SiteInfo.EstimatedXyz; //查找地球自转信息 //gpst2utc Time tutc = gpsTime.GpstToUtc(); Gnsser.Data.ErpItem erpv = null; if (DataSouceProvider.ErpDataService != null) { erpv = DataSouceProvider.ErpDataService.Get(tutc); } if (erpv == null) { erpv = ErpItem.Zero; } var pos = DataSouceProvider.UniverseObjectProvider.GetOrCreate(gpsTime, erpv); //Gnsser.Data.ErpItem erpv = epochInformation.DataSouceProvider.ErpDataService.Gete); //XYZ sunPos = new XYZ(); XYZ moonPos = new XYZ(); double gmst = 0.0; //epochInformation.DataSouceProvider.UniverseObjectProvider.GetSunPosition(gpsTime, erpv, ref sunPos, ref moonPos,ref gmst); NEU correction = GetSolidTidesCorrectValue(gpsTime, reciverPosition, pos.SunXyz, pos.MoonXyz); this.Correction = (correction); }
/// <summary> /// 字符串 /// </summary> /// <param name="n"></param> /// <returns></returns> public static string GetNEUString(NEU n) { return (StringUtil.FillSpaceLeft(n.N.ToString("0.0000"), 8) + " " + StringUtil.FillSpaceLeft(n.E.ToString("0.0000"), 8) + " " + StringUtil.FillSpaceLeft(n.U.ToString("0.0000"), 8)); }
/// <summary> /// 接收机天线改正 /// </summary> /// <param name="epochInformation"></param> public override void Correct(EpochInformation epochInformation) { HEN offsetARPHEN = epochInformation.SiteInfo.Hen; if (offsetARPHEN == null) { return; } // Vector from monument to ARP([UEN]),标石到天线参考点(ARP)的矢量。 NEU offsetARP = new NEU(offsetARPHEN.N, offsetARPHEN.E, offsetARPHEN.H); NEU correction = offsetARP; this.Correction = correction; //this.Correction = NEU.Zero;// correction; }
/// <summary> /// 极潮改正,参考RTKLIB模块 /// </summary> /// <param name="reciverPosition"></param> /// <param name="xDisplacement"></param> /// <param name="yDisplacement"></param> /// <returns></returns> private static NEU GetPoleTidesCorrectValue2(XYZ reciverPosition, double xDisplacement, double yDisplacement) { double[] pos = new double[2]; pos[0] = Math.Asin(reciverPosition.Z / reciverPosition.Length); pos[1] = Math.Atan2(reciverPosition.Y, reciverPosition.X); double cosl = Math.Cos(pos[1]); double sinl = Math.Sin(pos[1]); double e = 9E-3 * Math.Sin(pos[0]) * (xDisplacement * sinl + yDisplacement * cosl); double n = -9E-3 * Math.Cos(2.0 * pos[0]) * (xDisplacement * cosl - yDisplacement * sinl); double u = -32E-3 * Math.Sin(2.0 * pos[0]) * (xDisplacement * cosl - yDisplacement * sinl); NEU correction = new NEU(n, e, u); return(correction); }
/// <summary> /// 卫星天线相位中心改正,参照RTKLIB /// </summary> /// <param name="satelliteType"></param> /// <param name="satPos"></param> /// <param name="ReceiverPosition"></param> /// <param name="sunPosition"></param> /// <param name="svPCcorr"></param> /// <param name="antenna"></param> /// <returns></returns> private static double GetPhaseCorrection1(SatelliteNumber prn, XYZ satPos, XYZ ReceiverPosition, XYZ sunPosition, double svPCcorr, IAntenna antenna) { XYZ ru = ReceiverPosition - satPos; XYZ rz = -satPos; double[] eu = new double[3]; eu[0] = ru.X / ru.Length; eu[1] = ru.Y / ru.Length; eu[2] = ru.Z / ru.Length; double[] ez = new double[3]; ez[0] = rz.X / rz.Length; ez[1] = rz.Y / rz.Length; ez[2] = rz.Z / rz.Length; double cosa = eu[0] * ez[0] + eu[1] * ez[1] + eu[2] * ez[2]; cosa = cosa < -1.0 ? -1.0 : (cosa > 1.0 ? 1.0 : cosa); double nadir = Math.Acos(cosa) * CoordConsts.RadToDegMultiplier; //// The nadir angle should always smaller than 14.0 deg, // // but some times it's a bit bigger than 14.0 deg, we // // force it to 14.0 deg to stop throwing an exception. // // The Reference is available at: // // http://igscb.jpl.nasa.gov/igscb/resource/pubs/02_ott/session_8.pdf // nadir = (nadir > 14) ? 14.0 : nadir; double elev = 90.0 - nadir; // Get antenna eccentricity for frequency "G01" (L1), in // satellite reference system. // NOTE: It is NOT in ECEF, it is in UEN!!! RinexSatFrequency freq = new RinexSatFrequency(prn, 1); // NEU satAnt = antenna.GetAntennaEccentricity(AntennaFrequency.G01); NEU satAnt = antenna.GetPcoValue(freq); if (satAnt.Equals(NEU.Zero)) { return(0); } //Now, get the phase center variation. var var = antenna.GetPcvValue(freq, elev); //只有U方向有值 // Projection of "svAntenna" vector to line of sight vector rrho // svPCcorr = var.U; return(var); }
public override void Correct(EpochInformation epochInformation) { string markerName = epochInformation.SiteInfo.SiteName; // Time gpsTime = epochInformation.CorrectedTime; Time gpsTime = epochInformation.ReceiverTime; //gpst2utc Time tutc = gpsTime.GpstToUtc(); //查找地球自转信息 Gnsser.Data.ErpItem erpv = null; if (DataSouceProvider.ErpDataService != null) { erpv = DataSouceProvider.ErpDataService.Get(tutc); } if (erpv == null) { erpv = ErpItem.Zero; } //GPS时转UTC时,再加上ERP改正 gpsTime = tutc + erpv.Ut12Utc; // Geo.Algorithm.Matrix harmonics = new Geo.Algorithm.Matrix(6, 11, 0.0); // harmonics = epochInformation.AssistantInfo.Harmonics; if (markerName.Length > 4) { markerName = markerName.Substring(0, 4); } Geo.Algorithm.IMatrix harmonics = DataSouceProvider.OceanLoadingDataSource.Get(markerName); //GPSTK模块 // NEU correction = GetOceanTidesCorrectValue(gpsTime, harmonics); //RTKLIB模块 NEU correction = GetOceanTidesCorrectValue1(gpsTime, harmonics); this.Correction = (correction); }
public override void Correct(EpochInformation epochInformation) { Time gpsTime = epochInformation.ReceiverTime;//.CorrectedTime; XYZ reciverPosition = epochInformation.SiteInfo.EstimatedXyz; GeoCoord geoCoord = epochInformation.SiteInfo.ApproxGeoCoord; if (XYZ.IsZeroOrEmpty(reciverPosition)) { this.Correction = NEU.Zero; return; } //GPS时转UTC时 Time tutc = gpsTime.GpstToUtc(); //查找ERP信息 //查找地球自转信息 Gnsser.Data.ErpItem erpv = null; if (DataSouceProvider.ErpDataService != null) { erpv = DataSouceProvider.ErpDataService.Get(tutc); } if (erpv == null) { erpv = ErpItem.Zero; } //EarthPoleDisplacement double xp = erpv.Xpole;//arcsec double yp = erpv.Ypole; //RTKLIB的极潮改正模块 // NEU correction = GetPoleTidesCorrectValue2(reciverPosition, xp, yp); //GPSTK的极潮改正模块 NEU correction = GetPoleTidesCorrectValue(gpsTime, reciverPosition, xp, yp, geoCoord); this.Correction = (correction); }
public override void Correct(EpochInformation epochInformation) { if (XYZ.IsZeroOrEmpty(epochInformation.SiteInfo.EstimatedXyz) || epochInformation.EnabledSatCount == 0 || epochInformation.ReceiverTime.IsZero) { this.Correction = new NEU(); return; } // Time gpsTime = epochInformation.CorrectedTime; Time gpsTime = epochInformation.ReceiverTime; XYZ reciverPosition = epochInformation.SiteInfo.EstimatedXyz; GeoCoord geoPosition = epochInformation.SiteInfo.ApproxGeoCoord; XYZ rsun = new XYZ(); XYZ rmoon = new XYZ(); double gmst = 0; //gpst2utc Time tutc = gpsTime.GpstToUtc(); //查找地球自转信息 Gnsser.Data.ErpItem erpv = null; if (DataSouceProvider.ErpDataService != null) { erpv = DataSouceProvider.ErpDataService.Get(tutc); } if (erpv == null) { erpv = ErpItem.Zero; } Time tut = tutc + erpv.Ut12Utc; //采用RTKLIB的太阳月亮位置计算方法(历书计算方法不同,相关文献表明对最终的定位精度影响差别不大) DataSouceProvider.UniverseObjectProvider.GetSunPosition(gpsTime, erpv, ref rsun, ref rmoon, ref gmst); NEU Correction = GetSolidTidesCorrectValue(geoPosition, reciverPosition, rsun, rmoon, gmst); this.Correction = (Correction); }
/** Returns the effect of ocean tides loading (meters) at the given * station and epoch, in the Up-East-North (UEN) reference frame. * * @param name Station name (case is NOT relevant). * @param time Epoch to look up * * @return a Triple with the ocean tidas loading effect, in meters * and in the UEN reference frame. * * @throw InvalidRequest If the request can not be completed for any * reason, this is thrown. The text may have additional information * about the reason the request failed. */ /// <summary> /// 海洋负荷改正,采用GPSTK模块 /// 此处采用NEU表示,其中的各个分量相对应。 /// </summary> /// <param name="gpsTime">Epoch to look up</param> /// <param name="position">Position of interest</param> /// <returns></returns> public static NEU GetOceanTidesCorrectValue(Time gpsTime, Geo.Algorithm.IMatrix harmonics) { const int NUM_COMPONENTS = 3; const int NUM_HARMONICS = 11; double[] arguments = new double[11]; // List<double> arguments = new List<double>(11); //Compute arguments arguments = GetArg(gpsTime); double[] triple = new double[NUM_COMPONENTS]; for (int i = 0; i < NUM_COMPONENTS; i++) { double temp = 0.0; for (int k = 0; k < NUM_HARMONICS; k++) { double tttt = harmonics[i, k]; double ttt = arguments[k]; double tt = harmonics[i + 3, k]; temp += harmonics[i, k] * Math.Cos(arguments[k] - harmonics[i + 3, k] * CoordConsts.DegToRadMultiplier); } triple[i] = temp; } // This Triple is in Up, West, South reference frame double up = triple[0]; double west = triple[1]; double sourth = triple[2]; double north = -sourth; double east = -west; NEU oceanTides = new NEU(north, east, up); return(oceanTides); }
/** Returns the effect of pole tides (meters) at the given * position and epoch, in the Up-East-North (UEN) reference frame. * * @param[in] t Epoch to look up * @param[in] info Position of interest * * @return a Triple with the pole tide effect, in meters and in * the UEN reference frame. * * @throw InvalidRequest If the request can not be completed for any * reason, this is thrown. The text may have additional * information about the reason the request failed. * * @warning In order to use this method, you must have previously * set the current pole displacement parameters. * */ public NEU GetPoleTide(Time t, XYZ p) { //store the results NEU res = new NEU(0.0, 0.0, 0.0); //Declare J2000 reference time: January 1st, 2000, at noon Time j2000 = new Time(2000, 1, 1, 12, 0, 0.0); //Get current position's latitude and longitude, in radians GeoCoord geoCoord = Geo.Coordinates.CoordTransformer.XyzToGeoCoord_Rad(p.X, p.Y, p.Z); double latitude = geoCoord.Lat; double longitude = geoCoord.Lon; // Compute appropriate running averages // Get time difference between current epoch and // J2000.0, in years double timedif = (double)((t.MJulianDays - j2000.MJulianDays) / 365.25M); //IERS mean pole model //double xpbar = (0.054 + timedif * 0.00083); //double ypbar = (0.357 + timedif * 0.00395); double xpbar = 0.0; double ypbar = 0.0; #region IERS Conventions 2010 p115 if (t.Year < 2010) { xpbar = 55.974 * 1.0e-3 + timedif * 1.8243 * 1.0e-3 + timedif * timedif * 0.18413 * 1.0e-3 + timedif * timedif * timedif * 0.007024 * 1.0e-3; ypbar = 346.346 * 1.0e-3 + timedif * 1.7896 * 1.0e-3 + timedif * timedif * (-0.10729) * 1.0e-3 + timedif * timedif * timedif * (-0.000908) * 1.0e-3; } else { xpbar = 23.513 * 1.0e-3 + timedif * 7.6141 * 1.0e-3; ypbar = 358.891 * 1.0e-3 + timedif * (-0.6287) * 1.0e-3; } #endregion // Now, compute m1 and m2 parameters double m1 = (XDisplacement - xpbar); double m2 = (ypbar - YDisplacement); // Now, compute some useful values double sin2lat = (Math.Sin(2.0 * latitude)); double cos2lat = (Math.Cos(2.0 * latitude)); double sinlat = (Math.Sin(latitude)); double sinlon = (Math.Sin(longitude)); double coslon = (Math.Cos(longitude)); // Finally, get the pole tide values, in UEN reference // frame and meters double u = -0.033 * sin2lat * (m1 * coslon + m2 * sinlon); double e = +0.009 * sinlat * (m1 * sinlon - m2 * coslon); double n = -0.009 * cos2lat * (m1 * coslon + m2 * sinlon); res = new NEU(n, e, u); // Please be aware that the former equations take into account // that the IERS pole tide equations use CO-LATITUDE instead // of LATITUDE. See Wahr, 1985. return(res); }
/// <summary> /// 根据太阳计算卫星偏差 /// </summary> /// <param name="prn"></param> /// <param name="eph"></param> /// <param name="emissionTime"></param> /// <returns></returns> private XYZ GetSatAntOff(SatelliteNumber prn, IEphemeris eph, Time emissionTime) { ErpItem erpv = null; if (DataSouceProvider.ErpDataService != null) { erpv = DataSouceProvider.ErpDataService.Get(emissionTime); } if (erpv == null) { erpv = ErpItem.Zero; } XYZ rsun = new XYZ(); //sun position in ecef // rsun = EpochSat.EpochInfo.DataSouceProvider.UniverseObjectProvider.GetSunPosition(emissionTime); this.DataSouceProvider.UniverseObjectProvider.GetSunPosition(emissionTime, erpv, ref rsun); //unit vetcors of satellite fixed coordinates XYZ ez = -1 * eph.XYZ.UnitVector(); XYZ es = (rsun - eph.XYZ).UnitVector(); //outer product of 3D vectors XYZ r = new XYZ(); r.X = ez.Y * es.Z - ez.Z * es.Y; r.Y = ez.Z * es.X - ez.X * es.Z; r.Z = ez.X * es.Y - ez.Y * es.X; XYZ r0 = new XYZ(); r0.X = r.Y * ez.Z - r.Z * ez.Y; r0.Y = r.Z * ez.X - r.X * ez.Z; r0.Z = r.X * ez.Y - r.Y * ez.X; XYZ ex = r0.UnitVector(); XYZ ey = r.UnitVector(); //XYZ ex = new XYZ(); //ex.X = ey.Y * ez.Z - ey.Z * ez.Y; //ex.Y = ey.Z * ez.X - ey.X * ez.Z; //ex.Z = ey.X * ez.Y - ey.Y * ez.X; //use L1 value if (DataSouceProvider.AntennaDataSource == null) { return(new XYZ()); } IAntenna antenna = DataSouceProvider.AntennaDataSource.Get(prn.ToString(), emissionTime); //如果为空,则返回 0 坐标 if (antenna == null) { return(new XYZ()); } // Get antenna eccentricity for frequency "G01" (L1), in // satellite reference system. // NOTE: It is NOT in ECEF, it is in UEN!!! RinexSatFrequency freq = new RinexSatFrequency(prn, 1); // NEU satAnt = antenna.GetAntennaEccentricity(AntennaFrequency.G01); NEU satAnt = antenna.GetPcoValue(freq); XYZ dant = new XYZ(); dant.X = satAnt.E * ex.X + satAnt.N * ey.X + satAnt.U * ez.X; dant.Y = satAnt.E * ex.Y + satAnt.N * ey.Y + satAnt.U * ez.Y; dant.Z = satAnt.E * ex.Z + satAnt.N * ey.Z + satAnt.U * ez.Z; // Unitary vector from satellite to Earth mass center (ECEF) XYZ satToEarthUnit = (-1.0) * eph.XYZ.UnitVector(); // Unitary vector from Earth mass center to Sun (ECEF) XYZ earthToSunUnit = rsun.UnitVector(); // rj = rk x ri: Rotation axis of solar panels (ECEF) XYZ rj = satToEarthUnit.Cross(earthToSunUnit); // Redefine ri: ri = rj x rk (ECEF) earthToSunUnit = rj.Cross(satToEarthUnit); // Let's funcKeyToDouble ri to an unitary vector. (ECEF) earthToSunUnit = earthToSunUnit.UnitVector(); XYZ dant1 = new XYZ(); dant1.X = satAnt.E * rj.X + satAnt.N * earthToSunUnit.X + satAnt.U * satToEarthUnit.X; dant1.Y = satAnt.E * rj.Y + satAnt.N * earthToSunUnit.Y + satAnt.U * satToEarthUnit.Y; dant1.Z = satAnt.E * rj.Z + satAnt.N * earthToSunUnit.Z + satAnt.U * satToEarthUnit.Z; return(dant1); }
/// <summary> /// 卫星天线相位中心改正,参照GPSTK模块 /// </summary> /// <param name="satelliteType"></param> /// <param name="satPos"></param> /// <param name="ReceiverPosition"></param> /// <param name="sunPosition"></param> /// <param name="svPCcorr"></param> /// <param name="antenna"></param> /// <returns></returns> private static double GetPhaseCorrection(SatelliteNumber prn, XYZ satPos, XYZ ReceiverPosition, XYZ sunPosition, double svPCcorr, IAntenna antenna) { // Unitary vector from satellite to Earth mass center (ECEF) XYZ satToEarthUnit = (-1.0) * satPos.UnitVector(); // Unitary vector from Earth mass center to Sun (ECEF) XYZ earthToSunUnit = sunPosition.UnitVector(); // rj = rk x ri: Rotation axis of solar panels (ECEF) XYZ rj = satToEarthUnit.Cross(earthToSunUnit); // Redefine ri: ri = rj x rk (ECEF) earthToSunUnit = rj.Cross(satToEarthUnit); // Let's funcKeyToDouble ri to an unitary vector. (ECEF) earthToSunUnit = earthToSunUnit.UnitVector(); // Get vector from Earth mass center to receiver XYZ receiverPos = ReceiverPosition; // Compute unitary vector vector from satellite to RECEIVER XYZ satToReceverUnit = (receiverPos - satPos).UnitVector(); // When not using Antex information, if satellite belongs to block // "IIR" its correction is 0.0, else it will depend on satellite model. // We will need the elevation, in degrees. It is found using // dot product and the corresponding unitary angles double cosa = satToReceverUnit.Dot(satToEarthUnit); cosa = cosa < -1.0 ? -1.0 : (cosa > 1.0 ? 1.0 : cosa); double nadir = Math.Acos(cosa) * CoordConsts.RadToDegMultiplier; if (!DoubleUtil.IsValid(nadir)) { return(0); } // The nadir angle should always smaller than 14.0 deg, // but some times it's a bit bigger than 14.0 deg, we // force it to 14.0 deg to stop throwing an exception. // The Reference is available at: // http://igscb.jpl.nasa.gov/igscb/resource/pubs/02_ott/session_8.pdf nadir = (nadir > 14) ? 14.0 : nadir; double elev = 90.0 - nadir; // Get antenna eccentricity for frequency "G01" (L1), in // satellite reference system. // NOTE: It is NOT in ECEF, it is in UEN!!! RinexSatFrequency freq = new RinexSatFrequency(prn, 1); // NEU satAnt = antenna.GetAntennaEccentricity(AntennaFrequency.G01); NEU satAnt = antenna.GetPcoValue(freq); if (satAnt.Equals(NEU.Zero)) { return(0); } //Now, get the phase center variation. NEU var = new NEU(0, 0, antenna.GetPcvValue(freq, elev)); // We must substract them satAnt = satAnt - var; // Change to ECEF // 原 satAnt t is in UEN!!!,本satAnt为NEU,分量相对应 // satAnt[0] = U // Triple svAntenna( satAnt[2]*ri + satAnt[1]*rj + satAnt[0]*rk ); // XYZ svAntenna = satAnt.N * earthToSunUnit + satAnt.E * rj + satAnt.U * satToEarthUnit; XYZ svAntenna = -(var.N * earthToSunUnit + var.E * rj + var.U * satToEarthUnit); // Projection of "svAntenna" vector to line of sight vector rrho svPCcorr = (satToReceverUnit.Dot(svAntenna)); return(svPCcorr); }
/// <summary> /// 海潮改正模型,采用RTKLIB的模块 /// 2015.04.12 /// </summary> /// <param name="gpsTime"></param> /// <param name="harmonics"></param> /// <returns></returns> public static NEU GetOceanTidesCorrectValue1(Time gpsTime, Geo.Algorithm.IMatrix harmonics) { double[][] args = { new double[] { 1.40519E-4, 2.0, -2.0, 0.0, 0.00 }, /* M2 */ new double[] { 1.45444E-4, 0.0, 0.0, 0.0, 0.00 }, /* S2 */ new double[] { 1.37880E-4, 2.0, -3.0, 1.0, 0.00 }, /* N2 */ new double[] { 1.45842E-4, 2.0, 0.0, 0.0, 0.00 }, /* K2 */ new double[] { 0.72921E-4, 1.0, 0.0, 0.0, 0.25 }, /* K1 */ new double[] { 0.67598E-4, 1.0, -2.0, 0.0, -0.25 }, /* O1 */ new double[] { 0.72523E-4, -1.0, 0.0, 0.0, -0.25 }, /* P1 */ new double[] { 0.64959E-4, 1.0, -3.0, 1.0, -0.25 }, /* Q1 */ new double[] { 0.53234E-5, 0.0, 2.0, 0.0, 0.00 }, /* Mf */ new double[] { 0.26392E-5, 0.0, 1.0, -1.0, 0.00 }, /* Mm */ new double[] { 0.03982E-5, 2.0, 0.0, 0.0, 0.00 } /* Ssa */ }; //11 * 5 Time ep1975 = new Time(1975, 1, 1); //angular argument // double fday = gpsTime.SecondsOfDay;// gpsTime.Hour * 3600 + gpsTime.Minute * 60 + gpsTime.Fraction; double fday = gpsTime.Hour * 3600 + gpsTime.Minute * 60 + gpsTime.Seconds; Time gpsTime0 = gpsTime.Date; double days = (double)(gpsTime0 - ep1975) / 86400.0; double t, t2, t3, ang; double[] a = new double[5]; double[] dp = new double[3]; t = (27392.500528 + 1.000000035 * days) / 36525.0; t2 = t * t; t3 = t2 * t; a[0] = fday; a[1] = (279.69668 + 36000.768930485 * t + 3.03E-4 * t2) * SunMoonPosition.DegToRad; /* H0 */ a[2] = (270.434358 + 481267.88314137 * t - 0.001133 * t2 + 1.9E-6 * t3) * SunMoonPosition.DegToRad; /* S0 */ a[3] = (334.329653 + 4069.0340329577 * t + 0.010325 * t2 - 1.2E-5 * t3) * SunMoonPosition.DegToRad; /* P0 */ a[4] = 2.0 * SunMoonPosition.PI; //displancements by 11 constituents for (int i = 0; i < 11; i++) { ang = 0.0; for (int j = 0; j < 5; j++) { ang += a[j] * args[i][j]; } for (int j = 0; j < 3; j++) { dp[j] += harmonics[j, i] * Math.Cos(ang - harmonics[j + 3, i] * SunMoonPosition.DegToRad); } } double e = -dp[1]; double n = -dp[2]; double u = dp[0]; NEU res = new NEU(n, e, u); return(res); }
private static NEU GetSolidTidesCorrectValue(GeoCoord geoPosition, XYZ reciverPosition, XYZ rsun, XYZ rmoon, double gmst) { double[] pos = new double[2]; pos[0] = Math.Asin(reciverPosition.Z / reciverPosition.Length); pos[1] = Math.Atan2(reciverPosition.Y, reciverPosition.X); double sinp = Math.Sin(pos[0]); double cosp = Math.Cos(pos[0]); double sinl = Math.Sin(pos[1]); double cosl = Math.Cos(pos[1]); double[] E = new double[9]; E[0] = -sinl; E[3] = cosl; E[6] = 0.0; E[1] = -sinp * cosl; E[4] = -sinp * sinl; E[7] = cosp; E[2] = cosp * cosl; E[5] = cosp * sinl; E[8] = sinp; double[] eu = new double[3]; /* step1: time domain */ eu[0] = E[2]; eu[1] = E[5]; eu[2] = E[8]; double[] dr1 = tide_pl(eu, rsun, SunMoonPosition.GMS, pos); double[] dr2 = tide_pl(eu, rmoon, SunMoonPosition.GMM, pos); /* step2: frequency domain, only K1 radial */ double sin2l = Math.Sin(2.0 * pos[0]); double du = -0.012 * sin2l * Math.Sin(gmst + pos[1]); double[] dr = new double[3]; dr[0] = dr1[0] + dr2[0] + du * E[2]; //x dr[1] = dr1[1] + dr2[1] + du * E[5]; //y dr[2] = dr1[2] + dr2[2] + du * E[8]; //z double lat = geoPosition.Lat; double lon = geoPosition.Lon; double refLat = 0, refLon = 0; if (lat > 90.0 || lat < -90.0) { //如果在此,说明有大错误! refLat = 0.0; } else { refLat = lat * SunMoonPosition.DegToRad; } refLon = lon * SunMoonPosition.DegToRad; double sinlat = Math.Sin(refLat); double coslat = Math.Cos(refLat); double sinlon = Math.Sin(refLon); double coslon = Math.Cos(refLon); double[][] rotate = { new double[] { -coslon * sinlat, -sinlon, coslat *coslon }, new double[] { -sinlon * sinlat, coslon, coslat *sinlon }, new double[] { coslat, 0.0, sinlat }, }; double detN = rotate[0][0] * dr[0] + rotate[1][0] * dr[1] + rotate[2][0] * dr[2]; double detE = rotate[0][1] * dr[0] + rotate[1][1] * dr[1] + rotate[2][1] * dr[2]; double detH = rotate[0][2] * dr[0] + rotate[1][2] * dr[1] + rotate[2][2] * dr[2]; double e11 = -sinlon; double e12 = coslon; double e13 = 0.0; double e21 = -sinlat * coslon; double e22 = -sinlat * sinlon; double e23 = coslat; double e31 = coslat * coslon; double e32 = coslat * sinlon; double e33 = sinlat; double e = e11 * dr[0] + e12 * dr[1] + e13 * dr[2]; double n = e21 * dr[0] + e22 * dr[1] + e23 * dr[2]; double u = e31 * dr[0] + e32 * dr[1] + e33 * dr[2]; NEU newCorrection = new NEU(n, e, u); return(newCorrection); }
/** Returns the effect of pole tides (meters) at the given * position and epoch, in the Up-East-North (UEN) reference frame. * * @param[in] t Epoch to look up * @param[in] info Position of interest * * @return a Triple with the pole tide effect, in meters and in * the UEN reference frame. * * @throw InvalidRequest If the request can not be completed for any * reason, this is thrown. The text may have additional * information about the reason the request failed. * * @warning In order to use this method, you must have previously * set the current pole displacement parameters. * */ /// <summary> /// 固体潮改正 /// Returns the effect of solid Earth tides (meters) at the given position and epoch, in the Up-East-North (UEN) reference frame. /// 此处采用NEU表示,其中的各个分量相对应。 /// </summary> /// <param name="gpsTime">Epoch to look up</param> /// <param name="position">Position of interest</param> /// <returns></returns> public static NEU GetSolidTidesCorrectValue(Time gpsTime, XYZ position, XYZ sunPos, XYZ moonPos) { NEU solidTides = new NEU(); ////Objects to compute Sun and Moon positions //SunPosition sunPosition = new SunPosition(); //MoonPosition moonPosition = new MoonPosition(); //// Variables to hold Sun and Moon positions //XYZ sunPos = (sunPosition.GetPosition(gpsTime)); //XYZ moonPos = (moonPosition.GetPosition(gpsTime)); // Compute the factors for the Sun double rpRs = (position.X * sunPos[0] + position.Y * sunPos[1] + position.Z * sunPos[2]); double Rs2 = sunPos[0] * sunPos[0] + sunPos[1] * sunPos[1] + sunPos[2] * sunPos[2]; double rp2 = (position.X * position.X + position.Y * position.Y + position.Z * position.Z); double xy2p = (position.X * position.X + position.Y * position.Y); double sqxy2p = (Math.Sqrt(xy2p)); double sqRs2 = (Math.Sqrt(Rs2)); double fac_s = (3.0 * SunMoonPosition.MU_SUN * rp2 / (sqRs2 * sqRs2 * sqRs2 * sqRs2 * sqRs2)); double g1sun = (fac_s * (rpRs * rpRs / 2.0 - rp2 * Rs2 / 6.0)); double g2sun = (fac_s * rpRs * (sunPos[1] * position.X - sunPos[0] * position.Y) * Math.Sqrt(rp2) / sqxy2p); double g3sun = (fac_s * rpRs * (sqxy2p * sunPos[2] - position.Z / sqxy2p * (position.X * sunPos[0] + position.Y * sunPos[1]))); // Compute the factors for the Moon double rpRm = (position.X * moonPos[0] + position.Y * moonPos[1] + position.Z * moonPos[2]); double Rm2 = (moonPos[0] * moonPos[0] + moonPos[1] * moonPos[1] + moonPos[2] * moonPos[2]); double sqRm2 = (Math.Sqrt(Rm2)); double fac_m = (3.0 * SunMoonPosition.MU_MOON * rp2 / (sqRm2 * sqRm2 * sqRm2 * sqRm2 * sqRm2)); double g1moon = (fac_m * (rpRm * rpRm / 2.0 - rp2 * Rm2 / 6.0)); double g2moon = (fac_m * rpRm * (moonPos[1] * position.X - moonPos[0] * position.Y) * Math.Sqrt(rp2) / sqxy2p); double g3moon = (fac_m * rpRm * (sqxy2p * moonPos[2] - position.Z / sqxy2p * (position.X * moonPos[0] + position.Y * moonPos[1]))); // Effects due to the Sun double delta_sun1 = (H_LOVE * g1sun); double delta_sun2 = (L_LOVE * g2sun); double delta_sun3 = (L_LOVE * g3sun); // Effects due to the Moon double delta_moon1 = (H_LOVE * g1moon); double delta_moon2 = (L_LOVE * g2moon); double delta_moon3 = (L_LOVE * g3moon); // Combined effect //Up-East-North double up = delta_sun1 + delta_moon1; double east = delta_sun2 + delta_moon2; double north = delta_sun3 + delta_moon3; solidTides = new NEU(north, east, up); return(solidTides); }
/// <summary> /// 卫星天线相位中心改正,参照RTKLIB /// </summary> /// <param name="prn"></param> /// <param name="freq"></param> /// <param name="satPos"></param> /// <param name="ReceiverPosition"></param> /// <param name="sunPosition"></param> /// <param name="svPCcorr"></param> /// <param name="antenna"></param> /// <returns></returns> private static double GetPhaseCorrection1(SatelliteNumber prn, RinexSatFrequency freq, XYZ satPos, XYZ ReceiverPosition, GeoCoord StationLonLatHeight, XYZ sunPosition, double svPCcorr, IAntenna antenna) { XYZ ru = ReceiverPosition - satPos; XYZ rz = -satPos; double[] eu = new double[3]; eu[0] = ru.X / ru.Length; eu[1] = ru.Y / ru.Length; eu[2] = ru.Z / ru.Length; double[] ez = new double[3]; ez[0] = rz.X / rz.Length; ez[1] = rz.Y / rz.Length; ez[2] = rz.Z / rz.Length; double cosa = eu[0] * ez[0] + eu[1] * ez[1] + eu[2] * ez[2]; cosa = cosa < -1.0 ? -1.0 : (cosa > 1.0 ? 1.0 : cosa); double nadir = Math.Acos(cosa) * CoordConsts.RadToDegMultiplier; //// The nadir angle should always smaller than 14.0 deg, // // but some times it's a bit bigger than 14.0 deg, we // // force it to 14.0 deg to stop throwing an exception. // // The Reference is available at: // // http://igscb.jpl.nasa.gov/igscb/resource/pubs/02_ott/session_8.pdf nadir = (nadir > 14) ? 14.0 : nadir; double elev = 90.0 - nadir; // Get antenna eccentricity for frequency "G01" (L1), in // satellite reference system. // NOTE: It is NOT in ECEF, it is in UEN!!! //lly注释 //SatelliteFrequency freq = new SatelliteFrequency(prn, 1); // NEU satAnt = antenna.GetAntennaEccentricity(AntennaFrequency.G01); //NEU satAnt = antenna.TryGetAntennaEccentricity(freq); //if (satAnt.Equals(NEU.Zero)) // return 0; //Now, get the phase center variation. double u = antenna.GetPcvValue(freq, elev); NEU var = new NEU(0, 0, u); //只有U方向有值 // Projection of "svAntenna" vector to line of sight vector rrho svPCcorr = var.U; //Compute vector station-satellite, in ECEF //XYZ ray = satPos - ReceiverPosition; //Rotate vector ray to UEN reference frame //此处修改为 NEU 坐标系。 //NEU rayNeu = CoordTransformer.XyzToNeu(ray, StationLonLatHeight, AngleUnit.Degree); //XYZ ray0 = XYZ.RotateZ(ray, StationLonLatHeight.Lon); //XYZ ray1 = XYZ.RotateY(ray0, -StationLonLatHeight.Lat); //ray = XYZ.RotateZ(ray, lon); //ray = XYZ.RotateY(ray, -lat); //Convert ray to an unitary vector // XYZ xyzNeu = new XYZ(rayNeu.N, rayNeu.E, rayNeu.U); //NEU unit = rayNeu.UnitNeuVector(); //if (var == null) return 0; ////计算沿着射线方向的改正数。Compute corrections = displacement vectors components along ray direction. //double correctForL = var.Dot(unit); //if(svPCcorr != correctForL) //{ // correctForL = svPCcorr; //} return(var.U); }