Revision 776
Code cleanup and documentation
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 |
*/ |
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 |
} |
Also available in: Unified diff