Revision 776

View differences:

trunk/code/projects/colonet/client/Makefile
49 49

  
50 50
clean:
51 51
	$(RM) -r $(DIR)
52
	$(RM) *~
52 53

  
53 54
run:
54 55
	appletviewer http://128.2.99.176/colonet
trunk/code/projects/colonet/client/RobotIcon.java
1 1

  
2
import javax.swing.*;
3
import javax.swing.event.*;
4
import javax.imageio.*;
5 2
import java.awt.*;
6
import java.awt.image.*;
7
import java.awt.event.*;
8
import java.net.*;
9
import java.io.*;
10
import java.util.*;
11 3

  
12 4
/**
13 5
*	 RobotIcon class
14 6
*	 Provides a means for graphically representing and keeping track of webcam bots.
15 7
*/
16 8
public class RobotIcon {
9
	private int id;  // the XBee ID of the robot
10
	private Color color;  // the color used for painting the robot on screen.
11
	private Point location;  // the position of the robot in the coordinate system of the webcam image
12
	private Point destination;  // the destination of the robot, if homing or charging
13
	private int battery;  // the battery level, if available
17 14

  
18
	public int x, y;
19
	public int destx, desty;
20
	public int id;
21
	public Color color;
22
	public int battery;
23

  
24 15
	public RobotIcon (int id, int x, int y) {
25
		this.color = Color.RED;
26
		this.x = x;
27
		this.y = y;
28
		this.id = id;
29
		this.destx = -1;
30
		this.desty = -1;
31
		this.battery = -1;
16
		setID(id);
17
		setColor(Color.RED);
18
		setLocation(x, y);
19
		clearDestination();
20
		setBattery(-1);
32 21
	}
22
	
23
	/**
24
	*  Returns the ID of this RobotIcon.
25
	*/
26
	public int getID () {
27
	  return id;
28
	}
29
	
30
	/** 
31
	*  Sets the ID of this RobotIcon.
32
	*/
33
	public void setID (int newid) {
34
	  this.id = newid;
35
	}
36
	
37
	/**
38
	*  Returns the Color used for representing this RobotIcon on screen.
39
	*/
40
	public Color getColor () {
41
	  return color;
42
	}
43
	
44
	/** 
45
	*  Sets the Color used for representing this RobotIcon on screen.
46
	*/
47
	public void setColor (Color newcolor) {
48
	  this.color = newcolor;
49
	}
50
	
51
	/**
52
	*  Returns the battery level of this RobotIcon.
53
	*  TODO: what numbering system is this?
54
	*/ 
55
	public int getBattery () {
56
	  return battery;
57
	}
58
	
59
	/**
60
	*  Sets the battery level of this RobotIcon.
61
	*  TODO: what numbering system is this?
62
	*/
63
	public void setBattery (int newbattery) {
64
	  this.battery = newbattery;
65
	}
66
	
67
	/**
68
	*  Returns the location of this RobotIcon as a Point. The location is specified 
69
	*  in the coordinate system of the original webcam image, NOT the coordinate
70
	*  system of the scaled image as seen on screen.
71
	*/
72
	public Point getLocation () {
73
	  return location;
74
	}
33 75

  
34 76
	/**
35
	*	 Relocates this RobotIcon to a new coordinate point.
36
	*
77
	*	 Sets the location of this RobotIcon. The location should be specified in the
78
	*  coordinate system of the original webcam image, NOT the coordinate system of
79
	*  the scaled image as seen on screen.
37 80
	*/
38
	public void move (int newX, int newY) {
39
		this.x = newX;
40
		this.y = newY;
81
	public void setLocation (int x, int y) {
82
		location.setLocation(x, y);
41 83
	}
84
	
85
  /**
86
	*	 Sets the location of this RobotIcon. The location should be specified in the
87
	*  coordinate system of the original webcam image, NOT the coordinate system of
88
	*  the scaled image as seen on screen.
89
	*/
90
	public void setLocation (Point p) {
91
    location.setLocation(p);
92
	}
93
	
94
	/**
95
	*  Returns the destination of this RobotIcon as a Point. The location is specified 
96
	*  in the coordinate system of the original webcam image, NOT the coordinate
97
	*  system of the scaled image as seen on screen. If the RobotIcon has no current
98
	*  destination, then this method returns null.
99
	*/
100
	public Point getDestination () {
101
	  if (!hasDestination())
102
	    return null;
103
	  return destination;
104
	}
105
	
106
	/**
107
	*  Determines whether this RobotIcon currently has a destination, e.g., for homing
108
	*  to a specific point in the environment or finding a charging bay.
109
	*/
110
	public boolean hasDestination () {
111
	  return (destination.x >= 0 && destination.y >= 0);
112
	}
113
	
114
	/**
115
	*	 Sets the destination of this RobotIcon for the purposes of homing to a specific
116
	*  point in the environment of finding a charging bay. The destination point should
117
	*  be specified in the coordinate system of the original webcam image, NOT the 
118
	*  coordinate system of the scaled image as seen on screen.
119
	*/
120
	public void setDestination (int x, int y) {
121
		destination.setLocation(x, y);
122
	}
123
	
124
	/**
125
	*	 Sets the destination of this RobotIcon for the purposes of homing to a specific
126
	*  point in the environment of finding a charging bay. The destination point should
127
	*  be specified in the coordinate system of the original webcam image, NOT the 
128
	*  coordinate system of the scaled image as seen on screen.
129
	*/
130
	public void setDestination (Point p) {
131
		destination.setLocation(p);
132
	}
133
	
134
	/**
135
	*  Clears the destination Point for this RobotIcon, indicating that the robot is
136
	*  no longer homing.
137
	*/
138
	public void clearDestination () {
139
	  setDestination(-1, -1);
140
	}
42 141

  
43 142
	/**
44 143
	*	 Determines whether a given point is within the rectangle that circumscribes the
45
	*	 robot's circlular icon. Used for clicking on robots in webcam view.
46
	*
144
	*	 robot's circlular icon. Used for click detection on robots in webcam view. The
145
	*  parameter point should be specified in the coordinate system of the original
146
	*  webcam image, NOT the coordinate system of the scaled image as seen on screen.
47 147
	*/
48 148
	public boolean contains (int px, int py) {
49
	int radius = ColonetConstants.ROBOT_RADIUS;
50
		Rectangle rect = new Rectangle(x-radius, y-radius, 2*radius, 2*radius);
51
		return rect.contains(px, py);
149
		return this.getBoundingRectangle().contains(px, py);
52 150
	}
151
	
152
	/**
153
	*  Returns the Rectangle object that circumscribes the RobotIcon identifier circle
154
	*  that is painted on screen. The Rectangle is in the coordinate system of the 
155
	*  original webcam image NOT the coordinate system of the scaled image as seen 
156
	*  on screen.
157
	*/
158
	public Rectangle getBoundingRectangle () {
159
	  int radius = ColonetConstants.ROBOT_RADIUS;
160
	  return new Rectangle(location.x-radius, location.y-radius, 2*radius, 2*radius);
161
	}
53 162

  
163
  /**
164
  *  Provides a text representation of this RobotIcon object
165
  */
54 166
	public String toString () {
55
		String s = "RobotIcon at (" + x + "," + y + "), id " + id;
167
		String s = "RobotIcon at (" + location.x + "," + location.y + "), id " + id;
56 168
		return s;
57 169
	}
58 170
}
trunk/code/projects/colonet/client/RobotList.java
15 15
  * For a given Point, finds the robot that conatins this Point
16 16
  * graphically. The coordinate system is based on the dimensions
17 17
  * of the image returned by the webcam loader, not the coordinates
18
  * of the panel containing the image on in the applet. Returns null
18
  * of the panel containing the image in the applet. Returns null
19 19
  * if no robot contains the Point, or if the Point is null. If
20 20
  * multiple robots overlap the point, one will be chosen arbitrarily.
21 21
  */
......
30 30
		}
