/** * 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 waits at a given spot until a searcher notifies it that a person * in distress has been found. The Rescuer will go to the person and send * a message to the person to notify the person that he/she has been saved. * * 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 Rescuer extends Autonomous implements SocketReceiverListener{ /** The simulation controller, only used to determine our simulation environment boundaries. */ private Controller controller; /** A thread used for this robot to send wireless communication message. */ private Calling calling; // Knowledge /** The location of person that needs to be rescued. */ private Point distress; /** Our starting/home position. */ private Point dispatch; // States /** If true then remain idle. */ private boolean idle; /** If true then go rescue person. */ private boolean rescuing; /** Ir true then return to starting/home position. */ private boolean returning; /* ====================================================================== */ /** 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 Rescuer(Controller c, Point loc, int port, int range){ // Super our agent/user information. super(c, loc, port, range, "rescuer"); // Simulation controller //controller = c; dispatch = loc; idle = true; rescuing = false; returning = false; calling = new Calling(); calling.start(); } //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( rescuing ){ // Determine angle to distress to get help from double hyp = Controller.diff(distress, location); double opp = Math.abs(location.getY() - distress.getY()); double angle = Math.toDegrees(Math.asin(opp/hyp)); double fixed = 0; if( location.getX() <= distress.getX() && location.getY() <= distress.getY() ){ fixed = 360 - angle; }else if( location.getX() > distress.getX() && location.getY() <= distress.getY() ){ fixed = 180 + angle; }else if( location.getX() <= distress.getX() && location.getY() > distress.getY()){ fixed = angle; }else if( location.getX() > distress.getX() && location.getY() > distress.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); }else if( returning ){ // Determine angle to dispatch to get help from double hyp = Controller.diff(dispatch, location); double opp = Math.abs(location.getY() - dispatch.getY()); double angle = Math.toDegrees(Math.asin(opp/hyp)); double fixed = 0; if( location.getX() <= dispatch.getX() && location.getY() <= dispatch.getY() ){ fixed = 360 - angle; }else if( location.getX() > dispatch.getX() && location.getY() <= dispatch.getY() ){ fixed = 180 + angle; }else if( location.getX() <= dispatch.getX() && location.getY() > dispatch.getY()){ fixed = angle; }else if( location.getX() > dispatch.getX() && location.getY() > dispatch.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); } if ( hyp > 15 ){ actuateLocation( newLocation, newHeading); }else{ returning = false; idle = true; } } } } // Use this method to receive communication from other robots // and people agents. public void senseMessage(HelpMessage msg){ // If idle then we only listen to searcher to tell us to search again. if( idle ){ if( ((HelpMessage)msg).getMessage().equalsIgnoreCase("searching") ){ dispatch = this.getLocation(); }else if( ((HelpMessage)msg).getMessage().equalsIgnoreCase("request") ){ distress = ((HelpMessage)msg).getLocation(); idle = false; rescuing = true; actuateMessage(new HelpMessage("idle", getPort(), 1, null )); actuateLocation( this.getLocation(), this.getPosition().getHeading()); } // If searching then we only listen to a person in distress }else if( rescuing ){ if( ((HelpMessage)msg).getMessage().equalsIgnoreCase("help") ){ actuateMessage(new HelpMessage("rescuer", getPort(), 1, null )); rescuing = false; returning = true; } } } // Returns the current location of this autonomous robot. public Point getPoint(){ return this.getLocation(); } // Use this thread to communicate to other robots. class Calling extends Thread{ public void run(){ while(true){ try{ Thread.sleep(2000); }catch(Exception e){} if( idle ){ actuateMessage(new HelpMessage("rescuer", getPort(), 1, getPoint() )); } } } } } //class: Rescuer