| // ***************************************************************************** |
| // Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // which accompanies this distribution, and is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // Contributors: |
| // Regent L'Archeveque - initial API and implementation |
| // |
| // SPDX-License-Identifier: EPL-1.0 |
| // ***************************************************************************** |
| @GenModel(prefix="ApogyCoreEnvironmentEarthOrbitPlanner", |
| childCreationExtenders="true", |
| extensibleProviderFactory="true", |
| copyrightText="******************************************************************************* |
| Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency |
| All rights reserved. This program and the accompanying materials |
| are made available under the terms of the Eclipse Public License v1.0 |
| which accompanies this distribution, and is available at |
| http://www.eclipse.org/legal/epl-v10.html |
| |
| Contributors: |
| Regent L'Archeveque - initial API and implementation |
| |
| SPDX-License-Identifier: EPL-1.0 |
| *******************************************************************************", |
| modelName="ApogyCoreEnvironmentEarthOrbitPlanner", |
| complianceLevel="8.0", |
| suppressGenModelAnnotations="false", |
| dynamicTemplates="true", |
| templateDirectory="platform:/plugin/org.eclipse.apogy.common.emf.codegen/templates") |
| @GenModel(modelDirectory="/org.eclipse.apogy.core.environment.earth.orbit.planner/src-gen") |
| @GenModel(editDirectory= "/org.eclipse.apogy.core.environment.earth.orbit.planner.edit/src-gen") |
| |
| package org.eclipse.apogy.core.environment.earth.orbit.planner |
| |
| import java.util.List |
| import org.eclipse.apogy.common.Apogy |
| import org.eclipse.apogy.common.emf.EObjectReferencesList |
| import org.eclipse.apogy.common.emf.NamedDescribedElement |
| import org.eclipse.apogy.common.emf.TimeInterval |
| import org.eclipse.apogy.common.processors.Processor |
| import org.eclipse.apogy.core.environment.earth.EarthOutlook |
| import org.eclipse.apogy.core.environment.earth.orbit.EarthOrbitTool |
| import org.eclipse.apogy.core.environment.earth.orbit.EarthSpacecraft |
| import org.eclipse.apogy.core.environment.earth.orbit.OrbitAnalysisData |
| import org.eclipse.apogy.core.environment.earth.orbit.VisibilityPass |
| import org.eclipse.core.runtime.IProgressMonitor |
| |
| type ObservationPlan wraps EObjectReferencesList<ObservationAnalysisPlannerNode> |
| type ObservationAnalysisPlannerNodeList wraps List<ObservationAnalysisPlannerNode> |
| type VisibilityPassesList wraps List<VisibilityPass> |
| type IProgressMonitor wraps IProgressMonitor |
| type VisibilityPassReferencesList wraps EObjectReferencesList<VisibilityPass> |
| type Exception wraps java.lang.Exception |
| |
| /* |
| * Planner Facade. |
| */ |
| @Apogy(isSingleton="true", hasCustomClass="true") |
| class ApogyCoreEnvironmentEarthOrbitPlannerFacade{ |
| |
| /* |
| * Analyzes and generate the opportunities plan tree. This tree contains all the possible sequences |
| * to handle the requested observation target. This method runs inside a Job. |
| * @param passes List of passes to analyze. |
| * @param monitor Progress monitor. If null, NullProgressMonitor will be used. |
| * @return Refers the root node of the tree. |
| */ |
| op ObservationAnalysisPlannerNode generateObservationsPlanTree(VisibilityPassesList passes, IProgressMonitor monitor) |
| |
| /* |
| * Browses and processes the cost of each branches contained in the plan tree. This method runs in a job. |
| * @param data Observation analysis data that contains the context and the results required to conduct the analysis. |
| * @param monitor Progress monitor. If null, NullProgressMonitor will be used. |
| * @return Refers to the original planner but with updated data. |
| */ |
| op ObservationAnalysisPlanner computePlanCosts(ObservationAnalysisPlanner planner, IProgressMonitor monitor) |
| |
| /* |
| * Returns the {@link ObservationAnalysisPlannerTool} singleton of the active session. |
| * @return The reference to the {@link ObservationAnalysisPlannerTool} or null if not found. |
| */ |
| op ObservationAnalysisPlannerTool getObservationAnalysisPlannerTool() |
| |
| /* |
| * This method returns all the leafs of the specified root node. Each path from root to the leafs represents a solution. |
| * @param root Refers to the root of the tree structure. |
| * @return List of Observation Analysis Planner Leaf Nodes. |
| */ |
| op ObservationAnalysisPlannerNodeList getLeafs(ObservationAnalysisPlannerNode root) |
| |
| /* |
| * This method solution path based on the specified leaf. |
| * @param leaf Refers to a leaf that represents a solution of the tree structure. |
| * @return List of {@link ObservationAnalysisPlannerNode} from root to leaf. The leaf |
| * is included in the list but not the root. |
| */ |
| op ObservationPlan getPlannerSolution(ObservationAnalysisPlannerNode leaf) |
| |
| /* |
| * Returns the list of {@link VisibilityPass} contains in the specified list of nodes. |
| * @param nodesList List of nodes. |
| * @return Refers the list of passes. |
| */ |
| op VisibilityPassReferencesList getVisibilityPasses(ObservationAnalysisPlannerNodeList nodesList) |
| |
| /* |
| * Returns the total cost of all the stateless cost functions applicable to the specified visibility pass. |
| * @param node Refers the planner node. |
| * @return The total cost after the application of {@link AbstractCostFunction#getCoefficient()}. |
| */ |
| op double getNodeStatelessTotalCost(ObservationAnalysisPlannerNode node) |
| |
| /* |
| * Returns the total cost of all the stateful cost functions applicable to the specified planner node. |
| * @param node Refers the planner node. |
| * @return The total cost after the application of {@link AbstractCostFunction#getCoefficient()}. |
| */ |
| op double getNodeStatefulTotalCost(ObservationAnalysisPlannerNode node) |
| |
| /* |
| * Returns the total cost of all cost functions applicable to the specified planner node. |
| * @param node Refers the planner node. |
| * @return The total cost after the application of {@link AbstractCostFunction#getCoefficient()}. |
| * @see #getStatelessCostFunctionTotalCost(VisibilityPass) |
| * @see #getStatefulCostFunctionTotalCost(ObservationAnalysisPlannerNode) |
| */ |
| op double getNodeTotalCost(ObservationAnalysisPlannerNode node) |
| |
| /* |
| * Returns the total cost of the specified plan. |
| * @param plan Refers the plan. |
| * @return The total cost after the application of {@link AbstractCostFunction#getCoefficient()}. |
| * @see #getStatelessCostFunctionTotalCost(VisibilityPass) |
| * @see #getStatefulCostFunctionTotalCost(ObservationAnalysisPlannerNode) |
| */ |
| op double getSolutionTotalCost(ObservationPlan plan) |
| } |
| |
| /* |
| * Defines the Observation Analysis Tool. |
| */ |
| class ObservationAnalysisPlannerTool extends EarthOrbitTool |
| { |
| contains ObservationAnalysisPlanner[0..*] planners |
| refers ObservationAnalysisPlanner[1] activePlanner |
| |
| contains AbstractObservationPlanExporter[0..*] observationPlanExporters |
| } |
| |
| /* |
| * Default Apogy Observation Analysis Planner. |
| */ |
| @Apogy(hasCustomClass="true") |
| class ObservationAnalysisPlanner extends NamedDescribedElement{ |
| refers OrbitAnalysisData[1] orbitAnalysisData |
| |
| /* |
| * List of stateless cost functions. |
| */ |
| @GenModel(property="None") |
| contains AbstractStatelessCostFunction[0..*] statelessCostFunctions |
| |
| /* |
| * List of stateful cost functions. |
| */ |
| @GenModel(property="None") |
| contains AbstractStatefulCostFunction<CostFunctionState>[0..*] statefulCostFunctions |
| |
| /* |
| * Planner result. |
| */ |
| @GenModel(property="None") |
| contains ObservationAnalysisPlannerResult[1] result opposite planner |
| |
| /* |
| * Indicates if the planner is running. |
| */ |
| transient boolean running = "false" |
| } |
| |
| @Apogy(hasCustomClass="true") |
| class ObservationAnalysisPlannerNode{ |
| |
| container ObservationAnalysisPlannerResult result opposite planRootNode |
| |
| String ^id |
| refers VisibilityPass[0..1] pass |
| |
| @GenModel(property="None") |
| container ObservationAnalysisPlannerNode parent opposite children |
| |
| @GenModel(property="None") |
| contains ObservationAnalysisPlannerNode[0..*] children opposite parent |
| |
| |
| derived boolean rootNode get { |
| return parent === null |
| } |
| |
| refers local readonly volatile transient derived ObservationAnalysisPlannerNode plannerRootNode get { |
| if (parent === null) { |
| return this |
| } else { |
| return parent.plannerRootNode |
| } |
| } |
| |
| refers local readonly volatile transient derived ObservationAnalysisPlannerResult plannerResult get { |
| if (plannerRootNode === null) { |
| return null |
| } else { |
| return plannerRootNode.result |
| } |
| } |
| |
| refers local readonly volatile transient derived ObservationAnalysisPlanner planner get { |
| if (plannerRootNode.result === null) { |
| return null |
| } else { |
| return plannerResult.planner |
| } |
| } |
| |
| /* |
| * Map that contains the Stateful cost function results. |
| */ |
| contains StatefulCostFunctionMapEntry[0..*] statefulCostsMapEntries |
| |
| /* |
| * Cost of the current node. It corresponds to the sum of all applicable {@link StatelessCostFunctions} & |
| * {@link StatefulCostFunctions}. |
| */ |
| derived volatile transient readonly double cost = "0" |
| |
| /* |
| * Cumulative cost including the cost of this node up to its first level node. |
| */ |
| derived volatile transient readonly double cumulativeCost = "0" |
| |
| |
| /* |
| * Returns the level 1 node. The root node (top node without parent) contains the first level nodes. |
| */ |
| refers readonly volatile derived transient ObservationAnalysisPlannerNode firstLevelNode |
| |
| /* |
| * Returns the node level. |
| */ |
| readonly transient volatile derived int level |
| |
| /* |
| * Returns the solution duration processed from the to date of the last visibility pass (this node) and the from date of |
| * the first visibility pass (first level node). |
| */ |
| @Apogy(units="ms") |
| derived volatile transient readonly double solutionDuration = "0" |
| |
| /* |
| * Returns the duration of the pass associated to the current node. |
| */ |
| @Apogy(units="ms") |
| derived volatile transient readonly double passDuration = "0" |
| |
| /* |
| * Returns the sums of the duration of the current pass up to its first first level node pass. |
| * |
| */ |
| @Apogy(units="ms") |
| derived volatile transient readonly double totalPassesDuration = "0" |
| } |
| |
| @Apogy(hasCustomClass="true") |
| class ObservationAnalysisPlanGenerator extends Processor<VisibilityPassesList, ObservationAnalysisPlannerNode>, NamedDescribedElement{ |
| } |
| |
| @Apogy(hasCustomClass="true") |
| class ObservationAnalysisPlanCostsProcessor extends Processor<ObservationAnalysisPlanner, ObservationAnalysisPlanner>, NamedDescribedElement{ |
| } |
| |
| /** |
| * Base class for exporter of Observation Plan. |
| */ |
| abstract class AbstractObservationPlanExporter extends NamedDescribedElement |
| { |
| /** |
| * Exports a given Observation plan to a destination. |
| * @param plan The Observation Plan. |
| * @param planner The Planner that produced the Observation plan. |
| * @param A Progress Monitor that can be used to report progress on the export. |
| * @throw An exception is a problem occurs during the export. |
| */ |
| op void exportObservationPlan(ObservationPlan plan, ObservationAnalysisPlanner planner, IProgressMonitor monitor) throws Exception |
| } |
| |
| /** |
| * Default exporter of Observation Plan. This exporter exports the plan to a csv formatted file which location is specified by a URL. |
| */ |
| @Apogy(hasCustomClass="true") |
| class DefaultObservationPlanExporter extends AbstractObservationPlanExporter |
| { |
| /** |
| * The URL to the file to which to export the ObservationPlan. |
| */ |
| String fileURL |
| } |
| |
| /* |
| * Cost functions are used to compute the impact of executing a {@link Visibility} according |
| * to a series of custom parameters that are specialized in sub-classes. |
| * Please use the {@link Constants#InfiniteCostValue} to specified an infinite cost. |
| */ |
| @Apogy(hasCustomClass="true") |
| abstract class AbstractCostFunction extends NamedDescribedElement{ |
| /* |
| * Flag use to enable or disable the cost function. |
| */ |
| boolean enable = "true" |
| |
| /* |
| * Coefficient use to specify the weight of the cost function. |
| */ |
| @Apogy(min="0.0", max="1.0") |
| double coefficient = "0.5" |
| |
| /* |
| * Specifies the spacecrafts to apply the cost. If empty, the planner |
| * will apply to all spacecrafts defined in the {@OrbitAnalysisData}. |
| */ |
| refers EarthSpacecraft[0..*] applicableSpacecrafts |
| |
| /* |
| * Specifies the outlooks to apply the cost. If empty, the planner |
| * will apply to all outlooks defined in the {@OrbitAnalysisData}. |
| */ |
| refers EarthOutlook[0..*] applicableEarthOutlooks |
| } |
| |
| class CostFunctionState{ |
| } |
| |
| abstract class AbstractStatelessCostFunction extends AbstractCostFunction{ |
| op double computeCost(VisibilityPass pass) |
| } |
| |
| abstract class AbstractStatefulCostFunction<State extends CostFunctionState> extends AbstractCostFunction{ |
| /* |
| * FIXME Document this. |
| */ |
| op double computeCost(CostFunctionState previousState, CostFunctionState nextState, VisibilityPass pass) |
| |
| /* |
| * The planner invokes this method to map the cost function to its state. The default implementation |
| * returns a new instance of {@link EmptyCostFunctionState} |
| * This method may be overloaded to implement specific state depending of the cost function needed. |
| * @return Refers to the newly created state. |
| */ |
| op CostFunctionState createState() |
| } |
| |
| class ObservationAnalysisPlannerResult{ |
| container ObservationAnalysisPlanner planner opposite result |
| |
| contains ObservationAnalysisPlannerNode[1] planRootNode opposite result |
| |
| contains StatelessCostsMapEntry[0..*] statelessCostsMapEntries |
| } |
| |
| /* |
| * |
| * Stateless Map and Map Entries. |
| * |
| */ |
| class StatelessCostsMapEntry wraps java.util.Map$Entry{ |
| refers VisibilityPass key |
| contains StatelessCostFunctionMap[1] value |
| } |
| |
| class StatelessCostFunctionMap{ |
| contains StatelessCostFunctionMapEntry[0..*] statelessCostFunctionMapEntries |
| } |
| |
| class StatelessCostFunctionMapEntry wraps java.util.Map$Entry{ |
| refers AbstractStatelessCostFunction key |
| Double value |
| } |
| |
| |
| /* |
| * |
| * Stateful Map and Map Entries. |
| * |
| */ |
| class StatefulCostFunctionMapEntry wraps java.util.Map$Entry{ |
| refers AbstractStatefulCostFunction<CostFunctionState> key |
| contains StatefulCostFunctionMapEntryValue value |
| } |
| |
| class StatefulCostFunctionMapEntryValue{ |
| contains CostFunctionState state |
| double cost |
| } |
| |
| /* |
| * |
| * Pre-defined Cost Functions. |
| * |
| */ |
| |
| /* |
| * Eclipse Period. |
| */ |
| enum EclipsePeriod{ |
| NotInEclipse as "NOT_IN_ECLIPSE" = 0, |
| Penumbra as "PENUMBRA" = 1, |
| Umbra as "UMBRA" = 2 |
| } |
| |
| /* |
| * This cost function is used in the context of eclipses processing. |
| * The cost is applied if at any point in time the visibility pass completely |
| * or partially overlaps with the specified {@link EclipsePeriod}. |
| */ |
| @Apogy(hasCustomClass="true") |
| class EclipseCostFunction extends AbstractStatelessCostFunction{ |
| EclipsePeriod state = "NOT_IN_ECLIPSE" |
| double cost = "0.0" |
| } |
| |
| |
| /* |
| * This cost function can be used to determine if a pass overlaps a {@link TimeInterval}. |
| * The cost is applied if at any point in time the visibility pass completely |
| * or partially overlaps with the specified {@link TimeInterval}. |
| */ |
| @Apogy(hasCustomClass="true") |
| class TimeIntervalCostFunction extends AbstractStatefulCostFunction<CostFunctionState>, TimeInterval{ |
| /* |
| * Cost to apply if in the specified interval range. |
| */ |
| double cost = "0.0" |
| } |
| |
| /* |
| * This cost function may be used to evaluate the impact in term of resource (memory, power etc). |
| * The cost is infinite if the value gets under the specified minimum resource value or if the |
| * value gets above the maximum resource value. |
| */ |
| @Apogy(hasCustomClass="true") |
| class SimpleResourceCostFunction extends AbstractStatefulCostFunction<SimpleResourceCostFunctionState>{ |
| double initialResourceValue = "0.0" |
| double minimumResourceValue = "-1.0" |
| double maximumResourceValue = "1.0" |
| } |
| |
| /* |
| * State used to store the current resource level value. It is used with the {@link SimpleResourceCostFunction}. |
| */ |
| class SimpleResourceCostFunctionState extends CostFunctionState{ |
| double value = "0.0" |
| } |
| |
| /* |
| * This cost function is used to reject {@link VisilibiltyPass} if the current and subsequent passes are within a specified time period. |
| * If the process time is less than the specified minimumTimeSpam, the {@link Constants#INFINITE_COST_VALUE} is returned. |
| */ |
| @Apogy(hasCustomClass="true") |
| class MinimumTimeSpamCostFunction extends AbstractStatefulCostFunction<CostFunctionState>{ |
| long minimumTimeSpam = "0" |
| } |
| |
| /* |
| * This cost function returns a zero cost value if the processed {@link VisibilityPass} has a cross angle lower than the |
| * limit specified. If at any point in the history this condition is not met, {@link Constants#INFINITE_COST_VALUE} is returned. |
| */ |
| @Apogy(hasCustomClass="true") |
| class CrosstrackAngleCostFunction extends AbstractStatelessCostFunction{ |
| double cost = "0.0" |
| |
| @Apogy(units="rad") |
| double angle = "10.0" |
| } |