/// <summary> /// Load TLEs from a satellite database and create marker primitives for each satellite /// </summary> private void CreateSatellites(string fileName) { m_satellites.Clear(); JulianDate?epoch = null; StkSatelliteDatabase db = new StkSatelliteDatabase(GetDataFilePath("SatelliteDatabase"), fileName); foreach (StkSatelliteDatabaseEntry entry in db.GetEntries()) { if (entry.TwoLineElementSet != null) { Sgp4Propagator propagator = new Sgp4Propagator(entry.TwoLineElementSet); if (epoch == null) { epoch = propagator.InitialConditions.Epoch; } Duration epochDifference = epoch.Value - propagator.InitialConditions.Epoch; if (epochDifference < Duration.FromDays(1)) { m_satellites.Add(propagator.GetEvaluator(), entry.TwoLineElementSet.Epoch); } } } SetText(m_satellites.Count); JulianDate time = epoch.Value.ToTimeStandard(TimeStandard.InternationalAtomicTime); // Set epoch time m_animation.Pause(); m_animation.StartTime = time; m_animation.EndTime = time.AddDays(1.0); m_animation.Time = time; m_animation.PlayForward(); }
/// <summary> /// Creates a new instance with the provided properties. /// </summary> public IridiumSatellite(string name, IEnumerable <TwoLineElementSet> tles, Font font, double targetFrequency) { var earth = CentralBodiesFacet.GetFromContext().Earth; //Set the name and create the point from the TLE. Name = name; LocationPoint = new Sgp4Propagator(tles).CreatePoint(); OrientationAxes = new AxesVehicleVelocityLocalHorizontal(earth.InertialFrame, LocationPoint); //Create a transceiver modeled after Iridium specs. m_transceiver = new Transceiver { Name = Name + " Transceiver", Modulation = new ModulationQpsk(), OutputGain = 100.0, OutputNoiseFactor = 1.2, CarrierFrequency = targetFrequency, Filter = new RectangularFilter { Frequency = targetFrequency, UpperBandwidthLimit = 20.0e6, LowerBandwidthLimit = -20.0e6 }, InputAntennaGainPattern = new GaussianGainPattern(1.0, 0.55, 0.001), OutputAntennaGainPattern = new GaussianGainPattern(1.0, 0.55, 0.001) }; m_transceiver.InputAntenna.LocationPoint = new PointFixedOffset(ReferenceFrame, new Cartesian(0, -1.0, 0)); m_transceiver.OutputAntenna.LocationPoint = new PointFixedOffset(ReferenceFrame, new Cartesian(0, +1.0, 0)); // setup Marker graphics for the satellites var satelliteTexture = SceneManager.Textures.FromUri(Path.Combine(Application.StartupPath, "Data/Markers/smallsatellite.png")); m_markerGraphicsExtension = new MarkerGraphicsExtension(new MarkerGraphics { Texture = new ConstantGraphicsParameter <Texture2D>(satelliteTexture), DisplayParameters = new DisplayParameters { // hide marker when camera is closer than the below distance MinimumDistance = new ConstantGraphicsParameter <double>(17500000.0) } }); Extensions.Add(m_markerGraphicsExtension); // setup Model graphics for the satellites var modelUri = new Uri(Path.Combine(Application.StartupPath, "Data/Models/iridium.mdl")); m_modelGraphicsExtension = new ModelGraphicsExtension(new ModelGraphics { Uri = new ConstantGraphicsParameter <Uri>(modelUri), Scale = new ConstantGraphicsParameter <double>(50000.0), DisplayParameters = new DisplayParameters { // hide model when camera is further than the marker minimum distance above MaximumDistance = m_markerGraphicsExtension.MarkerGraphics.DisplayParameters.MinimumDistance } }); Extensions.Add(m_modelGraphicsExtension); // setup text graphics for the satellites m_textGraphicsExtension = new TextGraphicsExtension(new TextGraphics { Color = new ConstantGraphicsParameter <Color>(Color.Red), Font = new ConstantGraphicsParameter <Font>(font), Outline = new ConstantGraphicsParameter <bool>(true), OutlineColor = new ConstantGraphicsParameter <Color>(Color.Black), Text = new ConstantGraphicsParameter <string>(Name), Origin = new ConstantGraphicsParameter <Origin>(Origin.TopCenter), PixelOffset = new ConstantGraphicsParameter <PointF>(new PointF(0, -satelliteTexture.Template.Height / 2)) }); if (TextureFilter2D.Supported(TextureWrap.ClampToEdge)) { m_textGraphicsExtension.TextGraphics.TextureFilter = new ConstantGraphicsParameter <TextureFilter2D>(TextureFilter2D.NearestClampToEdge); } Extensions.Add(m_textGraphicsExtension); }
/// <summary> /// Create a Platform for the requested satellite using a TLE for position. /// The satellite will be visually represented by a labeled glTF model, /// the satellite's orbit will be shown, and vectors will be drawn for /// the body axes of the satellite, plus a vector indicating the direction /// of the sun. /// </summary> private void CreateSatellite() { // Get the current TLE for the given satellite identifier. var tleList = TwoLineElementSetHelper.GetTles(m_satelliteIdentifier, JulianDate.Now); // Use the epoch of the first TLE, since the TLE may have been loaded from offline data. m_epoch = tleList[0].Epoch; // Propagate the TLE and use that as the satellite's location point. var locationPoint = new Sgp4Propagator(tleList).CreatePoint(); m_satellite = new Platform { Name = "Satellite " + m_satelliteIdentifier, LocationPoint = locationPoint, // Orient the satellite using Vehicle Velocity Local Horizontal (VVLH) axes. OrientationAxes = new AxesVehicleVelocityLocalHorizontal(m_earth.FixedFrame, locationPoint), }; // Set the identifier for the satellite in the CZML document. m_satellite.Extensions.Add(new IdentifierExtension(m_satelliteIdentifier)); // Configure a glTF model for the satellite. m_satellite.Extensions.Add(new ModelGraphicsExtension(new ModelGraphics { // Link to a binary glTF file. Model = new CesiumResource(GetModelUri("satellite.glb"), CesiumResourceBehavior.LinkTo), // By default, Cesium plays all animations in the model simultaneously, which is not desirable. RunAnimations = false, })); // Configure a label for the satellite. m_satellite.Extensions.Add(new LabelGraphicsExtension(new LabelGraphics { // Use the name of the satellite as the text of the label. Text = m_satellite.Name, // Change the color of the label after 12 hours. This demonstrates specifying that // a value varies over time using intervals. FillColor = new TimeIntervalCollection <Color> { // Green for the first half day... new TimeInterval <Color>(JulianDate.MinValue, m_epoch.AddDays(0.5), Color.Green, true, false), // Red thereafter. new TimeInterval <Color>(m_epoch.AddDays(0.5), JulianDate.MaxValue, Color.Red, false, true), }, // Only show label when camera is far enough from the satellite, // to avoid visually clashing with the model. DistanceDisplayCondition = new Bounds(1000.0, double.MaxValue), })); // Configure graphical display of the orbital path of the satellite. m_satellite.Extensions.Add(new PathGraphicsExtension(new PathGraphics { // Configure the visual appearance of the line. Material = new PolylineOutlineMaterialGraphics { Color = Color.White, OutlineWidth = 1.0, OutlineColor = Color.Black, }, Width = 2.0, // Lead and Trail time indicate how much of the path to render. LeadTime = Duration.FromMinutes(44.0).TotalSeconds, TrailTime = Duration.FromMinutes(44.0).TotalSeconds, })); // Create vectors for the X, Y, and Z axes of the satellite. m_satelliteXAxis = CreateAxesVector(m_satellite, CartesianElement.X, Color.Green, "SatelliteX"); m_satelliteYAxis = CreateAxesVector(m_satellite, CartesianElement.Y, Color.Red, "SatelliteY"); m_satelliteZAxis = CreateAxesVector(m_satellite, CartesianElement.Z, Color.Blue, "SatelliteZ"); // Create a vector from the satellite to the Sun. // Compute the vector from the satellite's location to the Sun's center of mass. var sunCenterOfMassPoint = CentralBodiesFacet.GetFromContext().Sun.CenterOfMassPoint; var vectorSatelliteToSun = new VectorTrueDisplacement(m_satellite.LocationPoint, sunCenterOfMassPoint); // Create the visual vector. m_satelliteSunVector = new GraphicalVector { LocationPoint = m_satellite.LocationPoint, Vector = vectorSatelliteToSun, VectorGraphics = new VectorGraphics { Length = 5.0, Color = Color.Yellow, }, }; // Set the identifier for the vector in the CZML document. m_satelliteSunVector.Extensions.Add(new IdentifierExtension("SunVector")); // Orient the solar panels on the satellite model to point at the sun. var satelliteYVector = m_satellite.OrientationAxes.GetVectorElement(CartesianElement.Y); // allow only Z axis to rotate to follow sun vector. Constrain sun vector to Y, and satellite Y vector to X. var constrainedAxes = new AxesAlignedConstrained(satelliteYVector, AxisIndicator.First, vectorSatelliteToSun, AxisIndicator.Second); // Satellite axes are Vehicle Velocity Local Horizontal (VVLH) axes, where X is forward and Z is down, // but Cesium model axes are Z forward, Y up. So, create an axes rotates to the Cesium model axes. var offset = new UnitQuaternion(new ElementaryRotation(AxisIndicator.First, -Math.PI / 2)) * new UnitQuaternion(new ElementaryRotation(AxisIndicator.Third, Math.PI / 2)); var cesiumModelAxes = new AxesFixedOffset(m_satellite.OrientationAxes, offset); // The rotation will be from the Cesium model axes to the constrained axes. var solarPanelRotationAxes = new AxesInAxes(constrainedAxes, cesiumModelAxes); // Add a node transformation to rotate the SolarPanels node of the model. m_satellite.Extensions.GetByType <ModelGraphicsExtension>().ModelGraphics.NodeTransformations = new Dictionary <string, NodeTransformationGraphics> { { "SolarPanels", new NodeTransformationGraphics { Rotation = new AxesCesiumProperty(solarPanelRotationAxes) } } }; }