VacWorld

From Agent Factory

Jump to: navigation, search

Down below, you will find two examples of a cleaner agent for VacWorld.

Extended simple cleaner

Taking the simple cleaner code in the AgentSpeak tutorial and extending it to use a modified Whiteboard API to share information about the visited squares. Using that information, the vacs try to avoid squares visited by themselves or any other vac.


Agent code (VacBot.aspeak)

#agent VacBot #extends com.agentfactory.eis.EISAgent

module whiteboard -> vacworld.WhiteboardAPI;
action nextmethod(?d,?x,?y) -> vacworld.Next;

#implements #partial @postInitialize <- 		//setting up whiteboard at initialization
    whiteboard.setup;

+location(?x, ?y) : square(here, dust) <-              //a new move is initiated when there is a new location belief
    !clean,
    !doMove(?x,?y);

+location(?x, ?y) : ~square(here, dust) <-
    !doMove(?x,?y);

+!doMove(?x,?y) : name(?name) <-
    !addLocationInfo(?x,?y),			//adds the current square to the whiteboard
    !isNextVisited(?x,?y),				//creates the beliefs about the next possible squares
    try {
        !move(?x,?y)
    } recover {
        .println(?name + " had problem moving."),
        !doMove(?x,?y)
    };

+!move(?x,?y) : square(forward, dust) <-
    durative(eis.perform(move(forward)));

+!move(?x,?y) : square(left, dust) <-
    durative(eis.perform(move(left)));

+!move(?x,?y) : square(right, dust) <-
    durative(eis.perform(move(right)));

+!move(?x,?y) : ~square(forward, obstacle) & ~square(forward, vac) & ~isVisited(forward) <-	//if square is not an obstacle, a vac or has not been visited
    durative(eis.perform(move(forward)));

+!move(?x,?y) : ~square(left, obstacle) & ~square(left, vac) & ~isVisited(left) <- //if square is not an obstacle, a vac or has not been visited
    durative(eis.perform(move(left)));

+!move(?x,?y) : ~square(right, obstacle) & ~square(right, vac) & ~isVisited(right) <- //if square is not an obstacle, a vac or has not been visited
    durative(eis.perform(move(right)));

+!move(?x,?y) : ~square(forward, obstacle) & ~square(forward, vac) <- 
    durative(eis.perform(move(forward)));

+!move(?x,?y) : ~square(left, obstacle) & ~square(left, vac) <-
    durative(eis.perform(move(left)));

+!move(?x,?y) : ~square(right, obstacle) & ~square(right, vac) <-
    durative(eis.perform(move(right)));

+!move(?x,?y) : true <-
    try {
        durative(eis.perform(move(right)))	//if move fails try to move right
    } recover {
   	 try{
            durative(eis.perform(move(right))) //if move to right fails, try to move right (backwards from original direction)
        } recover {
            try{
                 durative(eis.perform(move(right))) //if move to right fails, try to move right (right from original direction)
            } recover {
                 !move
            }
   	 }
    };

+!clean : true <-
    eis.perform(light(on)),
    durative(eis.perform(clean)),
    eis.perform(light(off));

+!addLocationInfo(?x,?y): true <-
    whiteboard.setup,		//calling setup (just in case)
    whiteboard.put(?x,?y),	//putting coordinates
    whiteboard.view;		//updating information from whiteboard (getting info from other bots)

+!isNextVisited(?x,?y):direction(?d) <- //
    .abolishAll(next(?1,?2,?3)),	//removing all next beliefs (next squares)
    -isVisited(forward),			//removing previous isVisited beliefs
    -isVisited(left),
    -isVisited(right),
    nextmethod(?d,?x,?y);			//creating new next beliefs

+next(?a,?b,?c):visited(?b,?c) <-	//if square in next(square, x-coord, y-coord) has been visited (listed in whiteboard)
    +isVisited(?a);					//mark it as visited (create belief)


nextmethod(?d,?x,?y) action (Next.java)

package vacworld;

import com.agentfactory.clf.lang.Predicate;
import com.agentfactory.clf.interpreter.Action;

public class Next extends Action {

