Package joy :: Module plans :: Class Plan
[hide private]
[frames] | no frames]

Class Plan

source code



Abstract superclass of scheduled behaviors

Each Plan implements a "co-routine" consisting of a behavior
that executes in parallel with other plans. It has its own event
queue and event handler, and its own bindings to outputs.
  
Class Plan is use by subclassing it and overriding the behavior()
method with a generator -- i.e. a method that has a bunch of yield
statements in it. The yield statements MUST all be "yield None",
which can be abbreviated to "yield" with no parameters.
The yields indicate the locations at which the Plan returns control 
to the owner JoyApp.

Plans continue executing from where they stopped whenever the event
handler returns True. Otherwise it should return False. Other return
values will generate an exception.

Plans may be nested; simply yield the plan that is to take over control.
NOTE: Make sure that the nested Plan was start()-ed  

Some methods are designed to be used with yield, specifically:
  untilTime, forDuration

WARNING: JoyApp is single-threaded. If a behavior spends too long 
between yield statements the entire JoyApp waits for it to complete. 

Typical usage:
>>> class MyPlan( Plan ):
...   def __init__(self,app):   
...     Plan.__init__(self,app)
...
...   def onEvent( self, evt ):
...     if evt.type == MOUSEMOTION:
...       self.x = evt.pos[0]
...       return True
...     return False
...
...   def behavior(self):
...     print "Move mouse to the left"
...     while self.x > self.app.cfg.windowSize[0]*0.25:
...       yield
...     print "Move mouse to the right"
...     while self.x < self.app.cfg.windowSize[0]*0.75:
...       yield
...     print "Great job!! here are 3 tail wags for you"
...     for wag in xrange(3):
...       self.tailWagTo(100)
...       yield self.forDuration( 500 )
...       self.tailWagTo(-100)
...       yield self.forDuration( 500 )

BINDINGS: To allow plans to be easily adapted and re-used
without sub-classing, the Plan constructor accepts a list
of keyword argument "bindings" of the form <name>=<setter>,
where <setter> is either a callable or a string naming a
robot property to be resolved using app.robot.setterOf().
This allows self.<name> to be used in the Plan code for
setting values that will only be chosen at the time the
plan subclass instance is constructed. In the example above,
we could have used MyPlan( tailWagTo='Nx55/@set_pos' ) to create
an instance whose self.tailWagTo sets the position in robot
node 0x55. Similarly, tailWagTo='>tail wag' would bind the
output to the Scratch sensor named 'tail wag'

Instance Methods [hide private]
 
__init__(self, app, **binding)
Initialize a Plan within some JoyApp application.
source code
 
_initBindings(self, app, binding, allowOverride=False)
(protected) initialize bindings, resolving any string valued bindings
source code
 
push(self, *evts)
Push events into this Plan's event queue
source code
 
onEvent(self, evt)
(default) Event handler.
source code
 
behavior(self)
(default)
source code
 
untilTime(self, time)
A sub-plan that sleeps until a specified time.
source code
 
forDuration(self, duration)
A sub-plan that sleeps for a specified duration.
source code
 
isRunning(self)
Returns True if and only if this Plan is currently "running", i.e.
source code
 
start(self)
Start execution of a Plan's behavior.
source code
 
onStart(self)
(default)
source code
 
stop(self, force=False)
Stop (abnormally) the execution of a Plan's behavior
source code
 
onStop(self)
(default)
source code
 
_unwind(self, exinfo)
(private)
source code
 
_stepDoEvents(self)
(private)
source code
 
_oneStep(self)
(private)
source code
 
step(self)
Execute one time-step of Plan behavior.
source code
 
_stepNewSub(self, sub)
(private)
source code

Inherited from object: __delattr__, __format__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __sizeof__, __str__, __subclasshook__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, app, **binding)
(Constructor)

source code 

Initialize a Plan within some JoyApp application.

Overrides: object.__init__

push(self, *evts)

source code 

Push events into this Plan's event queue

Events are only queued while the Plan isRunning(); otherwise they are silently dropped.

onEvent(self, evt)

source code 
(default)
Event handler. Override this method to handle all events that 
were push()-ed to this Plan.

The sequential behavior() in this plan only runs if onEvent
returned True.

All Plan-s recieve a copy of all TIMEREVENT events. If your
sequential code does not need any other events, and just wants
to execute in parallel with other Plan-s, it is safe to leave
the default onEvent method, which always returns True 

NOTE: 
  onEvent MUST return True or False. Other values raise an 
  exception at runtime. 

behavior(self)

source code 

(default)

Override this method to implement the sequential behavior of a Plan

This method MUST be a python iterator, i.e. must contain a "yield" statement

untilTime(self, time)

source code 

A sub-plan that sleeps until a specified time.

Use this from .behavior() with a statement of the form:
   yield self.untilTime( wakeup )
to sleep until the specified wakeup time.

forDuration(self, duration)

source code 

A sub-plan that sleeps for a specified duration.

Use this from .behavior() with a statement of the form:
   yield self.forDuration( naplength )
to sleep for the specified duration

isRunning(self)

source code 

Returns True if and only if this Plan is currently "running", i.e. its .onEvent handler receives events and its .behavior has not terminated.

start(self)

source code 

Start execution of a Plan's behavior.

If Plan is already running -- issues a warning

onStart(self)

source code 

(default)

Override this method to perform operations when Plan starts but before the first events are processed.

stop(self, force=False)

source code 
Stop (abnormally) the execution of a Plan's behavior

If not running, this call is ignored.

INPUT:
  force -- boolean -- stop without raising termination exceptions in co-routines

onStop(self)

source code 

(default)

Override this method to perform operations when Plan terminates.

_unwind(self, exinfo)

source code 

(private)

Unwind Plan co-routines by throwing exceptions up the stack

_stepDoEvents(self)

source code 
(private)

Run onEvent() method on all incoming events

OUTPUT:
  True if plan can go idle (no relevant events) or False otherwise

_oneStep(self)

source code 
(private)

Execute one step from the iterator at the top of the stack

OUTPUT:
  co-routine to execute as sub-Plan, or None

step(self)

source code 

Execute one time-step of Plan behavior.

This method is called every time the .onEvent handler returns True for one or more events in a time-slice.

_stepNewSub(self, sub)

source code 

(private)

Plan yielded a sub-plan to execute -- process it