/// <summary> /// 通过两个时刻的位置,求轨道参数。 /// </summary> /// <param name="posA"></param> /// <param name="posB"></param> /// <returns></returns> public static KeplerEphemerisParam GetKeplerEphemerisParamFromTwoPos(XYZ posA, XYZ posB, double deltaTime) { throw new NotImplementedException("通过两个时刻的位置,求轨道参数,算法未实现!2016.06.06.16"); //2.6.1.1 计算轨道倾角i和升交点赤经Ω XYZ hXyz = posA.Cross(posB); double hLen = hXyz.Length; double r1 = posA.Length; double r2 = posB.Length; double vv = posB.Dot(posB); //计算轨道倾角 double ABLen = Math.Sqrt(hXyz.X * hXyz.X + hXyz.Y * hXyz.Y); double i = Math.Atan2(ABLen, hXyz.Z); // double i = Math.Acos(hXyz.Z / hLen); //表示在Z轴上的投影,与上结果计算一致 //double includedAngle = hXyz.GetIncludedAngle(new XYZ(0, 0, 1));//轨道倾角为两个平面法向量的夹角 //计算升交点赤经 double Ω = Math.Atan2(hXyz.X, -hXyz.Y); //用面积比法求半通径 double sinf2minusf1 = hXyz.Z / (r1 * r2 * Math.Cos(i)); return(null); //KeplerEphemerisParam param = new KeplerEphemerisParam //{ // ArgumentOfPerigee = ww, // Eccentricity = e, // Inclination = i, // LongOfAscension = Ω, // MeanAnomaly = M, // SqrtA = sqrtA //}; //return param; }
public OrbitParam CaculateOrbitParam(XYZ pos, XYZ dot, double time) { double u = 3.986005e14; //double sigma = 1e-6; XYZ cross = pos.Cross(dot); double A = cross.X; double B = cross.Y; double C = cross.Z; double sqrtAB = Math.Sqrt(A * A + B * B); // //角动量公式,可推出轨道倾角i double i = Math.Atan2(sqrtAB, C); //轨道倾角 double bigOmiga = Math.Atan2(-A, B); //升点赤经 的值 double r0 = pos.Length; double v0_2 = dot.Length * dot.Length; //由能量方程,可推出半长轴a的值 double a = 1.0 / (2 / r0 - v0_2 / u); //轨道长半径 double n = Math.Sqrt(u / a / a / a); //周期 double sqrta = Math.Sqrt(a); double sqrtu = Math.Sqrt(u); double eSinE = pos.Dot(dot) / sqrta / sqrtu; double eCosE = 1 - r0 / a; double e = Math.Sqrt(Math.Pow(eSinE, 2.0) + Math.Pow(eCosE, 2.0));//偏心率 double E = Math.Atan2(eSinE, eCosE); double t = time; //平近点角M与偏近点角E //迭代 double M = E - eSinE;//平近点角 double tao = t - M / n; //求出 E 么,偏近点角。 double tan2f = Math.Sqrt((1 + e) / (1 - e)) * Math.Tan(E / 2.0); double f = Math.Atan(tan2f) * 2; double smallOmiga = Math.Atan2(pos.Z / Math.Sin(i), pos.X * Math.Cos(bigOmiga) + pos.Y * Math.Sin(bigOmiga)) - f; return(new OrbitParam() { Eccentricity = e, LongOfAscension = bigOmiga, SemiMajor = a, EpochOfPerigee = tao, Inclination = i, MeanAnomaly = M, ArgumentOfPerigee = smallOmiga }); }
public void Cross() { var p1 = new XYZ(1, 2, 3); Assert.AreEqual(new XYZ(-4, 8, -4), p1.Crossed(new XYZ(3, 2, 1))); p1.Cross(new XYZ(3, 2, 1)); Assert.AreEqual(new XYZ(-4, 8, -4), p1); }
/// <summary> /// 默认的卫星天线相位改正。 /// </summary> /// <param name="satelliteType"></param> /// <param name="time"></param> /// <param name="satPos"></param> /// <param name="sunPosition"></param> /// <returns></returns> public static double DefautSatPhaseCorrector(SatelliteNumber prn, Time time, XYZ satPos, XYZ ReceiverPosition, XYZ sunPosition, SatInfoFile satData) { // 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. // This variable that will hold the correction, 0.0 by default double svPCcorr = 0.0; // If no Antex information is given, or if phase center information // uses a relative model, then use a simpler, older approach // Please note that in this case all GLONASS satellite are // considered as having phase center at (0.0, 0.0, 0.0). The former // is not true for 'GLONASS-M' satellites (-0.545, 0.0, 0.0 ), but // currently there is no simple way to take this into account. // For satellites II and IIA: if ((satData.GetBlock(prn, time) == "II") || (satData.GetBlock(prn, time) == "IIA")) { //First, build satellite antenna vector for models II/IIA XYZ svAntenna = 0.279 * earthToSunUnit + 1.023 * satToEarthUnit; // Projection of "svAntenna" vector to line of sight vector rrho svPCcorr = (satToReceverUnit.Dot(svAntenna)); } else { // For satellites belonging to block "I" if ((satData.GetBlock(prn, time) == "I")) { // First, build satellite antenna vector for model I XYZ svAntenna = (0.210 * earthToSunUnit + 0.854 * satToEarthUnit); // Projection of "svAntenna" to line of sight vector (rrho) svPCcorr = (satToReceverUnit.Dot(svAntenna)); } } return(svPCcorr); }
/// <summary> /// 计算开普勒根数 /// </summary> /// <param name="pos"></param> /// <param name="velocity"></param> /// <returns></returns> public static KeplerEphemerisParam GetKeplerEphemerisParam(XYZ pos, XYZ velocity) { //2.6.1.1 计算轨道倾角i和升交点赤经Ω XYZ hXyz = pos.Cross(velocity); double hLen = hXyz.Length; double r = pos.Length; double vv = velocity.Dot(velocity); //计算轨道倾角 //double ABLen = Math.Sqrt(hXyz.X * hXyz.X + hXyz.Y * hXyz.Y); //double i = Math.Atan2(ABLen, hXyz.Z); double i = Math.Acos(hXyz.Z / hLen); //表示在Z轴上的投影,与上结果计算一致 //double includedAngle = hXyz.GetIncludedAngle(new XYZ(0, 0, 1));//轨道倾角为两个平面法向量的夹角 //计算升交点赤经 double Ω = Math.Atan2(hXyz.X, -hXyz.Y); //2.6.1.2 计算轨道长半轴a, double a = 1 / (2 / r - vv / GM); //由活力公式计算 double sqrtA = Math.Sqrt(a); double n = Math.Sqrt(GM) / (sqrtA * sqrtA * sqrtA); //平运动角速度n //离心率e和平近点交M double rdotv = pos.Dot(velocity); double eCosE = 1 - r / a; double eSinE = rdotv / Math.Sqrt(GM * a); double e = Math.Sqrt(eSinE * eSinE + eCosE * eCosE); //离心率e double E = Math.Atan2(eSinE, eCosE); //偏近点角E double M = E - eSinE; //平近点角 //2.6.1.3 计算近升角距ω XYZ eXyz = velocity.Cross(hXyz) / GM - pos.UnitVector(); double ww = Math.Atan2(eXyz.Z, (eXyz.Y * Math.Sin(Ω) + eXyz.X * Math.Cos(Ω)) * Math.Sin(i)); double u = Math.Atan2(pos.Z, (pos.Y * Math.Sin(Ω) + pos.X * Math.Cos(Ω)) * Math.Sin(i)); double ff = u - ww;//真近点角 KeplerEphemerisParam param = new KeplerEphemerisParam { ArgumentOfPerigee = ww, Eccentricity = e, Inclination = i, LongOfAscension = Ω, MeanAnomaly = M, SqrtA = sqrtA }; return(param); }
/// <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); }
public void ValueType_XYZ() { var p1 = new XYZ(1, 2, 3); var p2 = new XYZ(4, 5, 6); Assert.AreEqual(14, p1.SquareModulus()); Assert.AreEqual(Math.Sqrt(14), p1.Modulus()); Assert.IsTrue(p1.IsEqual(p2, 3)); Assert.IsFalse(p1.IsEqual(p2, 2.99)); p2 = p1; p2.Add(new XYZ(1, 2, 3)); Assert.AreEqual(new XYZ(2, 4, 6), p2); Assert.AreEqual(new XYZ(2, 4, 6), p1.Added(new XYZ(1, 2, 3))); p2 += new XYZ(1, 2, 3); Assert.AreEqual(new XYZ(3, 6, 9), p2); p2 = new XYZ(1, 2, 3); p2.Cross(new XYZ(3, 2, 1)); Assert.AreEqual(new XYZ(-4, 8, -4), p2); Assert.AreEqual(new XYZ(-4, 8, -4), p1.Crossed(new XYZ(3, 2, 1))); Assert.AreEqual(Math.Sqrt(96), p1.CrossMagnitude(new XYZ(3, 2, 1))); Assert.AreEqual(96, p1.CrossSquareMagnitude(new XYZ(3, 2, 1))); p2 = new XYZ(1, 2, 3); p2.CrossCross(new XYZ(1, 2, 3), new XYZ(4, 5, 6)); Assert.AreEqual(new XYZ(-24, -6, 12), p2); Assert.AreEqual(new XYZ(-24, -6, 12), p1.CrossCrossed(new XYZ(1, 2, 3), new XYZ(4, 5, 6))); p2 = new XYZ(1, 2, 3); p2.Divide(2); Assert.AreEqual(new XYZ(0.5, 1, 1.5), p2); Assert.AreEqual(new XYZ(0.5, 1, 1.5), p1.Divided(2)); Assert.AreEqual(14, p1.Dot(new XYZ(1, 2, 3))); Assert.AreEqual(0, p1.DotCross(new XYZ(4, 5, 6), new XYZ(4, 5, 6))); p2 = new XYZ(1, 2, 3); p2.Multiply(2); Assert.AreEqual(new XYZ(2, 4, 6), p2); Assert.AreEqual(new XYZ(2, 4, 6), p1.Multiplied(2)); Assert.AreEqual(new XYZ(2, 4, 6), p1 * 2); p2 = new XYZ(1, 2, 3); p2.Multiply(new XYZ(1, 2, 3)); Assert.AreEqual(new XYZ(1, 4, 9), p2); Assert.AreEqual(new XYZ(1, 4, 9), p1.Multiplied(new XYZ(1, 2, 3))); Assert.AreEqual(new XYZ(1, 4, 9), p1 * new XYZ(1, 2, 3)); Mat m1 = new Mat(); m1.SetRotation(Dir.DZ.Coord, Math.PI / 2); p2 = new XYZ(4, 5, 6); Assert.AreEqual("-5,4,6", p2.Multiplied(m1).ToString()); Assert.AreEqual("-5,4,6", (p2 * m1).ToString()); p2.Multiply(m1); Assert.AreEqual("-5,4,6", p2.ToString()); p2 = new XYZ(1, 2, 3); p2.Normalize(); Assert.IsTrue(p2.IsEqual(new XYZ(0.26726, 0.53452, 0.80178), 0.00001)); Assert.IsTrue(p1.Normalized().IsEqual(new XYZ(0.26726, 0.53452, 0.80178), 0.00001)); p2 = new XYZ(1, 2, 3); p2.Reverse(); Assert.AreEqual(new XYZ(-1, -2, -3), p2); Assert.AreEqual(new XYZ(-1, -2, -3), p1.Reversed()); p2 = new XYZ(1, 2, 3); p2.Subtract(new XYZ(3, 2, 1)); Assert.AreEqual(new XYZ(-2, 0, 2), p2); Assert.AreEqual(new XYZ(-2, 0, 2), p1.Subtracted(new XYZ(3, 2, 1))); Assert.AreEqual(new XYZ(-2, 0, 2), p1 - new XYZ(3, 2, 1)); p2.SetLinearForm(new XYZ(1, 2, 3), new XYZ(4, 5, 6)); Assert.AreEqual(new XYZ(5, 7, 9), p2); p2.SetLinearForm(2, new XYZ(1, 2, 3), new XYZ(4, 5, 6)); Assert.AreEqual(new XYZ(6, 9, 12), p2); p2.SetLinearForm(2, new XYZ(1, 2, 3), 3, new XYZ(4, 5, 6)); Assert.AreEqual(new XYZ(14, 19, 24), p2); p2.SetLinearForm(2, new XYZ(1, 2, 3), 3, new XYZ(4, 5, 6), new XYZ(7, 8, 9)); Assert.AreEqual(new XYZ(21, 27, 33), p2); p2.SetLinearForm(2, new XYZ(1, 2, 3), 3, new XYZ(4, 5, 6), 4, new XYZ(7, 8, 9)); Assert.AreEqual(new XYZ(42, 51, 60), p2); p2.SetLinearForm(2, new XYZ(1, 2, 3), 3, new XYZ(4, 5, 6), 4, new XYZ(7, 8, 9), new XYZ(10, 11, 12)); Assert.AreEqual(new XYZ(52, 62, 72), p2); //TestContext.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", gp2.x, gp2.y, gp2.z)); }
/// <summary> /// 实时星历改正。 /// </summary> /// <param name="obs"></param> /// <param name="maxCorrectionSecond">允许的最大改正秒数,是否该每颗卫星单独考虑</param> protected void RTSp3InfoCorrected(RinexEpochObservation obs, double maxCorrectionSecond = 60)//Time time, SatelliteType satType) { Time time = obs.ReceiverTime; if (SSRSp3Section.Count == 0) { return; } if (time - SSRSp3Section.GetMaxTime() > maxCorrectionSecond) { return; } Sp3Section Sp3Section = new Sp3Section(); var keys = SSRSp3Section.Keys; foreach (var key in keys) { var obj = SSRSp3Section[key]; foreach (var item in obj) { if (!NavFile.Prns.Contains(item.Prn)) { continue; } var ss = new SingleParamNavFileEphService(NavFile); var unkown = NavFile.GetEphemerisParams(item.Prn).Find(b => Math.Abs(b.Time.TickTime.TotalSeconds - time.TickTime.TotalSeconds) < 3 * 3600); if (unkown == null) { continue; } if (ss == null) { continue; } Ephemeris ss1 = ss.Get(item.Prn, time); XYZ eA = ss1.XyzDot / ss1.XyzDot.Length; XYZ eC = ss1.XYZ.Cross(ss1.XyzDot) / (ss1.XYZ.Cross(ss1.XyzDot)).Length; XYZ eR = eA.Cross(eC) / (eA.Cross(eC)).Length; XYZ deltaO = item.XYZ + item.XyzDot * (time.TickTime.TotalSeconds - item.Time.TickTime.TotalSeconds); double x = eR.X * deltaO.X + eA.X * deltaO.Y + eC.X * deltaO.Z; double y = eR.Y * deltaO.X + eA.Y * deltaO.Y + eC.Y * deltaO.Z; double z = eR.Z * deltaO.X + eA.Z * deltaO.Y + eC.Z * deltaO.Z; if (x * x + y * y + z * z > 100) { } Ephemeris Sp3Record = new Ephemeris(); Sp3Record.Prn = item.Prn; Sp3Record.XYZ = ss1.XYZ - new XYZ(x, y, z); Sp3Record.Time = time; if (item.Prn.SatelliteType == SatelliteType.R) { Sp3Record.ClockBias = ss1.ClockBias + item.ClockBias; } else { double relativetime = 2 * ss1.XYZ.Dot(ss1.XyzDot) / (GnssConst.LIGHT_SPEED * GnssConst.LIGHT_SPEED); Sp3Record.ClockBias = ss1.ClockBias - ss1.RelativeCorrection - item.ClockBias; //relativetime + key.ClockBias; } Sp3Section.Add(Sp3Record.Prn, Sp3Record); } } if (Sp3Section.Count != 0) { Sp3Section.Time = time; Sp3File.Add(Sp3Section); } else { int a = 0; } if (Sp3File.Count > 11) { // Sp3File.Header = new Sp3Header(); Sp3File.Header.EpochInterval = 1; //Sp3File.TimePeriod = new BufferedTimePeriod(Sp3File.First.Time, Sp3File.Last.Time, 60); if (EphemerisService == null) { EphemerisService = new SingleSp3FileEphService(this.Sp3File.GetSatEphemerisCollection(), 10); } else { ((SingleSp3FileEphService)EphemerisService).SetSp3File(Sp3File.GetSatEphemerisCollection()); } } if (Sp3File.Count > 20) { Sp3File.RemoveFirst(); } }
/// <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> /// 计算天线缠绕改正,单位:弧度。 /// </summary> /// <param name="prn">卫星编号</param> /// <param name="time">时间</param> /// <param name="satPos">卫星位置</param> /// <param name="receiverPos">接收机位置</param> /// <param name="sunPos">太阳位置</param> /// <returns></returns> private double GetSatPhaseWindUpCorectValue(SatelliteNumber prn, Time time, XYZ satPos, XYZ receiverPos, XYZ sunPos, string AntennaType) { //Vector from SV to Sun center of mass XYZ gps_sun = sunPos - satPos; //Unitary vector from satellite to Earth mass center XYZ rk = (-1.0) * satPos.UnitVector(); //rj=rk * gps_sun, then make sure it is unitary XYZ rj = (rk.Cross(gps_sun)).UnitVector(); //Define ri: ri= rj * rk, then make sure it is unitary //Now, ri, rj, rk form a base in the satellite body reference frame, expressed in the ECEF reference frame XYZ ri = (rj.Cross(rk)).UnitVector(); // Get satellite rotation angle // Get vector from Earth mass center to receiver XYZ rxPos = new XYZ(receiverPos.X, receiverPos.Y, receiverPos.Z); // Compute unitary vector vector from satellite to RECEIVER XYZ rrho = (rxPos - satPos).UnitVector(); // Projection of "rk" vector to line of sight vector (rrho) double zk = rrho.Dot(rk); // Get a vector without components on rk (time.e., belonging // to ri, rj plane) XYZ dpp = (rrho - zk * rk); // Compute dpp components in ri, rj plane double xk = (dpp.Dot(ri)); double yk = (dpp.Dot(rj)); //Compute satellite rotation angle, in radians double alpha1 = Math.Atan2(yk, xk); // Get receiver rotation angle // Redefine rk: Unitary vector from Receiver to Earth mass center rk = (-1.0) * (rxPos.UnitVector()); // Let's define a NORTH unitary vector in the Up, East, North // (UEN) topocentric reference frame XYZ delta = new XYZ(0.0, 0.0, 1.0); // Rotate delta to XYZ reference frame GeoCoord nomNEU = Geo.Coordinates.CoordTransformer.XyzToGeoCoord(receiverPos); delta = XYZ.RotateY(delta, nomNEU.Lat); delta = XYZ.RotateZ(delta, -nomNEU.Lon); // Computation of reference trame unitary vectors for receiver // rj = rk x delta, and make it unitary rj = (rk.Cross(delta)).UnitVector(); // ri = rj x rk, and make it unitary ri = (rj.Cross(rk)).UnitVector(); // Projection of "rk" vector to line of sight vector (rrho) zk = rrho.Dot(rk); // Get a vector without components on rk (time.e., belonging // to ri, rj plane) dpp = rrho - zk * rk; // Compute dpp components in ri, rj plane xk = dpp.Dot(ri); yk = dpp.Dot(rj); // Compute receiver rotation angle, in radians double alpha2 = Math.Atan2(yk, xk); double wind_up = 0.0; // Find out if satellite belongs to block "IIR", because // satellites of block IIR have a 180 phase shift if (SatInfoService.GetBlock(prn, time) == "IIR") { wind_up = Math.PI;// 3.1415926535898;//PI } //if (AntennaType.Contains("IIR") && SatInfoService.GetBlock(prn, time) != "IIR") //{ // wind_up += 0; //} alpha1 = alpha1 + wind_up; SatVectorPhase satVecPhase = PhaseManager[prn]; double da1 = alpha1 - satVecPhase.PhaseOfSatellite; double da2 = (alpha2 - satVecPhase.PhaseOfReceiver); //double da1 = alpha1 - phase_satellite[satid].PreviousPhase; //double da2 = (alpha2 - phase_station[satid].PreviousPhase); // Let's avoid problems when passing from 359 to 0 degrees. double tmp1 = satVecPhase.PhaseOfSatellite; tmp1 += Math.Atan2(Math.Sin(da1), Math.Cos(da1)); satVecPhase.PhaseOfSatellite = tmp1; double tmp2 = satVecPhase.PhaseOfReceiver; tmp2 += Math.Atan2(Math.Sin(da2), Math.Cos(da2)); satVecPhase.PhaseOfReceiver = tmp2; // Compute wind up effect in radians wind_up = satVecPhase.PhaseOfSatellite - satVecPhase.PhaseOfReceiver; // Let's avoid problems when passing from 359 to 0 degrees. //PhaseData tmp1 = phase_satellite[satid]; //tmp1.PreviousPhase += Math.Atan2(Math.Sin(da1), Math.Cos(da1)); //phase_satellite[satid] = tmp1; //PhaseData tmp2 = phase_station[satid]; //tmp2.PreviousPhase += Math.Atan2(Math.Sin(da2), Math.Cos(da2)); //phase_station[satid] = tmp2; //// Compute wind up effect in radians //wind_up = phase_satellite[satid].PreviousPhase - // phase_station[satid].PreviousPhase; return(wind_up); }
/// <summary> /// 天线缠绕改正 方法2 参考RTKLIB /// 李林阳添加 2015.01.01 /// </summary> /// <param name="prn"></param> /// <param name="time"></param> /// <param name="satPos"></param> /// <param name="receiverPos"></param> /// <param name="epochSatellite"></param> /// <param name="sunPos"></param> /// <returns></returns> private double GetSatPhaseWindUpCorectValue(SatelliteNumber prn, Time time, XYZ satPos, XYZ receiverPos, EpochSatellite epochSatellite, XYZ sunPos) { #region XYZ rxPos = new XYZ(receiverPos.X, receiverPos.Y, receiverPos.Z); //李林阳加天线相位缠绕 /* unit vector satellite to receiver */ XYZ ek = (rxPos - satPos).UnitVector();; //接收机位置-卫星位置,单位化 // for (time=0;time<3;time++) r[time]=rr[time]-rs[time]; //if (!normv3(r, ek)) return; //单位化 /* unit vectors of satellite antenna */ //for (time = 0; time < 3; time++) r[time] = -rs[time]; //if (!normv3(r, ezs)) return; XYZ ezs = (-1.0 * satPos).UnitVector();//卫星位置的单位向量 //for (time = 0; time < 3; time++) r[time] = rsun[time] - rs[time]; //if (!normv3(r, ess)) return; XYZ ess = (sunPos - satPos).UnitVector(); //cross3(ezs, ess, r); //if (!normv3(r, eys)) return; XYZ eys = ezs.Cross(ess); eys = eys.UnitVector(); //cross3(eys, ezs, exs); XYZ exs = eys.Cross(ezs); /* unit vectors of receiver antenna */ GeoCoord geoCoord = epochSatellite.SiteInfo.EstimatedGeoCoord; //ecef2pos(rr, pos); //xyz2enu(pos, E); //exr[0] = E[1]; exr[1] = E[4]; exr[2] = E[7]; /* x = north */ //eyr[0] = -E[0]; eyr[1] = -E[3]; eyr[2] = -E[6]; /* y = west */ double Lat = geoCoord.Lat * CoordConsts.DegToRadMultiplier; double Lon = geoCoord.Lon * CoordConsts.DegToRadMultiplier; //geoCoord.Lat = geoCoord.Lat / CoordConsts.RadToDegMultiplier; //geoCoord.Lon = geoCoord.Lon / CoordConsts.RadToDegMultiplier; double[] exr = new double[3]; double[] eyr = new double[3]; double cosB = Math.Cos(Lat); double sinB = Math.Sin(Lat); double cosL = Math.Cos(Lon); double sinL = Math.Sin(Lon); exr[0] = -sinB * cosL; exr[1] = -sinB * sinL; exr[2] = cosB; /* x = north */ eyr[0] = sinL; eyr[1] = -cosL; eyr[2] = 0; /* y = west */ XYZ exr_ = new XYZ(); exr_.X = exr[0]; exr_.Y = exr[1]; exr_.Z = exr[2]; XYZ eyr_ = new XYZ(); eyr_.X = eyr[0]; eyr_.Y = eyr[1]; eyr_.Z = eyr[2]; /* phase windup effect */ //cross3(ek, eys, eks); //cross3(ek, eyr, ekr); XYZ eks = ek.Cross(eys); XYZ ekr = ek.Cross(eyr_); double[] ds = new double[3]; double[] dr = new double[3]; for (int i = 0; i < 3; i++) { //ds[time] = exs[time] - ek[time] * dot(ek, exs, 3) - eks[time]; //dr[time] = exr[time] - ek[time] * dot(ek, exr, 3) + ekr[time]; ds[i] = exs[i] - ek[i] * ek.Dot(exs) - eks[i]; dr[i] = exr[i] - ek[i] * ek.Dot(exr_) + ekr[i]; } XYZ ds_ = new XYZ(ds); XYZ dr_ = new XYZ(dr); //cosp = dot(ds, dr, 3) / norm(ds, 3) / norm(dr, 3); double cosp = ds_.Dot(dr_) / ds_.Length / dr_.Length; if (cosp < -1.0) { cosp = -1.0; } else if (cosp > 1.0) { cosp = 1.0; } //ph = acos(cosp) / 2.0 / PI; double ph = Math.Acos(cosp) / 2.0 / Math.PI; //cross3(ds, dr, drs); XYZ drs = ds_.Cross(dr_); //if (dot(ek, drs, 3) < 0.0) ph = -ph; if (ek.Dot(drs) < 0.0) { ph = -ph; } //*phw = ph + floor(*phw - ph + 0.5); /* in cycle */ //double wind_up = ph + Math.Floor(wind_up - ph + 0.5); PhaseManager[prn].CorrectionValue = ph + Math.Floor(PhaseManager[prn].CorrectionValue - ph + 0.5); double wind_up = PhaseManager[prn].CorrectionValue * 2 * Math.PI; //要处理异常IIR卫星,参见GPSTK,2015.02.08 //if (SatInfoService.GetBlock(satelliteType, time) == "IIR") //{ // if (wind_up > 0) // { // wind_up -= Math.PI; // } // else // { // wind_up += Math.PI; // } //} //已验证这种方法的精度,但对于IIR型卫星,如果处理,还未实现,因此该模型暂时不能用。 #endregion return(wind_up); }
public bool TryDecompose(out XYZ translation, out XYZ scaling, out Quaternion rotation) { Matrix4 matrix = this._matrix; translation = new XYZ(); scaling = new XYZ(); rotation = new Quaternion(); var XYZDouble = new XYZ(); if (matrix.m33 == 0.0) { return(false); } Matrix4 matrix4_3 = matrix; matrix4_3.m03 = 0.0; matrix4_3.m13 = 0.0; matrix4_3.m23 = 0.0; matrix4_3.m33 = 1.0; if (matrix4_3.GetDeterminant() == 0.0) { return(false); } if (matrix.m03 != 0.0 || matrix.m13 != 0.0 || matrix.m23 != 0.0) { if (!Matrix4.Inverse(matrix, out Matrix4 inverse)) { return(false); } matrix.m03 = matrix.m13 = matrix.m23 = 0.0; matrix.m33 = 1.0; } translation.X = matrix.m30; matrix.m30 = 0.0; translation.Y = matrix.m31; matrix.m31 = 0.0; translation.Z = matrix.m32; matrix.m32 = 0.0; XYZ[] cols = new XYZ[3] { new XYZ(matrix.m00, matrix.m01, matrix.m02), new XYZ(matrix.m10, matrix.m11, matrix.m12), new XYZ(matrix.m20, matrix.m21, matrix.m22) }; scaling.X = cols[0].GetLength(); cols[0] = cols[0].Normalize(); XYZDouble.X = cols[0].Dot(cols[1]); cols[1] = cols[1] * 1 + cols[0] * -XYZDouble.X; scaling.Y = cols[1].GetLength(); cols[1] = cols[1].Normalize(); XYZDouble.Y = cols[0].Dot(cols[2]); cols[2] = cols[2] * 1 + cols[0] * -XYZDouble.Y; XYZDouble.Z = cols[1].Dot(cols[2]); cols[2] = cols[2] * 1 + cols[1] * -XYZDouble.Z; scaling.Z = cols[2].GetLength(); cols[2] = cols[2].Normalize(); XYZ rhs = XYZ.Cross(cols[1], cols[2]); if (cols[0].Dot(rhs) < 0.0) { for (int index = 0; index < 3; ++index) { scaling.X *= -1.0; cols[index].X *= -1.0; cols[index].Y *= -1.0; cols[index].Z *= -1.0; } } double trace = cols[0].X + cols[1].Y + cols[2].Z + 1.0; double qx; double qy; double qz; double qw; if (trace > 0) { double s = 0.5 / Math.Sqrt(trace); qx = (cols[2].Y - cols[1].Z) * s; qy = (cols[0].Z - cols[2].X) * s; qz = (cols[1].X - cols[0].Y) * s; qw = 0.25 / s; } else if (cols[0].X > cols[1].Y && cols[0].X > cols[2].Z) { double s = Math.Sqrt(1.0 + cols[0].X - cols[1].Y - cols[2].Z) * 2.0; qx = 0.25 * s; qy = (cols[0].Y + cols[1].X) / s; qz = (cols[0].Z + cols[2].X) / s; qw = (cols[2].Y - cols[1].Z) / s; } else if (cols[1].Y > cols[2].Z) { double s = Math.Sqrt(1.0 + cols[1].Y - cols[0].X - cols[2].Z) * 2.0; qx = (cols[0].Y + cols[1].X) / s; qy = 0.25 * s; qz = (cols[1].Z + cols[2].Y) / s; qw = (cols[0].Z - cols[2].X) / s; } else { double s = Math.Sqrt(1.0 + cols[2].Z - cols[0].X - cols[1].Y) * 2.0; qx = (cols[0].Z + cols[2].X) / s; qy = (cols[1].Z + cols[2].Y) / s; qz = 0.25 * s; qw = (cols[1].X - cols[0].Y) / s; } rotation.X = qx; rotation.Y = qy; rotation.Z = qz; rotation.W = -qw; return(true); }
private void calculate_Click(object sender, EventArgs e) { bool fillWithZero = checkBox1.Checked; var intervalSec = double.Parse(textBox_interval.Text) * 60; var directory = this.directorySelectionControl1.Path; Geo.Utils.FileUtil.CheckOrCreateDirectory(directory); string[] SSRsp3Pathes = this.textBox_SSRsp3Pathes.Lines; string[] NavPathes = this.textBox_NavPathes.Lines; string[] ClockPathes = this.textBox1.Lines; if (SSRsp3Pathes.Length != NavPathes.Length) { return; } int fileCount = SSRsp3Pathes.Length; if (!System.IO.Directory.Exists(@"D:\Temp\SSR1\")) { System.IO.Directory.CreateDirectory(@"D:\Temp\SSR1\"); } EpochCountTableTextManager = new ObjectTableManager(); EpochCountTableTextManager.OutputDirectory = "D:\\Temp\\SSR1\\"; var SatEpochCountTable = EpochCountTableTextManager.GetOrCreate("BNCSatEpochCount");// + OriginalSSR.Header.Name); SatEpochCountTable.NewRow(); for (int i = 0; i < fileCount; i++) { #region 读取SSR产品 Time start0 = Time.MaxValue; Time end0 = Time.MinValue; OriginalSSRSp3 = new Sp3File(); OriginalSSRSp3MinusPreciseClockOutput = new Sp3File(); OriginalSSRSp3PlusNavOutput = new Sp3File(); Sp3Reader r = new Sp3Reader(SSRsp3Pathes[i]); OriginalSSRSp3 = r.ReadAll(); OriginalSSRSp3.CheckOrBuildIndexCollection(); Dictionary <string, int> SatEpochCount = new Dictionary <string, int>(); foreach (var item in OriginalSSRSp3.Prns) { SatEpochCount.Add(item.ToString(), OriginalSSRSp3.SatEphemerisCollection[item].Count); } SatEpochCountTable.AddItem("Day", start0.GetGpsWeekAndDay()); foreach (var item in SatEpochCount) { SatEpochCountTable.AddItem(item.Key, item.Value); } SatEpochCountTable.EndRow(); #endregion #region 读取广播星历 ParamNavFileReader NavReader = new ParamNavFileReader(NavPathes[i]); ephemeris = new SingleParamNavFileEphService(NavReader.ReadGnssNavFlie()); #endregion #region 读取钟差文件 //ClockFileReader reader = new ClockFileReader(ClockPathes[i]); //ClockFile = reader.ReadAll(); //if (ClockFile.ClockCount == 0) return; #endregion OriginalSSRSp3.CheckOrBuildIndexCollection(); for (Time time = OriginalSSRSp3.TimePeriod.Start; time <= OriginalSSRSp3.TimePeriod.End; time += 1) { Sp3Section Sp3Section = new Sp3Section(); Sp3Section.Time = time; foreach (var prn in OriginalSSRSp3.Prns) { var ss1 = OriginalSSRSp3.SatEphemerisCollection[prn].Values.FindLast(b => b.Time <= time); if (!ephemeris.Prns.Contains(prn)) { continue; } var ss = ephemeris.Get(prn, time); XYZ eA = ss.XyzDot / ss.XyzDot.Length; XYZ eC = ss.XYZ.Cross(ss.XyzDot) / (ss.XYZ.Cross(ss.XyzDot)).Length; XYZ eR = eA.Cross(eC) / (eA.Cross(eC)).Length; XYZ deltaO = ss1.XYZ + ss1.XyzDot * (time.Seconds - ss1.Time.Seconds); double x = eA.X * deltaO.X + eA.X * deltaO.Y + eC.X * deltaO.Z; double y = eA.Y * deltaO.X + eA.Y * deltaO.Y + eC.Y * deltaO.Z; double z = eA.Z * deltaO.X + eA.Z * deltaO.Y + eC.Z * deltaO.Z; Ephemeris Sp3Record = new Ephemeris(); Sp3Record.Prn = prn; Sp3Record.XYZ = ss.XYZ - new XYZ(x, y, z); if (prn.SatelliteType == SatelliteType.R) { Sp3Record.ClockBias = ss.ClockBias + ss1.ClockBias; } else { Sp3Record.ClockBias = ss.ClockBias - ss.RelativeCorrection + ss1.ClockBias; } Sp3Section.Add(prn, Sp3Record); } OriginalSSRSp3PlusNavOutput.Add(Sp3Section); } var resultPath = Path.Combine("D:\\Temp\\SSR1\\", OriginalSSRSp3.Name); Sp3Writer ClockFileWriter = new Sp3Writer(resultPath, OriginalSSRSp3PlusNavOutput); ClockFileWriter.SaveToFile(); } // List<AtomicClock> OriginalSSRDataSource = new List<AtomicClock>(); // List<AtomicClock> ClockFileDataSource = new List<AtomicClock>(); // foreach (var key in OriginalSSRSp3.Prns) // { // //OriginalSSRDataSource = OriginalSSR.GetClockItems(key); // ClockFileDataSource = ClockFile.GetClockItems(key); // if (ClockFileDataSource == null) continue; // List<AtomicClock> ErrorResult = new List<AtomicClock>(); // List<AtomicClock> SSRPlusNavResult = new List<AtomicClock>(); // foreach (var item1 in ClockFileDataSource) // { // AtomicClock item2 = new AtomicClock(); // var clk = OriginalSSRSp3.GetClockItem(item1.Prn.ToString(),item1.Time); // if (item1.ClockBias == 9999999999.0 || clk == null) // { // item1.ClockBias = 9999999999.0; // item2.Time = item1.Time; // item2.Prn = item1.Prn; // item2.Name = item1.Name; // item2.ClockType = item1.ClockType; // item2.ClockBias = 9999999999.0; // } // else // { // var NavItem = ephemeris.Get(item1.Prn, item1.Time); // item2.Time = item1.Time; // item2.Prn = item1.Prn; // item2.Name = item1.Name; // item2.ClockType = item1.ClockType; // item2.ClockBias = NavItem.ClockBias - NavItem.RelativeTime + clk.ClockBias; // item1.ClockBias = item2.ClockBias - item1.ClockBias; // } // SSRPlusNavResult.Add(item2); // ErrorResult.Add(item1); // } // OriginalSSRSp3MinusPreciseClockOutput.Add(key, ErrorResult); // OriginalSSRSp3PlusNavOutput.Add(key, SSRPlusNavResult); // } // double interval = double.Parse(this.textBox_interval.Text); // ClockEstimationFrom = this.dateTimePicker_from.Value; // ClockEstimationTo = this.dateTimePicker_to.Value; // OriginalSSRSp3.Header = new Sp3Header (); // OriginalSSRSp3.Header.AgencyName="Gnsser"; // OriginalSSRSp3.Header.EndTime= // .Name = "SSR" + OriginalSSRSp3.Header.Name; // OriginalSSRSp3.Header.CreationDate = DateTime.Now.ToString(); // OriginalSSRSp3.Header.CreationAgence = "Gnsser"; // OriginalSSRSp3.Header.ANALYSIS_CENTER = "Gnsser"; // OriginalSSRSp3.Header.CreationProgram = "Gnsser"; // OriginalSSRSp3MinusPreciseClockOutput.Header = OriginalSSRSp3.Header; // OriginalSSRSp3PlusNavOutput.Header = OriginalSSRSp3.Header; // var resutlPath = Path.Combine("D:\\Temp\\SSR1\\", OriginalSSRSp3.Header.Name); // var errorResutlPath = Path.Combine("D:\\Temp\\SSR1\\", "error" + OriginalSSRSp3.Header.Name); // ClockFileWriter ClockFileWriter = new ClockFileWriter(resutlPath, OriginalSSRSp3PlusNavOutput); // ClockFileWriter.SaveToFile(); // ClockFileWriter errorClockFileWriter = new ClockFileWriter(errorResutlPath, OriginalSSRSp3MinusPreciseClockOutput); // errorClockFileWriter.SaveToFile(); // TableTextManager = new TableObjectManager(); // TableTextManager.OutputDirectory = "D:\\Temp\\SSR1\\"; // var paramTable = TableTextManager.GetOrCreate(OriginalSSRSp3MinusPreciseClockOutput.Name + "errorSSRSat"); // int count = 0; // SatelliteNumber prnIndex = new SatelliteNumber(); // foreach (var key in OriginalSSRSp3MinusPreciseClockOutput) // { // if (key.Count > count) { count = key.Count; prnIndex = key[0].Prn; } // } // var standard = OriginalSSRSp3MinusPreciseClockOutput.GetClockItems(prnIndex); // double DoubleDiffer = 0; // foreach (var key in standard) // { // paramTable.NewRow(); // paramTable.AddItem("Epoch", key.Time); // foreach (var item1 in OriginalSSRSp3MinusPreciseClockOutput.Names) // { // if (item1 == key.Name.ToString()) continue; // var ss = OriginalSSRSp3MinusPreciseClockOutput.GetClockItem(item1, key.Time); // if (ss == null) // continue; // if (key.ClockBias == 9999999999.0 || ss.ClockBias == 9999999999.0) // DoubleDiffer = 0; // else DoubleDiffer = key.ClockBias - ss.ClockBias; // paramTable.AddItem(ss.Prn + "-" + key.Prn, DoubleDiffer * 1E9); // } // paramTable.EndRow(); // } // TableTextManager.WriteAllToFileAndCloseStream(); //} //EpochCountTableTextManager.WriteAllToFileAndCloseStream(); Geo.Utils.FileUtil.OpenDirectory("D:\\Temp\\SSR1\\"); }