      public boolean execute(Predicate activity){ 

            String dir = termAsString(activity,0); 		//getting direction
            int x = termAsInt(activity,1);				//x-coordinate
            int y = termAsInt(activity,2);				//y-coordinate		 
 
            //calculating the coordinates of the three possible next squares, and adding the beliefs 
            if(dir.equals("south")){
                  addBelief("next(right,"+(x-1)+","+(y)+")");
                  addBelief("next(left,"+(x+1)+","+(y)+")");
                  addBelief("next(forward,"+(x)+","+(y-1)+")");
            } else if(dir.equals("west")){
                  addBelief("next(right,"+(x)+","+(y+1)+")");
                  addBelief("next(left,"+(x)+","+(y-1)+")");
                  addBelief("next(forward,"+(x-1)+","+(y)+")");
            } else if(dir.equals("east")){
                  addBelief("next(right,"+(x)+","+(y-1)+")");
                  addBelief("next(left,"+(x)+","+(y+1)+")");
                  addBelief("next(forward,"+(x+1)+","+(y)+")");
            } else if(dir.equals("north")){
                  addBelief("next(right,"+(x+1)+","+(y)+")");
                  addBelief("next(left,"+(x-1)+","+(y)+")");
                  addBelief("next(forward,"+(x)+","+(y+1)+")");
            }
 
            return true;
      }
}


Whiteboard API (WhiteboardAPI.java)

package vacworld;

import com.agentfactory.clf.interpreter.Action;
import com.agentfactory.clf.interpreter.CoreUtilities;
import com.agentfactory.clf.interpreter.Module;
import com.agentfactory.clf.lang.Predicate;

public class WhiteboardAPI extends Module {
    private WhiteboardService service;

    public WhiteboardAPI() {
        addAction("setup", new Action() {
            @Override
            public boolean execute(Predicate activity) {
                agent.bindToPlatformService(WhiteboardService.NAME);
                service = (WhiteboardService) agent.getPlatformService(WhiteboardService.NAME);
                return true;
            }
        });
        addAction("put(?x,?y)", new Action() {
            @Override
            public boolean execute(Predicate activity) {
            	String location = CoreUtilities.presenter.toString(activity.termAt(0))+","+CoreUtilities.presenter.toString(activity.termAt(1));
                String info = "visited";
                service.putInformation(location,"visited"); //we only need to store the coordinates (key)
                return true;
            }
        });
        addAction("removeInfo(?x,?y)", new Action() {
            @Override
            public boolean execute(Predicate activity) {
            	String location = CoreUtilities.presenter.toString(activity.termAt(0))+","+CoreUtilities.presenter.toString(activity.termAt(1));
                service.removeInformation(location);
                return true;
            }
        });
        
        addAction("view", new Action() {
            @Override
            public boolean execute(Predicate activity) {
               if (service == null) return false;

               for (String bel : service.getInformation()) {
                   addBelief(bel);
               }
               return true;
           }
       });
   }
}


Modified WhiteboardService (WhiteboardService.java)

package vacworld; 

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.agentfactory.platform.impl.AbstractPlatformService;

public class WhiteboardService extends AbstractPlatformService {
    public static final String NAME = "af.std.wb";

    private Map<String, String> information;

    public WhiteboardService() { 
        information = new HashMap<String, String>(); 
    }

    public synchronized String getInformation(String key) { 
 
    	if(!information.containsKey(key))
    		return null;
    	
        return "information(" + key + "," + information.get(key) + ")";  
    }
    
    public synchronized List<String> getInformation() { 
        List<String> list = new ArrayList<String>(); 
 
        for (String key: information.keySet()) { 
            list.add("visited(" + key + ")"); 
        } 
        return list;  
    }
    
    public synchronized void putInformation(String location, String info) { 
        information.put(location, info);
        setChanged();
        notifyObservers();
    }

   public synchronized String removeInformation(String location) { 
       String temp = (String) information.remove(location);  
       setChanged();
       notifyObservers();
       return temp;
   }
}


To deploy the example create a VacWorld and an VacWordEIS java class

VacWorld.java

package vacworld;

import java.util.HashMap;
import java.util.Map;

public class VacWorld{
	 public static void main(String[] args) {
    	
        Map<String, String> designs = new HashMap<String, String>();
        designs.put("vacbot", "vacworld/VacBot.aspeak");
        new VacWorldEIS("vacworld", designs, "ita.jar");
        
    }
}

VacWorldEIS.java

package vacworld;

import java.util.List;
import java.util.Map;

import com.agentfactory.eis.EISDebugConfiguration;

