Click or drag to resize

Advanced Communications Code Sample

The following is a series of code samples which create a Link Budget for a "bent pipe" configuration with interference. Taken together, the code samples here provide a good starting point for new users. For a graphical representation of how all of the objects in this code sample fit together, see the figure in the Advanced Communications topic.

Note Note

The functionality described in this topic requires a license for the Communications Library.

Platform Ephemeris

The first thing to do is to look at the Reference Frames and Transformations topic in order to set up the central body's fixed frame transformation correctly. Otherwise, an exception may occur when transforming the platform position between the fixed and inertial frames. Next, set up the ephemeris for all the Platforms which represent various objects in the communication problem. For more information, see the Platforms topic.

C#
EarthCentralBody earth = CentralBodiesFacet.GetFromContext().Earth;

// Transponder on comm sat in geosynchronous orbit
JulianDate orbitEpochJD = new GregorianDate(2003, 6, 1, 12, 0, 0.0).ToJulianDate();
Motion<Cartesian> desiredElementsAtEpoch = new Motion<Cartesian>(
    new Cartesian(36338238.668737, -21389849.706789, -10540.168846), // initial position
    new Cartesian(1536.123210932, 2609.386729120, 533.378614845));   // initial velocity
TwoBodyPropagator desiredPropagator = new TwoBodyPropagator(
    orbitEpochJD,
    earth.InertialFrame,
    desiredElementsAtEpoch,
    WorldGeodeticSystem1984.GravitationalParameter);
Point desiredPropPoint = desiredPropagator.CreatePoint();

// Create a "Transponder" with two antennas
Platform uplinkRcvrAntenna = new Platform();
uplinkRcvrAntenna.LocationPoint = desiredPropPoint;
Platform downlinkXmtrAntenna = new Platform();
downlinkXmtrAntenna.LocationPoint = desiredPropPoint;

// Create an antenna for the "Transmitter" at Los Angeles (-116.3190184 deg W, 35.88957055 deg N)
Cartographic losAngeles = new Cartographic(-2.063741654357, 0.594323569195, 0);
Platform uplinkXmtrAntenna = new Platform();
uplinkXmtrAntenna.LocationPoint = new PointCartographic(earth, losAngeles);

// Create an antenna for the "Receiver" at Philadelphia (-75.1637918 deg W, 39.95233518 deg N)
Cartographic philadelphia = new Cartographic(-1.311855645194, 0.697299792751, 0);
Platform downlinkRcvrAntenna = new Platform();
downlinkRcvrAntenna.LocationPoint = new PointCartographic(earth, philadelphia);

Also, it is important to note how to correctly orient the Platform objects representing antennas. By convention, the antenna boresight is defined to lie along the z-axis of the body frame. Use an AxesAlignedConstrained to "track" the antenna along a certain vector, by specifying that vector as the Z-Axis.

C#
Vector earthZAxis = new VectorFixed(earth.InertialFrame.Axes, UnitCartesian.UnitZ);

// Constrain the "transponder" antenna orientations

// Comm sat uplink antenna points toward Los Angeles
uplinkRcvrAntenna.OrientationAxes =
    new AxesAlignedConstrained(
        new VectorApparentDisplacement(
            uplinkRcvrAntenna.LocationPoint,
            uplinkXmtrAntenna.LocationPoint,
            earth.InertialFrame),
        AxisIndicator.Third,
        earthZAxis,
        AxisIndicator.First);

// Comm sat downlink antenna points toward Philadelphia
downlinkXmtrAntenna.OrientationAxes =
    new AxesAlignedConstrained(
        new VectorApparentDisplacement(
            downlinkXmtrAntenna.LocationPoint,
            downlinkRcvrAntenna.LocationPoint,
            earth.InertialFrame),
        AxisIndicator.Third,
        earthZAxis,
        AxisIndicator.First);

// Transmitting antenna at Los Angeles points toward the
// receiving antenna on the comm sat
AxesNorthEastDown ned = new AxesNorthEastDown(earth, uplinkXmtrAntenna.LocationPoint);
Vector upLinkVector = new VectorApparentDisplacement(
    uplinkXmtrAntenna.LocationPoint,
    uplinkRcvrAntenna.LocationPoint,
    earth.InertialFrame);
Vector reference = new VectorCrossProduct(upLinkVector,
                                          new VectorFixed(ned, UnitCartesian.UnitZ));
