Packages
There are five main (Java) packages for the Machinetta software. Each
package contains the code for one aspect of the proxy's behavior.
The central package is State which provides the "memory" of the
proxy. The other modules use this memory as a "blackboard" via which
to share beliefs. Direct communication between modules, other than
the State is discouraged and generally not present in the
current implementation. Some indirect interaction occurs between
modules, but only via abstract interfaces and facilitated by the top
level proxy class.
The rationale behind this design is that the five packages should be
easily interchangeable, with various combinations of packages being
possible. For example, it should be possible to change the package
for communication (say, for allowing wireless communications) without
changing the coordination package.
Each package is described in more detail below.
(Nathan, perhaps include a link to the class diagram?)
State
The state maintains the current beliefs of the proxy. Proxy beliefs
are all subclasses of an abstract Belief class. Many beliefs are
generic (see Machinetta/State/BeliefTypes) but domain specific beliefs
can also be defined. The state does not "understand" the beliefs in
ay semantic way and does not do anything but store the beliefs.
The state uses a singleton pattern, so classes can create many
instances and all will refer to the same object (and thus have access
to the same set of stored beliefs).
Each belief must define a unique identifier to allow it to be accessed
and changed as required. If a belief changes, e.g., a belief about a
particular fire, then it should retain its original identifier, if the
changed belief should replace the previous belief.
A special class in the state package, BeliefsXML, allows automatic
translation of beliefs to XML. For this to work, the belief must have
a "no-arg constructor" (i.e., a constructor that takes no arguments)
and all variables that should be translated must be public. Most
variable types within a belief are OK and can be translated to XML,
from simple types, to other beliefs, to Vectors and Hashtables.
Other modules register with the state as listeners (in fact any
class can register with the state as a listener). In the course of
some reasoning, a class might post several beliefs to the state. When
it is complete, it should call notifyListeners(). When this is
called, all registered listeners will get a list of all recently
posted beliefs. This notifyListeners() call essentially acts
as the control for the overall proxy, since although individual
modules and classes can have internal threads, there is no
"proxy-wide" thread of control.
A special belief in the state the self RAPBelief encapsulates
known information about the local RAP the proxy is working with.
Communication
The communication module is responsible for communicating with other
proxies. This module does not reason about what to
communicate, only how to communicate. (The coordination module
does the how.) The communication module gets simple, abstract
messages to send in the form of objects and works out how to get them
to the destination. The module also receives messages from other
proxies and translates into simple message classes (the same classes
it sends out).
In the distribution on the download page, there are a couple of
alternative communication implementations. The most stable (because it
is the simplest), is LocalComms which uses a communications server to
route messages and uses the State module's ability to translate to XML
to send messages. Notice that the messages sent by this communication
implementation are extermemely (and unnecessarily) verbose.
RAPInterface
The RAPInterface module is the most domain (and RAP) dependant module.
It is responsible for communicating with the RAP (e.g., the agent).
Notice, that this module does not decide what to communicate
with the RAP but only how to communicate with the RAP. The
module translates a set of high level messages into a language the RAP
can understand. For example, one message is to assign a new role to
the RAP, while another is to ask the RAPs capability to perform some role.
RAPInterface implementations can range from simple sockets to send
messages to agents to complex interfaces for interacting with people.
AA
The AA module implements the adjustable autonomy of the proxy. This
module monitors the state for decisions that need to be made either by
the RAP or by the proxy and reasons about who should make that
decision. For example, when a RoleAllocationBelief is posted to the
state, the AA module reasons about whether to autonomously accept or
reject the role or ask the RAP whether to accept or reject. Once
decisions are made, the AA module posts the belief back to the state,
for the coordination module to handle.
If the AA module needs to communicate with the RAP it does not do so
directly, rather it creates an abstract message which it passes to the
RAPInterface (indirectly) to be communicated to the RAP. In this way,
the AA reasoning can be independant of the specific type of RAP. The
abstract information about the RAP that the AA does need to know, can
be found in the self RAPBelief in the state.
Coordination
The coordination module implements the key algorithms required for
teamwork (or whatever other coordination philosophy you might want to
implement). This module gets incoming messages from the communication
module and either creates new messages (sent via the communication
module) or posts beliefs in the state. It also monitors the state and
creates plans, etc. as applicable.
Principles
Below, we briefly describe a couple of the key design ideas in the Machinetta software.
Modules and Implementations
Each of the main modules follows the singleton pattern. This allows
the module to create an instance of the particular implementation
inside the module just once, regardless of how many instances of the
module are created.
Belief and Input Message Handlers
Since most of the modules are either message or belief driven, a
common pattern for implementation is to create belief and message
handlers. A message or belief handler is created for a particular
type of belief, e.g., a role allocation belief and registered
as a listener, with the implementation, for that type of belief. In
the main implementation of a module, changed beliefs are received and
routed to listeners only if they are of the particular type the
handler is expecting. See
Machinetta.DomainSpecific.DisasterSim.SimpleFBAA (the disaster
response simulation implementation of adjustable autonomy) for an
example of this design.