public class VacWorldEIS extends EISDebugConfiguration {

	public VacWorldEIS(String name, Map<String, String> designs, String jar){
		super(name,designs,jar);
		configure();
		addPlatformService(WhiteboardService.class, WhiteboardService.NAME);
		
	}
}

Dust aware cleaner

This example retains some of the elements of a simple cleaner, however it is different from it.

Each move consists of three phases (preMove, theMove and PostMove).


preMove:

  • gets location coordinates
  • checks if current location contains dust
  • if it contains dust, clean square
  • scans the neighbouring squares for dust (if found, location is published to the whiteboard)
  • if the current location is the target, remove targeted belief


theMove (the vac moves using the following conditions):

  • if there is dust in the forward, left or right square, move to that square
  • if there is a target, get the next move and make a move accordingly
  • if there is no target and there is an avaliable dust as target, choose it and make move accordingly
  • else make a move to an avaliable square


postMove:

  • initiate a new move


Vac code (vac.aspeak)

#agent vac #extends com.agentfactory.eis.EISAgent

module whiteboard -> vacworld2.WhiteboardAPI;	        //whiteboard
module getsquare -> vacworld2.GetSquare;		//get input square coordinates
module getdist -> vacworld2.GetDistance;		//get distance between two locations
module nav -> vacworld2.Nav;				//navigation module (used to get next move)

#implements #partial @postInitialize <- 
    whiteboard.setup,		                        //setting up whiteboard
    !makeMove;			                        //making first move

	
+!makeMove:true <-		                        //the move process
    !preMove,
    !theMove,
    !postMove;

+!preMove:square(here,dust) <-		                //current square has dust
    query(location(?x,?y)),			        //getting current location
    !clean,						//clean
    !detect,				                //scan neighbouring squares

    if(targeted(?x,?y)){			        //if target==current location
          -targeted(?x,?y)			        //remove target
    };
 
+!preMove:~square(here,dust) <-		                //current square does not have dust
    query(location(?x,?y)),
    !removeDust(?x,?y),
    !detect,
    if(targeted(?x,?y)){
          -targeted(?x,?y)
    };

+!theMove : square(forward, dust) <-		        //if forward square has dust, move forward
    durative(eis.perform(move(forward)));

+!theMove : square(left, dust) <-			//if left square has dust, move left
    durative(eis.perform(move(left)));

+!theMove : square(right, dust) <-			//if right square has dust, move right
    durative(eis.perform(move(right)));
	
+!theMove : targeted(?a,?b) <-				//if there is a target
    .abolishAll(nextMove(?r)),				//delete all nextMove(?r) beliefs
    query(direction(?dir)),				//get current direction
    if(targeted(?a,?b)){				//if there is a target (if added in as target dust might have been removed while deleting and querying direction)
          query(location(?x,?y)),
          nav.getNextMove(?a,?b,?x,?y,?dir),	        //get next move a:target x, b:target y, x:location x, y:location y 
          query(nextMove(?r)),				//query next move
          try{
                 durative(eis.perform(move(?r)))	//try next move
          } recover {
                 !theMove2		                //if it fails continue with move
          }
    } else {
          !theMove2				        //if target lost, continue with move
    };

+!theMove : dust(?a,?b) <-				//if there is no target, and there is dust avaliable
    !target(?a,?b),					//target avaliable dust
    .abolishAll(nextMove(?r)),
    query(direction(?dir)),
    query(location(?x,?y)),
    nav.getNextMove(?a,?b,?x,?y,?dir),
    query(nextMove(?r)),
    try{
          durative(eis.perform(move(?r)))
    } recover {
          !theMove2
    };

+!theMove:true <-	                                //if the previous conditions did not hold, continue with move
    !theMove2;

//the moves had to be named differently, as fails have to be directed to this point, and not redirected to the top of the move list
//these moves are the same as for the simple cleaner bot
+!theMove2 : ~square(forward, obstacle) & ~square(forward, vac) <-
    durative(eis.perform(move(forward)));

+!theMove2 : ~square(left, obstacle) & ~square(left, vac) <-
    durative(eis.perform(move(left)));

+!theMove2 : ~square(right, obstacle) & ~square(right, vac) <-
    durative(eis.perform(move(right)));