31 31
		return null;
32 32
  }  
33
  
34
  /**
35
  * Removes the destination coordinate for a specified robot. As
36
  * a result, no destination vector is painted for the robot on 
37
  * the webcam image. This method does not cause any command
38
  * to be sent to the robot.
39
  */
40
  public void cancelMoveTo (int id) {
41
    RobotIcon r = get(id);
42
    if (r != null)
43
      r.destx = r.desty = -1;
44
  }
45 33

  
46 34
}
trunk/code/projects/colonet/client/Colonet.java
492 492

  
493 493
		RobotIcon r = robotIcons.get(botNum);
494 494
		if (r != null) {
495
		    r.battery = batteryIcon.convert(level);  // set contextual battery meter
495
		    r.setBattery(batteryIcon.convert(level));  // set contextual battery meter
496 496
		    batteryIcon.setLevel(level);             // set solo battery meter
497 497
		}
498 498
		super.repaint();
......
514 514
			// Save previous robot information
515 515
			RobotIcon oldIcon = robotIcons.get(id);
516 516
			if (oldIcon != null) {
517
			    newIcon.battery = oldIcon.battery;
518
				newIcon.destx = oldIcon.destx;
519
				newIcon.desty = oldIcon.desty;
517
		    newIcon.setBattery(oldIcon.getBattery());
518
				newIcon.setDestination(oldIcon.getDestination());
520 519
			}