uplinkXmtrAntenna.OrientationAxes =
    new AxesAlignedConstrained(
        upLinkVector, AxisIndicator.Third, reference, AxisIndicator.Second);

// Receiving antenna at Philadelphia points toward the
// transmitting antenna on the comm sat
downlinkRcvrAntenna.OrientationAxes =
    new AxesAlignedConstrained(
        new VectorApparentDisplacement(
            downlinkRcvrAntenna.LocationPoint,
            downlinkXmtrAntenna.LocationPoint,
            earth.InertialFrame),
        AxisIndicator.Third,
        new VectorFixed(earth.InertialFrame.Axes, UnitCartesian.UnitZ),
        AxisIndicator.First);
Setting up a Transmitter and Receiver

Transmitters and receivers are defined as a function of their components. To set up a transmitter, specify the source of the original signal and process it using various SignalProcessors such as modulators and amplifiers.

C#
// Specify a frequency for the uplink
double frequencyForUplink = 14.5e9; // 14.5 GHz

// Create a digital signal based on a data rate of 16 Mbps
DigitalDataSource source = new DigitalDataSource();
source.DataRate = 16.0e6; // 16 Megabits per second

// Set the frequency and add digital modulation onto the signal
// Only necessary to compute Eb/No and Bit Error Rate
DigitalModulator<ModulationBpsk> modulator = new DigitalModulator<ModulationBpsk>();
modulator.CarrierFrequency = frequencyForUplink;
modulator.InputSignalProcessor = source;
modulator.DigitalModulation = new ModulationBpsk();

// Set the power for transmission
ConstantGainAmplifier amplifier = new ConstantGainAmplifier();
amplifier.Gain = CommunicationAnalysis.FromDecibels(60.0); // dBW
amplifier.InputSignalProcessor = modulator;

// Choose a gain pattern for the antenna
GaussianGainPattern antennaPattern = new GaussianGainPattern();
antennaPattern.Diameter = 1.0; // meters
antennaPattern.Efficiency = 0.55; // ratio between zero and one
antennaPattern.BacklobeGain = 0.001; // Watts (-30 dBW)

// Create an transmitting extension to make the platform into a functional antenna
RadioFrequencyTransmittingAntennaExtension transmitterAntenna = new RadioFrequencyTransmittingAntennaExtension();
transmitterAntenna.AntennaGainPattern = antennaPattern;

// Transmitter antenna gets its signal from the amplifier
transmitterAntenna.InputSignalProcessor = amplifier;

// Add the extension to the antenna Platform
uplinkXmtrAntenna.Extensions.Add(transmitterAntenna);

For the receiver, the setup is similar, with one notable difference. In order to support Link Budget parameters, use the SignalOutputExtension to specify the output of the receiver. This will be used in conjunction with the IntendedSignalStrategy to determine the scalar value of each Link Budget parameter. Also note that this example includes both an uplink and downlink. For problems without transponders or transceivers, be sure to match the receiving frequency with the one being transmitted.

C#
// Specify a frequency for the downlink
double frequencyForDownlink = 12.5e9; // 12.5 Ghz

// Create a receiving extension to make the platform into an antenna
RadioFrequencyReceivingAntennaExtension receiverAntenna = new RadioFrequencyReceivingAntennaExtension();
receiverAntenna.AntennaGainPattern = antennaPattern;
downlinkRcvrAntenna.Extensions.Add(receiverAntenna);

// Reduce the noise on the signal with a filter.
RectangularFilter receiverFilter = new RectangularFilter();
receiverFilter.InputSignalProcessor = receiverAntenna.OutputSignalProcessor;
receiverFilter.Frequency = frequencyForDownlink;
receiverFilter.LowerBandwidthLimit = -12e3; // 24 khz bandwidth
receiverFilter.UpperBandwidthLimit = 12e3;

// Amplify the signal prior to the output
ConstantGainAmplifier receiverAmplifier = new ConstantGainAmplifier();
receiverAmplifier.Gain = CommunicationAnalysis.FromDecibels(30);
receiverAmplifier.NoiseFactor = 2; // Adds 290 Kelvin thermal noise
receiverAmplifier.InputSignalProcessor = receiverFilter;

// Identify the output of the receiver for the link budget
SignalOutputExtension receiverOutput = new SignalOutputExtension(receiverAmplifier);
downlinkRcvrAntenna.Extensions.Add(receiverOutput);
Setting up Platforms to represent a Transponder

