3 import lejos
.robotics
.subsumption
.Behavior
;
6 * Arbitrator controls which Behavior object will become active in a behavior
7 * control system. Make sure to call start() after the Arbitrator is
9 * This class has three major responsibilities: <br>
10 * 1. Determine the highest priority behavior that returns <b> true </b> to
12 * 2. Suppress the active behavior if its priority is less than highest
14 * 3. When the action() method exits, call action() on the Behavior of highest
16 * The Arbitrator assumes that a Behavior is no longer active when action()
18 * therefore it will only call suppress() on the Behavior whose action() method
20 * It can make consecutive calls of action() on the same Behavior. <br>
21 * Requirements for a Behavior: <br>
22 * When suppress() is called, terminate action() immediately. <br>
23 * When action() exits, the robot is in a safe state (e.g. motors stopped)
26 * @author Roger Glassey
28 public class Arbitrator
{
30 private final int NONE
= -1;
31 private Behavior
[] _behavior
;
32 // highest priority behavior that wants control ; set by start() used by
34 private int _highestPriority
= NONE
;
35 private int _active
= NONE
; // active behavior; set by monitor, used by
37 private boolean _returnWhenInactive
;
40 * Monitor is an inner class. It polls the behavior array to find the
41 * behavior of hightst priority. If higher than the active behavior, it
42 * calls active.suppress()
44 private Monitor monitor
;
47 * Allocates an Arbitrator object and initializes it with an array of
48 * Behavior objects. The index of a behavior in this array is its priority
49 * level, so the behavior of the largest index has the highest the priority
50 * level. The behaviors in an Arbitrator can not be changed once the
51 * arbitrator is initialized.<BR>
52 * <B>NOTE:</B> Once the Arbitrator is initialized, the method start() must
53 * be called to begin the arbitration.
56 * an array of Behavior objects.
57 * @param returnWhenInactive
58 * if <B>true</B>, the <B>start()</B> method returns when no
61 public Arbitrator(Behavior
[] behaviorList
, boolean returnWhenInactive
) {
62 _behavior
= behaviorList
;
63 _returnWhenInactive
= returnWhenInactive
;
65 monitor
= new Monitor();
66 monitor
.setDaemon(true);
70 * Same as Arbitrator(behaviorList, false) Arbitrator start() never exits
73 * An array of Behavior objects.
75 public Arbitrator(Behavior
[] behaviorList
) {
76 this(behaviorList
, false);
80 * This method starts the arbitration of Behaviors and runs an endless loop.
82 * Note: Arbitrator does not run in a separate thread. The start() method
83 * will never return unless <br>
84 * 1. no action() method is running and <br>
85 * 2. no behavior takeControl() returns <B> true </B> and <br>
86 * 3. the <i>returnWhenInacative </i> flag is true,
90 while (_highestPriority
== NONE
) {
91 Thread
.yield();// wait for some behavior to take contro
94 synchronized (monitor
) {
95 if (_highestPriority
!= NONE
) {
96 _active
= _highestPriority
;
98 } else if (_returnWhenInactive
) {// no behavior wants to run
99 monitor
.more
= false;// 9 shut down monitor thread
102 } // monitor released before action is called
103 if (_active
!= NONE
) // _highestPrioirty could be NONE
105 _behavior
[_active
].action();
106 _active
= NONE
; // no active behavior at the moment
113 this.monitor
.more
= false;
118 * Finds the highest priority behavior that returns <B>true </B> to
119 * takeControl(); If this priority is higher than the active behavior, it
120 * calls active.suppress(). If there is no active behavior, calls suppress()
121 * on the most recently active behavior.
123 private class Monitor
extends Thread
{
126 int maxPriority
= _behavior
.length
- 1;
130 // FIND HIGHEST PRIORITY BEHAVIOR THAT WANTS CONTROL
131 synchronized (this) {
132 _highestPriority
= NONE
;
133 int active_behavior
= _active
; // BB modded
134 if (active_behavior
== NONE
)
135 active_behavior
= 0; // BB modded
136 for (int i
= maxPriority
; i
>= active_behavior
; i
--) // BB
138 if (_behavior
[i
].takeControl()) {
139 _highestPriority
= i
;
143 int active
= _active
;// local copy: avoid out of bounds
145 if (active
!= NONE
&& _highestPriority
> active
) {
146 _behavior
[active
].suppress();
148 } // end synchronize block - main thread can run now