/**
* 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