Skip to content

Instantly share code, notes, and snippets.

@mksquires
Created June 6, 2019 22:09
Show Gist options
  • Save mksquires/1e83e9d0fae05ad7ea32922c674c943c to your computer and use it in GitHub Desktop.
Save mksquires/1e83e9d0fae05ad7ea32922c674c943c to your computer and use it in GitHub Desktop.
An example of STK Components in C# with Radar and Tracking
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