Basic Communications Code Sample
The following are a set of code samples that are meant to show how to set up a communications scenario. A transmitter in Los Angeles, California transmits a signal to a communications transceiver onboard a low-Earth orbit satellite. That satellite then retransmits the signal to a receiver in Philadelphia, Pennsylvania. After the initial link budget is determined, interference sources are added and the link budget is reevaluated. LinkBudget scalars are then generated and an Access calculation is performed on two link constraints.
The functionality described in this topic requires a license for the Communications Library.
First we need to know the locations of the transmitter and receiver. Once we have those, we can create a SimpleDigitalTransmitter and a SimpleReceiver. We'll set their locations, but not their orientations yet. We'll tell the CommunicationSystem to orient them later.
We're also setting the noise factor and filter parameters for the receiver. This will ensure we can calculate the carrier-to-noise values correctly.
SimpleDigitalTransmitter uplinkTransmitter = new SimpleDigitalTransmitter(); Cartographic losAngeles = new Cartographic(-2.063741654357, 0.594323569195, 0); uplinkTransmitter.setLocationPoint(new PointCartographic(earth, losAngeles)); // Freq is 14.5 GHz, dataRate is 16 Mb/s, EIRP is 30 dBW, Gain is 100 dB, modulating BPSK by default // Create Simple Receiver in Philadelphia SimpleReceiver downlinkReceiver = new SimpleReceiver(); Cartographic philadelphia = new Cartographic(-1.311855645194, 0.697299792751, 0); downlinkReceiver.setLocationPoint(new PointCartographic(earth, philadelphia)); downlinkReceiver.setNoiseFactor(2.0); downlinkReceiver.setFilterBandwidth(40e6); downlinkReceiver.setTargetFrequency(uplinkTransmitter.getCarrierFrequency());
Transceivers receive a signal, possibly condition it in some way, and then retransmit it. The reception and transmission locations and orientations on the transceiver are independent, allowing for separate targeting. In this example, we create a location for the transceiver (actually a location for its receiving antenna) from a Sgp4Propagator by calling the createPoint method. We specify the receiving gain pattern as an IsotropicGainPattern. We add a RectangularFilter to filter out unwanted noise and interference as well.
For the transceiver's transmitter, we use the same location as the receiver, but change the gain pattern to a GaussianGainPattern and set the transmission carrier frequency. Finally, we specify the amount of output noise and the output modulation type.
// Create the Transceiver, modulating QPSK on the downlink // Create a propagator for the satellite Sgp4Propagator propagator = new Sgp4Propagator(new TwoLineElementSet( "1 99999U 11227.75000000 -.00000381 00000-0 -16082-4 0 00008\n" + "2 99999 045.0199 346.3022 0007665 267.1681 308.9875 15.22470225000011")); // Create the transceiver and set its properties Transceiver satelliteTransceiver = new Transceiver(); satelliteTransceiver.setName("Satellite Transceiver"); satelliteTransceiver.getInputAntenna().setLocationPoint(propagator.createPoint()); satelliteTransceiver.setInputAntennaGainPattern(new IsotropicGainPattern()); satelliteTransceiver.setCarrierFrequency(uplinkTransmitter.getCarrierFrequency()); satelliteTransceiver.setOutputNoiseFactor(1.2); // Add a rectangular filter satelliteTransceiver.setFilter(new RectangularFilter()); satelliteTransceiver.getFilter().setLowerBandwidthLimit(-500e6); // -500 MHz satelliteTransceiver.getFilter().setUpperBandwidthLimit(500e6); // +500 MHz satelliteTransceiver.getFilter().setFrequency(uplinkTransmitter.getCarrierFrequency()); // Use the same location as the input antenna for the output antenna satelliteTransceiver.getOutputAntenna().setLocationPoint(new PlatformLocationPoint(satelliteTransceiver.getInputAntenna())); // Different gain pattern on output GaussianGainPattern transmitterPattern = new GaussianGainPattern(); satelliteTransceiver.setOutputAntennaGainPattern(transmitterPattern); transmitterPattern.setBacklobeGain(0.001); // decimal transmitterPattern.setDiameter(1.0); // meters transmitterPattern.setEfficiency(0.55); // percent as a fraction // Output Modulation satelliteTransceiver.setModulation(new ModulationQpsk());
To evaluate the link budget and manage the links for this system, we create a CommunicationSystem object and add the items we've created to it. First, we add additional signal propagation models to the system; these are on top of the default propagation models: FreeSpacePathLossModel and DopplerShiftModel.
// The receivers and transmitters are setup, now we create a CommunicationSystem // and add additional propagation models. CommunicationSystem commsys = new CommunicationSystem(); // Add two more propagation models, besides the defaults. commsys.getLinks().getDefaultPropagationModels().add(new AtmosphericAttenuationModelItuRP676(ItuRP676Version.VERSION5)); commsys.getLinks().getDefaultPropagationModels().add(new RainAttenuationModelItuRP618(ItuRP618RainAttenVersion.VERSION9));
CommunicationSystem has a Links (get) property that holds a collection of links in this system. We could add the entire comm system we've set up so far with the addChain method, which creates links and adds them all at once, but this is described in a previous example. Instead, we'll highlight how to add links to the CommunicationSystem in different ways. It's important when creating your own links that you set them up completely. When you add a link itself, the CommunicationSystem assumes it's complete. If you are adding your own link, ensure it has a WirelessLinkExtension.
// There are three different ways to add links into the communications system--- // First we show the long way by manually creating and adding all three links. // This includes the uplink, the downlink and the internal hardware link inside of the transceiver. // Create a link from the transmitter to the transceivers receiving antenna. LinkSpeedOfLight uplink = new LinkSpeedOfLight(uplinkTransmitter, satelliteTransceiver.getInputAntenna(), earth.getInertialFrame()); uplink.setName("LA Uplink"); uplink.getExtensions().add(new WirelessLinkExtension()); commsys.getLinks().add(uplink); // Add the transceivers internal hardware link itself commsys.getLinks().add(satelliteTransceiver.getHardwareLink()); // Create a link from the transceivers output antenna to the receiver. LinkSpeedOfLight downlink = new LinkSpeedOfLight(satelliteTransceiver.getOutputAntenna(), downlinkReceiver, earth.getInertialFrame()); downlink.setName("PA Downlink"); downlink.getExtensions().add(new WirelessLinkExtension()); commsys.getLinks().add(downlink); // Second, we can use the helper functions to create and add individual links. // Note that in this case we don't need to specify the input or output antennas // for the transceiver, this is determined automatically by the context in which // it is used. Also, we don't have to add the internal hardware link either, // since this is done automatically. commsys.getLinks().add("LA Uplink", uplinkTransmitter, satelliteTransceiver); commsys.getLinks().add("PA Downlink", satelliteTransceiver, downlinkReceiver); // Finally, the easiest way is to use AddChain to pass in the entire link at once. commsys.getLinks().addChain(uplinkTransmitter, satelliteTransceiver, downlinkReceiver); // No matter how a link is added, it can be retrieved just as easily using // any of the available Find methods. Object thisUplink = commsys.getLinks().findFirst(uplinkTransmitter, satelliteTransceiver); LinkSpeedOfLight desiredUplink = (thisUplink instanceof LinkSpeedOfLight) ? (LinkSpeedOfLight) thisUplink : null; Object thisDownlink = commsys.getLinks().findFirst(satelliteTransceiver, downlinkReceiver); LinkSpeedOfLight desiredDownlink = (thisDownlink instanceof LinkSpeedOfLight) ? (LinkSpeedOfLight) thisDownlink : null;
Once the links are added you can automatically orient all antennas to target each other. There's a list of rules defining how the targeting takes place in the CommunicationSystem.configureAntennaTargeting method. This method sets the OrientationAxes (get / set) property of the communication objects to a AxesTargetingLink type, using the DefaultReferenceVector (get / set) definition.
// Since we didn't manually specify the OrientationAxes properties for our objects, // we can automatically configure them with the call below. // Be sure to check the results of the orientation. AntennaTargetingResultCollection configurationResults = commsys.configureAntennaTargeting();
CommunicationSystem provides both instance and static methods for evaluating a link budget. In our case, we'll use the instance methods, allowing the CommunicationSystem to handle the details of the SignalPropagationGraph, the WirelessLinkExtension, and so on.
When we call the CommunicationSystem.getLinkBudgetEvaluator method, it returns a Evaluator<LinkBudget>, which we can use to evaluate the given link budget at a given time. Note that when you get an evaluator from the CommunicationSystem, the current DefaultPropagationModels (get) and DefaultReferenceVector (get / set) are used for all future evaluations of that instance of the evaluator. If you change either of those properties of the CommunicationSystem, you'll have to get a new evaluator for your changes to take effect.
When getting a link budget evaluator, we have to tell the CommunicationSystem which link we want to evaluate. We can do this by providing a reference to the link itself, or by using one of the find or findFirst methods. In addition to the link, we have to specify the intended signal of interest in the CommunicationSystem, using an IntendedSignalStrategy.
// Now evaluate the link budget for the uplink (we already know some of the access times from STK) JulianDate startAccess = new JulianDate(GregorianDate.parse("16 Aug 2011 10:35:00")); JulianDate stopAccess = new JulianDate(GregorianDate.parse("16 Aug 2011 12:30:00")); JulianDate singleTimeToEvaluate = new JulianDate(GregorianDate.parse("16 Aug 2011 10:37:13.826")); // When retrieving evaluators, we need to specify our desired signal. IntendedSignalByTransmitter intendedSignal = new IntendedSignalByTransmitter(uplinkTransmitter); // Create an Evaluator group to optimize the evaluator calculations. // Since the CommunicationSystem has many evaluators within it, you should always create an EvaluatorGroup EvaluatorGroup group = new EvaluatorGroup(); // Retrieve evaluators for the uplink and downlink signals. // For more information on evaluators, see the "Evaluators And Evaluator Groups" topic under "Patterns". Evaluator<LinkBudget> uplinkLinkBudgetEval = commsys.getLinkBudgetEvaluator(desiredUplink, intendedSignal, group); Evaluator<LinkBudget> downlinkLinkBudgetEval = commsys.getLinkBudgetEvaluator(desiredDownlink, intendedSignal, group); // Optimize the evaluator group - this will speed up evaluations group.optimizeEvaluators(); // Evaluate the LinkBudget LinkBudget uplinkBudget = uplinkLinkBudgetEval.evaluate(singleTimeToEvaluate); LinkBudget downlinkBudget = downlinkLinkBudgetEval.evaluate(singleTimeToEvaluate);
Adding interference sources will add additional noise to the system. We create three new SimpleDigitalTransmitters, each slightly off-frequency from the intended signal. In the constructor for each interferer, we set their position to be close to the original transmitter. After creation, we adjust their OrientationAxes (get / set), using their new location as a reference. We don't need to target these, they're just general jammers, so we set their OrientationAxes (get / set) to AxesEastNorthUp.
// Add some uplink interference sources, slightly off frequency SimpleDigitalTransmitter uplinkInterferer1 = new SimpleDigitalTransmitter( "Jammer 1", new PointFixedOffset(uplinkTransmitter.getReferenceFrame(), new Cartesian(1000, 1000, 20)), uplinkTransmitter.getCarrierFrequency() * 1.05, // 5% over frequency means the jamming freq is 15.225 GHz or 725 MHz past the center freq // of the true transmitter. If the filter on your receiver is not this wide (a bandwidth // of 1.45 GHz minimum), you won't see interference from this jammer. Our transceiver's // filter above is not this wide, so we won't see the effects of this jammer. Widen // the transceiver's bandwidth to see greater interference, or narrow to reduce the // interference effect. uplinkTransmitter.getEffectiveIsotropicRadiatedPower(), uplinkTransmitter.getDataRate()); SimpleDigitalTransmitter uplinkInterferer2 = new SimpleDigitalTransmitter( "Jammer 2", new PointFixedOffset(uplinkTransmitter.getReferenceFrame(), new Cartesian(-1000, 1000, 25)), uplinkTransmitter.getCarrierFrequency() * 1.04, uplinkTransmitter.getEffectiveIsotropicRadiatedPower(), uplinkTransmitter.getDataRate()); SimpleDigitalTransmitter uplinkInterferer3 = new SimpleDigitalTransmitter( "Jammer 3", new PointFixedOffset(uplinkTransmitter.getReferenceFrame(), new Cartesian(0, -1000, 15)), uplinkTransmitter.getCarrierFrequency() * 0.98, uplinkTransmitter.getEffectiveIsotropicRadiatedPower(), uplinkTransmitter.getDataRate()); // Orient them // The other antennas remain oriented, we'll specify these antenna's orientation's explicitly uplinkInterferer1.setOrientationAxes(new AxesEastNorthUp(earth, new PlatformLocationPoint(uplinkInterferer1))); uplinkInterferer2.setOrientationAxes(new AxesEastNorthUp(earth, new PlatformLocationPoint(uplinkInterferer2))); uplinkInterferer3.setOrientationAxes(new AxesEastNorthUp(earth, new PlatformLocationPoint(uplinkInterferer3)));
CommunicationSystem contains two collections used in interference analysis. The TransmitToAll (get) collection contains transmitters that are intended to transmit to all receivers in the CommunicationSystem. When you add a transmitter to this collection, the CommunicationSystem creates links from it to all receivers currently defined in the Links (get) property. There is also a ReceiveFromAll (get) collection where you add receivers that should accept interference from all transmitters in the Links (get) property.
A receiver does not have to be in the ReceiveFromAll (get) collection to be affected by an interference source. If you happen to add a receiver to the Links (get) collection after you add all of your transmitters, you can add the receiver to the ReceiveFromAll (get) collection to get all the correct links generated.
// Add these jammers to the commsys TransmitToAll collection commsys.getTransmitToAll().add(uplinkInterferer1); commsys.getTransmitToAll().add(uplinkInterferer2); commsys.getTransmitToAll().add(uplinkInterferer3); // Now that we've changed the commsys, we need to ask for a new evaluator. uplinkLinkBudgetEval = commsys.getLinkBudgetEvaluator(desiredUplink, intendedSignal, group); group.optimizeEvaluators(); // Reevaluate, get the entire LinkBudget over the time we're looking at, every 60 seconds DateMotionCollection1<LinkBudget> uplinkBudgetOverTime = uplinkLinkBudgetEval.evaluate(startAccess, stopAccess, Duration.fromSeconds(60), null);
Using a CommunicationObjectConstraint, we can create multiple constraints on our signal and evaluate when we have access to the signal based on those constraints.
// While the actual link budget itself is very useful, in order to use communications results // in other access queries, we need to get the scalar definitions of the link budget. LinkBudgetScalars uplinkScalars = commsys.getLinkBudgetScalars(desiredUplink, intendedSignal); // Setup a range for our CarrierToInterference values double minThreshold = 0; double maxThreshold = 5.0; // Combine two link budget constraints CommunicationObjectConstraint interferenceConstraint = new CommunicationObjectConstraint(uplinkScalars.getCarrierToInterference(), minThreshold, maxThreshold); // Bit Error rate up to 0.1 only CommunicationObjectConstraint berConstraint = new CommunicationObjectConstraint(uplinkScalars.getBitErrorRate(), 0.0, 0.1); // Combine access constraints (queries) using boolean operators AccessQuery combinedQuery = AccessQuery.and(interferenceConstraint, berConstraint); // Use the satellite transceiver platform as the observer AccessEvaluator accessEval = combinedQuery.getEvaluator(desiredUplink.getReceiver()); // Compute Access AccessQueryResult result = accessEval.evaluate(startAccess, stopAccess);