public void Add(MotionEvaluator <Cartesian> evaluator, JulianDate epoch) { Cartesian position = evaluator.Evaluate(epoch); m_noAccessPositions.Add(position); m_satellites.Add(evaluator); }
private void OnTimeChanged(object sender, TimeChangedEventArgs e) { if (m_temeToFixedEvaluator == null) { return; } JulianDate date = e.Time; Matrix3By3 temeToFixed = new Matrix3By3(m_temeToFixedEvaluator.Evaluate(date)); KinematicTransformation transformation = m_fixedToFacilityTopoEvaluator.Evaluate(date, 0); List <int> satellitesToRemove = null; m_satellites.ClearPositions(); for (int i = 0; i < m_satellites.Count; ++i) { MotionEvaluator <Cartesian> satellite = m_satellites.GetSatellite(i); try { // Update position of marker representing this satellite Cartesian position = satellite.Evaluate(date).Rotate(temeToFixed); // Compute access from satellite to facility if (m_showAccess) { Cartesian positionInTopo = transformation.Transform(position); AzimuthElevationRange azimuthElevationRange = new AzimuthElevationRange(positionInTopo); m_satellites.AppendPosition(position, azimuthElevationRange.Elevation > 0.0); } else { m_satellites.AppendPosition(position, false); } } catch (Exception) { if (satellitesToRemove == null) { satellitesToRemove = new List <int>(); } satellitesToRemove.Add(i); } } // Remove satellites that could not be evaluated if (satellitesToRemove != null) { m_satellites.RemoveUsingIndexList(satellitesToRemove); SetText(m_satellites.Count); } m_satellites.SetMarkerBatches(); }
/// <summary> /// Method to calculate all the data required for the graphs. /// </summary> private void OnAddReceiverClick(object sender, EventArgs e) { #region CreateAndConfigureReceiver // Let's create the GPSReceiver. The receiver stores many properties and has a defined location. This location // is the point of reference for visibility calculations. receiver = new GpsReceiver(); // add receiver to the tree TreeNode newNode = new TreeNode(Localization.Receiver); rootNode.Nodes.Add(newNode); // Easy reference to Earth Central body used to initialize the ElevationAngleAccessConstraint and // to calculate the Az/El/Range Data. EarthCentralBody earth = CentralBodiesFacet.GetFromContext().Earth; // set the receiver properties based on user selections // The receiver has a receiver FrontEnd that contains the visibility and tracking constraints // Be sure to convert your angles to Radians! double minimumAngle = Trig.DegreesToRadians(Double.Parse(MaskAngle.Text)); receiver.ReceiverConstraints.Clear(); receiver.ReceiverConstraints.Add(new ElevationAngleConstraint(earth, minimumAngle)); receiver.NumberOfChannels = (int)NumberOfChannels.Value; receiver.NoiseModel = new ConstantGpsReceiverNoiseModel(0.8); // The receiver's methods of reducing the number of visible satellites to the limit imposed by the number of channels if (BestNSolType.Checked) { receiver.ReceiverSolutionType = GpsReceiverSolutionType.BestN; } else { receiver.ReceiverSolutionType = GpsReceiverSolutionType.AllInView; } // create a new location for the receiver by using the Cartographic type from AGI.Foundation.Coordinates // again, remember to convert from degrees to Radians! (except the height of course) Cartographic position = new Cartographic(Trig.DegreesToRadians(double.Parse(Longitude.Text)), Trig.DegreesToRadians(double.Parse(Latitude.Text)), double.Parse(ReceiverHeight.Text)); // Now create an antenna for the GPS receiver. We specify the location of the antenna by assigning a // PointCartographic instance to the LocationPoint property. We specify that the antenna should be oriented // according to the typically-used East-North-Up axes by assigning an instance of AxesEastNorthUp to // the OrientationAxes property. While the orientation of the antenna won't affect which satellites are visible // or tracked in this case, it will affect the DOP values. For example, the EDOP value can be found in // DilutionOfPrecision.X, but only if we've configured the antenna to use East-North-Up axes. PointCartographic antennaLocationPoint = new PointCartographic(earth, position); Platform antenna = new Platform { LocationPoint = antennaLocationPoint, OrientationAxes = new AxesEastNorthUp(earth, antennaLocationPoint) }; receiver.Antenna = antenna; #endregion // update the tree to reflect the correct receiver info newNode.Nodes.Add(new TreeNode(string.Format(Localization.FixedMaskAngle + "= {0:0.00} " + Localization.degrees, MaskAngle.Text))); newNode.Nodes.Add(new TreeNode(string.Format(Localization.NumberOfChannels + "= {0}", NumberOfChannels.Value))); newNode.Nodes.Add(new TreeNode(string.Format(Localization.SolutionType + "= {0}", receiver.ReceiverSolutionType == GpsReceiverSolutionType.AllInView ? Localization.AllInView : Localization.BestN))); newNode.Nodes.Add(new TreeNode(string.Format(Localization.Latitude + "= {0:0.000000} " + Localization.degrees, Latitude.Text))); newNode.Nodes.Add(new TreeNode(string.Format(Localization.Longitude + "= {0:0.000000} " + Localization.degrees, Longitude.Text))); newNode.Nodes.Add(new TreeNode(string.Format(Localization.Height + "= {0:0.000} " + Localization.meters, ReceiverHeight.Text))); rootNode.Expand(); newNode.Expand(); #region CalculateDataForGraphs // Now, we'll open the almanac SemAlmanac almanac; using (Stream stream = openAlmanacDialog.OpenFile()) using (StreamReader reader = new StreamReader(stream)) { // Read the SEM almanac from an almanac stream reader. almanac = SemAlmanac.ReadFrom(reader, 1); } // Now create a PlatformCollection to hold GpsSatellite object instances. The SemAlmanac method CreateSatellitesFromRecords returns // just such a collection. We'll use this set of satellites as the set from which we'll try and track. There is a // GpsSatellite object for each satellite specified in the almanac. PlatformCollection gpsSatellites = almanac.CreateSatelliteCollection(); // We provide the receiver with the complete set of gpsSatellites to consider for visibility calculations. // This is usually all SVs defined in the almanac - however you may want to remove SVs that aren't healthy. This can // be done by creating the gpsSatellites collection above using another version of the CreateSatellitesFromRecords method that // takes a SatelliteOutageFileReader. receiver.NavigationSatellites = gpsSatellites; // Optimization opportunity: Add the following code in a thread. This will help for long duration analyses. // Now that we have the receiver and location setup, we need to evaluate all the pertinent data. // using a SatelliteTrackingEvaluator, we can track satellites and using a DOP Evaluator, // we can calculate DOP at a specified time. // The receiver's GetSatelliteTrackingEvaluator method will provide a SatelliteTrackingEvaluator for you. // Similarly, the GetDilutionOfPrecisionEvaluator provides the DOP evaluator. // We create all evaluators in the same EvaluatorGroup for the best performance. EvaluatorGroup group = new EvaluatorGroup(); Evaluator <int[]> satTrackingEvaluator = receiver.GetSatelliteTrackingIndexEvaluator(group); Evaluator <DilutionOfPrecision> dopEvaluator = receiver.GetDilutionOfPrecisionEvaluator(group); // We also need to create an evaluator to compute Azimuth/Elevation for each of the SVs MotionEvaluator <AzimuthElevationRange>[] aerEvaluators = new MotionEvaluator <AzimuthElevationRange> [gpsSatellites.Count]; for (int i = 0; i < gpsSatellites.Count; ++i) { Platform satellite = receiver.NavigationSatellites[i]; VectorTrueDisplacement vector = new VectorTrueDisplacement(antenna.LocationPoint, satellite.LocationPoint); aerEvaluators[i] = earth.GetAzimuthElevationRangeEvaluator(vector, group); } // First we'll initialize the data structures used to plot the data for (int i = 0; i < DOPData.Length; i++) { // PointPairList is defined in the ZedGraph reference DOPData[i] = new PointPairList(); } // 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 we''ll create the variables we'll need for iterating through time. // The propagator requires a Duration type be used to specify the timestep. Duration dur = stopjd - startjd; double timestep = Double.Parse(TimeStep.Text); // Initialize the progressbar with appropriate values progressBar1.Maximum = (int)dur.TotalSeconds; progressBar1.Step = (int)timestep; // now we'll iterate through time by adding seconds to the start time JulianDate // creating a new JulianDate 'evaluateTime' each time step. for (double t = 0; t <= dur.TotalSeconds; t += timestep) { JulianDate evaluateTime = startjd.AddSeconds(t); // The string 'trackedSVs' is the start of a string we'll continue to build through this time // iteration. It will contain the info we'll need to put in the DOP graph tooltips for the different // DOP series (VDOP, HDOP, etc.) String trackedSVs = Localization.Tracked + ": "; // The evaluator method GetTrackedSatellites will take the current time and the initial list of satellites and // determine which satellites can be tracked based on the receiver constraints setup earlier. This method // returns a PlatformCollection object as well (though we'll cast each member of the Collection to a GPSSatellite type) int[] trackedSatellites = satTrackingEvaluator.Evaluate(evaluateTime); foreach (int satelliteIndex in trackedSatellites) { Platform satellite = receiver.NavigationSatellites[satelliteIndex]; // Now we have access to a Platform object representing a GPS satellite and calculate the azimuth and elevation // of each. Note that we're just calculating the azimuth and elevation, but could just as easily get the // range as well. AzimuthElevationRange aer = aerEvaluators[satelliteIndex].Evaluate(evaluateTime); // Get the GpsSatelliteExtension attached to the platform. The extension extends a // platform with GPS-specific information. In this case, we need the // satellites PRN. GpsSatelliteExtension extension = satellite.Extensions.GetByType <GpsSatelliteExtension>(); // Create two separate PointPairLists to hold the data stored by Time and Azimuth PointPairList thisTimePointList, thisAzPointList; // Before we can arbitrarily create new PointPair Lists, we have to see if the Data Storage structures already contain a list // for this PRN. // The variables AzElData_TimeBased and AzElData_AzimuthBased are dictionaries that hold the PointPairLists using the PRN // as a key. We use this structure to store a large amount of data for every satellite in a single, easy to access, variable. // if the satellite we're currently looking at already has a list defined in the dictionary, we'll use that one, otherwise // we'll create a new list if (AzElData_TimeBased.ContainsKey(extension.PseudoRandomNumber)) { thisTimePointList = AzElData_TimeBased[extension.PseudoRandomNumber]; AzElData_TimeBased.Remove(extension.PseudoRandomNumber); } else { thisTimePointList = new PointPairList(); } if (AzElData_AzimuthBased.ContainsKey(extension.PseudoRandomNumber)) { thisAzPointList = AzElData_AzimuthBased[extension.PseudoRandomNumber]; AzElData_AzimuthBased.Remove(extension.PseudoRandomNumber); } else { thisAzPointList = new PointPairList(); } // Now to get the actual Azimuth and elevation data // Converting your Radians to degrees here makes the data appear in a more readable format. We also constrain the azimuth // to be within the interval [0, 2*pi] double azimuth = Trig.RadiansToDegrees(Trig.ZeroToTwoPi(aer.Azimuth)); double elevation = Trig.RadiansToDegrees(aer.Elevation); #endregion // now create the point for the Azimuth based data PointPair thisAzPoint = new PointPair(azimuth, elevation); // and add the tooltip (ZedGraph uses the Tag property on a PointPair for the tooltip on that datapoint ) thisAzPoint.Tag = String.Format("PRN {0}, {1}, " + Localization.Az + ": {2:0.000}, " + Localization.El + ": {3:0.000}", extension.PseudoRandomNumber, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), azimuth, elevation); // and finally add this point to the list thisAzPointList.Add(thisAzPoint); // now we'll do the same for the time-based data, instead of adding the Az and El, we'll add the time and El. // Create a new XDate object to store the time for this point double txd = (double)new XDate(evaluateTime.ToDateTime()); // add the time and elevation data to this point PointPair thisTimePoint = new PointPair(txd, Trig.RadiansToDegrees(aer.Elevation)); // Create the tooltip tag thisTimePoint.Tag = String.Format("PRN {0}, {1}, " + Localization.Az + ": {2:0.000}, " + Localization.El + ": {3:0.000}", extension.PseudoRandomNumber, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), azimuth, elevation); // finally add this point to the list thisTimePointList.Add(thisTimePoint); //Now that this data is all calculated, we'll add the point lists to the correct data structures for the GpsSatellite we're working with AzElData_TimeBased.Add(extension.PseudoRandomNumber, thisTimePointList); AzElData_AzimuthBased.Add(extension.PseudoRandomNumber, thisAzPointList); // now update the 'trackedSVs' string to be used for the DOP data tooltip // wee need to do this inside the GpsSatellite loop because we need to get the entire list of tracked SVs for this time step. // we won't use this string until we're out of the loop however. trackedSVs += extension.PseudoRandomNumber.ToString() + ", "; } // now we're out of the GpsSatellite loop, we'll do some string manipulation to get the tooltip for the DOP data. // (gets rid of the last inserted comma) string svs = trackedSVs.Substring(0, trackedSVs.LastIndexOf(' ') - 1); try { // Now we use the evaluator to calculate the DilutionOfPrecision for us for this timestep DilutionOfPrecision dop = dopEvaluator.Evaluate(evaluateTime); // if the dop object throws an exception, there aren't enough tracked satellites to form a navigation solution (typically < 4 tracked) // in that case we leave the data for this time unfilled. The graph will then have empty spots for this time. // Here we create a new PointPair and a new XDate to add to the X-Axis PointPair pp; double txd = (double)new XDate(evaluateTime.ToDateTime()); // add the East DOP value and the time to the PointPair and set the tooltip tag property for this series. pp = new PointPair(txd, dop.X); pp.Tag = String.Format("{0}\n{1} " + Localization.EDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.X); // add the point to the 0th element of the DOPData structure DOPData[0].Add(pp); // repeat for North DOP pp = new PointPair(txd, dop.Y); pp.Tag = String.Format("{0}\n{1} " + Localization.NDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.Y); DOPData[1].Add(pp); // repeat for the Vertical DOP pp = new PointPair(txd, dop.Z); pp.Tag = String.Format("{0}\n{1} " + Localization.VDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.Z); DOPData[2].Add(pp); // repeat for the Horizontal DOP pp = new PointPair(txd, dop.XY); pp.Tag = String.Format("{0}\n{1} " + Localization.HDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.XY); DOPData[3].Add(pp); // repeat for the Position DOP pp = new PointPair(txd, dop.Position); pp.Tag = String.Format("{0}\n{1} " + Localization.PDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.Position); DOPData[4].Add(pp); // repeat for the Time DOP pp = new PointPair(txd, dop.Time); pp.Tag = String.Format("{0}\n{1} " + Localization.TDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.Time); DOPData[5].Add(pp); // repeat for the Geometric DOP pp = new PointPair(txd, dop.Geometric); pp.Tag = String.Format("{0}\n{1} " + Localization.GDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.Geometric); DOPData[6].Add(pp); // Notice here that the different DOP values (East, North, etc) were denoted by the dop.X, dop.Y etc. This is because the // DOP values could be in any coordinate system. In our case, we're in the ENU coordinate system an X represents East, Y // represents North, Z represents Vertical, XY represents horizontal. You can change the reference frame the DOP is reported in // but you will then have to understand that the dop.X value corresponds to your X-defined axis and so on. } catch { // Do Nothing here - we just won't add the data to the data list } // update the progress bar - we're done with this time step! progressBar1.PerformStep(); } // finally update the graphs UpdateDopGraph(); updateAzElGraph(); // reset the progress bar progressBar1.Value = 0; // and set the appropriate button states SetControlStates(true); }