ckbot :: logical :: Cluster :: Class Cluster
[hide private]
[frames] | no frames]

Class Cluster

source code


Concrete class representing a CKBot cluster, which is a collection of modules residing on the same bus.

A Cluster contains a Protocol class to manage communication with the modules.

A Cluster instance is itself a dictionary of modules, addressed by their node ID-s. This dictionary is populated by the .populate() method. Clusters also implement the reflection iterators itermodules, iterhwaddr, and iterprop.

Typically, users will use the convenience attribute .at, which provides syntactic sugar for naming modules in a cluster using names defined when the cluster is .populate()-ed. These allow ipython tab completion to be used to quickly explore which modules are available.

Typical use:

>>> c = Cluster()
>>> c.populate(3,{ 0x91 : 'left', 0xb2 : 'head',0x5d : 'right'} )
>>> for m in c.itervalues():
>>>   m.get_od(c.p)
>>> c.at.head.od.set_pos( 3000 ) # via object dictionary
>>> c.at.head.set_pos(4500) # via process message
Instance Methods [hide private]
new empty dictionary

__init__(self, arch=None, port=None, *args, **kwargs)
Create a new cluster.
source code
 
populate(self, count=None, names={}, timeout=2, timestep=0.1, required=set(), fillMissing=None, walk=False, autonamer=lambda nid: "Nx%02X" % nid)
Tries to populate the cluster based on heartbeats observed on the bus.
source code
 
discover(self, count=0, timeout=2, timestep=0.1, required=set(), raiseClass=DiscoveryError)
Discover which nodes are in the cluster.
source code
None
update(self)
Allow stateful members to update; propagates to
source code
 
off(self)
Make all servo or motor modules go slack
source code
 
who(self, t=10)
Show which modules are currently visible on the bus runs for t seconds
source code
 
add(self, *modules)
Add the specified modules (as returned from .newModuleIX())
source code
 
newModuleIX(self, nid, name=None)
Build the interface for a module...
source code
 
__delitem__(self, nid)
del x[y]
source code
 
itermodules(self) source code
 
iterhwaddr(self) source code
 
iterprop(self, attr=False, perm='') source code
 
getLive(self, limit=None)
Use heartbeats to get set of live node ID-s...
source code
 
modOfClp(self, clp)
Find the module containing a given property
source code
 
_getAttrOfClp(self, clp, attr)
(private) Obtain python attribute of a cluster property identified by a clp
source code
 
getterOf(self, clp)
Obtain a getter function for a cluster property
source code
 
setterOf(self, clp)
Obtain a setter function for a cluster property
source code

Inherited from dict: __cmp__, __contains__, __eq__, __ge__, __getattribute__, __getitem__, __gt__, __iter__, __le__, __len__, __lt__, __ne__, __new__, __repr__, __setitem__, __sizeof__, clear, copy, fromkeys, get, has_key, items, iteritems, iterkeys, itervalues, keys, pop, popitem, setdefault, values, viewitems, viewkeys, viewvalues

Inherited from object: __delattr__, __format__, __reduce__, __reduce_ex__, __setattr__, __str__, __subclasshook__

Class Methods [hide private]
 
parseClp(cls, clp)
parse a class property name into head and tail parts
source code
Static Methods [hide private]
 
build_hwaddr(nid, index)
build a hardware address for a property from node and index
source code
Class Variables [hide private]
  REX_HW = re.compile("([a-fA-F0-9]{2})(:)([a-fA-F0-9]{4})")
  REX_PROP = re.compile("([a-zA-Z_]\w*)(/)((?:[a-zA-Z_]\w*)|(?:0...
  REX_ATTR = re.compile("([a-zA-Z_]\w*)(/@)([a-zA-Z_]\w*)")

Inherited from dict: __hash__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arch=None, port=None, *args, **kwargs)
(Constructor)

source code 

Create a new cluster. Optionally, also .populate() it

