/// <summary> /// 提取观测量的权逆阵。是否只提取对角阵?? /// </summary> /// <param name="fileA"></param> /// <param name="fileB"></param> /// <returns></returns> public static double[][] GetCovaMatrixOfObs(SinexFile fileA, SinexFile fileB) { int paramCountA = fileA.EstimateParamCount; int row = paramCountA + fileB.EstimateParamCount; double[][] array = MatrixUtil.Create(row); //fileA直接设置。 //这里应该定权! SinexStatistic statisticA = fileA.GetStatistic(); SinexStatistic statisticB = fileB.GetStatistic(); SinexStatistic statisticNew = SinexStatistic.Merge(statisticA, statisticB); double varFactorA = statisticNew.VarianceOfUnitWeight / statisticA.VarianceOfUnitWeight; double varFactorB = statisticNew.VarianceOfUnitWeight / statisticB.VarianceOfUnitWeight; double[][] matrixA = fileA.GetEstimateCovaMatrix(); double[][] matrixB = fileB.GetEstimateCovaMatrix(); MatrixUtil.Multiply(matrixA, varFactorA); MatrixUtil.Multiply(matrixB, varFactorB); MatrixUtil.SetSubMatrix(array, matrixA); MatrixUtil.SetSubMatrix(array, matrixB, paramCountA, paramCountA); return(array); }
/// <summary> /// 依据输入和平差信息,构建平差结果Sinex文件 /// </summary> /// <param name="fileA"></param> /// <param name="fileB"></param> /// <param name="apriori"></param> private void BuildResultSinex(SinexFile fileA, SinexFile fileB, double[][] apriori) { //统计信息 SinexStatistic stat = SinexStatistic.Merge(fileA.GetStatistic(), fileB.GetStatistic()); stat.NumberOfDegreesOfFreedom = p.Freedom; stat.NumberOfObservations = p.ObsMatrix.Observation.Count; stat.NumberOfUnknown = p.ParamCount; stat.VarianceOfUnitWeight = p.VarianceOfUnitWeight; result.SolutionStattisticsBlock.Items = stat.GetSolutionStatistics(); //先验值 result.SolutionAprioriBlock.Items.AddRange(fileA.SolutionAprioriBlock.Items); foreach (var item in fileB.SolutionAprioriBlock.Items) { if (!result.SolutionAprioriBlock.Items.Contains(item)) { result.SolutionAprioriBlock.Items.Add(item); } } //测站估值 result.SolutionEstimateBlock.Items.AddRange(fileA.SolutionEstimateBlock.Items); foreach (var item in fileB.SolutionEstimateBlock.Items) { if (!result.SolutionEstimateBlock.Items.Contains(item)) { result.SolutionEstimateBlock.Items.Add(item); } } int i = 0; foreach (var item in result.SolutionEstimateBlock.Items) { item.ParameterValue = apriori[i][0]; item.StdDev = p.CovaOfEstimatedParam[i, i]; i++; } //矩阵 result.SolutionMatrixEstimateCova.Items = SinexMatrixConvertor.GetMatrixLines(p.CovaOfEstimatedParam.Array); }
/// <summary> /// 单点定位结果转化为Sinex文件 /// </summary> /// <returns></returns> public static SinexFile Build(SingleSiteGnssResult result) { SinexFile sinex = new SinexFile("Gnsser"); sinex.SolutionEpochBlock.Items.Add(new SolutionEpoch() { DateStart = result.ReceiverTime, DateEnd = result.ReceiverTime, DateMean = result.ReceiverTime, ObservationCode = "P", PointCode = "A", SiteCode = result.SiteInfo.SiteName, SolutionID = "0001" }); SinexStatistic stat = new SinexStatistic() { NumberOfUnknown = result.ResultMatrix.ParamCount, NumberOfObservations = result.ResultMatrix.ObsMatrix.Observation.Count, VarianceOfUnitWeight = result.ResultMatrix.VarianceOfUnitWeight, NumberOfDegreesOfFreedom = result.ResultMatrix.Freedom }; sinex.SolutionStattisticsBlock.Items = stat.GetSolutionStatistics(); GeoCoord approxGeo = CoordTransformer.XyzToGeoCoord(result.ApproxXyz); sinex.SiteIdBlock.Items.Add(new SiteId() { SiteCode = result.SiteInfo.SiteName, PointCode = "A", UniqueMonumentId = result.SiteInfo.MarkerNumber, ApproximateHeight = approxGeo.Height, ApproximateLatitude = approxGeo.Lat, ApproximateLongitude = approxGeo.Lon, ObservationCode = "P", GeoCoord = result.GeoCoord, StationDescription = "Single Point" }); int index = 0; sinex.SolutionEstimateBlock.Items.AddRange(new SolutionValue[] { new SolutionValue() { Index = 1 + index++, ParameterType = "STAX", ParameterValue = result.EstimatedXyz.X, SiteCode = result.SiteInfo.SiteName, RefEpoch = result.ReceiverTime, PointCode = "A", ParameterUnits = "m", ConstraintCode = "2", StdDev = Math.Sqrt(result.ResultMatrix.CovaOfEstimatedParam[index - 1, index - 1]), SolutionID = "0001" }, new SolutionValue() { Index = 1 + index++, ParameterType = "STAY", ParameterValue = result.EstimatedXyz.Y, SiteCode = result.SiteInfo.SiteName, RefEpoch = result.ReceiverTime, PointCode = "A", ParameterUnits = "m", ConstraintCode = "2", StdDev = Math.Sqrt(result.ResultMatrix.CovaOfEstimatedParam[index - 1, index - 1]), SolutionID = "0001" }, new SolutionValue() { Index = 1 + index++, ParameterType = "STAZ", ParameterValue = result.EstimatedXyz.Z, SiteCode = result.SiteInfo.SiteName, RefEpoch = result.ReceiverTime, PointCode = "A", ParameterUnits = "m", ConstraintCode = "2", StdDev = Math.Sqrt(result.ResultMatrix.CovaOfEstimatedParam[index - 1, index - 1]), SolutionID = "0001" }, new SolutionValue() { Index = 1 + index++, ParameterType = "RBIAS", ParameterValue = result.RcvClkErrDistance, SiteCode = result.SiteInfo.SiteName, RefEpoch = result.ReceiverTime, PointCode = "A", ParameterUnits = "m", ConstraintCode = "2", StdDev = Math.Sqrt(result.ResultMatrix.CovaOfEstimatedParam[index - 1, index - 1]), SolutionID = "0001" } }); // sinex. sinex.SolutionMatrixEstimateCova.Items = SinexMatrixConvertor.GetMatrixLines(result.ResultMatrix.CovaOfEstimatedParam.Array); return(sinex); }
/// <summary> /// 基于 Sinex 文件的分区平差。 /// </summary> /// <param name="files">具有公共参数的分区</param> public SinexBlockAdjust(params SinexFile[] files) { if (files.Length <= 1) { throw new ArgumentException("输入的SINEX文件数量不可少于2!"); } this.files = files; //检查一下是否只包含坐标,如否,则清理。 foreach (var item in files) { if (!item.IsOnlyEstimateCoordValue) { item.CleanNonCoordSolutionValue(); } } //提取公共测站名称 List <string> sameSites = null; new List <string>(); foreach (var item in files) { if (sameSites == null) { sameSites = new List <string>(); sameSites.AddRange(item.GetSiteCods()); } else { sameSites = SinexFile.GetSameSiteCodes(item, sameSites); } } if (sameSites.Count == 0) { throw new ArgumentException("分区没有公共点,不可执行分区平差!"); } //计算统一单位权中误差 double commonVarFactor = GetVarianceFactor(files); //组建分区 DateTime from = DateTime.Now; List <BlockAdjustItem> items = new List <BlockAdjustItem>(); foreach (var file in files) { //获取公共参数所在的编号,都转化为X,Y,Z分别的参数 List <int> commonParamIndexes = file.GetParamIndexes(sameSites); //公共参数的索引 List <int> blockParamIndexes = file.GetParamIndexesExcept(sameSites); //区内参数的索引 List <int> newIndexes = new List <int>(blockParamIndexes); //新索引顺序 newIndexes.AddRange(commonParamIndexes); int blockParamCount = blockParamIndexes.Count; int obsCount = file.EstimateParamCount; int commonParamCount = commonParamIndexes.Count; //分区内参数系数阵 obsCount x paramCount double[][] coeffA = MatrixUtil.Create(obsCount, blockParamCount); for (int i = 0; i < blockParamCount; i++) { coeffA[i][i] = 1.0; } //观测值 obsCount x 1 double[][] obs = MatrixUtil.Create(obsCount, 1); for (int i = 0; i < obsCount; i++) { if (i < blockParamCount)//区内参数 { obs[i][0] = file.SolutionEstimateBlock.Items[blockParamIndexes[i]].ParameterValue; } else//公共参数 { obs[i][0] = file.SolutionEstimateBlock.Items[commonParamIndexes[i - blockParamCount]].ParameterValue; } } //观测值权逆阵 obsCount x obsCount //注意:此处应该统一化权阵 double[][] inverseOfObs = null; if (file.HasEstimateCovaMatrix) { inverseOfObs = file.GetEstimateCovaMatrix(); MatrixUtil.SymmetricExchange(inverseOfObs, newIndexes); MatrixUtil.Multiply(inverseOfObs, commonVarFactor / file.GetStatistic().VarianceOfUnitWeight); } //else if (file.HasNormalEquationMatrix && file.HasNormalEquationVectorMatrix) //{ // //方法待验证 // double[][] normal = file.GetNormalEquationMatrix(); // double[] righHand = file.GetNormalEquationVector(); // Geo.Algorithm.Matrix n = new Geo.Algorithm.Matrix(normal); // Geo.Algorithm.Matrix u = new Geo.Algorithm.Matrix(MatrixUtil.Create( righHand)); // inverseOfObs = n.Inverse.Array; // double lTpl = file.GetStatistic().WeightedSqureSumOfOMinusC; // double vTpv = lTpl - (u.Transpose() * n * u)[0,0]; // double varFactor = vTpv / file.GetStatistic().NumberOfDegreesOfFreedom; // MatrixUtil.Multiply(inverseOfObs, varFactor); // MatrixUtil.SymmetricExchange(inverseOfObs, newIndexes); // MatrixUtil.Multiply(inverseOfObs, commonVarFactor / file.GetStatistic().VarianceOfUnitWeight); //} else//去相关 { inverseOfObs = MatrixUtil.Create(obsCount); for (int i = 0; i < obsCount; i++) { if (i < blockParamCount)//区内参数 { inverseOfObs[i][i] = Math.Pow(file.SolutionEstimateBlock.Items[blockParamIndexes[i]].StdDev, 2); } else//公共参数 { inverseOfObs[i][i] = Math.Pow(file.SolutionEstimateBlock.Items[commonParamIndexes[i - blockParamCount]].StdDev, 2); } } MatrixUtil.Multiply(inverseOfObs, commonVarFactor / file.GetStatistic().VarianceOfUnitWeight); } //分区内对公共参数的系数阵 obsCount x commonParamCount double[][] coeffB = MatrixUtil.Create(obsCount, commonParamCount); for (int i = blockParamCount; i < obsCount; i++) { coeffB[i][i - blockParamCount] = 1; } BlockAdjustItem item = new BlockAdjustItem(coeffA, obs, inverseOfObs, coeffB); items.Add(item); } ba = new BlockAdjustment(items.ToArray(), false); //创建结果SINEX文件,文件只包含公共参数的内容 ResultSinexFile = new SinexFile("Gnsser"); //测站名称 int commonSiteCount = ba.CommonParamCount / 3; List <SiteId> siteIds = new List <SiteId>(); for (int i = 0; i < commonSiteCount; i++) { siteIds.Add(files[0].GetSiteId(sameSites[i])); } ResultSinexFile.SiteIdBlock = SinexFactory.CreateSiteIdBlock(siteIds); //统计信息 SinexStatistic statistic = new SinexStatistic() { NumberOfUnknown = ba.CommonParamCount, NumberOfDegreesOfFreedom = ba.Freedom, VarianceOfUnitWeight = ba.VarianceOfUnitWeight, SquareSumOfResidualsVTPV = ba.SquareSumOfResidualsVTPV, NumberOfObservations = ba.ObsCount }; ResultSinexFile.SolutionStattisticsBlock = SinexFactory.CreateSolutionStattisticsBlock(statistic.GetSolutionStatistics()); //估值 List <SolutionValue> estList = new List <SolutionValue>(); Time refEchop = files[0].SolutionEstimateBlock.Items[0].RefEpoch; for (int i = 0; i < commonSiteCount; i++) { int paramIndex = i * 3; SolutionValue svX = new SolutionValue(paramIndex + 1, siteIds[i].SiteCode, "STAX", ba.CommonParams[paramIndex + 0][0], refEchop, ba.CommonParamRmsVector[paramIndex + 0]); SolutionValue svY = new SolutionValue(paramIndex + 2, siteIds[i].SiteCode, "STAY", ba.CommonParams[paramIndex + 1][0], refEchop, ba.CommonParamRmsVector[paramIndex + 1]); SolutionValue svZ = new SolutionValue(paramIndex + 3, siteIds[i].SiteCode, "STAZ", ba.CommonParams[paramIndex + 2][0], refEchop, ba.CommonParamRmsVector[paramIndex + 2]); estList.AddRange(new SolutionValue[] { svX, svY, svZ }); } ResultSinexFile.SolutionEstimateBlock = SinexFactory.CreateSolutionEstimateBlock(estList); //协方差 ResultSinexFile.SolutionMatrixEstimateCova = SinexFactory.CreateSolutionMatrixEstimateCova(ba.CovaOfCommonParams); this.TimeSpan = DateTime.Now - from; }