Created
June 6, 2019 22:09
-
-
Save mksquires/1e83e9d0fae05ad7ea32922c674c943c to your computer and use it in GitHub Desktop.
An example of STK Components in C# with Radar and Tracking
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void ExampleOfTrackingWithRadar() | |
{ | |
// An example using STK Components in C# . Radar analysis with a tracked aircraft. | |
// This example snippet (NUnit test) features the following mission requirements: | |
// - Target aircraft position updated externally from live data which we will simulate | |
// - Transmitter to receiver Power | |
// - Mitchell-Walker probability of detection | |
// - ~34 Radar, 1 aircraft | |
// - ~7Hz analysis rate | |
// Note- This architecture can handle additional aircraft. | |
// basic setup steps | |
ExampleEntity.RegisterEntityClass(); | |
var earth = CentralBodiesFacet.GetFromContext().Earth; | |
var now = JulianDate.Now; | |
var analysisInterval = new TimeInterval(now, now.AddMinutes(1.0)); | |
int numberOfRadars = 34; | |
var context = new TransactionContext(); | |
// we arrange in a circle about Central Park | |
var centralParkManhattan = new Cartographic(Trig.DegreesToRadians(-73.968285), Trig.DegreesToRadians(40.785091), 0.0); | |
var initialAircraftPosition = new Cartographic(Trig.DegreesToRadians(-73.968285), Trig.DegreesToRadians(40.785091), 1000); | |
// create TrackingLibrary aircraft | |
var aircraftEntity = new ExampleEntity(context, "UAV_1"); | |
var aircraftParameter = new EntityParameter<ExampleEntity>(); | |
var aircraft = new Platform | |
{ | |
LocationPoint = new EntityPoint<ExampleEntity>(aircraftParameter), | |
OrientationAxes = new EntityAxes<ExampleEntity>(aircraftParameter) // we wind up not using this, but we could use this to set live orientation data | |
}; | |
context.DoTransactionally(transaction => | |
{ | |
aircraftEntity.LastUpdate.SetValue(transaction, now); | |
aircraftEntity.Position.SetValue(transaction, earth.Shape.CartographicToCartesian(initialAircraftPosition)); | |
}); | |
AddRadarTargetExtensions(aircraft, earth); | |
// use this as the target platform in AddTransmitterExtensions and AddReceiverExtensions to effectively turn off targeting | |
var fixedLocationPlatform = new Platform("fixedLocation"); | |
fixedLocationPlatform.LocationPoint = new PointCartographic(earth, initialAircraftPosition); | |
// Create some spiffy radars | |
var radarPlatforms = Enumerable.Range(0, numberOfRadars).Select(index => | |
{ | |
var radar = new MonostaticRadar(); | |
var geodesic = new EllipsoidGeodesic(earth.Shape, centralParkManhattan, (double)index / numberOfRadars * Constants.TwoPi, 10000.0); // 10Km distance | |
radar.Transmitter = new Platform(string.Format("radar transmitter {0}", index)); | |
radar.Receiver = new Platform(string.Format("radar receiver {0}", index)); | |
// location | |
radar.Transmitter.LocationPoint = new PointCartographic(earth, geodesic.FinalPoint); | |
radar.Receiver.LocationPoint = new PointCartographic(earth, geodesic.FinalPoint); | |
// add transmitter and receiver extensions (including orientation axes) | |
AddTransmitterExtensions(radar.Transmitter, aircraft, earth); | |
AddReceiverExtensions(radar.Receiver, aircraft, earth); | |
return radar; | |
}).ToList(); | |
// create analysis scalars | |
var analysisScalars = Enumerable.Range(0, numberOfRadars).Select(index => | |
{ | |
var scalars = new RadarScalars(); | |
var transmitterToTargetLink = new LinkSpeedOfLight(radarPlatforms[index].Transmitter, aircraft, earth.InertialFrame); | |
transmitterToTargetLink.Extensions.Add(new WirelessLinkExtension()); // default propagation models. change to desired models | |
var targetToReceiverLink = new LinkSpeedOfLight(aircraft, radarPlatforms[index].Receiver, earth.InertialFrame); | |
targetToReceiverLink.Extensions.Add(new WirelessLinkExtension()); | |
var propagationGraph = new SignalPropagationGraph(); | |
propagationGraph.AddLink(transmitterToTargetLink); | |
propagationGraph.AddLink(targetToReceiverLink); | |
IntendedSignalStrategy intendedSignalStrategy = new IntendedSignalByTransmitter(radarPlatforms[index].Transmitter); | |
scalars.ripScalar = new TransmitterToTargetReceivedIsotropicPowerScalar(radarPlatforms[index].Transmitter, aircraft, radarPlatforms[index].Receiver, intendedSignalStrategy, propagationGraph); | |
scalars.mwScalar = new MitchellWalkerProbabilityOfDetectionScalar(radarPlatforms[index].Transmitter, aircraft, radarPlatforms[index].Receiver, intendedSignalStrategy, propagationGraph); | |
return scalars; | |
}).ToList(); | |
// create all needed evaluators | |
var group = new EvaluatorGroup(); | |
var analysisScalarEvaluators = Enumerable.Range(0, numberOfRadars).Select(index => | |
{ | |
var evaluators = new RadarScalarEvaluators(); | |
var mwEvaluator = analysisScalars[index].mwScalar.GetEvaluator(group); | |
evaluators.MwScalarEvaluator = group.Parameterize(mwEvaluator, TransactionParameter.Instance, aircraftParameter); | |
var ripEvaluator = analysisScalars[index].ripScalar.GetEvaluator(group); | |
evaluators.RipScalarEvaluator = group.Parameterize(ripEvaluator, TransactionParameter.Instance, aircraftParameter); | |
return evaluators; | |
}).ToList(); | |
// run live analysis | |
var timeStep = Duration.FromSeconds(0.142); | |
int circleDivisions = 360; | |
// simulate a route | |
var aircraftRoute = new Cartesian[circleDivisions]; | |
for (int i = 0; i < circleDivisions; i++) | |
{ | |
var geodesic = new EllipsoidGeodesic(earth.Shape, centralParkManhattan, (double)i / circleDivisions * Constants.TwoPi, 1000.0); // 1Km distance | |
var position = earth.Shape.CartographicToCartesian(geodesic.FinalPoint); | |
aircraftRoute[i] = position; | |
} | |
// this loop represents simulating updating the position of the aircraft and performing the analysis at a rate of ~7Hz (see the timestep above) | |
int div = 0; | |
for (JulianDate date = analysisInterval.Start; date < analysisInterval.Stop; date += timeStep) | |
{ | |
context.DoTransactionally(transaction => | |
{ | |
// update position & stamp with date of last update | |
aircraftEntity.LastUpdate.SetValue(transaction, date); | |
aircraftEntity.Position.SetValue(transaction, aircraftRoute[div]); | |
Console.WriteLine("-----"); | |
Console.WriteLine(" Time " + date + "Aircraft " + aircraftEntity.CallSign + " Position " + aircraftEntity.Position.GetValue(transaction)); | |
for (int i = 0; i < numberOfRadars; i++) | |
{ | |
double ripResults = analysisScalarEvaluators[i].RipScalarEvaluator.Evaluate(date, transaction, aircraftEntity); | |
double mwResults = analysisScalarEvaluators[i].MwScalarEvaluator.Evaluate(date, transaction, aircraftEntity); | |
Console.WriteLine(" Radar Station " + i + | |
" MW PDet " + mwResults + " RIP " + CommunicationAnalysis.ToDecibels(ripResults)); | |
} | |
Console.WriteLine("-----"); | |
div = (div + 1) % circleDivisions; | |
}); | |
} | |
} | |
/// <summary> | |
/// Decorates the platform> that is a radar target. | |
/// </summary> | |
/// <param name="targetPlatform">The platform representing the radar target.</param> | |
/// <param name="earth">The Earth.</param> | |
public void AddRadarTargetExtensions(Platform targetPlatform, CentralBody earth) | |
{ | |
SwerlingTargetModel aircraftSwerlingModel = SwerlingTargetModel.II; | |
// we use this frame to fake velocity from points in ECEF. Normally you would use FixedFrame | |
targetPlatform.OrientationAxes = new AxesVehicleVelocityLocalHorizontal(earth.InertialFrame, targetPlatform.LocationPoint); | |
double[] clockAngles = { 0.0, Constants.HalfPi, Math.PI, Constants.ThreeHalvesPi }; | |
double[] rcsCoeffs = { 20.0, 10.0, 0.0, 10.0 }; | |
var sphericalCrossSection = new SphericalTabularMonostaticCrossSectionScatteringCoefficient(clockAngles, rcsCoeffs); | |
// Construct the radar cross section platform extension with a constant cross section coefficient | |
var targetExtension = new TargetRadarCrossSectionExtension(sphericalCrossSection); | |
//Additional signal data can be added to each frequency band which will be added to the processed reflected signal, which can be discovered by downstream processors. Below we are | |
//adding a data structure to the signal data which indicates the frequency band Swerling case of this target, used by the downstream Mitchell-Walker probability-of-detection algorithm. | |
targetExtension.FrequencyBands[0].SignalData.Add(new SignalSwerlingTargetModel(aircraftSwerlingModel)); | |
targetPlatform.Extensions.Add(targetExtension); | |
} | |
/// <summary> | |
/// Decorates a radar receiver platform with the necessary items needed to receive radar signals. | |
/// </summary> | |
/// <param name="receiverPlatform">The platform that represents the radar receiver.</param> | |
/// <param name="targetPlatform">The target platform. This is used for active targeting only.</param> | |
/// <param name="earth">The Earth.</param> | |
public void AddReceiverExtensions(Platform receiverPlatform, Platform targetPlatform, CentralBody earth) | |
{ | |
int pulseCount = 20; | |
double wavelength = 0.1; //meters | |
double frequency = Constants.SpeedOfLight / wavelength; | |
double pulseRepetitionFrequency = 1.0e6; | |
double pulseWidth = 1 / (2 * pulseRepetitionFrequency); | |
double noiseBandwidth = 1.0 / pulseWidth; | |
double halfNoiseBandwidth = noiseBandwidth / 2.0; | |
double lowNoiseAmplifierGain = 1e4; | |
double antennaNoiseTemperature = 290.0; | |
double antennaDiameter = 3.0; //meters; | |
double antennaEfficiency = 0.8; | |
double antennaBacklobeGain = 0.001; | |
// use AxesAlignedConstrained axes type | |
var earthZaxis = new VectorFixed(earth.FixedFrame.Axes, UnitCartesian.UnitZ); | |
Axes targetTrackingAxes = new AxesAlignedConstrained(new VectorTrueDisplacement(targetPlatform.LocationPoint, | |
receiverPlatform.LocationPoint), AxisIndicator.Third, earthZaxis, AxisIndicator.First); | |
receiverPlatform.OrientationAxes = targetTrackingAxes; | |
var parabolicGainPattern = new ParabolicGainPattern(antennaDiameter, antennaEfficiency, antennaBacklobeGain); | |
// we configure the extension that we will add to the platform | |
var receiverAntennaExtension = new RadarReceivingAntennaExtension(parabolicGainPattern, antennaNoiseTemperature); | |
receiverPlatform.Extensions.Add(receiverAntennaExtension); | |
var filter = new RectangularFilter(receiverAntennaExtension.OutputSignalProcessor, 0.0, frequency, -halfNoiseBandwidth, halfNoiseBandwidth); | |
// low noise amplifier | |
var lowNoiseAmplifier = new ConstantGainAmplifier(filter, lowNoiseAmplifierGain); | |
// configure signal output extension | |
var signalOutput = new SignalOutputExtension(lowNoiseAmplifier); | |
receiverPlatform.Extensions.Add(signalOutput); | |
// process the received radar signal | |
var waveformIntegrator = new PerfectFixedNumberOfPulsesWaveformIntegrator(pulseCount); | |
waveformIntegrator.AttachSignalProcessorAsInput(lowNoiseAmplifier); | |
var processedWaveformOutput = new ProcessedRadarWaveformOutputExtension(waveformIntegrator); | |
receiverPlatform.Extensions.Add(processedWaveformOutput); | |
} | |
/// <summary> | |
/// Decorates a transmitter platform with the necessary items to transmit radar signals. | |
/// </summary> | |
/// <param name="transmitterPlatform">The platform that represents the radar transmitter.</param> | |
/// <param name="targetPlatform">The target platform. This is used for active targeting only.</param> | |
/// <param name="earth">The Earth.</param> | |
public void AddTransmitterExtensions(Platform transmitterPlatform, Platform targetPlatform, CentralBody earth) | |
{ | |
//Transmit waveform properties. | |
double pulseRepetitionFrequency = 1.0e6; | |
double pulseWidth = 1 / (2 * pulseRepetitionFrequency); | |
int pulseCount = 20; | |
//Transmitter properties | |
double wavelength = 0.1; //meters | |
double frequency = Constants.SpeedOfLight / wavelength; | |
double amplifierGain = 1e4; | |
double antennaDiameter = 3.0; //meters; | |
double antennaEfficiency = 0.8; | |
double antennaBacklobeGain = 0.001; | |
var parabolicGainPattern = new ParabolicGainPattern(antennaDiameter, antennaEfficiency, | |
antennaBacklobeGain); | |
// use AxesAlignedConstrained axes type | |
var earthZaxis = new VectorFixed(earth.FixedFrame.Axes, UnitCartesian.UnitZ); | |
Axes targetTrackingAxes = new AxesAlignedConstrained(new VectorTrueDisplacement(targetPlatform.LocationPoint, | |
transmitterPlatform.LocationPoint), AxisIndicator.Third, earthZaxis, AxisIndicator.First); | |
transmitterPlatform.OrientationAxes = targetTrackingAxes; | |
// transmitter identification extension | |
var transmitterIdentifier = new IdentifiableTransmitterExtension(); | |
var additionalSignalData = new SignalDataCollection | |
{ | |
transmitterIdentifier.Identifier | |
}; | |
// add a pulsed signal source | |
var pulsedSignalData = new PulsedSignalData(pulseRepetitionFrequency, pulseWidth, pulseCount); | |
var pulsedSignalSource = new PulsedSignalSource(pulsedSignalData, additionalSignalData); | |
// add modulator | |
var modulator = new PulsedSignalModulator(pulsedSignalSource, Constants.SpeedOfLight / wavelength); | |
// add amplifier. in this case a simple gain amplifier | |
var amplifier = new ConstantGainAmplifier(modulator, amplifierGain); | |
// add transmitter extension | |
var transmittingAntennaExtension = new RadarTransmittingAntennaExtension(amplifier, parabolicGainPattern); | |
transmitterPlatform.Extensions.Add(transmittingAntennaExtension); | |
transmitterPlatform.Extensions.Add(transmitterIdentifier); | |
} | |
/// <summary> | |
/// The parameterized scalar values representing the analysis. | |
/// </summary> | |
public class RadarScalarEvaluators | |
{ | |
/// <summary> | |
/// Gets or sets the Mitchell-Walker probability of detection scalar evaluator. | |
/// </summary> | |
public ParameterizedMotionEvaluator2<Transaction, ExampleEntity, double> MwScalarEvaluator { get; set; } | |
/// <summary> | |
/// Gets or sets the RIP scalar evaluator. | |
/// </summary> | |
public ParameterizedMotionEvaluator2<Transaction, ExampleEntity, double> RipScalarEvaluator { get; set; } | |
} | |
/// <summary> | |
/// The scalars involved in analyzing the radar system. | |
/// </summary> | |
public class RadarScalars | |
{ | |
/// <summary> | |
/// Gets or sets the Mitchell-Walker probability of detection scalar. | |
/// </summary> | |
public MitchellWalkerProbabilityOfDetectionScalar mwScalar { get; set; } | |
/// <summary> | |
/// Gets or sets the Transmitter to target RIP scalar. | |
/// </summary> | |
public TransmitterToTargetReceivedIsotropicPowerScalar ripScalar { get; set; } | |
} | |
/// <summary> | |
/// A pair of platforms that represent a monostatic radar. | |
/// </summary> | |
public class MonostaticRadar | |
{ | |
/// <summary> | |
/// Gets or sets the radar transmitter platform. | |
/// </summary> | |
public Platform Transmitter { get; set; } | |
/// <summary> | |
/// Gets or sets the radar receiver platform. | |
/// </summary> | |
public Platform Receiver { get; set; } | |
} | |
/// <summary> | |
/// An example of an entity that may be used with the tracking library. | |
/// </summary> | |
public class ExampleEntity : IEntityIdentifier, | |
IEntityLastUpdate, | |
IEntityVelocity, | |
IEntityOrientation | |
{ | |
/// <summary> | |
/// Register's the entity's descriptors. | |
/// </summary> | |
public static void RegisterEntityClass() | |
{ | |
EntityDescriptor<ExampleEntity>.Default = new ExampleEntityDescriptor(); | |
} | |
/// <summary> | |
/// Initializes the example entity. | |
/// </summary> | |
/// <param name="context">The context for reading and writing entity values.</param> | |
/// <param name="callSign">The name of the entity.</param> | |
public ExampleEntity(TransactionContext context, string callSign) | |
{ | |
if (context == null) | |
throw new ArgumentNullException("context"); | |
if (callSign == null) | |
throw new ArgumentNullException("callSign"); | |
m_callSign = callSign; | |
m_lastUpdate = new TransactedProperty<JulianDate>(context, this); | |
m_position = new TransactedProperty<Cartesian>(context, this); | |
m_velocity = new TransactedProperty<Cartesian>(context, this); | |
m_orientation = new TransactedProperty<UnitQuaternion>(context, this); | |
} | |
/// <summary> | |
/// Gets the callsign (name) of the entity. | |
/// </summary> | |
public object EntityIdentifier | |
{ | |
get { return m_callSign; } | |
} | |
/// <summary> | |
/// Gets the date of the last update of the entity. | |
/// </summary> | |
public TransactedProperty<JulianDate> LastUpdate | |
{ | |
get { return m_lastUpdate; } | |
} | |
/// <summary> | |
/// Gets the position of the entity. | |
/// </summary> | |
public TransactedProperty<Cartesian> Position | |
{ | |
get { return m_position; } | |
} | |
/// <summary> | |
/// Gets the velocity of the entity. | |
/// </summary> | |
public TransactedProperty<Cartesian> Velocity | |
{ | |
get { return m_velocity; } | |
} | |
/// <summary> | |
/// Gets the orientation of the entity. | |
/// </summary> | |
public TransactedProperty<UnitQuaternion> Orientation | |
{ | |
get { return m_orientation; } | |
} | |
/// <summary> | |
/// Gets the callsign (name) of the entity. | |
/// </summary> | |
public string CallSign | |
{ | |
get { return m_callSign; } | |
} | |
private string m_callSign; | |
private TransactedProperty<Cartesian> m_position; | |
private TransactedProperty<Cartesian> m_velocity; | |
private TransactedProperty<JulianDate> m_lastUpdate; | |
private TransactedProperty<UnitQuaternion> m_orientation; | |
} | |
/// <summary> | |
/// The example entity's descriptor. | |
/// </summary> | |
public class ExampleEntityDescriptor : EntityDescriptor<ExampleEntity>, | |
IEntityPositionDescriptor, | |
IEntityOrientationDescriptor | |
{ | |
/// <summary> | |
/// Gets the position's reference frame, which is ECEF. | |
/// </summary> | |
public ReferenceFrame PositionReferenceFrame | |
{ | |
get { return CentralBodiesFacet.GetFromContext().Earth.FixedFrame; } | |
} | |
/// <summary> | |
/// Gets the orientation axes. | |
/// </summary> | |
public Axes OrientationAxes | |
{ | |
get { return PositionReferenceFrame.Axes; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment