/** * Title: iSIM * Copyright: Copyright (c) 2002 * Company: University of Oregon Computer Science Dept. * * @author Jason Prideaux * @version 1.0 * */ package agent.autonomous; import agent.*; import controller.*; import gui.*; import transport.*; import transport.protocol.*; import java.awt.*; import java.awt.event.*; import java.util.Date; import java.io.*; /* ====================================================================== */ /** This class represents a mobile autonomous robot. It has knowledge and * state. The states determine the current goal of the robot. This robot * simply searches the world for a person in distress. Once found, the * robot will notify a Rescuer to save person. Once the Rescuer has saved * the person, this robot will then continue to look for more people. * * When the robot senses data/communication it will respond by making some * sort of actuation. So if the sensors were to fail. This robot would * be dead in the water. * */ public class Searcher extends Autonomous implements SocketReceiverListener{ /** The simulation controller, only used to determine our simulation environment boundaries. */ private Controller controller; // Knowledge /** The location of the rescuer robot. */ private Point rescuer; /** The location of person that needs to be rescued that we found. */ private Point distress; // States /** If true then remain idle. */ private boolean idle; /** If true then search the world. */ private boolean searching; /** If true then go to rescuer to get help. */ private boolean requesting; /* ====================================================================== */ /** This constructor sets up the information needed for the robot. * Naturally the robot must know its own abilities. The simulation * controller is needed so that it can be given to the mediator class, * Autonomous.java, which serves as an inbetween for a robot and the * simulator. * * @param c The iSIM controller. * @param loc The location of the agent. * @param port The communication port need to speak with iSIM. * @param range The wireless max range. * */ public Searcher(Controller c, Point loc, int port, int range){ // Super our agent/user information. super(c, loc, port, range, "searcher"); // Simulation controller controller = c; // our initial state. idle = true; searching = false; requesting = false; } //Constructor // Use this method to receive new location data. public void senseLocation(Point location, double heading){ if( !idle ){ Point newLocation = location; double newHeading = heading; if( searching ){ // Right now we search randomly double coin = Math.random(); if( coin < 0.3333 ){ newHeading += 45; }else if( coin < 0.6667 ){ newHeading -= 45; } if( newHeading < 0 ){ newHeading = 315; }else if( newHeading > 315 ){ newHeading = 0; } int x = (int)(location.getX()+(Math.cos(Math.toRadians(newHeading))*15)); int y = (int)(location.getY()+(Math.sin(Math.toRadians(newHeading))*-15)); if( x < 15 ){ newHeading = 0; }else if( y < 15 ){ newHeading = 270; }else if( x > (controller.getChartComp().getSize().getWidth()-15) ){ newHeading = 180; }else if( y > (controller.getChartComp().getSize().getHeight()-15) ){ newHeading = 90; }else{ newLocation = new Point(x,y); } actuateLocation( newLocation, newHeading); }else if( requesting ){ // Determine angle to rescuer to get help from double hyp = Controller.diff(rescuer, location); double opp = Math.abs(location.getY() - rescuer.getY()); double angle = Math.toDegrees(Math.asin(opp/hyp)); double fixed = 0; if( location.getX() <= rescuer.getX() && location.getY() <= rescuer.getY() ){ fixed = 360 - angle; }else if( location.getX() > rescuer.getX() && location.getY() <= rescuer.getY() ){ fixed = 180 + angle; }else if( location.getX() <= rescuer.getX() && location.getY() > rescuer.getY()){ fixed = angle; }else if( location.getX() > rescuer.getX() && location.getY() > rescuer.getY()){ fixed = 180 - angle; } double adjust = fixed%45; if( adjust < 22.5 ){ newHeading = ((int)(fixed/45))*45; }else{ newHeading = ((int)(fixed/45)+1)*45; } if( newHeading < 0 ){ newHeading = 315; }else if( newHeading > 315 ){ newHeading = 0; } int x = (int)(location.getX()+(Math.cos(Math.toRadians(newHeading))*15)); int y = (int)(location.getY()+(Math.sin(Math.toRadians(newHeading))*-15)); if( x < 15 ){ newHeading = 0; }else if( y < 15 ){ newHeading = 270; }else if( x > (controller.getChartComp().getSize().getWidth()-15) ){ newHeading = 180; }else if( y > (controller.getChartComp().getSize().getHeight()-15) ){ newHeading = 90; }else{ newLocation = new Point(x,y); } actuateLocation( newLocation, newHeading); } } } // Use this method to receive communication from other robots // and people agents. public void senseMessage(HelpMessage msg){ // If idle then we only listen to rescuer to tell us to search again. if( idle ){ if( ((HelpMessage)msg).getMessage().equalsIgnoreCase("rescuer") ){ rescuer = ((HelpMessage)msg).getLocation(); idle = false; searching = true; actuateMessage(new HelpMessage("searching", getPort(), 1, null )); actuateLocation( this.getLocation(), this.getPosition().getHeading()); } // If searching then we only listen to a person in distress }else if( searching ){ if( ((HelpMessage)msg).getMessage().equalsIgnoreCase("help") ){ distress = ((HelpMessage)msg).getLocation(); searching = false; requesting = true; } // If going to request help, then we only listen for a rescuer. }else if( requesting ){ if( ((HelpMessage)msg).getMessage().equalsIgnoreCase("rescuer") ){ actuateMessage(new HelpMessage("request", getPort(), 1, distress )); }else if( ((HelpMessage)msg).getMessage().equalsIgnoreCase("idle") ){ idle = true; requesting = false; } } } } //class: Searcher