+!theMove2 : true <-
    try {
          durative(eis.perform(move(right)))
    } recover {
          try{
                durative(eis.perform(move(right)))
          } recover {
                try{
                       durative(eis.perform(move(right)))
                } recover {
                       !theMove
                }
          }
    };

//target input coordinates 
+!target(?x,?y):true <-
    whiteboard.setup,
    +targeted(?x,?y), 				                //add target belief
    whiteboard.removeInfo(?x,?y),	                        //remove target dust from whiteboard
    .send(inform, agentID(".*",addresses("local:vacworld.eis.ucd.ie")), targeted); 
                                                               //send update info to all bots


+!postMove:true <-                                             //make new move
    !makeMove;

+!clean : location(?x,?y) <-                                   //clean current square
    eis.perform(light(on)),
    durative(eis.perform(clean)),
    eis.perform(light(off)),
    query(location(?x,?y)),
    !removeDust(?x,?y);                                        //remove dust information

//to update the dust beliefs
+!updateDustInfo:true <- 
    whiteboard.setup,			                        //setting up whiteboard (just in case)
    .abolishAll(dust(?i,?j)), 	                                //removing all dust beliefs
    whiteboard.view;			                        //getting new beliefs

+!removeDust(?x,?y):true<-
    whiteboard.setup,
    whiteboard.removeInfo(?x,?y),                              //remove dust info from whiteboard
    -dust(?x,?y),                                              //remove dust belief
    .send(inform, agentID(".*",addresses("local:vacworld.eis.ucd.ie")), cleaned(?x,?y));	         
                                                               //send cleaned message to all bots

//scan neighbouring squares for dust
+!detect:square(?pos,dust)&location(?x,?y)&direction(?dir) <-  //if there is dust
    foreach(square(?pos,dust)){                                //for each location
          getsquare.getsq(?dir,?x,?y,?pos)                     //get its coordinates (creates dustFound belief)
    },
    .send(inform, agentID(".*",addresses("local:vacworld.eis.ucd.ie")), updated(?x,?y));      
                                                               //send update information with vac's location

+!detect:true <-                                               //do nothing if conditions are not met
    .nil;

+dustFound(?x,?y):true <-                                      //belief generated when dust is found 
    whiteboard.setup,
    whiteboard.put(?x,?y),                                     //put dust information on whiteboard
    -dustFound(?x,?y);	                                        //remove dustFound belief

//update message, only bost which are from a distance of 8 from the source bot update their beliefs
+message(inform, agentID(?from, ?addr), updated(?x,?y)):true <-
    query(location(?a,?b)),
    getdist.getdist(?x,?y,?a,?b),                              //get distance between bot and source bot
    query(distance(?x,?y,?a,?b,?dist)),
    if(?dist<8){                                               //if distance is less than 8 update
           !updateDustInfo
    }
    if(~targeted(?a,?b)){                                      //if there is no target update
           !updateDustInfo
    }
    -message(inform, agentID(?from, ?addr), updated),          //remove message belief
    -distance(?x,?y,?a,?b,?dist);                              //remove distance belief

//targetet message (all bots are required to update their beliefs)
+message(inform, agentID(?from, ?addr), targeted):true <-
    !updateDustInfo,
    -message(inform, agentID(?from, ?addr), targeted);

//clean update, warns bots about cleaned dust, if bot had cleaned dust as target, target belief is removed	
+message(inform, agentID(?from, ?addr), cleaned(?x,?y)):true <-
    if(targeted(?x,?y)){
           -targeted(?x,?y)
    };


Nav module (Nav.java)

Module to get the next move required to get to a certain location

package vacworld2;

import java.awt.List;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

import com.agentfactory.clf.interpreter.Action;
import com.agentfactory.clf.interpreter.Module;
import com.agentfactory.clf.interpreter.Sensor;
import com.agentfactory.clf.lang.Predicate;

public class Nav extends Module {

     int tX = -1;                                             //target x
     int tY = -1;                                             //target y
     int lX = -1;                                             //current x
     int lY = -1;                                             //current y
     String dir = null;                                       //direction