In cases where the receiving and transmitting antennas for a transponder have different orientations and possibly different positions, two Platforms are used to represent the transponder, connected by an instantaneous link. Only a single Platform is needed in the case where the receiving and transmitting antennas are the same device pointed in the same direction. In this case, simply add the RadioFrequencyReceivingAntennaExtension and RadioFrequencyTransmittingAntennaExtension onto the same Platform and hook the output of the receiving antenna into the input of the transmitting antenna.

A filter is needed to limit the noise experienced by the transponder hardware. Without a filter, the noise bandwidth is infinite and the carrier to noise will be zero. Also note that this problem includes the presence of interference. Any interfering signals outside the filter's bandwidth will be eliminated from the output signal and the following links.

C#
// Create a receiving extension to allow the comm sat antenna platform
// to receive signals from free space
RadioFrequencyReceivingAntennaExtension uplinkReceiver = new RadioFrequencyReceivingAntennaExtension();
uplinkReceiver.AntennaGainPattern = antennaPattern;
uplinkRcvrAntenna.Extensions.Add(uplinkReceiver);

// Use a filter to constrain the noise on the signal
// Note - this is needed for calculating C/N for the transponder
//        and to eliminate interference from being retransmitted
RectangularFilter filter = new RectangularFilter();
filter.InputSignalProcessor = uplinkReceiver.OutputSignalProcessor;
filter.Frequency = frequencyForUplink;
filter.LowerBandwidthLimit = -16.0e6; // 32 MHz bandwidth
filter.UpperBandwidthLimit = 16.0e6;

// Amplify the signal before retransmitting it
ConstantGainAmplifier xpdrAmplifier = new ConstantGainAmplifier();
xpdrAmplifier.Gain = CommunicationAnalysis.FromDecibels(100.0); // 100.0 dBW gain
xpdrAmplifier.InputSignalProcessor = filter;
xpdrAmplifier.NoiseFactor = 2; // Adds 290 Kelvin thermal noise

// Identify the output of the transponder prior to demodulating/remodulating
// Note - this is needed for calculating a link budget for the uplink
SignalOutputExtension outputExtension = new SignalOutputExtension();
outputExtension.SignalOutput = xpdrAmplifier;

// Add the output extension to the receiver antenna platform to identify the output
// for link budget calculations
uplinkRcvrAntenna.Extensions.Add(outputExtension);

// Change the modulation between the uplink and the downlink
DigitalDemodulator<ModulationBpsk> demodulator = new DigitalDemodulator<ModulationBpsk>();
demodulator.InputSignalProcessor = xpdrAmplifier;
DigitalModulator<ModulationQpsk> reModulator = new DigitalModulator<ModulationQpsk>();
reModulator.DigitalModulation = new ModulationQpsk();
reModulator.CarrierFrequency = frequencyForDownlink;
reModulator.InputSignalProcessor = demodulator;

// Create a transmitting extension to allow the second transponder antenna
// to retransmit the signal
RadioFrequencyTransmittingAntennaExtension downlinkTransmitter = new RadioFrequencyTransmittingAntennaExtension();
downlinkTransmitter.AntennaGainPattern = antennaPattern;

// Transmit the signal after remodulating
downlinkTransmitter.InputSignalProcessor = reModulator;
downlinkXmtrAntenna.Extensions.Add(downlinkTransmitter);
Setting up the Propagation Graph

In order to inform the receivers of which objects are transmitting signals, use a SignalPropagationGraph which represents all the active communication links. Remember to add a WirelessLinkExtension to each link and specify which SignalPropagationModels to use, specified in the correct order. By default, the WirelessLinkExtension includes free space path loss and doppler shift.

Also note that it is possible to include link constraints with an AccessConstraintsExtension. The receiving antennas will take the constraints into account when evaluating which links are producing signals. For complex problems involving a lot of links or long time frames, this can save a significant amount of computation. For even more savings, consider using a precomputed access solution for each link by using AccessResultExtension.

C#
// Set up light time delay links
LinkSpeedOfLight upLink = new LinkSpeedOfLight(uplinkXmtrAntenna, uplinkRcvrAntenna, earth.InertialFrame);
LinkSpeedOfLight downLink = new LinkSpeedOfLight(downlinkXmtrAntenna, downlinkRcvrAntenna, earth.InertialFrame);

// Create WirelessLinkExtensions to the two wireless links that use the
// same propagation models.
WirelessLinkExtension upLinkExt = new WirelessLinkExtension();

