//##################################################################### /// <summary> /// 根据星历表,创建新的PathPrimitive</para> /// </summary> /// <param name="ephemeris">卫星星历数据</param> /// <param name="frame">参考系</param> public static PathPrimitive CreatePathPrimitiveFromEphemeris(DateMotionCollection <Cartesian> ephemeris, ReferenceFrame frame) { try { List <PathPoint> points = new List <PathPoint>(); for (int i = 0; i < ephemeris.Count; i++) { points.Add(new PathPointBuilder(ephemeris.Values[i], ephemeris.Dates[i], Color.Yellow).ToPathPoint()); } PathPrimitive pathPrimitive = new PathPrimitive(); //pathPrimitive.UpdatePolicy = new DurationPathPrimitiveUpdatePolicy(new Duration(0, 60), PathPrimitiveRemoveLocation.RemoveLocationFront); pathPrimitive.ReferenceFrame = frame; //pathPrimitive.AddRangeToFront(points); pathPrimitive.AddRangeToBack(points); pathPrimitive.Width = 3.0F; SceneManager.Animation.Time = ephemeris.Dates[0]; return(pathPrimitive); } catch (Exception ex) { throw new Exception(ex.Message + "\n" + "向3D图中画卫星轨迹出错!"); } }
//######################################################################################### /// <summary> /// 由T0时刻初始状态,积分dt后的状态,返回最后的状态 /// </summary> /// <param name="dT">积分时长(s)</param> /// <returns>最后时间点位置、速度</returns> public Motion <Cartesian> Propagate(double dT) { // 数据初始化 EphemerisData = new DateMotionCollection <Cartesian>(); //归一化 UnitL = 1.0; UnitT = 1.0; UnitV = 1.0; Step = InitialStepsize; //初始步长 if (IsNormalize) { UnitL = Re; UnitT = Math.Sqrt(UnitL * UnitL * UnitL / Mu); UnitV = UnitL / UnitT; Step = InitialStepsize / UnitT; // 初始步长 } //设置微分方程自变量X[] double[] x = new double[6] { InitialCondition.Value.X / UnitL, InitialCondition.Value.Y / UnitL, InitialCondition.Value.Z / UnitL, InitialCondition.FirstDerivative.X / UnitV, InitialCondition.FirstDerivative.Y / UnitV, InitialCondition.FirstDerivative.Z / UnitV }; // 数值积分 SolveDt(T0 / UnitT, (T0 + dT) / UnitT, x); // 返回最后时间点位置、速度 return(new Motion <Cartesian>(EphemerisData.Values.Last(), EphemerisData.FirstDerivatives.Last())); }
/// <summary> /// Propagate a Platform using a NumericalPropagator configured with the entered KeplerianElements, /// ForceModels, NumericalIntegrator, and start and stop dates. /// </summary> private void PropagateSatellite() { KeplerianElements orbitalElements = m_keplerianOrbitalElementsEntry.KeplerianElementValues; if (orbitalElements == null) { return; } Motion <Cartesian> initialMotion = orbitalElements.ToCartesian(); PropagationNewtonianPoint point = new PropagationNewtonianPoint(m_elementID, m_forceModelSettings.CurrentCentralBody.InertialFrame, initialMotion.Value, initialMotion.FirstDerivative); point.Mass = new ScalarFixed(double.Parse(m_mass.Text)); m_forceModelSettings.SetForceModelsOnPoint(point, new ScalarFixed(double.Parse(m_area.Text))); CentralBody primaryCentralBody = m_forceModelSettings.CurrentCentralBody; NumericalPropagatorDefinition state = new NumericalPropagatorDefinition(); state.IntegrationElements.Add(point); state.Integrator = m_integratorSettings.GetIntegrator(); JulianDate start = new JulianDate(GregorianDate.ParseExact(m_start.Text, DateFormat, null)); JulianDate end = new JulianDate(GregorianDate.ParseExact(m_end.Text, DateFormat, null)); state.Epoch = start; NumericalPropagator propagator = state.CreatePropagator(); propagator.StepTaken += (sender, args) => { // Telling the propagator to stop if we get too close to the central body Cartesian position = propagator.Converter.ConvertState <Cartesian>(m_elementID, args.CurrentState).Value; if (position.Magnitude <= primaryCentralBody.Shape.SemimajorAxisLength + 10000) { args.Indication = PropagationEventIndication.StopPropagationAfterStep; } }; DateMotionCollection <Cartesian> answer = null; var backgroundCalculation = new BackgroundCalculation(); backgroundCalculation.DoWork += (sender, e) => { // actually propagate var result = propagator.Propagate(end.Subtract(start), 1, backgroundCalculation); answer = result.GetDateMotionCollection <Cartesian>(m_elementID); }; backgroundCalculation.ProgressChanged += (sender, e) => m_propagationProgress.Value = e.ProgressPercentage; backgroundCalculation.RunWorkerCompleted += (sender, e) => { // when finished, draw the satellite DrawSatellite(answer, primaryCentralBody.InertialFrame); m_propagate.Enabled = true; }; m_propagate.Enabled = false; backgroundCalculation.RunWorkerAsync(); }
/// <summary> /// Draw the ephemeris in the Insight3D window. /// </summary> /// <param name="ephemeris">The date, position (and velocity) information of the object being displayed.</param> /// <param name="inertialFrame">The inertial frame to display the graphics in.</param> private void DrawSatellite(DateMotionCollection <Cartesian> ephemeris, ReferenceFrame inertialFrame) { // Clean up the previous run's graphics foreach (Primitive primitive in m_primitivesAddedToScene) { SceneManager.Primitives.Remove(primitive); } m_primitivesAddedToScene.Clear(); if (m_platform != null) { m_display.ServiceProviders.Remove(m_platform); } // Draw the orbit List <PathPoint> points = new List <PathPoint>(); for (int i = 0; i < ephemeris.Count; i++) { points.Add(new PathPointBuilder(ephemeris.Values[i], ephemeris.Dates[i]).ToPathPoint()); } PathPrimitive path = new PathPrimitive { ReferenceFrame = inertialFrame }; path.AddRangeToFront(points); SceneManager.Primitives.Add(path); m_primitivesAddedToScene.Add(path); // Put a marker where the satellite is at a given time LagrangePolynomialApproximation interpolationAlgorithm = new LagrangePolynomialApproximation(); TranslationalMotionInterpolator interpolator = new TranslationalMotionInterpolator(interpolationAlgorithm, 2, ephemeris); m_platform = new Platform { LocationPoint = new PointInterpolator(inertialFrame, interpolator) }; Texture2D texture = SceneManager.Textures.FromUri(@"Data\Markers\Satellite.png"); m_platform.Extensions.Add(new MarkerGraphicsExtension(new MarkerGraphics { Texture = new ConstantGraphicsParameter <Texture2D>(texture) })); m_display.ServiceProviders.Add(m_platform); m_display.ApplyChanges(); // Set the date to the start of the ephemeris SceneManager.Animation.Time = ephemeris.Dates[0]; }
/// <summary> /// 从Table表中,创建新的PathPrimitive /// <para>表中提供的位置、速度要与参考系一致</para> /// </summary> /// <param name="dt">表名</param> /// <param name="colNames">表列名称(t,x,y,z,Vx,Vy,Vz)</param> /// <param name="frame">坐标系</param> /// <returns></returns> public static PathPrimitive CreatePathPrimitiveFromTable(DataTable dt, JulianDate jd0, string[] colNames, ReferenceFrame frame) { try { DateMotionCollection <Cartesian> ephemeris = new DateMotionCollection <Cartesian> (); //将Table中的相应参数读入 JulianDate jd; Cartesian R, V; foreach (DataRow dr in dt.Rows) { jd = jd0.AddSeconds((double)dr[colNames[0]]); R = new Cartesian((double)dr[colNames[1]], (double)dr[colNames[2]], (double)dr[colNames[3]]); V = new Cartesian((double)dr[colNames[4]], (double)dr[colNames[5]], (double)dr[colNames[6]]); ephemeris.Add(jd, R, V); } return(CreatePathPrimitiveFromEphemeris(ephemeris, frame)); } catch (Exception ex) { throw new Exception(ex.Message + "\n" + "从Table中创建PathPrimitive出错!"); } }
/// <summary> /// Method to export ephemeris to STK .e file /// </summary> #region ExportEphemeris private void OnExportEphemerisClick(object sender, EventArgs e) { // Open the almanac file SemAlmanac almanac; using (Stream stream = openAlmanacDialog.OpenFile()) using (StreamReader reader = new StreamReader(stream)) { almanac = SemAlmanac.ReadFrom(reader, 1); } // setup the progressbar // GPSElement contains a list of PRNs (PRNList) available in the almanac. progressBar1.Maximum = almanac.Count; progressBar1.Step = 1; // get just the almanac path here. This will allow us to place the new .e files in the same place the almanac was opened from. string outputPath = Path.GetDirectoryName(openAlmanacDialog.FileName); // Create a .e file for every PRN in the element set... foreach (SemAlmanacRecord record in almanac) { // provide a name and path for the new .e file. string filename = String.Format("PRN_{0:00}.e", record.PseudoRandomNumber); string path = outputPath + "\\" + filename; // check that the path exists if (File.Exists(path)) { // ask if it's OK to overwrite existing files. If it's not, advance the progress bar (passed this SV) and continue to the next SV if (MessageBox.Show(string.Format("{0} " + Localization.existsOverwrite, filename), Localization.FileExists, MessageBoxButtons.YesNo) == DialogResult.No) { progressBar1.PerformStep(); continue; } } // ok to overwrite existing files (or no file existed already) // the using block here will use the sw variable to write the .e file stream to. using (StreamWriter writer = File.CreateText(path)) { JulianDate startjd; JulianDate stopjd; // We need to know which time standard to use here. if the user has specified that GPS time is to be used // we need to create the JulianDates with the GlobalPositioningSystemTime standard. if (GPSTimeRadio.Checked) { startjd = new JulianDate(StartTime.Value, TimeStandard.GlobalPositioningSystemTime); stopjd = new JulianDate(StopTime.Value, TimeStandard.GlobalPositioningSystemTime); } else { // otherwise, the default time standard is UTC startjd = new JulianDate(StartTime.Value); stopjd = new JulianDate(StopTime.Value); } // Now that we know the start and stop times for the .e file, we need to propagate the orbits // the NavstarISGps200DPropagator take a Duration type for the timestep - let's create it // using the user-specified timestep value double timestep = double.Parse(TimeStep.Text); Duration timestepDuration = Duration.FromSeconds(timestep); // declare a NavstarISGps200DPropagator - this is used to propagate the satellite positions // assign an instance of the propagator. The propagator constructor takes an almanac element set (for a single satellite) NavstarISGps200DPropagator propagator = new NavstarISGps200DPropagator(record); // now create an StkEphemerisFile object and assign its Ephemeris property the output of the propagator StkEphemerisFile file = new StkEphemerisFile(); DateMotionCollection <Cartesian> ephemeris = propagator.Propagate(startjd, stopjd, timestepDuration, 0, propagator.ReferenceFrame); StkEphemerisFile.EphemerisTimePos ephemerisFormat = new StkEphemerisFile.EphemerisTimePos { CoordinateSystem = propagator.ReferenceFrame, EphemerisData = ephemeris }; file.Data = ephemerisFormat; // write the .e ephemeris to the stream opened in this using block file.WriteTo(writer); } // end of using block // update the progress bar progressBar1.PerformStep(); } // end of PRN List // we're done! Reset the progress bar progressBar1.Value = 0; }