     public Nav() {
	
           //action to set target (getNextMove support setting target)
           addAction("setTarget(?x,?y)",new Action(){

                   public boolean execute(Predicate activity){

                           tX = termAsInt(activity,0);
                           tY = termAsInt(activity,1);

                           return true;
                   }
           });

           //get the next move from current location to target
           addAction("getNextMove(?a,?b,?x,?y,?dir)",new Action(){

                   public boolean execute(Predicate activity){
                           boolean fault = false;

                           tX = termAsInt(activity,0);
                           tY = termAsInt(activity,1);
                           try {
                                  lX = termAsInt(activity,2);
                           } catch (Exception e){              //catch in case of invalid input
                                  fault = true;
                           }

                           try {
                                  lY = termAsInt(activity,3);
                           } catch (Exception e){              //catch in case input is invalid
                                  fault = true;
                           }

                           dir = termAsString(activity,4);

                           String out = nextMove();

                           if(!fault){
                                  addBelief("nextMove("+out+")");
                           } else {                            //in case of invalid input return forward as next move
                                  addBelief("nextMove(forward)");
                           }

                           return true;
                    }
            });
     }

     //method to calculate next move
     public String nextMove(){
            int Xdiff = lX-tX;
            int Ydiff = lY-tY;
            String out = "";

            if(tX==-1||tY==-1){
                  out = "forward";
            } else {	
                  if(Xdiff!=0){
                         if(dir.equals("north")){
                                 if(Xdiff<0){
                                        out = "right";
                                 } else {
                                        out = "left";
                                 }
                         } else if(dir.equals("south")){
                                 if(Xdiff<0){
                                        out = "left";
                                 } else {
                                        out = "right";
                                 }
                         } else if(dir.equals("east")){
                                 if(Xdiff<0){
                                        out = "forward";
                                 } else {
                                        if(Ydiff<0){
                                               out = "right";
                                        } else {
                                               out = "left";
                                        }
                                 }
                         } else if(dir.equals("west")){
                                 if(Xdiff>0){
                                        out = "forward";
                                 } else {
                                        if(Ydiff<0){
                                               out = "left";
                                        } else {
                                               out = "right";
                                        }
                                 }
                         }
                  } else {
                         if(dir.equals("north")){
                                 if(Ydiff<0){
                                        out = "left";
                                 } else {
                                        out = "forward";
                                 }
                         } else if(dir.equals("south")){
                                 if(Ydiff<0){
                                        out = "forward";
                                 } else {
                                        out = "left";
                                 }
                         } else if(dir.equals("east")){
                                 if(Ydiff<0){
                                        out = "right";
                                 } else {
                                        out = "left";
                                 }
                         } else if(dir.equals("west")){
                                 if(Ydiff<0){
                                        out = "left";
                                 } else {
                                        out = "right";
                                 }
                         }
                  }

                  if(out.equals("")){
                         out = "forward";
                  }
           }

           return out;
      }
}


GetSquare.java -- same code as for the Extended simple cleaner


DetDist (GetDistance.java)

To calculate the distance between two locations

package vacworld2;

import com.agentfactory.clf.interpreter.Action;
import com.agentfactory.clf.interpreter.Module;
import com.agentfactory.clf.interpreter.Sensor;
import com.agentfactory.clf.lang.Predicate;

public class GetDistance extends Module {

     public GetDistance() {
	
           addAction("getdist(?x,?y,?a,?b)",new Action(){

                   public boolean execute(Predicate activity){

                          int x = termAsInt(activity,0);
                          int y = termAsInt(activity,1);
                          int a = termAsInt(activity,2);
                          int b = termAsInt(activity,3);

                          int dist = Math.abs(x-a)+Math.abs(y-b);

                          addBelief("distance("+x+","+y+","+a+","+b+","+dist+")");

                          return true;
                   }
           });
     }
}


Whiteboard API (WhiteboardAPI.java)

Changed put(?x,?y) action

addAction("put(?x,?y)", new Action() {
      @Override
      public boolean execute(Predicate activity) {
            String location = CoreUtilities.presenter.toString(activity.termAt(0))+","+CoreUtilities.presenter.toString(activity.termAt(1));
            String info = "dust";
            service.putInformation(location,info);
            return true;
      }
});


Whiteboard service (WhiteboardService.java)

Changed getInformation(key) method

public synchronized String getInformation(String key) { 

    if(!information.containsKey(key))
          return null;

    return "dust(" + key + ")";  
}


To deploy, use the VacWorld and the VacWorldEIS java classes, and replace

designs.put("vacbot", "vacworld/VacBot.aspeak");

with

designs.put("vacbot", "vacworld2/vac.aspeak");

in the VacWorld class.