blob: f03f2604e4991a98174477548d24dec20cf40f31 [file] [log] [blame]
// *****************************************************************************
// 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"
}