521
			if (newIcon.id >= 0) {
522
				newIcon.color = Color.GREEN;
520
			if (newIcon.getID() >= 0) {
521
				newIcon.setColor(Color.GREEN);
523 522
			}
524 523
			newList.put(id, newIcon);
525 524
		}
......
534 533
    System.out.println("Got move update: " + line);
535 534
    String [] str = line.split(" ");
536 535
    int id = Integer.parseInt(str[1]);
537
    robotIcons.cancelMoveTo(id);
536
    robotIcons.get(id).clearDestination();
538 537
  }
539 538
	
540 539
	/**
......
620 619
				
621 620
				RobotIcon r = robotIcons.get(selectedBot);
622 621
				if (r != null) {
623
					r.destx = pt.x;
624
					r.desty = pt.y;
622
					r.setDestination(pt);
625 623
					if (csi != null) {
626
						csi.sendAbsoluteMove(r.id, r.destx, r.desty);
624
						csi.sendAbsoluteMove(r.getID(), pt.x, pt.y);
627 625
					}
628 626
				}
629 627
				return;
......
633 631
			if ((e.getButton() == MouseEvent.BUTTON2 || e.getButton() == MouseEvent.BUTTON3)  
634 632
          && e.getID() == MouseEvent.MOUSE_PRESSED
635 633
          && station != null && station.contains(e.getX(), e.getY())) {
636
        if (selectedBot >= 0)
634
        if (selectedBot >= 0) {
635
          RobotIcon r = robotIcons.get(selectedBot);
636
          if (r != null) {
637
            Point p = panelWebcam.convertPoint(station.getX(), station.getY());
638
            r.setDestination(p);
639
          }
637 640
          csi.sendRecharge(selectedBot);
641
        }
638 642
				return;
639 643
			}
640 644

  
......
648 652
				if (selectedBot < 0) {
649 653
					return;
650 654
				}
651

  
652 655
				RobotIcon r = robotIcons.get(selectedBot);
653 656
				if (r != null) {
654
					r.destx = pt.x;
655
					r.desty = pt.y;
657
					r.setDestination(pt);
656 658
					if (csi != null) {
657
						csi.sendAbsoluteMove(r.id, r.destx, r.desty);
659
						csi.sendAbsoluteMove(r.getID(), pt.x, pt.y);
658 660
					}
659 661
				}
660 662
				return;
......
670 672
				panelWebcam.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
671 673
				for (Map.Entry<Integer,RobotIcon> entry : robotIcons.entrySet()) {
672 674
					RobotIcon r = entry.getValue();
673
					r.destx = pt.x;
674
					r.desty = pt.y;
675
					r.setDestination(pt);
676
          //TODO: send absolute move commands
675 677
				}
676 678
				return;
677 679
			}
......
711 713
			// Otherwise, we are selecting a bot, or doing nothing
712 714
			RobotIcon r = robotIcons.getBoundingIcon(pt);
713 715
      if (r != null)
714
        selectedBot = r.id;
716
        selectedBot = r.getID();
715 717
		}
716 718
	}
717 719

  
......
793 795
			} else if (source == btnF) { // Robot Movement Controls
794 796
				vectorController.setMaxForward();
795 797
				vectorController.sendToServer();
796
				robotIcons.cancelMoveTo(selectedBot);
798
				robotIcons.get(selectedBot).clearDestination();
797 799
			} else if (source == btnB) {
798 800
				vectorController.setMaxReverse();
799 801
				vectorController.sendToServer();
800
				robotIcons.cancelMoveTo(selectedBot);
802
				robotIcons.get(selectedBot).clearDestination();
801 803
			} else if (source == btnL) {
802 804
				vectorController.setMaxLeft();
803 805
				vectorController.sendToServer();
804
				robotIcons.cancelMoveTo(selectedBot);
806
				robotIcons.get(selectedBot).clearDestination();
805 807
			} else if (source == btnR) {
806 808
				vectorController.setMaxRight();
807 809
				vectorController.sendToServer();
808
				robotIcons.cancelMoveTo(selectedBot);
810
				robotIcons.get(selectedBot).clearDestination();
809 811
			} else if (source == btnActivate) {
810 812
				vectorController.setZero();
811 813
				vectorController.sendToServer();
812
				robotIcons.cancelMoveTo(selectedBot);
814
				robotIcons.get(selectedBot).clearDestination();
813 815
      } else if (source == btnSetBounds) {
814 816
        boundary.set = true;
815 817
        panelWebcam.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
......
842 844
			  else
843 845
          csi.sendRecharge(2);
844 846
			} else if (source == btnCommand_StopCharging) {
845
			  if (selectedBot >= 0)
847
			  if (selectedBot >= 0) {
848
			    robotIcons.get(selectedBot).clearDestination();
846 849
			    csi.sendRechargeStop(selectedBot);
847
			  else
850
			  } else {
851
			    robotIcons.get(2).clearDestination();
848 852
          csi.sendRechargeStop(2);
853
        }
849 854
			} else if (source == btnAddTask) { // Queue Management
850 855
				taskAddWindow.prompt();
851 856
			} else if (source == btnRemoveTask) {
......
896 901
						if (count % 30 == 0) {
897 902
							for (Map.Entry<Integer,RobotIcon> entry : robotIcons.entrySet()) {
898 903
								RobotIcon r = entry.getValue();
899
									int id = r.id;
904
									int id = r.getID();
900 905
										if (id >= 0) {
901 906
										csi.sendBatteryRequest(id);
902 907
									}
......
999 1004
				bufferedGraphics.setStroke(new BasicStroke(2));
1000 1005
				for (Map.Entry<Integer,RobotIcon> entry : robotIcons.entrySet()) {
1001 1006
					RobotIcon r = entry.getValue();
1002
					bufferedGraphics.setColor(r.color);
1007
					bufferedGraphics.setColor(r.getColor());
1003 1008
					// Identifier circle
1004
					int px = (int) (x + r.x * scale);
1005
					int py = (int) (y + r.y * scale);
1009
					int px = (int) (x + r.getLocation().x * scale);
1010
					int py = (int) (y + r.getLocation().y * scale);
1006 1011
					int radius = ColonetConstants.ROBOT_RADIUS;
1007 1012
					bufferedGraphics.drawOval(px-radius, py-radius, 2*radius, 2*radius);
1008 1013
					// ID, if applicable
1009
					if (r.id > 0) {
1014
					if (r.getID() > 0) {
1010 1015
					    bufferedGraphics.setFont(new Font("arial", Font.PLAIN, 36));
1011
					    bufferedGraphics.drawString("" + r.id, px-10, py+10);
1016
					    bufferedGraphics.drawString("" + r.getID(), px-10, py+10);
1012 1017
					}
1013 1018
					// Battery
1014
					if (r.battery >= 0) {
1015
					    int pixels = r.battery * ColonetConstants.BATTERY_WIDTH / 100;
1016
						if (r.battery > 50)
1019
					if (r.getBattery() >= 0) {
1020
					    int pixels = r.getBattery() * ColonetConstants.BATTERY_WIDTH / 100;
1021
						if (r.getBattery() > 50)
1017 1022
						    bufferedGraphics.setColor(Color.GREEN);
1018
						else if (r.battery > 25)
1023
						else if (r.getBattery() > 25)
1019 1024
						    bufferedGraphics.setColor(Color.YELLOW);
1020 1025
						else
1021 1026
						    bufferedGraphics.setColor(Color.RED);
......
1024 1029
						bufferedGraphics.drawRect(px+20, py+20, ColonetConstants.BATTERY_WIDTH, ColonetConstants.BATTERY_HEIGHT);
1025 1030
					}
1026 1031
					// If the robot has a destination, draw the vector
1027
					if (r.destx >= 0) {
1028
						bufferedGraphics.drawLine(px, py, (int)(x + r.destx * scale), (int)(y + r.desty * scale));
1032
					if (r.hasDestination()) {
1033
						bufferedGraphics.drawLine(px, py, (int)(x + r.getDestination().x * scale), (int)(y + r.getDestination().y * scale));
1029 1034
					}
1030 1035
				}
1031 1036
			}
......
1033 1038
			// Identify currently-selected robot
1034 1039
			RobotIcon r = robotIcons.get(selectedBot);
1035 1040
			if (r != null) {
1036
				int px = (int) (x + r.x * scale);
1037
				int py = (int) (y + r.y * scale);
1041
				int px = (int) (x + r.getLocation().x * scale);
1042
				int py = (int) (y + r.getLocation().y * scale);
1038 1043
				int radius = ColonetConstants.ROBOT_RADIUS;
1039 1044
				bufferedGraphics.setColor(Color.BLACK);
1040 1045
				bufferedGraphics.drawOval(px-radius-6, py-radius-6, 2*radius+12, 2*radius+12);
......
1052 1057
			if (img == null) {
1053 1058
				return new Point(e.getX(), e.getY());
1054 1059
			}
1060
			return convertPoint(e.getX(), e.getY());
1061
		}
1062
		
1063
		/**
1064
		* Convert a point on the webcam panel to a coordinate that is consistent with the
1065
		* original size of the image that the panel contains.
1066
		*/
1067
		public Point convertPoint (int panelx, int panely) {
1055 1068

  
1056 1069
			// Calculate scaling
1057 1070
			int border = ColonetConstants.WEBCAM_BORDER;
1058
			int clickx = e.getX();
1059
			int clicky = e.getY();
1071
			int clickx = panelx;
1072
			int clicky = panely;
1060 1073
			int maxWidth = getWidth() - 2*border;
1061 1074
			int maxHeight = getHeight() - 2*border;
1062 1075
			double widthRatio = 1.0 * maxWidth / img.getWidth();
trunk/code/projects/colonet/client/VectorController.java
42 42

  
43 43
	/**  Set the robot motion vector. The "vector" is defined as 
44 44
	* (0,0)->(x,y) where (0,0) is in the center of the targeting ring.
45
	* Does nothing if the specified point is outside the ring.
45 46
	* @param x The x coordinate of the point.
46 47
	* @param y The y coordinate of the point.
47 48
	*/

Also available in: Unified diff