Access queries are a flexible tool for solving complex intervisibility problems, such as:
When can my aircraft see at least 4 GPS satellites?
When can the Spirit rover transmit data to Earth, either directly or via Mars Odyssey?
When can LandSat take a picture of a target and send it to a ground station, relaying it via any TDRS satellite?
When can my aircraft see a ground station and not be seen by any of a set of satellites?
Any of the types of problems that can be solved with the STK Chain and Constellation objects.
Access queries use access constraints to model individual requirements that must be satisfied in order for access to be available, allowing constraints on any number of different objects to be combined in a single access problem. and allowing those constraints to be combined in arbitrary ways using boolean operators. Access queries support the following boolean operators:
And - AccessQueryAnd
Or - AccessQueryOr
Not - AccessQueryNot
At Least N - AccessQueryAtLeastN
At Most N - AccessQueryAtMostN
Exactly N - AccessQueryExactlyN
Additionally, a single access constraint, all by itself, is an access query. That means that it can, once configured, be evaluated directly to determine the intervals when that single constraint is satisfied. For example:
AltitudeConstraint constraint = CreateAnyOldAltitudeConstraint(); AccessEvaluator evaluator = constraint.GetEvaluator(); AccessQueryResult result = evaluator.Evaluate(startDate, stopDate);
In order for a constraint to be used as a query or as a part of a query, it must be fully configured. Specifically, it is necessary to set the ConstrainedObject property if it is an ISingleObjectConstraint, or the ConstrainedLink property if it is an ILinkConstraint.
In an ISingleObjectConstraint, the ConstrainedObject property should be set to the object to which the constraint is applied. For example, in an AltitudeConstraint, the ConstrainedObject property is the aircraft (or any other type of object) whose altitude is required to be within a range of altitudes.
Platform aircraft = CreateAnyOldAircraft(); // Create a constraint and configure it to constrain the altitude of the aircraft. AltitudeConstraint aircraftAltitudeLessThan1000 = new AltitudeConstraint(); aircraftAltitudeLessThan1000.ConstrainedObject = aircraft; aircraftAltitudeLessThan1000.MaximumValue = 1000.0;
A link has two ends: a Transmitter end and a Receiver end. The link models the geometric relationship between them. A link can describe where the transmitter appears to be when observed by the receiver and where the receiver will be when it receives the signal transmitted by the transmitter. It can also model the delay when communicating over the link.
DME Component Libraries comes with two link classes:
LinkInstantaneous - This link models instantaneous communication between a transmitter and receiver. There is no delay between time of transmission and time of reception, and both ends of the link reflect their true position when observed by the other end of the link.
LinkSpeedOfLight - This link models communication between a transmitter and receiver that takes place at the speed of light. The delay between time of transmission and time of reception depends on the distance between the objects. Also, the apparent position of either end when observed by the other reflects light-time delay and, optionally, aberration.
Both types of links implement IServiceProvider and are extensible in the same way that Platform is extensible. By default, they model only the geometric relationship between a transmitter and a receiver, available through the ILinkService service. However, like any extensible object, they can also be extended with additional capabilities. See the Service Providers topic for more information.
As the name implies, a link constraint is a constraint which is applied to a link. As such, it constrains the relationship between two objects. Many access constraints in DME Component Libraries are link constraints, for example ElevationAngleConstraint and SensorVolumeConstraint.
To use a link constraint as a query, the ConstrainedLink and ConstrainedLinkEnd properties must be set. The ConstrainedLink property should be set to the LinkInstantaneous or LinkSpeedOfLight that models how the two objects are related. The ConstrainedLinkEnd property should identify which end of the link (the transmitter or receiver) is observing the other object for the purposes of the constraint. For example, when using an ElevationAngleConstraint, the ConstrainedLinkEnd property identifies which end of the link is observing the elevation angle to the other object.
Some constraints that implement ILinkConstraint, such as CentralBodyObstructionConstraint, do not actually use the configured ConstrainedLinkEnd, because the constraint applies to the link as a whole.
The following example shows how to create and configure a link constraint:
EarthCentralBody earth = CentralBodiesFacet.GetFromContext().Earth; Platform facility = CreateAnyOldFacility(); Platform satellite = CreateAnyOldSatellite(); // Create a link relating the facility and satellite LinkSpeedOfLight satelliteToFacility = new LinkSpeedOfLight(satellite, facility, earth.InertialFrame); // Create a constraint and configure it with the link. ElevationAngleConstraint facilitySeesSatellite = new ElevationAngleConstraint(); facilitySeesSatellite.ConstrainedLink = satelliteToFacility; facilitySeesSatellite.ConstrainedLinkEnd = LinkRole.Receiver; facilitySeesSatellite.MinimumValue = 0.0;
While a fully configured constraint can be used alone as a query, the real power of access queries comes from combining constraints in various ways. Constraints (and other queries) can be combined together to define a complex problem. For example:
// See previous examples for the construction of 'facilitySeesSatellite' and // 'aircraftAltitudeLessThan1000'. AltitudeConstraint aircraftAltitudeGreaterThan5000 = new AltitudeConstraint(); aircraftAltitudeGreaterThan5000.ConstrainedObject = aircraft; aircraftAltitudeGreaterThan5000.MinimumValue = 5000.0; ElevationAngleConstraint facilitySeesAircraft = new ElevationAngleConstraint(); facilitySeesAircraft.ConstrainedLink = new LinkInstantaneous(aircraft, facility); facilitySeesAircraft.ConstrainedLinkEnd = LinkRole.Receiver; facilitySeesAircraft.MinimumValue = 0.0; AccessQuery query = facilitySeesSatellite & facilitySeesAircraft & (aircraftAltitudeLessThan1000 | aircraftAltitudeGreaterThan5000);
Operator overloading makes it very natural to express these boolean arrangements of constraints. The same query can also be expressed by explicitly constructing query objects:
AccessQuery verboseQuery = new AccessQueryAnd(facilitySeesSatellite, facilitySeesAircraft, new AccessQueryOr(aircraftAltitudeLessThan1000, aircraftAltitudeGreaterThan5000));
Inherent in every access constraint are various tolerances that dictate the computational effort, accuracy, and precision of the access query result. For any given AccessConstraint, as the system computes access it explores the analysis time domain via the JulianDateFunctionExplorer mechanism. The JulianDateFunctionExplorer has several associated tolerances for detecting constraint function threshold crossings (satisfaction). One such tolerance is the CrossingDateTolerance. This tolerance is set to 5 milliseconds by default. For scenarios where rapidly moving objects are involved, the objects could move an appreciable distance in this short time frame. This fact may affect the satisfaction intervals to an unacceptable degree if highly precise geometric boundaries are involved. Other important tolerances exist in the JulianDateFunctionExplorer that may affect output and should be considered when setting precise satisfaction intervals. It is recommended that users read the associated documentation to determine if modification is necessary to meet analysis requirements.
Tolerances specific to the access query in question may also be involved in the final output. For example, constraints derived from MinimumMaximumAccessConstraint use both a MinimumTolerance and a MaximumTolerance. If we look at RangeConstraint, which is derivative of the min/max access constraint, these two tolerances affect what range values count within the minimum and maximum range boundaries. Thus in this specific example, proximity to a range boundary will be affected by both the time tolerances in the function explorer and the geometric tolerances in the range constraint. We therefore recommend that in addition to keeping the function explorer's tolerances in mind, the user should also consider the tolerances involved in the specific constraint used.
DME Component Libraries also includes capabilities to easily create an access query from higher-level constructs:
FromObject - Given a link between two objects, this method constructs a query from all of the constraints attached to the link itself or to the objects on either end using AccessConstraintsExtension instances.
AnyPath - Given a transmitter, a receiver, and a list of possible links that can be traversed between the two, returns a query that determines when any path exists for the transmitter to communicate with the receiver. Constraints attached to the links and the objects themselves with AccessConstraintsExtension are used to determine when individual links and participants are valid.
The queries that result from these higher-level constructs can be combined with constraints and with other higher-level constructs in the same way as any other query.
Access queries account for link delay through multiple hops. This is extremely important for obtaining correct answers in interplanetary scenarios. It also yields more accurate answers even in Earth-centric cases, particularly with high orbits.
Consider the case of a ground station on Mars, a relay satellite in low Mars orbit, and a ground station on Earth. We want to know when the Mars ground station can transmit a message, relayed via the satellite in Mars orbit, such that it can be received by the Earth ground station. Since it can often take on the order of 20 minutes to transmit a signal at the speed of light between Earth and Mars, it is vital to keep track of which participant is observing events such as the start and end of access.
As an illustration of the effect, imagine that we already know when access begins and ends, and we arrange for the Mars ground station to send a transmission precisely at the time that access starts. Because the satellite in Mars orbit is relatively close to the surface of Mars, it receives and then relays the transmission just a few milliseconds after transmission by the ground station. About 20 minutes later, the signal can be picked up by the ground station on Earth. One way you can think of this is that access "starts" at different times for the different participants. The time intervals when the Earth ground station can receive a signal from the Mars ground station are shifted about 20 minutes later than the time intervals when the Mars ground station can transmit a signal that can be received on Earth.
In general, access queries will take care of these details for you. The only thing you must do is tell the system, at the time you create an evaluator for a query, which participant is the time observer:
AccessQuery query = CreateAnyOldQuery(); Platform marsGroundStation = CreateAnyOldMarsGroundStation(); AccessEvaluator evaluator = query.GetEvaluator(marsGroundStation); JulianDate start = new GregorianDate(2008, 6, 25, 12, 0, 0.0).ToJulianDate(); JulianDate stop = new GregorianDate(2008, 6, 26, 12, 0, 0.0).ToJulianDate(); AccessQueryResult result = evaluator.Evaluate(start, stop);
Here we are evaluating the access from June 25, 2008 at noon until June 26, 2008 at noon. These times represent events observed by whichever participant has been designated the time observer, in this case the Mars ground station. So, very specifically, we are asking when, between those two times, the Mars ground station could transmit a signal that could be received and relayed by the orbiting satellite and then received by the Earth ground station.
The AGI.Foundation.Access namespace contains a number of useful types other than those mentioned in the above example. In addition, the AGI.Foundation.Access.Constraints namespace contains many other access constraints besides the two mentioned here. To gain a fuller understanding of the ways in which DME Component Libraries supports access computation and constraints, you may want to browse through those namespaces.