예제 #1
0
파일: OStation.cs 프로젝트: mfkiwl/GeoFun
        /// <summary>
        /// 计算相位平滑伪距值
        /// 对于30s采样率的
        /// </summary>
        /// <remarks>
        /// 参考 任晓东. 多系统GNSS电离层TEC高精度建模及差分码偏差精确估计[D].
        /// </remarks>
        public void SmoothP41()
        {
            double f1 = Common.GPS_F1;
            double f2 = Common.GPS_F2;

            OArc arc = null;

            foreach (var prn in Arcs.Keys)
            {
                for (int i = 0; i < Arcs[prn].Count; i++)
                {
                    // 取某颗卫星的一个观测弧段
                    arc = Arcs[prn][i];

                    // 整个弧段P4+L4的均值<P4+L4>
                    double p4l4 = 0;
                    for (int j = 1; j < arc.Length; j++)
                    {
                        p4l4 = p4l4 * j / (j + 1) + arc[j]["P4"] / (j + 1);
                    }

                    // 平滑P4
                    for (int j = 0; j < arc.Length; j++)
                    {
                        arc[j].SatData.Add("SP4", arc[j]["L4"] - p4l4);
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// 将弧段以index为界分为2段,index为第2段的起始索引
        /// </summary>
        /// <param name="index">第二段开始的索引</param>
        /// <returns></returns>
        public OArc[] Split(int index)
        {
            if (index < 0 || index >= Length)
            {
                return(null);
            }

            // 第一段
            OArc arc1 = new OArc();

            arc1.PRN        = PRN;
            arc1.File       = File;
            arc1.Station    = Station;
            arc1.StartIndex = StartIndex;
            arc1.EndIndex   = StartIndex + index - 1;

            // 第2段[index,end]
            OArc arc2 = new OArc();

            arc2.Station    = Station;
            arc2.File       = File;
            arc2.PRN        = PRN;
            arc2.StartIndex = StartIndex + index;
            arc2.EndIndex   = EndIndex;

            // EndIndex = StartIndex + (index - 1 < 0 ? 0 : index - 1);

            return(new OArc[] { arc1, arc2 });
        }
예제 #3
0
 /// <summary>
 /// 浅拷贝
 /// </summary>
 /// <param name="arc"></param>
 public OArc(OArc arc)
 {
     PRN        = arc.PRN;
     File       = arc.File;
     Station    = arc.Station;
     StartIndex = arc.StartIndex;
     EndIndex   = arc.EndIndex;
 }
예제 #4
0
파일: OStation.cs 프로젝트: mfkiwl/GeoFun
        /// <summary>
        /// 对弧段进行滑动窗口拟合
        /// </summary>
        /// <param name="arc"></param>
        /// <param name="length">窗口的长度 单位:历元</param>
        /// <param name="order">多项式拟合的阶数</param>
        public void Fit(ref OArc arc, int length, int order)
        {
            int             si  = 0;
            int             ei  = si + length;
            double          sp4 = 0d;
            PolynomialModel pm  = new PolynomialModel();

            while (si < arc.Length)
            {
                if (ei > arc.Length)
                {
                    ei = arc.Length;
                }

                // 只有一个历元
                if (si == ei)
                {
                    arc[si]["vtec"] = 0d;
                    break;
                }

                List <double> x     = new List <double>();
                List <double> y     = new List <double>();
                List <int>    index = new List <int>();
                for (int i = si; i < ei; i++)
                {
                    sp4 = arc[i]["vtec"];
                    if (Math.Abs(sp4) > 1e-10)
                    {
                        x.Add(i);
                        y.Add(sp4);
                        index.Add(i);
                    }
                }

                double        sigma;
                List <double> residue;
                if (pm.Fit(x, y, out residue, out sigma))
                {
                    for (int i = 0; i < x.Count; i++)
                    {
                        // 剔粗差
                        if (Math.Abs(residue[i]) < 5 * sigma && Math.Abs(residue[i]) < 2.5)
                        {
                            arc[index[i]]["vtec"] = residue[i];
                        }
                        else
                        {
                            arc[index[i]]["vtec"] = 0d;
                        }
                    }
                }

                si  = ei;
                ei += length;
            }
        }
예제 #5
0
파일: OStation.cs 프로젝트: mfkiwl/GeoFun
 public void DetectArcs()
 {
     for (int i = 0; i < 32; i++)
     {
         string      prn     = string.Format("G{0:0#}", i + 1);
         List <OArc> arcList = OArc.Detect(this, prn);
         Arcs.Add(prn, arcList);
     }
 }
예제 #6
0
파일: OStation.cs 프로젝트: mfkiwl/GeoFun
        /// <summary>
        /// 计算相位平滑伪距值
        /// </summary>
        public void SmoothP4()
        {
            ObsHelper.CalL4(ref Epoches);
            ObsHelper.CalP4(ref Epoches);

            foreach (var prn in Arcs.Keys)
            {
                for (int i = 0; i < Arcs[prn].Count; i++)
                {
                    OArc arc = Arcs[prn][i];
                    Smoother.SmoothP4ByL4(ref arc);
                }
            }
        }
예제 #7
0
파일: Smoother.cs 프로젝트: mfkiwl/GeoFun
        /// <summary>
        /// 滑动平均
        /// </summary>
        /// <param name="arc">弧段</param>
        /// <param name="meas">要平滑的观测值名称</param>
        /// <param name="order">阶数</param>
        public static void Smooth(ref OArc arc, string meas, int order)
        {
            if (arc is null)
            {
                return;
            }

            int left = 0, right = 0;

            if (order % 2 == 0)
            {
                left  = order / 2;
                right = left - 1;
            }
            else
            {
                left = right = (order - 1) / 2;
            }

            double[] values  = new double[arc.Length];
            double[] values1 = new double[arc.Length];
            for (int i = left; i < arc.Length - right; i++)
            {
                values[i] = arc[i][meas];

                int    k    = 0;
                double mean = 0d;
                for (int j = i - left; j < i + right + 1; j++)
                {
                    if (Math.Abs(arc[j][meas]) < 1e-10)
                    {
                        continue;
                    }

                    mean = mean * k / (k + 1) + arc[j][meas] / (k + 1);
                    k++;
                }

                values[i] = mean;
            }
            for (int i = 0; i < arc.Length; i++)
            {
                arc[i]["dtec"] = arc[i][meas] - values[i];
                arc[i][meas]   = values[i];
            }

            arc.StartIndex += left;
            arc.EndIndex   -= right;
        }
예제 #8
0
파일: OStation.cs 프로젝트: mfkiwl/GeoFun
        public void DetectCycleSlip()
        {
            for (int k = 0; k < Arcs.Keys.Count; k++)
            {
                string prn = Arcs.Keys.ElementAt(k);

                //// 旧的弧段
                Stack <OArc> oldArcs = new Stack <OArc>();
                //// 探测后新的弧段
                List <OArc> newArcs = new List <OArc>();

                for (int i = Arcs[prn].Count - 1; i >= 0; i--)
                {
                    oldArcs.Push(Arcs[prn][i].Copy());
                }

                int  index = -1;
                OArc arc   = null;
                while (oldArcs.Count() > 0)
                {
                    arc = oldArcs.Pop();
                    if (ObsHelper.DetectCycleSlip(ref arc, out index))
                    {
                        // 根据返回周跳的索引将弧段分为2段
                        OArc[] arcs = arc.Split(index);

                        // 前一段加入已检测的列表
                        if (arcs[0].Length >= Options.ARC_MIN_LENGTH)
                        {
                            newArcs.Add(arcs[0]);
                        }

                        // 后一段加入未检测列表
                        if (arcs[1].Length >= Options.ARC_MIN_LENGTH)
                        {
                            oldArcs.Push(arcs[1]);
                        }
                    }
                    else
                    {
                        newArcs.Add(arc);
                    }
                }

                Arcs[prn] = newArcs;
            }
        }
예제 #9
0
파일: OStation.cs 프로젝트: mfkiwl/GeoFun
        public void CalVTEC()
        {
            foreach (var prn in Arcs.Keys)
            {
                for (int i = 0; i < Arcs[prn].Count; i++)
                {
                    OArc arc = Arcs[prn][i];

                    for (int j = 0; j < arc.Length; j++)
                    {
                        if (Math.Abs(arc[j]["SP4"]) > 1e-10)
                        {
                            arc[j]["vtec"] = Iono.STEC2VTEC(9.52437 * arc[j]["SP4"], arc[j].Elevation);
                        }
                    }
                }
            }
        }
예제 #10
0
파일: OStation.cs 프로젝트: mfkiwl/GeoFun
        public void CalP4L4()
        {
            OArc   arc = null;
            double p1 = 0d, p2 = 0d, l1 = 0d, l2 = 0d;

            foreach (var prn in Arcs.Keys)
            {
                for (int i = 0; i < Arcs[prn].Count; i++)
                {
                    // 取某颗卫星的一个观测弧段
                    arc = Arcs[prn][i];

                    for (int j = 0; j < arc.Length; j++)
                    {
                        p1 = arc[j].SatData["P1"];
                        p2 = arc[j].SatData["P2"];
                        l1 = arc[j].SatData["L1"];
                        l2 = arc[j].SatData["L2"];
                        if (p1 == 0d)
                        {
                            p1 = arc[j].SatData["C1"];
                        }

                        if (p1 != 0d || p2 != 0d)
                        {
                            arc[j]["P4"] = p2 - p1;
                        }
                        else
                        {
                            arc[j]["P4"] = 0;
                        }

                        if (l1 != 0 && l2 != 0)
                        {
                            arc[j]["L4"] = l2 - l1;
                        }
                        else
                        {
                            arc[j]["L4"] = 0;
                        }
                    }
                }
            }
        }
예제 #11
0
파일: Smoother.cs 프로젝트: mfkiwl/GeoFun
        /// <summary>
        /// 平滑一个弧段
        /// </summary>
        /// <param name="arc"></param>
        public static void SmoothP4ByL4_1(ref OArc arc)
        {
            double power = 1;

            // P4预报值
            double p4_est = 0d;

            for (int i = 1; i < arc.Length; i++)
            {
                power = power - DEC_POWER;
                if (power < MIN_POWER)
                {
                    power = MIN_POWER;
                }
                p4_est = arc[i - 1]["P4"] + arc[i]["L4"] - arc[i - 1]["L4"];

                arc[i]["P4"] = arc[i]["P4"] * power + (1 - power) * p4_est;
            }
        }
예제 #12
0
        /// <summary>
        /// 计算ROTI
        /// </summary>
        /// <param name="arc"></param>
        /// <remarks>
        /// 2019.研究台风引起电离层扰动的形态特征.许九靖. 安徽理工大学.
        /// </remarks>
        public static void CalROTI(ref OArc arc)
        {
            if (arc is null)
            {
                return;
            }

            // 利用相位观测值计算相对STEC信号
            for (int i = 1; i < arc.Length; i++)
            {
                if (Math.Abs(arc[i]["L4"]) < 1e-13 ||
                    Math.Abs(arc[i + 1]["L4"]) < 1e-13)
                {
                    continue;
                }

                arc[i]["ltec"] = 9.52437 * (arc[i]["L4"] - arc[i - 1]["L4"]);
            }

            int order = 9;
            int left, right;

            left = right = (order - 1) / 2;
            Vector <double> seg = new DenseVector(order);

            for (int i = left; i < arc.Length - right; i++)
            {
                for (int j = 0; j < order; j++)
                {
                    seg[j] = arc[i - left + j]["ltec"];
                }

                arc[i]["roti"] = Math.Sqrt(seg.DotProduct(seg) / order - Math.Pow(seg.Mean(), 2));
            }

            arc.StartIndex += left + 1;
            arc.EndIndex   -= right + 1;
        }
예제 #13
0
        public static void CalDoubleDiff(ref OArc arc)
        {
            if (arc is null)
            {
                return;
            }

            for (int i = 1; i < arc.Length - 1; i++)
            {
                if (Math.Abs(arc[i - 1]["L4"]) < 1e-13 ||
                    Math.Abs(arc[i]["L4"]) < 1e-13 ||
                    Math.Abs(arc[i + 1]["L4"]) < 1e-13)
                {
                    continue;
                }

                arc[i]["L6"] = 9.52437 * ((arc[i + 1]["L4"] - arc[i]["L4"]) -
                                          (arc[i]["L4"] - arc[i - 1]["L4"]));
            }

            arc.StartIndex += 1;
            arc.EndIndex   -= 1;
        }
예제 #14
0
파일: OStation.cs 프로젝트: mfkiwl/GeoFun
        public void Fit(ref OArc arc)
        {
            List <int>    index = new List <int>();
            List <double> x     = new List <double>();
            List <double> y     = new List <double>();

            for (int i = 0; i < arc.Length; i++)
            {
                if (Math.Abs(arc[i]["SP4"]) > 1e-3)
                {
                    index.Add(i);

                    x.Add(i);
                    y.Add(arc[i]["SP4"]);
                }
            }

            PolynomialModel pm = PolynomialModel.Fit(x, y, 3);

            for (int i = 0; i < x.Count; i++)
            {
                arc[index[i]]["SP4"] -= pm.CalFit(x[i]);
            }
        }
예제 #15
0
파일: Smoother.cs 프로젝트: mfkiwl/GeoFun
        /// <summary>
        /// 平滑一个弧段
        /// </summary>
        /// <param name="arc"></param>
        public static void SmoothP4ByL4(ref OArc arc, string type = "hatch")
        {
            if (type == "hatch")
            {
                // 整个弧段P4+L4的均值<P4+L4>
                int      n = 0;
                double   p4, l4;
                double   p4l4    = 0d;
                double[] p4l4All = new double[arc.Length];
                for (int i = 0; i < arc.Length; i++)
                {
                    p4 = arc[i]["P4"];
                    l4 = arc[i]["L4"];
                    if (p4 != 0 && l4 != 0)
                    {
                        p4l4 += p4 + l4;
                        n++;
                    }
                    p4l4All[i] = p4 + l4;
                }
                if (n > 0)
                {
                    p4l4 /= n;
                }

                // 平滑P4
                for (int j = 0; j < arc.Length; j++)
                {
                    p4 = arc[j]["P4"];
                    l4 = arc[j]["L4"];

                    arc[j].SatData["SP4"] = 0;
                    if (p4 != 0 && l4 != 0)
                    {
                        arc[j].SatData["SP4"] = p4l4 - l4;
                    }
                }
            }
            else
            {//双向hatch滤波
                double[] sp4Forward  = new double[arc.Length];
                double[] sp4Backward = new double[arc.Length];

                // 前向
                double power     = 1;
                double MIN_POWER = 0.01;
                double POWER_DEC = 0.02;
                sp4Forward[0] = arc[0]["P4"];
                for (int i = 1; i < arc.Length; i++)
                {
                    power         = power - POWER_DEC >= MIN_POWER ? power - POWER_DEC : MIN_POWER;
                    sp4Forward[i] = (sp4Forward[i - 1] + arc[i]["L4"] - arc[i - 1]["L4"]) * (1 - power) +
                                    arc[i]["P4"] * power;
                }

                // 后向
                power = 1d;
                sp4Backward[arc.Length - 1] = arc[arc.Length - 1]["P4"];
                for (int i = arc.Length - 2; i >= 0; i--)
                {
                    power          = power - POWER_DEC >= MIN_POWER ? power - POWER_DEC : MIN_POWER;
                    sp4Backward[i] = (sp4Forward[i + 1] + arc[i]["L4"] - arc[i + 1]["L4"]) * (1 - power) +
                                     arc[i]["P4"] * power;
                }

                if (arc.Length > 60)
                {
                    for (int i = 0; i < 30; i++)
                    {
                        arc[i]["SP4"] = sp4Backward[i];
                    }
                    for (int i = arc.Length - 1; i >= arc.Length - 30; i--)
                    {
                        arc[i]["SP4"] = sp4Forward[i];
                    }
                    for (int i = 30; i < arc.Length - 30; i++)
                    {
                        arc[i]["SP4"] = sp4Forward[i] / 2d + sp4Backward[i] / 2d;
                    }
                }
                else
                {
                    int midIndex = arc.Length / 2;
                    for (int i = 0; i < midIndex; i++)
                    {
                        arc[i]["SP4"] = sp4Backward[i];
                    }
                    for (int i = midIndex; i < arc.Length; i++)
                    {
                        arc[i]["SP4"] = sp4Forward[i];
                    }
                }
            }
        }
예제 #16
0
        /// <summary>
        /// 探测周跳
        /// </summary>
        /// <remarks>
        /// GPS周跳探测与修复的算法研究与实现.彭秀英.2004
        /// </remarks>
        public static bool DetectCycleSlip(ref OArc arc, out int index)
        {
            index = -1;

            // i-1历元宽巷模糊度估计值
            double NW1 = 0d;
            // i历元宽巷模糊度估计值
            double NW2 = 0d;
            // i+1历元宽巷模糊度估计值
            double NW3 = 0d;

            // i-1历元宽巷模糊度估计值精度
            double delta1 = 0d;
            // i历元宽巷模糊度估计值精度
            double delta2 = 0d;

            // GPS L1频率(Hz)
            double f1 = Common.GPS_F1;
            // GPS L2频率(Hz)
            double f2 = Common.GPS_F2;

            // GPS L1波长(m)
            double l1 = Common.GPS_L1;
            // GPS L2波长(m)
            double l2 = Common.GPS_L2;

            // L1精度(m)
            double dL1 = Common.DELTA_L1;
            // L2精度(m)
            double dL2 = Common.DELTA_L2;
            // P1精度(m)
            double dP1 = Common.DELTA_P1;
            // P2精度(m)
            double dP2 = Common.DELTA_P2;

            double vp1, vp2, vl1, vl2;

            GetMeas(arc[0], out vp1, out vp2, out vl1, out vl2, out dP1);
            // 初始化NW(i-1)
            NW1 = (1 / (f1 - f2) *
                   (f1 * vl1 * l1 - f2 * vl2 * l2) -
                   1 / (f1 + f2) *
                   (f1 * vp1 + f2 * vp2)) / Common.GPS_Lw;

            GetMeas(arc[1], out vp1, out vp2, out vl1, out vl2, out dP1);
            // 初始化NW(i)
            NW2 = (1 / (f1 - f2) *
                   (f1 * vl1 * l1 - f2 * vl2 * l2) -
                   1 / (f1 + f2) *
                   (f1 * vp1 + f2 * vp2)) / Common.GPS_Lw;

            // 初始化δ(i-1)
            delta1 = Math.Sqrt(
                1 / Math.Pow(f1 - f2, 2) * (f1 * f1 * dL1 + f2 * f2 * dL2) +
                1 / Math.Pow(f1 + f2, 2) * (f1 * f1 * dP1 + f2 * f2 + dP2)
                );

            // 前一历元gf值
            double lstGF = arc[0]["GF"];
            // 当前历元gf值
            double curGF = arc[0]["GF"];

            int arcLen = arc.Length - 1;

            for (int i = 1; i < arcLen; i++)
            {
                if (!GetMeas(arc[i + 1], out vp1, out vp2, out vl1, out vl2, out _))
                {
                    index = i + 1;
                    return(true);
                }

                NW3 = (1 / (f1 - f2) *
                       (f1 * vl1 * l1 - f2 * vl2 * l2) -
                       1 / (f1 + f2) *
                       (f1 * vp1 + f2 * vp2)) / Common.GPS_Lw;

                delta2 = Math.Sqrt(delta1 * delta1 * i / (i + 1) + Math.Pow(NW2 - NW1, 2) / (i + 1));

                // MW探测
                if (Math.Abs(NW2 - NW1) > 4 * delta1)
                {
                    if (Math.Abs(NW3 - NW2) < 1)
                    {
                        arc[i].CycleSlip = true;
                    }
                    else
                    {
                        arc[i].Outlier = true;
                    }

                    // 有周跳,分割成新弧段
                    //OArc newArc = arc.Split(i + 1);
                    //arc.Station.Arcs[arc.PRN].Add(newArc);
                    index = i + 1;
                    Common.msgBox.Print(string.Format("\r\n检测到周跳,时间:{0},历元:{1:0000},编号:{2}", arc[i + 1].Epoch, i + 1 + arc.StartIndex, arc[i + 1].SatPRN));
                    return(true);
                }

                NW1    = NW1 * i / (i + 1) + NW2 / (i + 1);
                NW2    = NW3;
                delta1 = delta2;

                lstGF = curGF;
                curGF = arc[i]["GF"];
                if (arc[i].CycleSlip || arc[i].Outlier)
                {
                    continue;
                }

                // GF探测
                if (!arc[i].CycleSlip)
                {
                    if (Math.Abs(curGF - lstGF) > Options.Threshold_GF)
                    {
                        arc[i].CycleSlip = true;
                    }
                }

                // 检查LLI
                if (!arc[i].CycleSlip)
                {
                    if (arc[i]["L1"] == 1 || arc[i]["L2"] == 1)
                    {
                        arc[i].CycleSlip = true;
                    }
                }
            }
            return(false);
        }
예제 #17
0
        public static List <OArc> Detect(OStation sta, string prn, int minArcLen = -1)
        {
            if (sta is null)
            {
                return(null);
            }
            if (minArcLen < 0)
            {
                minArcLen = Options.ARC_MIN_LENGTH;
            }

            List <OArc> arcs = new List <OArc>();

            int    start = -1;
            double l1, l2, p1, p2, c1;

            for (int i = 0; i < sta.EpochNum; i++)
            {
                bool flag = true;
                if (!sta.Epoches[i].AllSat.ContainsKey(prn))
                {
                    flag = false;
                }
                else
                {
                    l1 = sta.Epoches[i][prn]["L1"];
                    l2 = sta.Epoches[i][prn]["L2"];
                    p1 = sta.Epoches[i][prn]["P1"];
                    p2 = sta.Epoches[i][prn]["P2"];
                    c1 = sta.Epoches[i][prn]["C1"];

                    if (l1 == 0 || l2 == 0 || p2 == 0)
                    {
                        flag = false;
                    }
                    else if (p1 == 0 && c1 == 0)
                    {
                        flag = false;
                    }
                    else if (sta.Epoches[i][prn].Outlier)
                    {
                        flag = false;
                    }
                    else if (sta.Epoches[i][prn].CycleSlip)
                    {
                        flag = false;
                    }
                }

                if (flag)
                {
                    // 弧段继续
                    if (start > -1)
                    {
                        continue;
                    }
                    // 弧段开始
                    else
                    {
                        start = i;
                    }
                }
                else
                {
                    // 弧段结束
                    if (start > -1)
                    {
                        if (i - start > minArcLen)
                        {
                            OArc arc = new OArc();
                            arc.StartIndex = start + 10;
                            arc.EndIndex   = i - 1 - 10;
                            arc.Station    = sta;
                            arc.PRN        = prn;
                            arcs.Add(arc);
                        }
                        start = -1;
                    }
                    else
                    {
                        continue;
                    }
                }
            }

            return(arcs);
        }