// Add Propagation Models
// Note that the propagation models are applied in order.
// So, if a model is to be computed before doppler and/or freespace loss,
// make sure it is in the correct place in the list.
upLinkExt.PropagationModels.Insert(0, new AtmosphericAttenuationModelItuRP676Version9());
upLinkExt.PropagationModels.Add(new RainAttenuationModelItuRP618Version12());

WirelessLinkExtension downLinkExt = new WirelessLinkExtension(upLinkExt.PropagationModels);

// Add wireless extensions to the links
upLink.Extensions.Add(upLinkExt);
downLink.Extensions.Add(downLinkExt);

// If the links might be obstructed by a central body for part of the analysis,
// add a constraint to indicate times when the signal does not make it to the receiver.
// The receiver won't evaluate obstructed signals.
upLink.Extensions.Add(new AccessConstraintsExtension(new CentralBodyObstructionConstraint(upLink, earth)));
downLink.Extensions.Add(new AccessConstraintsExtension(new CentralBodyObstructionConstraint(downLink, earth)));

// A crosslink between the two Platforms of the "Transponder" is needed for
// access to know how to move times between the two links
LinkInstantaneous crossLink = new LinkInstantaneous(uplinkRcvrAntenna, downlinkXmtrAntenna);

// Add the links to the propagation graph
SignalPropagationGraph propagationGraph = new SignalPropagationGraph();
propagationGraph.AddLink(upLink);
propagationGraph.AddLink(crossLink);
propagationGraph.AddLink(downLink);
Setting up Interference

Adding interference to a communication problem is as simple as adding additional signal sources, creating links with the appropriate WirelessLinkExtension, and adding them to the SignalPropagationGraph. The receiving antennas will then evaluate the incoming interfering links along with the "intended" one. Note that it is entirely possible that an "interfering" signal can be mistaken for the "intended" signal if the problem is set up such that the IntendedSignalStrategy cannot tell the difference and the interfering signal has more power.

The following code configures interference for the uplink. If the interference isn't filtered out, it will be retransmitted.

C#
SignalSource interferenceSource = new SignalSource();
interferenceSource.SignalToTransmit = Signal.CreateSignal(
    CommunicationAnalysis.FromDecibels(1), // 1 dBW power (weak signal)
    14.470e9,  // 14.5 GHz frequency
    -16.0e6, 16.0e6); // 32 MHz bandwidth

// Specify four interference sources surrounding the transmitter
int N = 4;
for (int i = 0; i < N; i++)
{
    Platform interferer = new Platform();
    double angle = Constants.TwoPi * i / N;
    double offset = Trig.DegreesToRadians(0.1);
    interferer.LocationPoint = new PointCartographic(
        earth,
        new Cartographic(
            losAngeles.Longitude + offset * Math.Cos(angle),
            losAngeles.Latitude + offset * Math.Sin(angle), 0));
    interferer.OrientationAxes = uplinkXmtrAntenna.OrientationAxes;
    transmitterAntenna = new RadioFrequencyTransmittingAntennaExtension();
    // Instead of targeting the transponder, just radiate in all directions
    transmitterAntenna.AntennaGainPattern = new IsotropicGainPattern();
    transmitterAntenna.InputSignalProcessor = interferenceSource;
    interferer.Extensions.Add(transmitterAntenna);

    // Remember to add the link to the propagation graph
    LinkSpeedOfLight link = new LinkSpeedOfLight(interferer, uplinkRcvrAntenna, earth.InertialFrame);
    WirelessLinkExtension wirelessExtension = new WirelessLinkExtension(upLinkExt.PropagationModels);
    link.Extensions.Add(wirelessExtension);
    propagationGraph.AddLink(link);

}

The following code configures interference for the downlink.

C#
foreach (Platform satellite in interferenceConstellation)
{
    // Point the interferers toward the "target"
    satellite.OrientationAxes =
        new AxesAlignedConstrained(
            new VectorApparentDisplacement(
                satellite.LocationPoint,
                downlinkRcvrAntenna.LocationPoint,
                earth.InertialFrame),
            AxisIndicator.Third,
            new VectorFixed(
                earth.InertialFrame.Axes,
                UnitCartesian.UnitZ),
            AxisIndicator.First);
    transmitterAntenna = new RadioFrequencyTransmittingAntennaExtension();
    transmitterAntenna.AntennaGainPattern = antennaPattern;
    transmitterAntenna.InputSignalProcessor = interferenceSource;
    satellite.Extensions.Add(transmitterAntenna);

    // Setup light time delay links
    LinkSpeedOfLight link = new LinkSpeedOfLight(satellite, downlinkRcvrAntenna, earth.InertialFrame);

    // Use the same propagation models on the wireless extension
    WirelessLinkExtension wirelessExtension = new WirelessLinkExtension(downLinkExt.PropagationModels);
    link.Extensions.Add(wirelessExtension);

    // Add central body obstruction constraint to link
    AccessConstraintsExtension linkConstraints = new AccessConstraintsExtension(
        new CentralBodyObstructionConstraint(link, earth));
    link.Extensions.Add(linkConstraints);

    // Remember to add the link to the propagation graph
    propagationGraph.AddLink(link);
}
Setting up Link Budget Evaluators

