/** * Coordinates a prioritised set * of tasks. Tasks with higher priority * completely block those of a * lower priority. Creates the following * tasks with increasing order of priority: * - Wander: wander around * - RightBumber: avoid obstacles on the right. * - LeftBumber: avoid obstacles on the left. * Plus it gates access to the effectors * (i.e. the motors) ensuring * that it's priority policy is strictly * enforced. */ class Subsumption implements ButtonListener { public boolean running; public int owner; Task tasks[]; public Subsumption() { running = true; Button.RUN.addButtonListener(this); tasks = new Task[3]; tasks[0]=new Wander(); tasks[1]=new RightBumber(); tasks[2]=new LeftBumber(); tasks[0].start(); tasks[1].start(); tasks[2].start(); } int getPriority(Task t) { for (int i=0; i<tasks.length; i++) { if (tasks[i] == t) return i; } return -1; } /** * Arbitrates between the various tasks. */ public synchronized void execute(Task requestor) { int pri = getPriority(requestor); // If its a lower priorty than // the current task, ignore it. if (pri < owner) return; // This is the new owner of // the single output that we have owner = pri; // Start new owner from // beginning (even if it was the same one) tasks[owner].reset(); } /** * Only allow the owner to do stuff, * just in case some other task calls us */ public synchronized void setMotor(Task requestor, Motor motor, int power, boolean forward) { if (owner == getPriority(requestor)) { motor.setPower(power); if (forward) motor.forward(); else motor.backward(); } } /** * Task has finished. * Re-start next runnable task. */ public synchronized void release(Task releaser) { int pri = getPriority(releaser); // If it isn't the owner // releasing, ignore it. if (owner == pri) { // Search for the first // runnable task. // There is always one. for(int i=pri-1; i >= 0; i--) { if (tasks[i].running()) { owner = i; tasks[owner].reset(); } } } } /** * Called within the scope of * a thread defined by * Button.addButtonListener(). */ public void buttonPressed(Button b) { running=false; } public void buttonReleased(Button b) { } }