/// <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(EpochSatellite input) { var correction = new Dictionary <RinexSatFrequency, double>(); this.Correction = correction; 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文件中"); } return; } List <RinexSatFrequency> frequences = input.RinexSatFrequences; XYZ rcvPos = input.SiteInfo.EstimatedXyz; if (rcvPos.Equals(XYZ.Zero))//测站未获取近似值,不改正 { log.Warn(input.ReceiverTime + ", " + input.Name + ", 测站未获取近似值,不改正PCV"); this.Correction = correction; return; } var elev = input.GeoElevation; var azim = input.Polar.Azimuth; foreach (var item in antenna.Data) { var satFreq = item.Key; double pcv = 0; if (IsUseAzimuthAntenna) { pcv = antenna.GetPcvValue(satFreq, elev, azim); } else { pcv = antenna.GetPcvValue(satFreq, elev); ///**PCV 是站星距离,不是ENU, 不用再次改正 */ //不信,可以试试:转换成站星方向改正等效距离算法如下: //double rangeCorretion = CoordUtil.GetDirectionLength(pcv, input.Polar); ////approx, 用以验证 //double test = pcv.U * Math.Sin(input.GeoElevation * Geo.CoordConsts.DegToRadMultiplier); //double differ = rangeCorretion - test; } correction.Add(satFreq, pcv); } //多频的权宜之计 if (input.EpochInfo.SatelliteTypes.Count > 0) { correction[RinexSatFrequency.BdsA] = antenna.GetPcvValue(RinexSatFrequency.GpsA, elev); correction[RinexSatFrequency.BdsB] = antenna.GetPcvValue(RinexSatFrequency.GpsB, elev); correction[RinexSatFrequency.GalileoA] = correction[RinexSatFrequency.BdsA]; correction[RinexSatFrequency.GalileoB] = correction[RinexSatFrequency.BdsB]; } this.Correction = correction; }
/// <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 /// </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); }