After everything is set up, simply create the Scalar representing Link Budget parameters of interest and get the appropriate evaluators. Note that some are related to the receiver, some to the "transponder", and some to the transmitter. There are two ways to handle light time delay. First, a LinkDelayEvaluator can be obtained from the ILinkService or from a LinkPath. This will take the time at the receiver and adjust it to the time at the "transponder" or transmitter. Alternately, it is possible to create a ScalarDelayedByLink which wraps the Link Budget parameter of interest. This way, it is possible to evaluate all the scalars with respect to the receiver's clock and the scalars referenced to the "transponder" or transmitter will be adjusted automatically. For simplicity in the example, the evaluators are evaluated for a single time and a LinkDelayEvaluator is used to adjust the evaluation times for the "transponder" and transmitter.

C#
// Specify the "intendedUplinkSignal" Signal for the uplink
IntendedSignalStrategy intendedUplinkSignal =
    new IntendedSignalByModulation<ModulationBpsk>(frequencyForUplink);

// Indicate the "intendedUplinkSignal" Signal for the downlink
IntendedSignalStrategy intendedDownlinkSignal =
    new IntendedSignalByModulation<ModulationQpsk>(frequencyForDownlink);

// Create a single EvaluatorGroup to optimize all the evaluators
EvaluatorGroup group = new EvaluatorGroup();

// EIRP evaluators- Get the output of the transmitter antenna after applying gains
ScalarEvaluator eirpUplinkEvaluator = new ScalarEffectiveIsotropicRadiatedPower(
    upLink, propagationGraph, intendedUplinkSignal).GetEvaluator(group);

ScalarEvaluator eirpDownlinkEvaluator = new ScalarEffectiveIsotropicRadiatedPower(
    downLink, propagationGraph, intendedDownlinkSignal).GetEvaluator(group);

// Antenna Gain evaluators - Get the gain in the link direction
ScalarEvaluator uplinkReceiverGain = new ScalarAntennaGainInLinkDirection(
    upLink, LinkRole.Receiver, propagationGraph, intendedUplinkSignal).GetEvaluator(group);
ScalarEvaluator downlinkReceiverGain = new ScalarAntennaGainInLinkDirection(
    downLink, LinkRole.Receiver, propagationGraph, intendedDownlinkSignal).GetEvaluator(group);

ScalarEvaluator uplinkTransmitterGain = new ScalarAntennaGainInLinkDirection(
    upLink, LinkRole.Transmitter, propagationGraph, intendedUplinkSignal).GetEvaluator(group);
ScalarEvaluator downlinkTransmitterGain = new ScalarAntennaGainInLinkDirection(
    downLink, LinkRole.Transmitter, propagationGraph, intendedDownlinkSignal).GetEvaluator(group);

// RIP evaluators- Get from the link
ScalarEvaluator uplinkReceivedIsotropicPower = new ScalarReceivedIsotropicPower(
    upLink, propagationGraph, intendedUplinkSignal).GetEvaluator(group);

ScalarEvaluator downlinkReceivedIsotropicPower = new ScalarReceivedIsotropicPower(
    downLink, propagationGraph, intendedDownlinkSignal).GetEvaluator(group);

// C/N C/No evaluators - Get the carrier to noise and carrier to noise density
ScalarEvaluator uplinkCOverN = new ScalarCarrierToNoise(
    uplinkRcvrAntenna, propagationGraph, intendedUplinkSignal).GetEvaluator(group);
ScalarEvaluator uplinkCOverNo = new ScalarCarrierToNoiseDensity(
    uplinkRcvrAntenna, propagationGraph, intendedUplinkSignal).GetEvaluator(group);

ScalarEvaluator downlinkCOverN = new ScalarCarrierToNoise(
    downlinkRcvrAntenna, propagationGraph, intendedDownlinkSignal).GetEvaluator(group);
