|
||||||||||
PREV NEXT | FRAMES NO FRAMES |
See:
Description
Packages | |
---|---|
cz.cuni.amis.pogamut.shady | Shady - experimental POSH-like engine. |
cz.cuni.amis.pogamut.sposh | Classes and interfaces used with behavior class. |
cz.cuni.amis.pogamut.sposh.context | Context is an object shared among all primitives of the plan. |
cz.cuni.amis.pogamut.sposh.elements | This package contains parser for Yaposh plan, classes that represent elements of the plan and some auxiliry classes. |
cz.cuni.amis.pogamut.sposh.engine | Yaposh engine and its executors used to evaluate yaposh plan. |
cz.cuni.amis.pogamut.sposh.engine.timer | |
cz.cuni.amis.pogamut.sposh.exceptions | |
cz.cuni.amis.pogamut.sposh.executor | Classes for creation and execution of primitives. |
This library contains Yaposh, dynamic planner based on SPOSH.
This library contains
Yaposh is quite similar to behavior trees, the plan itself is a Directed Acyclic Graphs (DAG). The root node of Yaposh plan is called DriveCollection
(DC).
DC is a root of the plan, but not the object that stores all nodes of the plan, that would be PoshPlan
. The PoshPlan
contains DC of plan and all action patterns, comepetnces and adopts of the plan.
The DC has several children (at least one) called drives (DriveElement
). Each drive consists from its name, trigger and reference to some other node. The trigger is a condition that must be satisfied in order for drive to be elegible for selection.
DC can also have a goal, condition that specifies when the agent has fulfilled its goal in the environment. If goal is satisfied, there is no need to evaluate the rest of the plan.
The reference to some other node is called TriggeredAction
. The referenced node can be action(A), competence (C) or action pattern (AP), but not CompetenceElement or DriveElement nor Sense. Each node that can be referenced (A/AP/C) has a name. When TriggeredAction
references another node, it specifies name of referenced node and arguments passed to the referenced node (e.g. name "move-home" and argument $speed=5). The engine will take the name (e.g. "move-home") and finds node with identical name (A/AP/C).
Action node is a leaf that is not defined in the plan. It is defined outside of the plan and it is responsibility of the IWorkExecutor
to connect referenced name to correct action and execute the action. Actions of Yaposh are classes implementing the IAction
interface.
Action patterns (AP) are nodes that represent sequence, each AP has a list of references to other nodes (actions or another APs) and its job is to execute referenced nodes in specified sequence.
Competence node is a priority selector, the competence has several (at least one) children of type CompetenceElement
called choices. The choice consists from name of choice, trigger and reference to another node. Job of competence is to select one of its choices.
User shouldn't use constructors of nodes, but LapElementsFactory
factory instead.
The plan works by executing nodes. Each drive has its own stack of executors, note that thare are multiple stacks. The plan is executed in steps, in each step, stack of some drive is changed. Step of the plan starts with selection of drive that should be executed. That is done by selecting first drive (i.e. the one with highest priority) with satisfied trigger.
Once drive is selected, we look at its stack and if it is empty, add executor of referenced node to the top of the stack. If drive stack is not empty, take the executor at the top of the stack and execute it. It will do execute the node and return value that says how should engine change the drive stack (e.g. add executor for another element at the top, remove top executor, clear the stack...).
We will now describe executors for nodes (they are being executed is they are on top of the drive stack).
Executor of action will take the name of action and asks IWorkExecutor
to execute the action and according to returned ActionResult
change stack (running - remove the executor on the top, failed - clear stack).
Executor of action pattern keeps an index into the list of its node references. Each time it is executed, it takes the referenced node with specified index and adds its executor to the top of stack. If executor has executed all its references, it removes itself from the stack.
Executor of competence finds its first choice with satisfied trigger and adds executor of the referenced node from the choice to the top of the stack.
// plan id is used by LapPath, e.g. /P:1/.. is plan with id 1 int planId = 0; PoshPlan plan = parsePlan(planSource); ITimer timer = new SystemClockTimer(); PoshEngine = new PoshEngine(planId, plan, timer, Logger.getLogger("Yaposh")); // Work executor that actually executes the primitives IWorkExecutor workExecutor = getWorkExecutor(); // Execute the executor of the selected drive EvaluationResultInfo result = engine.evaluatePlan(workExecutor);
You can parse plan using PoshParser
, see grammar file poshParser.jj
.
Reader planReader = new StringReader(....); PoshParser parser = new PoshParser(planReader); PoshPlan parsedPlan = parser.parsePlan();
Action and sense nodes of the plan are called primitives, they are the only nodes that actually interact with the environment or agent, either by retrieving info (sense) or by changing something (action).
Primitives are executed by a class implementing IWorkExecutor
, best one is StateWorkExecutor
(also used by Yaposh). This executor uses instances of classes as primitives, classes implementing ISense
are senses and classes implementing IAction
are actions. The plan is using fully qualified names (FQN) of the classes as reference to the primitives, e.g. "cz.cuni.Turn" is a reference in the plan to an action node of the plan.
FQN names of classes are rather unpleasant for normal work with primitives, the primitive classes can have human readable name annotated using @PrimitiveInfo
. The data from the annotation are used in the editor of plans Shed and the debugger Dash, so user won't see FQN, but the name specified in the annotation.
User can implement the primitive simply by implementing interface IAction, but it is better to use one of provided abstract classes:
VariableContext
@Param("$color") String color
.VariableContext
@Param("$limit") Integer limit
.@PrimitiveInfo(name = "See player", description = "Does agent see any player?") public class SeePlayer extends StateSense<FollowContext, Boolean> { public SeePlayer(FollowContext ctx) { super(ctx); } @Override public Boolean query(VariableContext params) { return ctx.getPlayers().canSeePlayers(); } }
Example sense SeePlayer, it will have name "See player" in Shed editor.
|
||||||||||
PREV NEXT | FRAMES NO FRAMES |