INPUT:
  arch -- optional -- python module containing arch.Bus and
    arch.Protocol to use for low level communication. Defaults
    to DEFAULT_ARCH
    
    Can also be a Protocol instance ready to be used.
    
    Supported architectures include:
      can -- CAN-bus CKBot 1.4 and earlier
      hitec -- modified hitec servos
      dynamixel -- Robotis Dynamixel RX, EX and MX
      pololu -- pololu Maestro servo controllers
      nobus -- software simulated modules for no-hardware-needed 
        testing of code.
      
  port -- specification of the communication port to use, as per
    ckbot.port2port.newConnection. port defaults to DEFAULT_PORT, and
    is ignored if arch is an initialized AbstractProtocol instance.
    
    This can be used to specify serial devices and baudrates, e.g.
    port = 'tty={glob="/dev/ttyACM1",baudrate=115200}'
  
  *argc, **kw -- if any additional parameters are given, the
    .populate(*argc,**kw) method is invoked after initialization
    
ATTRIBUTES:
  p -- instance of Protocol for communication with modules
  at -- instance of the Attributes class.
  limit -- float -- heartbeat time limit before considering node dead
  _updQ -- list -- collection of objects that need update() calls

Returns:
new empty dictionary

Overrides: object.__init__

populate(self, count=None, names={}, timeout=2, timestep=0.1, required=set(), fillMissing=None, walk=False, autonamer=lambda nid: "Nx%02X" % nid)

source code 

Tries to populate the cluster based on heartbeats observed on the bus.
Will terminate when either at least count modules were found or timeout
seconds have elapsed. While waiting, checks bus once every timestep seconds.
If timed out, raises an IOError exception.

If the bus already got all the heartbeats needed, populate() should 
terminate without sleeping.

If provided, names gives a dictionary of module names based on their node 
ID. Node IDs that aren't found in the dictionary have a name automatically
generated from the ID by calling autonamer.

INPUT:
  count, timeout, timestep, required, fillMissing-- see self.discover()
  fillMissing -- class / bool -- fills in any missing yet required modules
        with instances of this class. If boolean true, uses MissingModule
        NOTE: the nobus mechanism bypasses this; use nobus.NID_CLASS
  names -- dictionary of Modules names based with node id as their key.
  walk -- bool -- if true, walks each module to indentify its interface
  autonamer -- names the modules if no names are given.

discover(self, count=0, timeout=2, timestep=0.1, required=set(), raiseClass=DiscoveryError)

source code 

Discover which nodes are in the cluster.
Termination condition for discovery is that at least count modules were
discovered, and that all of the required modules were found.
If this hasn't happened after a duration of timeout seconds (+/- a timestep),
discover raises a DiscoveryError.
In the special case of count==0 and required=set(), discover collects
all node ID-s found until timeout, and does not return an error.
INPUT:
  count -- number of modules -- if 0 then collects until timeout
  timeout -- time to listen in seconds
  timestep -- how often to read the CAN buffer
  required -- set -- requires that all these nids are found
  raiseClass -- class -- exception class to raise on timeout
OUTPUT:
  python set of node ID numbers    

update(self)

source code 

Allow stateful members to update; propagates to

Returns: None
Overrides: dict.update

newModuleIX(self, nid, name=None)

source code 

Build the interface for a module
INPUTS
    nid -- int -- node identifier for use on the bus
    name -- string -- name for the module, or None if regenerating
        an existing module whose name is already known
OUTPUTS
    mod -- Module subclass representing this node

__delitem__(self, nid)
(Index deletion operator)

source code 

del x[y]

Overrides: dict.__delitem__
(inherited documentation)

getLive(self, limit=None)

source code 

Use heartbeats to get set of live node ID-s
INPUT:
  limit -- float -- heartbeats older than limit seconds in 
     the past are ignored
OUTPUT:
  python set of node ID numbers

parseClp(cls, clp)
Class Method

source code 

parse a class property name into head and tail parts

use this method to validate class property name syntax.

OUTPUT: kind, head, tail
    where kind is one of ":", "/", "/@"        

getterOf(self, clp)

source code 

Obtain a getter function for a cluster property

If property is not readable, returns a DelayedPermissionError

setterOf(self, clp)

source code 

Obtain a setter function for a cluster property

If property is not writeable, returns a DelayedPermissionError


Class Variable Details [hide private]

REX_PROP

Value:
re.compile("([a-zA-Z_]\w*)(/)((?:[a-zA-Z_]\w*)|(?:0x[a-fA-F0-9]{4}))")