/* * SocSmallSimSRV.java */ package EDU.gatech.cc.is.abstractrobot; import java.awt.*; import java.util.Enumeration; import EDU.gatech.cc.is.util.Vec2; import EDU.gatech.cc.is.util.CircularBuffer; import EDU.gatech.cc.is.util.Units; import EDU.gatech.cc.is.simulation.*; import EDU.gatech.cc.is.communication.*; import EDU.gatech.cc.is.util.*; import EDU.cmu.cs.coral.util.Polygon2; import EDU.cmu.cs.coral.util.Circle2; /** * Implements SocSmall for simulation. * You should see the specifications in SocSmall for details on * how to use these methods. *

*

* Copyright * (c)1997, 1998 Tucker Balch * * @see SocSmall * @author Tucker Balch * @version $Revision: 1.4 $ */ public class SocSmallSimSRV extends Simple implements SocSmall, SimulatedObject { private CircularBuffer trail; // the robot's trail private int[] opponent_ids; // pointers to opponents private KinSensorSim kin_sensor; // senses our kin private TransceiverSim transceiver; // communicates to robots private Vec2 position; // location of the robot private GolfBallSim theball; // ball object private Vec2 steer; // robot heading private double speed; // current speed private Color foreground, // colors for drawing background; private long time; // elapsed time private double timed; // double version of time private double left, // used for drawing purposes right, top, bottom; private SimulatedObject[] all_objects // to keep track of other = new SimulatedObject[0]; // objects in the simulation private int visionclass; // how other robots see us public static final boolean DEBUG = false;// set true for debug // messages public static final double VISION_RANGE = .685;// set true for debug // messages private boolean on_east_team = false; // which team we are on private boolean on_west_team = false; private Vec2 kick_off_pos = new Vec2();// initial position // for kick offs private Vec2 receive_pos = new Vec2();// initial position when // not kicking off private Vec2 team_goal; // location of goal to defend private Vec2 opponent_goal; // location of other goal /** * Instantiate a SocSmallSimSRV object. Be sure * to also call init with proper values. * @see SocSmallSimSRV#init */ public SocSmallSimSRV() { if (DEBUG) System.out.println("SocSmall: instantiated."); // defaults position = new Vec2(0,0); steer = new Vec2(1,0); foreground = Color.black; background = Color.black; top = 10; bottom = -10; left = -10; right = 10; } /** * Initialize a SocSmallSimSRV object. Some of the parameters * are ignored because soccer robots have specific starting * places and headings. * @param xp if negative, it means this robot is on the west team, * east team otherwise. * @param yp ignored. * @param tp ignored. * @param ignore ignored. * @param f color 1 for the robot. * @param b color 2 for the robot. * @param v vision class of the robot (usually 1 or 2 depending * on whether on west team or east team). * @param i unique simulation id (NOT the same as player number!). */ public void init(double xp, double yp, double tp, double ignore, Color f, Color b, int v, int i, long s) { trail = new CircularBuffer(100); if (DEBUG) System.out.println("MultiForageN150Sim: initialized" +" at "+xp+","+yp); /*--- set global parameters ---*/ setID(i); kin_sensor = new KinSensorSim(this); transceiver = new TransceiverSim(this, this); foreground = f; background = b; time = 0; timed = 0; visionclass = v; if (xp<0) // on the west team { on_west_team = true; on_east_team = false; team_goal = new Vec2(-1.37,0); opponent_goal = new Vec2(1.37,0); } else // on east team { on_west_team = false; on_east_team = true; team_goal = new Vec2(1.37,0); opponent_goal = new Vec2(-1.37,0); } int num = getID()%5; if (num == 0) { kick_off_pos = new Vec2(1.2,0); receive_pos = new Vec2(1.2,0); } else if (num == 1) { kick_off_pos = new Vec2(0.5,0); receive_pos = new Vec2(0.5,0.25); } else if (num == 2) { kick_off_pos = new Vec2(0.15,0.5); receive_pos = new Vec2(0.15,0.5); } else if (num == 3) { kick_off_pos = new Vec2(0.15,0.0); receive_pos = new Vec2(0.50,-0.25); } else if (num == 4) { kick_off_pos = new Vec2(0.15,-0.5); receive_pos = new Vec2(0.15,-0.5); } if (on_west_team) // west team kicks off first { kick_off_pos.setx(-kick_off_pos.x); receive_pos.setx(-receive_pos.x); position = new Vec2(kick_off_pos.x, kick_off_pos.y); } else // east receives position = new Vec2(receive_pos.x, receive_pos.y); steer = getOpponentsGoal(-1); } /** * Take a simulated step; */ public void takeStep(long time_increment, SimulatedObject[] all_objs) { if (DEBUG) System.out.println("SocSmallSimSRV.TakeStep()"); /*--- keep pointer to the other objects ---*/ all_objects = all_objs; /*--- locate the ball, if we haven't already ---*/ if (theball == null) { for (int i=0; i (MAX_STEER*time_incd)) { if (sturn<0) sturn = -MAX_STEER*time_incd; else sturn = MAX_STEER*time_incd; } steer.sett(steer.t + sturn); /*--- compute velocity ---*/ Vec2 velocity = new Vec2(steer.x, steer.y); velocity.setr(base_speed * desired_speed); /*--- compute a movement step ---*/ Vec2 mvstep = new Vec2(velocity.x, velocity.y); mvstep.setr(mvstep.r * time_incd); /*--- test the new position to see if in bounds ---*/ // use bounds of official RoboCup soccer field Vec2 pp = new Vec2(position.x, position.y); pp.add(mvstep); if ((pp.x+RADIUS > 1.37)||(pp.x-RADIUS < -1.37)) { velocity.setx(0); mvstep.setx(0); } if ((pp.y+RADIUS > 0.7625)||(pp.y-RADIUS < -0.7625)) { velocity.sety(0); mvstep.sety(0); } /*--- test the new position to see if on top of obstacle ---*/ pp = new Vec2(position.x, position.y); boolean moveok = true; pp.add(mvstep); for (int i=0; i 0.0) && (scale < 1.0) ) { return true; } } } return false; // closest point to object on each edge of polygon not within object } public Vec2 getCenter(Vec2 from) { Vec2 tmp = new Vec2(position.x, position.y); tmp.sub(from); return(tmp); } public void push(Vec2 d, Vec2 v) { // sorry no pushee robots! } public void pickUp(SimulatedObject o) { // sorry no pickupee robots! } public void putDown(Vec2 p) { // sorry no put downee robots! } public void setVisionClass(int v) { visionclass = v; } public int getVisionClass() { return(visionclass); } public Color getForegroundColor() { return foreground; } public Color getBackgroundColor() { return background; } /** * Draw the robot in a specific spot. */ public void draw(Vec2 pos, Graphics g, int w, int h, double t, double b, double l, double r) { Vec2 old_pos = position; position = pos; draw(g,w,h,t,b,l,r); position = old_pos; } private Point last = new Point(0,0); /** * Draw the robot's Trail. */ public void drawTrail(Graphics g, int w, int h, double t, double b, double l, double r) { top =t; bottom =b; left =l; right =r; if (DEBUG) System.out.println("draw "+ w + " " + h + " " + t + " " + b + " " + l + " " + r + " "); double meterspp = (r - l) / (double)w; int xpix = (int)((position.x - l) / meterspp); int ypix = (int)((double)h - ((position.y - b) / meterspp)); /*--- record the point ---*/ Point p = new Point(xpix,ypix); if ((last.x!=xpix)||(last.y!=ypix)) trail.put(p); last = p; /*--- get the list of all points ---*/ Enumeration point_list = trail.elements(); /*--- draw the trail ---*/ g.setColor(background); Point from = (Point)point_list.nextElement(); while (point_list.hasMoreElements()) { Point next = (Point)point_list.nextElement(); g.drawLine(from.x,from.y,next.x,next.y); from = next; } } private String display_string = "blank"; /** * Set the String that is printed on the robot's display. * For simulated robots, this appears printed below the agent * when view "Robot State" is selected. * @param s String, the text to display. */ public void setDisplayString(String s) { display_string = s; } /** * Draw the robot's state. */ public void drawState(Graphics g, int w, int h, double t, double b, double l, double r) { top =t; bottom =b; left =l; right =r; if (DEBUG) System.out.println("draw "+ w + " " + h + " " + t + " " + b + " " + l + " " + r + " "); double meterspp = (r - l) / (double)w; int radius = (int)(RADIUS / meterspp); int xpix = (int)((position.x - l) / meterspp); int ypix = (int)((double)h - ((position.y - b) / meterspp)); /*--- draw State ---*/ g.setColor(background); g.drawString(display_string,xpix+radius+3,ypix-radius); displayVectors.draw(g,w,h,t,b,l,r); } /** * Set the length of the trail (in movement steps). * @param l int, the length of the trail. */ public void setTrailLength(int l) { trail = new CircularBuffer(l); } /** * Clear the trail. */ public void clearTrail() { trail.clear(); } /** * Draw the robot's ID. */ public void drawID(Graphics g, int w, int h, double t, double b, double l, double r) { top =t; bottom =b; left =l; right =r; if (DEBUG) System.out.println("draw "+ w + " " + h + " " + t + " " + b + " " + l + " " + r + " "); double meterspp = (r - l) / (double)w; int radius = (int)(RADIUS / meterspp); int xpix = (int)((position.x - l) / meterspp); int ypix = (int)((double)h - ((position.y - b) / meterspp)); /*--- draw ID ---*/ g.setColor(background); g.drawString(String.valueOf(getID()%5),xpix-radius,ypix-radius); } /** * Draw the object as an icon. * Default is just to do a regular draw. */ public void drawIcon(Graphics g, int w, int h, double t, double b, double l, double r) { draw(g, w, h, t, b, l, r); } /** * Draw the robot. */ public void draw(Graphics g, int w, int h, double t, double b, double l, double r) { top =t; bottom =b; left =l; right =r; if (DEBUG) System.out.println("draw "+ w + " " + h + " " + t + " " + b + " " + l + " " + r + " "); double meterspp = (r - l) / (double)w; if (DEBUG) System.out.println("meterspp "+meterspp); int radius = (int)(RADIUS / meterspp); int steerd = (int)Units.RadToDeg(steer.t); int xpix = (int)((position.x - l) / meterspp); int ypix = (int)((double)h - ((position.y - b) / meterspp)); if (DEBUG) System.out.println("robot at"+ " at "+xpix+","+ypix); /*--- draw the main body ---*/ g.setColor(foreground); g.fillArc(xpix - radius, ypix - radius, radius + radius, radius + radius, steerd, 90); g.fillArc(xpix - radius, ypix - radius, radius + radius, radius + radius, steerd+180, 90); g.setColor(background); g.fillArc(xpix - radius, ypix - radius, radius + radius, radius + radius, steerd+90, 90); g.fillArc(xpix - radius, ypix - radius, radius + radius, radius + radius, steerd+270, 90); /*--- draw steer ---*/ g.setColor(Color.black); int dirx = xpix + (int)((double)radius * Math.cos(steer.t)); int diry = ypix + -(int)((double)radius * Math.sin(steer.t)); g.drawLine(xpix, ypix, dirx, diry); } /** * Clean up. */ public void quit() { } /** * Gets time elapsed since the robot was instantiated. * Since this is simulation, it may not match real elapsed time. */ public long getTime() { return(time); } private long last_Opponentst = 0; private Vec2 last_Opponents[] = new Vec2[0]; /** * Get an array of Vec2s that point egocentrically from the * center of the robot to the Opponents currently sensed by the * robot. * @param timestamp only get new information if * timestamp > than last call or timestamp == -1 . * @return the sensed Opponents. */ public Vec2[] getOpponents(long timestamp) { if((timestamp > last_Opponentst)||(timestamp == -1)) { if (timestamp != -1) last_Opponentst = timestamp; last_Opponents = kin_sensor.getOpponents(all_objects); //--- check to see if they are too far away to see for (int i=0; i= SocSmallSimSRV.VISION_RANGE) { //--- put them in arbitrary spot last_Opponents[i] = getOpponentsGoal(timestamp); last_Opponents[i].setr( SocSmallSimSRV.VISION_RANGE +0.1); } } } // make a copy Vec2[] retval = new Vec2[last_Opponents.length]; for (int i = 0; i than last call or timestamp == -1 . * @return the sensed teammates. */ public Vec2[] getTeammates(long timestamp) { if((timestamp > last_Teammatest)||(timestamp == -1)) { if (timestamp != -1) last_Teammatest = timestamp; last_Teammates = kin_sensor.getTeammates(all_objects); } //--- check to see if they are too far away to see for (int i=0; i= SocSmallSimSRV.VISION_RANGE) { //--- put them in arbitrary spot last_Teammates[i] = getOurGoal(timestamp); last_Teammates[i].setr( SocSmallSimSRV.VISION_RANGE +0.1); } } // make a copy Vec2[] retval = new Vec2[last_Teammates.length]; for (int i = 0; i=SocSmallSimSRV.VISION_RANGE) { retval = getOurGoal(timestamp); retval.setr(SocSmallSimSRV.VISION_RANGE +0.1); //System.out.println("out of range"); } return(retval); } long last_JustScoredt = 0; int last_JustScored = 0; /** * Get an integer that indicates whether a scoring event * just occured. * @param timestamp only get new information * if timestamp > than last call or timestamp == -1. * @return 1 if team just scored, -1 if scored against, * 0 otherwise. */ public int getJustScored(long timestamp) { if((timestamp > last_JustScoredt)||(timestamp == -1)) { if (timestamp != -1) last_JustScoredt = timestamp; last_JustScored = 0; if (theball==null) return(0); else { if (on_east_team) { if (theball.eastKickOff()) last_JustScored = -1; if (theball.westKickOff()) last_JustScored = 1; } else { if (theball.eastKickOff()) last_JustScored = 1; if (theball.westKickOff()) last_JustScored = -1; } } } return(last_JustScored); } public Vec2 getOurGoal(long timestamp) { Vec2 retval = new Vec2(team_goal.x, team_goal.y); retval.sub(position); return(retval); } public Vec2 getOpponentsGoal(long timestamp) { Vec2 retval = new Vec2(opponent_goal.x, opponent_goal.y); retval.sub(position); return(retval); } /** * Return an int represting the player's ID on the team. * This value may not be valid if the simulation has not * been "set up" yet. Do not use it during initialization. * @param timestamp only get new information if * timestamp > than last call or timestamp == -1 . * @return the number. */ public int getPlayerNumber(long timestamp) { return(kin_sensor.getPlayerNumber(all_objects)); } public boolean canKick(long timestamp) { boolean retval = false; Vec2 kickpos = new Vec2(steer.x, steer.y); kickpos.setr(RADIUS); kickpos.add(position); if (theball!=null) { Vec2 tmp = theball.getCenter(kickpos); if (tmp.r<=KICKER_SPOT_RADIUS) retval = true; } return(retval); } public void kick(long timestamp) { Vec2 d = new Vec2(0,0); Vec2 v = new Vec2(KICKER_SPEED,0); v.sett(steer.t); if (theball != null) theball.push(d,v); } private long last_Obstaclest = 0; private Vec2 last_Obstacles[]; private int num_Obstacles; /** * Get an array of Vec2s that point egocentrically from the * center of the robot to the obstacles currently sensed by the * bumpers and sonars. * @param timestamp only get new information if * timestamp > than last call or timestamp == -1 . * @return the sensed obstacles. */ public Vec2[] getObstacles(long timestamp) { if((timestamp > last_Obstaclest)||(timestamp == -1)) { if (timestamp != -1) last_Obstaclest = timestamp; Vec2 tmp_objs[] = new Vec2[all_objects.length]; num_Obstacles = 0; /*--- check all objects ---*/ for(int i = 0; i than last call or timestamp == -1. * @return the position. * @see Simple#resetPosition */ public Vec2 getPosition(long timestamp) { return(new Vec2(position.x, position.y)); } /** * Get the position of the robot in global coordinates. * @return the position. * @see Simple#resetPosition */ public Vec2 getPosition() { return(new Vec2(position.x, position.y)); } /** * Reset the odometry of the robot in global coordinates. * This might be done when reliable sensor information provides * a very good estimate of the robot's location, or if you * are starting the robot in a known location other than (0,0). * Do this only if you are certain you're right! * @param position the new position. * @see Simple#getPosition */ public void resetPosition(Vec2 posit) { position.setx(posit.x); position.setx(posit.y); } /** */ public double getSteerHeading(long timestamp) { return(steer.t); } /** */ public void resetSteerHeading(double heading) { /* ensure in legal range */ heading = Units.ClipRad(heading); /* set the angle */ steer.sett(heading); } private double desired_heading; /** */ public void setSteerHeading(long timestamp, double heading) { /* ensure in legal range */ desired_heading = Units.ClipRad(heading); } private double desired_speed = 0; /** * @see SocSmallSimSRV#setSpeed */ public void setSpeed(long timestamp, double speed) { /* ensure legal range */ if (speed > 1.0) speed = 1.0; else if (speed < 0) speed = 0; desired_speed = speed; } private double base_speed = MAX_TRANSLATION; /** * @see SocSmallSimSRV#setBaseSpeed */ public void setBaseSpeed(double speed) { if (speed > MAX_TRANSLATION) speed = MAX_TRANSLATION; else if (speed < 0) speed = 0; base_speed = speed; } /*--- Transceiver methods ---*/ public void multicast(int[] ids, Message m) throws CommunicationException { transceiver.multicast(ids, m, all_objects); } public void broadcast(Message m) { transceiver.broadcast(m, all_objects); } public void unicast(int id, Message m) throws CommunicationException { transceiver.unicast(id, m, all_objects); } public CircularBufferEnumeration getReceiveChannel() { return(transceiver.getReceiveChannel()); } public void setCommunicationMaxRange(double m) { transceiver.setCommunicationMaxRange(m); } public void receive(Message m) { transceiver.receive(m); } public boolean connected() { return(true); } }