ScalarEvaluator downlinkCOverNo = new ScalarCarrierToNoiseDensity(
    downlinkRcvrAntenna, propagationGraph, intendedDownlinkSignal).GetEvaluator(group);

// C/I C/(N+I) evaluators - Get the interference figures
ScalarEvaluator uplinkCOverI = new ScalarCarrierToInterference(
    uplinkRcvrAntenna, propagationGraph, intendedUplinkSignal).GetEvaluator(group);
ScalarEvaluator uplinkCOverNI = new ScalarCarrierToNoisePlusInterference(
    uplinkRcvrAntenna, propagationGraph, intendedUplinkSignal).GetEvaluator(group);

ScalarEvaluator downlinkCOverI = new ScalarCarrierToInterference(
    downlinkRcvrAntenna, propagationGraph, intendedDownlinkSignal).GetEvaluator(group);
ScalarEvaluator downlinkCOverNI = new ScalarCarrierToNoisePlusInterference(
    downlinkRcvrAntenna, propagationGraph, intendedDownlinkSignal).GetEvaluator(group);

// BER Eb/No - Get the digital signal figures
ScalarEvaluator uplinkBitEnergyOverNo = new ScalarEnergyPerBitToNoiseDensity<ModulationBpsk>(
    uplinkRcvrAntenna, propagationGraph, intendedUplinkSignal).GetEvaluator(group);
ScalarEvaluator uplinkBitErrorRate = new ScalarBitErrorRate<ModulationBpsk>(
    uplinkRcvrAntenna, propagationGraph, intendedUplinkSignal).GetEvaluator(group);

ScalarEvaluator downlinkBitEnergyOverNo = new ScalarEnergyPerBitToNoiseDensity<ModulationQpsk>(
    downlinkRcvrAntenna, propagationGraph, intendedDownlinkSignal).GetEvaluator(group);
ScalarEvaluator downlinkBitErrorRate = new ScalarBitErrorRate<ModulationQpsk>(
    downlinkRcvrAntenna, propagationGraph, intendedDownlinkSignal).GetEvaluator(group);

// Use a LinkDelayEvaluator to get the time at which to evaluate the transmitter
LinkDelayEvaluator downLinkDelay =
    downLink.GetOffsetToTransmissionTimeEvaluator(group);

// Use a LinkPath to get the combined delay of the two intended links
LinkPath pathFromTransmitterToReceiver = new LinkPath();
pathFromTransmitterToReceiver.Add(upLink);
pathFromTransmitterToReceiver.Add(crossLink);
pathFromTransmitterToReceiver.Add(downLink);
LinkDelayEvaluator linkPathDelay = pathFromTransmitterToReceiver.GetLinkPathDelayEvaluator(group, LinkRole.Receiver);
Evaluator<Signal> intendedSignalEvaluator =
    intendedDownlinkSignal.GetIntendedSignalEvaluator(group, propagationGraph, receiverOutput.SignalOutput);

// Optimize the evaluators!
// This makes sure that all of the above Scalars don't repeat calculations when evaluating
// the entire link budget at a given time.
group.OptimizeEvaluators();
Using Link Budget Parameters in Access

The Scalars representing Link Budget parameters can also be used as thresholds in an access calculation. Unlike ScalarConstraint, which uses a fixed step size, communication constraints will use a slightly more sophisticated sampling algorithm.

C#
double minThreshold = CommunicationAnalysis.FromDecibels(14.198);
double maxThreshold = CommunicationAnalysis.FromDecibels(1000);

// Combine two link budget constraints
CommunicationObjectConstraint interferenceConstraint = new CommunicationObjectConstraint(
    new ScalarCarrierToInterference(downlinkRcvrAntenna, propagationGraph, intendedDownlinkSignal),
    minThreshold, maxThreshold);
CommunicationObjectConstraint berConstraint = new CommunicationObjectConstraint(
    new ScalarBitErrorRate<ModulationBpsk>(downlinkRcvrAntenna, propagationGraph, intendedDownlinkSignal),
    0.0, 0.012271);

// Combine access constraints (queries) using boolean operators
AccessQuery combinedQuery = berConstraint & interferenceConstraint;

// Use the philadelphia platform as the time observer
AccessEvaluator accessEval = combinedQuery.GetEvaluator(downlinkRcvrAntenna);
// Compute Access
AccessQueryResult result = accessEval.Evaluate(startAccess, stopAccess);