POSH (Parallel-rooted, Ordered
Slip-stack Hierarchical) dynamic plans are the structures used for action selection
(also known as behavior
arbitration or coordination)
in Behavior Oriented Design (BOD).
planning (also known as reactive
planning) is a way of doing action selection for a situated agent
whereby a system chooses its next action by doing a quick look-up on an
existing data structure. What makes the system dynamic / reactive
is that the decision about what to do next is based on the current
state of the world, as perceived through the situated agent's
sensors. However, if an agent responds only to its environment, it can
wind up dithering between goals. Thus a dynamic plan typically
also uses some sort of internal state to keep track of the agent's
current goals. POSH plans record some of that state in the plan
itself. An active instance of a POSH plan which is in use by an
agent is a dynamic data structure. It remembers what subtask the
agent was currently pursuing, although it also provides a way to encode
when that subtask should be abandoned, or when a more important new
goal or task should take over.
This page provides information on:
files have a .lap extension (it stands for `learnable action
patterns', a name I made up early in my PhD research (~1994).
Now I focus more on the design of these
plans, though Mark Wood
is working on learning them.) Because the syntax was written to
be easy to
parse in Lisp, if you want to edit them by hand you should use an
editor that matches parentheses for
you, like emacs.
We also now also have a special-purpose
editor as part of ABODE, the BOD IDE.
It is useful for visualising some plans, but unfortunately (as of
March2008) needs updating to work with current plan files...
There are currently two different lap file formats, one for POSH
running a scheduled slip-stack and one for POSH with a strict
slip-stack. Details about the
two different versions of POSH are described in
Sections 4.6.2 & 4.6.3 of my dissertation.
Here's the description of a lap file for the scheduled
slip-stack, taken from the comments in the
file posh-script.lisp, which parses these plans:
Note: acts & senses are represented below just as names / tokens. A name may
be the name of any POSH type, including an act, sense, drive collection,
AP or competence.
name :: [a token]
sol-time :: (<time-unit> #)
time-unit:: minutes, seconds, hz(1/sec), pm(1/min), none(not real time)
should maybe add hours, days, microseconds?
goal :: (goal <ap>)
Competence :: (C <name> <sol-time> <goal> <other-elements>)
where time is for timeout, Ymir-like
Drive-collection :: (DC|RDC <name> <goal> <drive-elements>)
RDC for real-time systems
other-elements :: (elements (<comp-element>+)+)
inner paren is priority level
drive-elements :: (drives (<drive-element>+)+)
inner () is priority
comp-element :: (<name> (trigger <ap>) <name> [#])
2nd name is an action, followed by optional # of retries
drive-element :: (<name> (trigger <ap>) <name> [<sol-time>])
drive name, trigger, POSH root, [freq. for scheduling]
ap :: (<act|(sense [value [predicate]])>*)
default value is t, default predicate is eq
"act" can be an action primitive or a composite
Action-pattern :: (AP <name> <sol-time> <ap>)
where time is for timeout, Ymir-like
Here are some old examples of scheduled POSH lap files. See my publications page for full reference info on any mentioned papers.
NOTE: These files were created before ABODE came into use, and use old commenting formats. If you want a comment to stick in your file where you put it, you need to either:
;; @element <name-of-element> [comments]
The following elements have a different syntax when used with the strict slip-stack implementation (see the comments in lapparser.py for the full grammar):
Note: as the strict slip-stack does not support time-outs, the <sol-time>
tokens are accepted but ignored if given.
act :: <name>
can be a primitive or a composite
sense-act :: <name>
a simple sense that might also perform an action.
Its return value is casted to a boolean
sense :: (nil) | (<name> [<value> [<predicate>])
if value is given, then return value of sense is
compared to value. Comparison mode is defined by
predicate, "==" is assumed if no predicate is given.
Sense (nil) always fails
ap :: ( <act | sense-act | sense>* )
value :: # | string | nil
predicate :: == | = | != | < | > | <= | >=
both '==' and '=' test for equality
goal :: nil | (GOAL <ap>)
goal 'nil' always fails
trigger :: nil | (TRIGGER <ap>)
trigger 'nil' always succeeds
time-unit :: HOURS | MINUTES | SECONDS | NONE
freq :: (<freq-unit> #)
freq-unit :: HOURS | MINUTES | SECONDS | HZ | PM | NONE
comment :: "any string"
Drive-collection :: (SDC|SRDC <name> [<goal>] <drive-elements>)
SRDC for real-time systems, goal always fails if
drive-element :: (<name> [<trigger>] <name> [<freq>] [<comment>])
drive name, optional trigger (always triggers if not
given), POSH root, optional frequency, optional comment
Competence :: (C <name> [<sol-time>] [<goal>] <other-elements> [<comment>])
comp-element :: (<name> [<trigger>] <name> [#] [<comment>])
element name, optional trigger (always triggers if
not given), action/competence/action pattern,
optional # of retries, optinal comment
Action-pattern :: (AP <name> [<sol-time>] <ap> [<comment>])
last element of <ap> can also be a competence