这一节是对原文的翻译:http://help.agi.com/AGIComponents/html/EvaluatorParameterization.htm
求值器模式的工作原理是假设分析所需的所有信息都是预先知道的。也就是说,开发人员从已知的数据集创建定义对象,然后执行所需的分析。这样就可以为特定的计算创建高度优化的求值器。然而,在某些情况下,并非所有输入到计算中的信息都是预先知道的。在这些情况下,使用占位符对象设计系统可能很有用,这些对象经过专门设计,以便在随后实际求值时提供实际输入值。
正常的求值器是时间的函数,参数化求值器扩展了这个概念,以支持与其他参数相关的函数。
典型求值器
下面的代码示例显示了一个典型的分析情况,该情况使用普通求值器来确定无人机与其地面站之间是否存在过境。建立了两个平台,利用航路点建立了无人机的航路,并确定了地面站的位置。创建并求值一个AccessEvaluator,以便计算对链路的过境。Evaluator针对这个特定场景进行了优化,只要检查IThreadAware接口,Evaluator就可以同时从多个线程使用。
var earth = CentralBodiesFacet.GetFromContext().Earth;
var uavStart = new JulianDate(new GregorianDate(1980, 8, 1, 0, 0, 0));
var uavStop = new JulianDate(new GregorianDate(1980, 8, 1, 1, 0, 0));
var waypoints = new Waypoint[2];
waypoints[0] = new Waypoint(uavStart, new Cartographic(0, 0, 1000), 100, 10);
waypoints[1] = new Waypoint(waypoints[0], earth.Shape, new Cartographic(1, 1, 1000), 100);
var uavPropagator = new WaypointPropagator(earth, waypoints);
var uav = new Platform
{
LocationPoint = uavPropagator.CreatePoint(),
OrientationAxes = Axes.Root
};
var groundStation = new Platform
{
LocationPoint = new PointCartographic(earth, new Cartographic(0.0, 0.0, 0.0)),
OrientationAxes = Axes.Root
};
var link = new LinkInstantaneous(uav, groundStation);
var constraint = new CentralBodyObstructionConstraint(link, earth);
var evaluator = constraint.GetEvaluator();
if (evaluator.Evaluate(uavStart) != AccessClassification.AccessExists)
{
Console.WriteLine("No access found!");
}
这种方法假定你预先知道路径,以便使用路径点预报程序创建路径点。但是,假设你正在使用跟踪库跟踪一个实际的无人机操作,并且正在接收有关其位置的连续更新。
要使用标准求值器模式,每次收到新位置时,都会向预报器添加新的路径点,并且需要创建新的求值器。由于在内部进行的耗时优化,重复创建这样的求值器可能会变得非常耗时。求值器的设计是为了方便在只有时间变化的情况下进行有效的计算。此外,在本例中,将定义对象的属性同时从多个线程更改为WaypointPropagator是不安全的。导致每个求值器必须拥有定义路径的数据的自己的副本。基本上,求值器模式不是针对这种情况设计的。
参数化的求值器
参数化的求值器通过允许你预先指定所有已知信息来处理这种类型的场景,但是为直到求值时才会知道的数据插入占位符定义对象。下面的代码示例演示了如何设计与上述相同的过境计算,但在这种情况下,无人机的位置和方向是使用占位符从uavEntity实体中检索信息来定义的,随着任务的进行,该实体将使用跟踪库不断更新。
var earth = CentralBodiesFacet.GetFromContext().Earth;
var entityParameter = new EntityParameter<ExampleEntity>();
var uav = new Platform
{
LocationPoint = new EntityPoint<ExampleEntity>(entityParameter),
OrientationAxes = new EntityAxes<ExampleEntity>(entityParameter)
};
var groundStation = new Platform
{
LocationPoint = new PointCartographic(earth, new Cartographic(0.0, 0.0, 0.0)),
OrientationAxes = Axes.Root
};
var link = new LinkInstantaneous(uav, groundStation);
var constraint = new CentralBodyObstructionConstraint(link, earth);
var group = new EvaluatorGroup();
var evaluator = constraint.GetEvaluator(null, group);
var parameterizedEvaluator =
group.Parameterize(evaluator, TransactionParameter.Instance, entityParameter);
context.DoTransactionally(transaction =>
{
//Note that it is assumed that uavEntity is an entity
//object being managed by a different thread responsible
//for processing the live data as it is received.
JulianDate date = uavEntity.LastUpdate.GetValue(transaction);
AccessClassification result = parameterizedEvaluator.Evaluate(date, transaction, uavEntity);
if (result != AccessClassification.AccessExists)
{
Console.WriteLine("No access found!");
}
});
无人机平台的LocationPoint和OrientationAxes属性分别定义为EntityPoint<ExampleEntity>和EntityAxes<ExampleEntity>实例。这两个占位符定义对象都是使用相同的EntityParameter<ExampleEntity>实例构造的,这表示这两个对象都是在同一个实体参数上参数化的。然后,在EvaluatorGroup上调用参数化方法以创建参数化的Evaluator,该Evaluator将在事务和实体上参数化。最后,我们对参数化求值器进行求值,传递要求值的时间、事务和无人机实体。在内部,这些附加参数用于填充用于定义问题的占位符定义对象,在本例中是位置和方向,然后执行过境计算。
上面的示例显示一个动态移动的对象访问一个典型的地面位置,其位置可以在前面定义。这个相同的模式可以扩展到对两个实体之间的链接进行建模,其中两个实体都被数据馈送不断更新。例如,假设地面站实际上是一辆通信卡车,独立于无人机移动。以下代码示例显示了如何对其进行建模:
var earth = CentralBodiesFacet.GetFromContext().Earth;
var uavEntityParameter = new EntityParameter<ExampleEntity>();
var commsTruckEntityParameter = new EntityParameter<ExampleEntity>();
var uav = new Platform
{
LocationPoint = new EntityPoint<ExampleEntity>(uavEntityParameter),
OrientationAxes = new EntityAxes<ExampleEntity>(uavEntityParameter)
};
var commsTruck = new Platform
{
LocationPoint = new EntityPoint<ExampleEntity>(commsTruckEntityParameter),
OrientationAxes = new EntityAxes<ExampleEntity>(commsTruckEntityParameter)
};
var link = new LinkInstantaneous(uav, commsTruck);
var constraint = new CentralBodyObstructionConstraint(link, earth);
var group = new EvaluatorGroup();
var evaluator = constraint.GetEvaluator(null, group);
var parameterizedEvaluator =
group.Parameterize(evaluator, TransactionParameter.Instance, uavEntityParameter, commsTruckEntityParameter);
context.DoTransactionally(transaction =>
{
//Note that it is assumed that uavEntity and truckEntity
//are entity objects being managed by a different thread
//responsible for processing the live data as it is received.
JulianDate date = JulianDate.Now;
AccessClassification result = parameterizedEvaluator.Evaluate(date, transaction, uavEntity, truckEntity);
if (result != AccessClassification.AccessExists)
{
Console.WriteLine("No access found!");
}
});
注意,我们创建了两个EntityParameter<ExampleEntity>实例:一个表示无人机,一个表示卡车。然后使用每个参数构建相应的平台,并像以前一样构建过境查询。这可以根据需要扩展到包括尽可能多的平台和实体。
Evaluator参数化与STK组件中可用的任何Evaluator一起工作,并且在执行计算需要随时间变化而变化的任何情况下都有用。