/// <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); }
/// <summary> /// 计算改正数 /// </summary> /// <param name="input"></param> public override void Correct(EpochInformation input) { if (input.EnabledSatCount == 0) { return; } var correction = new Dictionary <RinexSatFrequency, NEU>(); IAntenna antenna = input.SiteInfo.Antenna; if (antenna == null) { if (!WarnedSites.Contains(input.SiteInfo.SiteName)) { WarnedSites.Add(input.SiteInfo.SiteName); log.Warn(input.Name + "接收机天线为: " + input.SiteInfo.AntennaType + ", " + input.SiteInfo.AntennaNumber + " 没有在天线文件夹中找到该类型的天线,无法进行 PCV 改正,精度影响可达10厘米(特别是高程)!请到 https://www.ngs.noaa.gov/ANTCAL/ 下载对应天线改正信息,并追加到.atx文件中"); } this.Correction = correction; return; } foreach (var item in antenna.Data) { var satFreq = item.Key; var pco = antenna.GetPcoValue(satFreq); //这个值不变,实际上一次赋值就可以了!!//2018.08.02, czs,in hmx correction.Add(satFreq, pco); } //多频的权宜之计 if (input.SatelliteTypes.Count > 0) { correction[RinexSatFrequency.BdsA] = correction[RinexSatFrequency.GpsA]; correction[RinexSatFrequency.BdsB] = correction[RinexSatFrequency.GpsB]; correction[RinexSatFrequency.GalileoA] = correction[RinexSatFrequency.GpsA]; correction[RinexSatFrequency.GalileoB] = correction[RinexSatFrequency.GpsB]; } this.Correction = correction; }
/// <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); }