Project

General

Profile

Revision 320

Added by Greg Tress over 16 years ago

battery meter is in testing stage, included in the gui now.

View differences:

trunk/code/projects/colonet/ColonetGUI/Colonet.xcodeproj/gmtress.pbxuser
163 163
					PBXFileDataSource_Warnings_ColumnID,
164 164
				);
165 165
			};
166
			PBXPerProjectTemplateStateSaveDate = 218754119;
167
			PBXWorkspaceStateSaveDate = 218754119;
166
			PBXPerProjectTemplateStateSaveDate = 218756837;
167
			PBXWorkspaceStateSaveDate = 218756837;
168 168
		};
169 169
		perUserProjectItems = {
170 170
			A30FC0970CBD7DFA000A16EC /* PBXTextBookmark */ = A30FC0970CBD7DFA000A16EC /* PBXTextBookmark */;
......
174 174
			A3D78E650CB72FF100A79632 /* PBXTextBookmark */ = A3D78E650CB72FF100A79632 /* PBXTextBookmark */;
175 175
			A3DAF7F40D09EC670015B97D /* PBXTextBookmark */ = A3DAF7F40D09EC670015B97D /* PBXTextBookmark */;
176 176
			A3DAF7F50D09EC670015B97D /* PBXTextBookmark */ = A3DAF7F50D09EC670015B97D /* PBXTextBookmark */;
177
			A3DAF7F60D09EC670015B97D /* PBXTextBookmark */ = A3DAF7F60D09EC670015B97D /* PBXTextBookmark */;
178
			A3DAF7F70D09EC670015B97D /* PBXTextBookmark */ = A3DAF7F70D09EC670015B97D /* PBXTextBookmark */;
179
			A3DAF7F80D09EC670015B97D /* PBXTextBookmark */ = A3DAF7F80D09EC670015B97D /* PBXTextBookmark */;
177
			A3DAF8800D09F6B90015B97D /* PBXTextBookmark */ = A3DAF8800D09F6B90015B97D /* PBXTextBookmark */;
178
			A3DAF88C0D09F6F20015B97D /* PBXTextBookmark */ = A3DAF88C0D09F6F20015B97D /* PBXTextBookmark */;
180 179
			A3F558940CF276B100E3EBD1 /* PBXTargetBookmark */ = A3F558940CF276B100E3EBD1 /* PBXTargetBookmark */;
181
			A3F7AA550D04F0F000C2BF9C /* PBXTextBookmark */ = A3F7AA550D04F0F000C2BF9C /* PBXTextBookmark */;
182 180
			A3FD76ED0CEBBBC10048CD0C /* PBXTextBookmark */ = A3FD76ED0CEBBBC10048CD0C /* PBXTextBookmark */;
183 181
		};
184 182
		sourceControlManager = A341617E0C989B510007BEF2 /* Source Control */;
......
188 186
	00E68290FEC88D7311DB9C8B /* Colonet.java */ = {
189 187
		uiCtxt = {
190 188
			sepNavIntBoundsRect = "{{0, 0}, {1011, 11760}}";
191
			sepNavSelRange = "{9612, 0}";
192
			sepNavVisRect = "{{0, 3745}, {1011, 525}}";
189
			sepNavSelRange = "{9135, 0}";
190
			sepNavVisRect = "{{0, 3738}, {1011, 525}}";
193 191
			sepNavWindowFrame = "{{38, 133}, {613, 699}}";
194 192
		};
195 193
	};
......
342 340
		vrLen = 912;
343 341
		vrLoc = 5611;
344 342
	};
345
	A3DAF7F60D09EC670015B97D /* PBXTextBookmark */ = {
343
	A3DAF8800D09F6B90015B97D /* PBXTextBookmark */ = {
346 344
		isa = PBXTextBookmark;
347
		fRef = 00E68291FEC88ED911DB9C8B /* index.html */;
348
		name = "index.html: 25";
345
		fRef = 00E68290FEC88D7311DB9C8B /* Colonet.java */;
346
		name = "Colonet.java: 271";
349 347
		rLen = 0;
350
		rLoc = 773;
348
		rLoc = 9135;
351 349
		rType = 0;
352
		vrLen = 959;
353
		vrLoc = 407;
350
		vrLen = 1065;
351
		vrLoc = 9042;
354 352
	};
355
	A3DAF7F70D09EC670015B97D /* PBXTextBookmark */ = {
353
	A3DAF88C0D09F6F20015B97D /* PBXTextBookmark */ = {
356 354
		isa = PBXTextBookmark;
357
		fRef = A34161900C989CB30007BEF2 /* ColonetServerInterface.java */;
358
		name = "ColonetServerInterface.java: 207";
359
		rLen = 0;
360
		rLoc = 5797;
361
		rType = 0;
362
		vrLen = 912;
363
		vrLoc = 5611;
364
	};
365
	A3DAF7F80D09EC670015B97D /* PBXTextBookmark */ = {
366
		isa = PBXTextBookmark;
367 355
		fRef = 00E68290FEC88D7311DB9C8B /* Colonet.java */;
368
		name = "Colonet.java: 289";
356
		name = "Colonet.java: 271";
369 357
		rLen = 0;
370
		rLoc = 9612;
358
		rLoc = 9135;
371 359
		rType = 0;
372 360
		vrLen = 1037;
373 361
		vrLoc = 9042;
......
499 487
		isa = PBXTargetBookmark;
500 488
		trg = A3F558890CF2766C00E3EBD1 /* doc */;
501 489
	};
502
	A3F7AA550D04F0F000C2BF9C /* PBXTextBookmark */ = {
503
		isa = PBXTextBookmark;
504
		fRef = 00E68290FEC88D7311DB9C8B /* Colonet.java */;
505
		name = "Colonet.java: 279";
506
		rLen = 0;
507
		rLoc = 9612;
508
		rType = 0;
509
		vrLen = 1508;
510
		vrLoc = 8569;
511
	};
512 490
	A3FD76ED0CEBBBC10048CD0C /* PBXTextBookmark */ = {
513 491
		isa = PBXTextBookmark;
514 492
		fRef = A3FD76EE0CEBBBC10048CD0C /* index.html */;
trunk/code/projects/colonet/ColonetGUI/Colonet.xcodeproj/gmtress.perspective
226 226
			<key>Layout</key>
227 227
			<array>
228 228
				<dict>
229
					<key>BecomeActive</key>
230
					<true/>
231 229
					<key>ContentConfiguration</key>
232 230
					<dict>
233 231
						<key>PBXBottomSmartGroupGIDs</key>
......
307 305
					<key>Dock</key>
308 306
					<array>
309 307
						<dict>
308
							<key>BecomeActive</key>
309
							<true/>
310 310
							<key>ContentConfiguration</key>
311 311
							<dict>
312 312
								<key>PBXProjectModuleGUID</key>
......
324 324
										<key>_historyCapacity</key>
325 325
										<integer>0</integer>
326 326
										<key>bookmark</key>
327
										<string>A3DAF7F80D09EC670015B97D</string>
327
										<string>A3DAF88C0D09F6F20015B97D</string>
328 328
										<key>history</key>
329 329
										<array>
330 330
											<string>A3C65E6B0CD275C200D77B7B</string>
......
332 332
											<string>A3F558940CF276B100E3EBD1</string>
333 333
											<string>A3DAF7F40D09EC670015B97D</string>
334 334
											<string>A3DAF7F50D09EC670015B97D</string>
335
											<string>A3F7AA550D04F0F000C2BF9C</string>
335
											<string>A3DAF8800D09F6B90015B97D</string>
336 336
										</array>
337 337
										<key>prevStack</key>
338 338
										<array>
......
340 340
											<string>A3D78E650CB72FF100A79632</string>
341 341
											<string>A3C65E1D0CD262BC00D77B7B</string>
342 342
											<string>A30FC0970CBD7DFA000A16EC</string>
343
											<string>A3DAF7F60D09EC670015B97D</string>
344
											<string>A3DAF7F70D09EC670015B97D</string>
345 343
										</array>
346 344
									</dict>
347 345
									<key>SplitCount</key>
......
441 439
			</array>
442 440
			<key>TableOfContents</key>
443 441
			<array>
444
				<string>A3DAF7F90D09EC670015B97D</string>
442
				<string>A3DAF88D0D09F6F20015B97D</string>
445 443
				<string>1CA23ED40692098700951B8B</string>
446
				<string>A3DAF7FA0D09EC670015B97D</string>
444
				<string>A3DAF88E0D09F6F20015B97D</string>
447 445
				<string>A34161A50C989E610007BEF2</string>
448
				<string>A3DAF7FB0D09EC670015B97D</string>
446
				<string>A3DAF88F0D09F6F20015B97D</string>
449 447
				<string>1CA23EDF0692099D00951B8B</string>
450 448
				<string>1CA23EE00692099D00951B8B</string>
451 449
				<string>1CA23EE10692099D00951B8B</string>
......
515 513
								</array>
516 514
							</array>
517 515
							<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
518
							<string>{{0, 0}, {1258, 662}}</string>
516
							<string>{{0, 0}, {0, 0}}</string>
519 517
						</dict>
520 518
						<key>PBXTopSmartGroupGIDs</key>
521 519
						<array/>
......
555 553
										<string>A34161AD0C989F140007BEF2</string>
556 554
										<key>PBXProjectModuleLabel</key>
557 555
										<string>Colonet.java</string>
558
										<key>_historyCapacity</key>
559
										<integer>0</integer>
560
										<key>bookmark</key>
561
										<string>A3F7AA590D04F0F000C2BF9C</string>
562 556
										<key>history</key>
563 557
										<array>
564 558
											<string>A3FD76ED0CEBBBC10048CD0C</string>
565 559
											<string>A3C65E6B0CD275C200D77B7B</string>
566
											<string>A3C65F670CD6FD9900D77B7B</string>
567 560
											<string>A3F558940CF276B100E3EBD1</string>
568
											<string>A3F7AA3E0D04EC9900C2BF9C</string>
569
											<string>A3F7AA420D04EC9900C2BF9C</string>
570 561
										</array>
571 562
										<key>prevStack</key>
572 563
										<array>
......
596 587
						</dict>
597 588
						<dict>
598 589
							<key>Proportion</key>
599
							<string>132pt</string>
590
							<string>0pt</string>
600 591
							<key>Tabs</key>
601 592
							<array>
602 593
								<dict>
......
694 685
			</array>
695 686
			<key>TableOfContents</key>
696 687
			<array>
697
				<string>A3F7AA480D04EC9C00C2BF9C</string>
688
				<string>A3DAF8900D09F6F20015B97D</string>
698 689
				<string>1CA23EE50692099D00951B8B</string>
699
				<string>A3F7AA490D04EC9C00C2BF9C</string>
690
				<string>A3DAF8910D09F6F20015B97D</string>
700 691
				<string>A34161AC0C989F140007BEF2</string>
701
				<string>A3F7AA4A0D04EC9C00C2BF9C</string>
692
				<string>A3DAF8920D09F6F20015B97D</string>
702 693
				<string>XCMainBuildResultsModuleGUID</string>
703 694
				<string>1CA23EE80692099D00951B8B</string>
704
				<string>A3F7AA4B0D04EC9C00C2BF9C</string>
695
				<string>A3DAF8930D09F6F20015B97D</string>
705 696
			</array>
706 697
			<key>ToolbarConfiguration</key>
707 698
			<string>xcode.toolbar.config.buildAndRun</string>
trunk/code/projects/colonet/ColonetGUI/Colonet.java
3 3
//
4 4

  
5 5
import javax.swing.*;
6
import javax.swing.event.*;
7
import javax.imageio.*;
6 8
import java.awt.*;
7 9
import java.awt.image.*;
8 10
import java.awt.event.*;
9 11
import java.net.*;
10 12
import java.io.*;
11 13
import java.util.Random;
12
import java.applet.*;
13 14

  
14
public class Colonet extends JApplet implements ActionListener, MouseListener, Runnable {
15 15

  
16
	final int CANVAS_SIZE = 500;  //don't make this too large, or the applet will be slow.
16
/**
17
*	The Colonet Graphical User Interface Applet for use locally and over an internet connection.
18
*	@author Gregory Tress
19
*	
20
*
21
*/
22
public class Colonet extends JApplet implements ActionListener, MouseInputListener, KeyListener, Runnable {
23

  
24
	final int CANVAS_SIZE = 500;  //the applet may be slow if the canvas gets too large
17 25
	final int BUFFER = 50;
18 26
	final int RADIUS = 30;
19 27

  
......
23 31
	JButton btnConnect;	
24 32
	JButton btnGraph;
25 33
	JLabel lblConnectionStatus;
26
	JTextArea txtInput;
34
	JTextArea txtMatrix;
27 35
	JTextArea txtInfo; 
28 36
	JPanel panelConnect;
29 37
	JPanel panelServerInterface;
30 38
	
31
	// Stats
32
	JLabel lblBattery;
33
	JLabel lblTokenPasses;
34
	JLabel lblHastToken;
35
	JPanel panelStats;
36
	JPanel panelBattery;
37
	
38 39
	// South
39 40
	JPanel panelSouth;
40 41
	JTextArea log;
......
45 46
	JTabbedPane tabPaneControl;
46 47
	JPanel panelRobotControl;
47 48
	JPanel panelRobotDirection;
49
	JPanel panelRobotDirectionButtons;
48 50
	JPanel panelRobotCommands;
49 51
	JButton btnF, btnB, btnL, btnR, btnActivate;
52
	JComboBox cmbRobotNum;
53
	JLabel lblBattery;
54
	JPanel panelBattery;
55
	VectorController vectorController;
56
	BufferedImage imageVectorControl;
57
	JButton btnCommand_StopTask;
58
	JButton btnCommand_ResumeTask;
59
	JButton btnCommand_ChargeNow;
60
	JButton btnCommand_StopCharging;
50 61
	
51 62
	// Task Manager
52 63
	JPanel panelTaskManager;
......
59 70
	JButton btnRemoveTask;
60 71
	JButton btnMoveTaskUp;
61 72
	JButton btnMoveTaskDown;
73
	JButton btnUpdateTasks;
74
	TaskAddWindow taskAddWindow;
62 75
	
63
	// Graphics
64
	JPanel panel;
76
	//Webcam and Graph
77
	WebcamPanel panelWebcam;
78
	GraphicsPanel panelGraph;
65 79
	GraphicsConfiguration gc;
66 80
	volatile BufferedImage image;
67 81
	volatile Graphics2D canvas;
68 82
	int cx, cy;
83
	JTabbedPane tabPaneMain;
69 84
	
85
	
70 86
	Socket socket;					
71
	OutputStreamWriter out;			//TODO: add a BufferedWriter
72
	DataListener datalistener;  
87
	OutputStreamWriter out;
88
	DataUpdater dataUpdater;  
73 89
	
74 90
	Font botFont;
75 91
	Random random = new Random();
......
77 93
	volatile int numBots;
78 94
	volatile int selectedBot;  //the user has selected this bot
79 95
	volatile Rectangle[] botRect;  //contains boundary shapes around bots for click detection
96
	volatile int[] xbeeID;
80 97
	
81 98
	Thread drawThread;
99
	Simulator simulator;
82 100
	SelectionIndicator indicator;
83
	PacketMonitor packetMonitor;
101
	WebcamLoader webcamLoader;
84 102
	ColonetServerInterface csi;
85 103

  
86 104
	
87 105
	public void init () {
88
		// set the default look and feel
89
        String laf = UIManager.getSystemLookAndFeelClassName();
106
		// set the default look and feel - choose one
107
        //String laf = UIManager.getSystemLookAndFeelClassName();
108
		String laf = UIManager.getCrossPlatformLookAndFeelClassName();
109
		//String laf = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
90 110
        try {
91 111
            UIManager.setLookAndFeel(laf);
92 112
        } catch (UnsupportedLookAndFeelException exc) {
......
104 124
			SwingUtilities.invokeAndWait(r);
105 125
		} catch (InterruptedException e) {
106 126
			//Not really sure why we would be in this situation
107
			System.out.println(e);
127
			System.out.println("InterruptedException in init: " + e);
108 128
		} catch (java.lang.reflect.InvocationTargetException e) {
109
			//This should never happen. Seriously.
110
			System.out.println(e);
129
			//This could happen for various reasons if there is a problem in createAndShowGUI
130
			e.printStackTrace();
111 131
		}
112 132
	}
113 133
	
114 134
	public void destroy () {
115 135
		try { drawThread.interrupt(); } catch (Exception e) { }
116 136
		try { indicator.interrupt(); } catch (Exception e) { }
117
		try { packetMonitor.interrupt(); } catch (Exception e) { }
118 137
	}
119 138

  
120 139
	private synchronized void createAndShowGUI () {
121 140
		// init graphical elements
122
		panel = new JPanel(false);  //set automatic double-buffering to false. we are doing it manually.
141
		// Get the graphics configuration of the screen to create a buffer
142
		gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
143
			.getDefaultScreenDevice().getDefaultConfiguration();
144
		image = gc.createCompatibleImage(CANVAS_SIZE,CANVAS_SIZE);
145
		canvas = image.createGraphics();
146
		canvas.setStroke(new BasicStroke(2));  //set pen width
147
		panelGraph = new GraphicsPanel(false, image);  //set automatic double-buffering to false. we are doing it manually.
148
		panelWebcam = new WebcamPanel();
149
		tabPaneMain = new JTabbedPane();
150
		tabPaneMain.add(panelWebcam, "Webcam");
151
		tabPaneMain.add(panelGraph, "Graph");
123 152
		
153
		// Calculate center of canvas
154
		cx = image.getWidth() / 2;
155
		cy = image.getHeight() / 2;
156
		
157
		botFont = new Font("Arial", Font.PLAIN, 14);
158
		tokenLoc = 0;
159
		numBots = 0;
160
		selectedBot = 0;
161
		
124 162
		// Connection area
125
		txtInput = new JTextArea("- 9 3 - 1\n- - - 5 -\n4 - - - 2\n- - - - -\n1 - - 3 -");
126
		txtInput.setBorder(BorderFactory.createTitledBorder("Input Matrix"));
163
		txtMatrix = new JTextArea();
164
		txtMatrix.setBorder(BorderFactory.createTitledBorder("Input Matrix"));
127 165
		txtInfo = new JTextArea();
128 166
		txtInfo.setBorder(BorderFactory.createTitledBorder("Info"));
129 167
		txtInfo.setEditable(false);
130 168
		btnGraph = new JButton("Run");
131
		txtHost = new JTextField("roboclub1.frc.ri.cmu.edu");
169
		txtHost = new JTextField("roboclub9.frc.ri.cmu.edu");
132 170
		txtHost.setBorder(BorderFactory.createTitledBorder("Host"));
133 171
		txtPort = new JTextField("10123");
134 172
		txtPort.setBorder(BorderFactory.createTitledBorder("Port"));
......
140 178
		panelConnect.add(txtHost);
141 179
		panelConnect.add(txtPort);
142 180
		panelConnect.add(btnConnect);
143
		panelConnect.add(txtInfo);
144
		panelConnect.add(btnGraph);
181
		//panelConnect.add(btnGraph);
145 182
		panelServerInterface = new JPanel();
146 183
		panelServerInterface.setLayout(new GridLayout(2,1));
147 184
		panelServerInterface.add(panelConnect);
148
		panelServerInterface.add(txtInput);
149
				
150
		// Status Elements
151
		lblTokenPasses = new JLabel();
152
		lblBattery = new JLabel(new BatteryIcon(75, 100, 100));
153
		panelStats = new JPanel();
154
		panelStats.setLayout(new GridLayout(4,2));
155
		panelStats.add(new JLabel("Token Passes / sec          "));
156
		panelStats.add(lblTokenPasses);
157
		panelStats.add(new JLabel("Battery     "));
158
		panelStats.add(lblBattery);
159
		panelStats.add(new JLabel("Token Passes / sec     "));
160
		panelStats.add(lblTokenPasses);
161
		
162
		//TODO: add panelStats somewhere!
163

  
185
		panelServerInterface.add(txtMatrix);
186
	
164 187
		// Robot direction panel
165 188
		panelRobotDirection = new JPanel();
189
		panelRobotDirectionButtons = new JPanel();
166 190
		btnF = new JButton("^");
167 191
		btnB = new JButton("v");
168 192
		btnL = new JButton("<");
169 193
		btnR = new JButton(">");
170 194
		btnActivate = new JButton("o");
171
		panelRobotDirection = new JPanel();
172
		panelRobotDirection.setLayout(new GridLayout(3,3));
173
		panelRobotDirection.add(new JLabel(""));
174
		panelRobotDirection.add(btnF);
175
		panelRobotDirection.add(new JLabel(""));
176
		panelRobotDirection.add(btnL);
177
		panelRobotDirection.add(btnActivate);
178
		panelRobotDirection.add(btnR);
179
		panelRobotDirection.add(new JLabel(""));
180
		panelRobotDirection.add(btnB);
181
		panelRobotDirection.add(new JLabel(""));
195
		panelRobotDirectionButtons.setLayout(new GridLayout(1,5));
196
		panelRobotDirectionButtons.add(btnActivate);
197
		panelRobotDirectionButtons.add(btnF);
198
		panelRobotDirectionButtons.add(btnB);
199
		panelRobotDirectionButtons.add(btnL);
200
		panelRobotDirectionButtons.add(btnR);
182 201
		
202
		imageVectorControl = gc.createCompatibleImage(395, 220);
203
		vectorController = new VectorController(imageVectorControl);
204
		panelRobotDirection.setLayout(new BorderLayout());
205
		panelRobotDirection.add(vectorController, BorderLayout.CENTER);
206
		panelRobotDirection.add(panelRobotDirectionButtons, BorderLayout.SOUTH);
207
		
183 208
		// Robot Control and Commands
184 209
		panelRobotCommands = new JPanel();
185
		panelRobotCommands.setLayout(new FlowLayout());
186
		panelRobotCommands.add(new JLabel("Commands go here"));
210
		panelRobotCommands.setLayout(new GridLayout(5,2));
211
		cmbRobotNum = new JComboBox();
212
		lblBattery = new JLabel(new BatteryIcon(75, 100, 100));
213
		btnCommand_StopTask = new JButton("Stop Current Task");
214
		btnCommand_ResumeTask = new JButton("Resume Current Task");
215
		btnCommand_ChargeNow = new JButton("Recharge Now");
216
		btnCommand_StopCharging = new JButton("Stop Recharging");
217
		panelRobotCommands.add(new JLabel("Select Robot to Control: "));
218
		panelRobotCommands.add(cmbRobotNum);
219
		panelRobotCommands.add(new JLabel("Battery Level: "));
220
		panelRobotCommands.add(lblBattery);
221
		panelRobotCommands.add(btnCommand_StopTask);
222
		panelRobotCommands.add(btnCommand_ResumeTask);
223
		panelRobotCommands.add(btnCommand_ChargeNow);
224
		panelRobotCommands.add(btnCommand_StopCharging);
187 225
		panelRobotControl = new JPanel();
188 226
		panelRobotControl.setLayout(new GridLayout(2,1));
189 227
		panelRobotControl.add(panelRobotDirection);
......
193 231
		panelTaskManager = new JPanel();
194 232
		panelTaskManager.setLayout(new BorderLayout());
195 233
		taskListModel = new DefaultListModel();
196
		taskListModel.addElement("Map the Environment");
197
		taskListModel.addElement("Clean Up Chemical Spill");
198
		taskListModel.addElement("Grow Plants");
199
		taskListModel.addElement("Save the Cheerleader");
200
		taskListModel.addElement("Save the World");
201 234
		taskList = new JList(taskListModel);
202 235
		taskList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
203 236
		taskList.setSelectedIndex(0);
204 237
		spTaskManager = new JScrollPane(taskList);
205 238
		panelTaskManagerControls = new JPanel();
206
		panelTaskManagerControls.setLayout(new GridLayout(1,3));
239
		panelTaskManagerControls.setLayout(new GridLayout(1,4));
207 240
		panelTaskManagerControlsPriority = new JPanel();
208 241
		panelTaskManagerControlsPriority.setLayout(new GridLayout(1,2));
209 242
		btnAddTask = new JButton("Add...");
210 243
		btnRemoveTask = new JButton("Remove");
211 244
		btnMoveTaskUp = new JButton("^");
212 245
		btnMoveTaskDown = new JButton("v");
246
		btnUpdateTasks = new JButton("Update");
213 247
		panelTaskManagerControlsPriority.add(btnMoveTaskUp);
214 248
		panelTaskManagerControlsPriority.add(btnMoveTaskDown);
215 249
		panelTaskManagerControls.add(btnAddTask);
216 250
		panelTaskManagerControls.add(btnRemoveTask);
251
		panelTaskManagerControls.add(btnUpdateTasks);
217 252
		panelTaskManagerControls.add(panelTaskManagerControlsPriority);
218 253
		panelTaskManager.add(spTaskManager, BorderLayout.CENTER);
219 254
		panelTaskManager.add(panelTaskManagerControls, BorderLayout.SOUTH);
220 255
		panelTaskManager.add(new JLabel("Current Task Queue"), BorderLayout.NORTH);
256
		taskAddWindow = new TaskAddWindow();
221 257
		
222 258
		// Message log
223 259
		log = new JTextArea();
......
225 261
			ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, 
226 262
			ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
227 263
		spLog.setBorder(BorderFactory.createTitledBorder("Log"));
228
		spLog.setPreferredSize(new Dimension(0, 150));
264
		spLog.setPreferredSize(new Dimension(0, 120));
229 265
		log.setEditable(false);
230 266
		
231 267
		// Main control mechanism
232 268
		panelControl = new JPanel();
233 269
		panelControl.setLayout(new GridLayout(1,1));
234 270
		tabPaneControl = new JTabbedPane(JTabbedPane.TOP);
235
		tabPaneControl.setPreferredSize(new Dimension(300, 0));
271
		tabPaneControl.setPreferredSize(new Dimension(330, 0));
236 272
		tabPaneControl.addTab("Connection", panelServerInterface);
237 273
		tabPaneControl.addTab("Robots", panelRobotControl);
238 274
		tabPaneControl.addTab("Tasks", panelTaskManager);
239
		tabPaneControl.addTab("Stats", panelStats);
240 275
		panelControl.add(tabPaneControl);
241 276
		
242 277
		// Set up elements in the south
243 278
		panelSouth = new JPanel();
244 279
		panelSouth.setLayout(new GridLayout(1,2));
245
		panelSouth.add(spLog);
280
		//panelSouth.add(spLog);
246 281

  
282
		// Put all elements in the ContentPane
247 283
		this.getContentPane().setLayout(new BorderLayout());
248
		this.getContentPane().add(panel, BorderLayout.CENTER);
284
		this.getContentPane().add(tabPaneMain, BorderLayout.CENTER);
249 285
		this.getContentPane().add(panelSouth, BorderLayout.SOUTH);
250 286
		this.getContentPane().add(panelControl, BorderLayout.EAST);
251 287
		this.setVisible(true);
252 288
		
289
		/* Add all listeners here */
290
		// Task Management
253 291
		btnAddTask.addActionListener(this);
254 292
		btnRemoveTask.addActionListener(this);
255 293
		btnMoveTaskUp.addActionListener(this);
256 294
		btnMoveTaskDown.addActionListener(this);
295
		btnUpdateTasks.addActionListener(this);
296
		// Robot Control
297
		btnF.addActionListener(this);
298
		btnB.addActionListener(this);
299
		btnL.addActionListener(this);
300
		btnR.addActionListener(this);
301
		btnF.addKeyListener(this);
302
		btnB.addKeyListener(this);
303
		btnL.addKeyListener(this);
304
		btnR.addKeyListener(this);
305
		btnActivate.addActionListener(this);
306
		btnActivate.addKeyListener(this);
307
		cmbRobotNum.addKeyListener(this);
308
		vectorController.addMouseMotionListener(this);
309
		vectorController.addMouseListener(this);
310
		btnCommand_StopTask.addActionListener(this);
311
		btnCommand_ResumeTask.addActionListener(this);
312
		btnCommand_ChargeNow.addActionListener(this);
313
		btnCommand_StopCharging.addActionListener(this);
314
		// Other
257 315
		btnGraph.addActionListener(this);
258 316
		btnConnect.addActionListener(this);
259
		panel.addMouseListener(this);
317
		panelGraph.addMouseListener(this);
318
		this.addMouseMotionListener(this);	
260 319
		
261
		
262
		// Get the graphics configuration of the screen to create a buffer
263
		gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
264
			.getDefaultScreenDevice().getDefaultConfiguration();
265
		image = gc.createCompatibleImage(CANVAS_SIZE,CANVAS_SIZE);
266
		canvas = image.createGraphics();
267
		canvas.setStroke(new BasicStroke(2));  //set pen width
268
		
269
		// Calculate center of canvas
270
		cx = image.getWidth() / 2;
271
		cy = image.getHeight() / 2;
272
		
273
		botFont = new Font("Arial", Font.PLAIN, 30);
274
		tokenLoc = 0;
275
		numBots = 0;
276
		selectedBot = 0;
277
		
320
				
278 321
		// Set up dependent threads
279 322
		indicator = new SelectionIndicator(canvas);
280 323
		indicator.setRadius(RADIUS+3, 15);  //a tad more than the bot radius
281
		packetMonitor = new PacketMonitor();
282
		datalistener = new DataListener();
283
		
284
		csi = new ColonetServerInterface(log);
324
		simulator = new Simulator();
325
		webcamLoader = new WebcamLoader(this);
326
		dataUpdater = new DataUpdater();
327
		csi = new ColonetServerInterface(this);
285 328
	
286 329
	}
287 330
	
288 331
	public synchronized void paint (Graphics g) {
289
		/*	First, redraw the graphical components in the applet. 
332
		/*	Redraw the graphical components in the applet. 
290 333
			This paint method overrides the built-in paint of the 
291 334
			JApplet, and we don't want to deal with redrawing the
292 335
			components manually. Fuck that shit. */
336
		step();
293 337
		super.paint(g);
294
		
295
		// Place the buffered image on the screen, inside the panel
296
		panel.getGraphics().drawImage(image, 0, 0, Color.WHITE, this);
297
		
298 338
	}
299 339
	
300 340
	public synchronized void update (Graphics g) {
301 341
		paint(g);
302 342
	}
303 343
	
304
	public void actionPerformed (ActionEvent e) {
305
		Object source = e.getSource();
306
		if (source == btnGraph) {
307
			btnGraph.setEnabled(false);
308
			lblConnectionStatus.setText("Simulating");
309
			
310
			//Start dependent threads
311
			drawThread = new Thread(this, "drawThread");
312
			drawThread.start();
313
			indicator.start();
314
			packetMonitor.start();
315
		} else if (source == btnConnect) {
316
			doSocket();
317
		} else if (source == btnRemoveTask) {
318
			try {
319
				taskListModel.remove(taskList.getSelectedIndex());
320
			} catch (ArrayIndexOutOfBoundsException ex) {
321
			}
322
		}
323
	}
324
	
325 344
	private void randomize () {
326 345
		Random r = new Random();
327 346
		StringBuilder s = new StringBuilder();
......
339 358
			if (i != count-1) s.append("\n");
340 359
		}
341 360
		
342
		txtInput.setText(s.toString());
361
		txtMatrix.setText(s.toString());
343 362
	}
344 363
	
345
	private void doSocket () {
346
		csi.connect(txtHost.getText(), txtPort.getText());
347
	}
348
	
349 364
	public void drawRobot (int id, int x, int y) {
350 365
		//save the bot in memory, so we can tell if we click on it later
351 366
		botRect[id] = new Rectangle(x-RADIUS, y-RADIUS, 2*RADIUS, 2*RADIUS);
......
356 371
		
357 372
		//draw the label
358 373
		canvas.setFont(botFont);
359
		canvas.drawString("" + id, x-10, y+10);
374
		try {
375
			canvas.drawString("" + xbeeID[id], x-20, y+2);
376
		} catch (Exception e) {
377
			canvas.drawString("???", x-22, y+2);
378
		}
360 379
	}
361 380
	
362 381
	public void drawConnection (int start, int end, int radius, Color color) {
......
403 422
	
404 423
	public void run () {
405 424
		while (true) {
406
			step();
407 425
			repaint();
408 426
			try { 
409 427
				Thread.sleep(90);
......
424 442
		canvas.fillRect(0, 0, image.getWidth(), image.getHeight());
425 443
		
426 444
		// parse the matrix, to see what robots exist
427
		String [] rows = txtInput.getText().split("\n");
445
		String [] rows = txtMatrix.getText().split("\n");
428 446
		numBots = rows.length;
429 447
		String [][] entries = new String[numBots][numBots];
430 448
		valid = true;
......
474 492
			// draw the selection indicator
475 493
			indicator.draw();
476 494
			
477
		} else {// if matrix is not valid
495
		} else {  // if matrix is not valid
478 496
			this.showStatus("Error: Invalid matrix");
479 497
		}
480 498
	
481 499
	}
482 500
	
483
	/*	At this point, moveToken is only called by the simulator.
484
	*	In the future, it can be rewritten to account for non-standard
485
	*	token passing or deleted if the information can be retrieved
486
	*	directly from the Colonet server instead.
487
	*/
488
	public void moveToken () {
489
		try {
490
			tokenLoc = (tokenLoc+1)%numBots;
491
		} catch (ArithmeticException e) {  // in case numRobots is zero
501
	public JTextArea getLog () {
502
		return log;
503
	}
504
	
505
	public JTextArea getMatrixInput () {
506
		return txtMatrix;
507
	}
508
	
509
	public void parseMatrix (String line) {
510
		txtMatrix.setText("");
511
		String [] str = line.split(" ");
512
		int num = Integer.parseInt(str[2]);
513
		for (int i = 0; i < num; i++) {
514
			for (int j = 0; j < num; j++) {
515
				String next = str[3 + i*num + j];
516
				if (next.equals("-1"))
517
					txtMatrix.append("-");
518
				else 
519
					txtMatrix.append(next);
520
				if (j < num - 1) 
521
					txtMatrix.append(" ");
522
			}
523
			if (i < num - 1) 
524
				txtMatrix.append("\n");
492 525
		}
493 526
		
494
		packetMonitor.addTokenPass();
495 527
	}
496 528
	
529
	public void parseQueue (String line) {
530
		log.append("Got queue update\n");
531
	}
532
	
533
	public void parseXBeeIDs (String line) {
534
		String [] str = line.split(" ");
535
		int num = Integer.parseInt(str[2]);
536
		xbeeID = new int[num];
537
		for (int i = 0; i < num; i++)
538
			xbeeID[i] = Integer.parseInt(str[i+3]);
539
		
540
		//update the list of robots to control
541
		//but save the old value first
542
		Object oldSelection = cmbRobotNum.getSelectedItem();
543
		cmbRobotNum.removeAllItems();
544
		cmbRobotNum.addItem(new String("   All   "));
545
		for (int i = 0; i < num; i++)
546
			cmbRobotNum.addItem(new String("" + xbeeID[i]));
547
		cmbRobotNum.setSelectedItem(oldSelection);
548
	}
549
	
550
	public void parseBattery (String line) {
551
		String [] str = line.split(" ");
552
		int botNum = Integer.parseInt(str[2]);
553
		int batteryVal = Integer.parseInt(str[3]);
554
		if (cmbRobotNum != null && cmbRobotNum.getSelectedIndex()-1 == botNum)
555
			lblBattery.setText("" + batteryVal);
556
	}
557
	
497 558
	//
498
	// MouseEvent methods
559
	// MouseListener methods
499 560
	//
500
	public void mouseExited(MouseEvent e) {}
501
	public void mouseEntered(MouseEvent e) {}
502
	public void mouseReleased(MouseEvent e) {}
503
	public void mouseClicked(MouseEvent e) {}
561
	public void mouseExited(MouseEvent e) {
562
	}
563
	public void mouseEntered(MouseEvent e) {
564
	}
565
	public void mouseReleased(MouseEvent e) {
566
		vectorController.notifyMouseEvent(e, true);
567
	}
568
	public void mouseClicked(MouseEvent e) {
569
		vectorController.notifyMouseEvent(e, false);
570
	}
504 571
	public void mousePressed(MouseEvent e) {
505 572
		try {
506 573
			for (int i = 0; i < numBots; i++) {
507
				if (botRect[i].contains(e.getPoint()))
574
				if (botRect[i].contains(e.getPoint())) {
508 575
					selectedBot = i;
576
					cmbRobotNum.setSelectedIndex(i+1);
577
				}
509 578
			}
510 579
		} catch (Exception ex) {
511
			System.out.println(e);
512 580
		}
581
	}
582
	public void mouseDragged(MouseEvent e) {
583
		vectorController.notifyMouseEvent(e, false);
584
	}
585
	public void mouseMoved(MouseEvent e) {
586
	}
513 587
	
588
	//
589
	// KeyListener methods
590
	//
591
	public void keyPressed (KeyEvent e) {
592
		int code = e.getKeyCode();
593
		if (code == KeyEvent.VK_UP) {
594
			vectorController.setMaxForward();
595
			vectorController.sendToServer();
596
		} else if (code == KeyEvent.VK_DOWN) {
597
			vectorController.setMaxReverse();
598
			vectorController.sendToServer();
599
		} else if (code == KeyEvent.VK_LEFT) {
600
			vectorController.setMaxLeft();
601
			vectorController.sendToServer();
602
		} else if (code == KeyEvent.VK_RIGHT) {
603
			vectorController.setMaxRight();
604
			vectorController.sendToServer();
605
		} else if (code == KeyEvent.VK_S) {
606
			vectorController.setZero();
607
			vectorController.sendToServer();
608
		}
514 609
	}
610
	public void keyReleased (KeyEvent e) {
611
	}
612
	public void keyTyped (KeyEvent e) {
613
	}
515 614
	
615
	
616
	//
617
	// ActionListener method
618
	//
619
	public void actionPerformed (ActionEvent e) {
620
		Object source = e.getSource();
621
		if (source == btnGraph) {
622
			btnGraph.setEnabled(false);
623
			//Start dependent threads
624
			drawThread = new Thread(this, "drawThread");
625
			drawThread.start();
626
			indicator.start();
627
			simulator.start();
628
			webcamLoader.start();
629
		} else if (source == btnConnect) {
630
			csi.connect(txtHost.getText(), txtPort.getText());
631
			dataUpdater.start();
632
			drawThread = new Thread(this, "drawThread");
633
			drawThread.start();
634
			indicator.start();
635
			simulator.start();
636
			webcamLoader.start();
637
		}
638
		// Robot Movement Controls
639
		else if (source == btnF) {
640
			vectorController.setMaxForward();
641
			vectorController.sendToServer();
642
		} else if (source == btnB) {
643
			vectorController.setMaxReverse();
644
			vectorController.sendToServer();
645
		} else if (source == btnL) {
646
			vectorController.setMaxLeft();
647
			vectorController.sendToServer();
648
		} else if (source == btnR) {
649
			vectorController.setMaxRight();
650
			vectorController.sendToServer();
651
		} else if (source == btnActivate) {
652
			vectorController.setZero();
653
			vectorController.sendToServer();
654
		}
655
		// Robot Commands (non-movement)
656
		else if (source == btnCommand_StopTask) {
657
		
658
		} else if (source == btnCommand_ResumeTask) {
659
		
660
		} else if (source == btnCommand_ChargeNow) {
661
		
662
		} else if (source == btnCommand_StopCharging) {
663
		
664
		}
665
			
666
		// Queue Management
667
		else if (source == btnAddTask) {
668
			taskAddWindow.prompt();
669
		} else if (source == btnRemoveTask) {
670
			if (taskList.getSelectedIndex() >= 0);
671
				csi.sendQueueRemove(taskList.getSelectedIndex());
672
			csi.sendQueueUpdate();
673
		} else if (source == btnMoveTaskUp) {
674
			csi.sendQueueReorder(taskList.getSelectedIndex(), taskList.getSelectedIndex() - 1);
675
			csi.sendQueueUpdate();
676
		} else if (source == btnMoveTaskDown) {
677
			csi.sendQueueReorder(taskList.getSelectedIndex(), taskList.getSelectedIndex() + 1);
678
			csi.sendQueueUpdate();
679
		} else if (source == btnUpdateTasks) {
680
			csi.sendQueueUpdate();
681
		}
682
	}
683
	
516 684
	/*
517 685
	*	SelectionIndicator thread.
518 686
	*	Graphical representation of the selection marker
......
524 692
	*/
525 693
	private class SelectionIndicator extends Thread {
526 694
	
527
		final int INDICATOR_DELAY = 100;
528
		final double DTHETA = 0.3;    //larger values make the marker rotate faster
695
		final int INDICATOR_DELAY = 180;
696
		final double DTHETA = 0.4;    //larger values make the marker rotate faster
529 697
		Graphics2D g;   //canvas to draw on
530 698
		boolean running;
531 699
		
......
605 773
			//recalculate radius, if it will look cool, lolz
606 774
			int newr = r;
607 775
			if (steps < 100)
608
        newr = (int)( r + 200/(steps+1) );
776
			newr = (int)( r + 200/(steps+1) );
609 777
			
610 778
			//precompute values for dx and dy
611 779
			int dx_inner = (int)(newr * Math.cos(theta));
......
698 866
		}
699 867
		
700 868
		private void step () {
701
			// simulate passing the token
702
			moveToken();
869
			// don't do anything! the colonet should work on its own!
703 870
		}
704 871
	
705 872
	}
706 873
	
707 874
	/*
708
	*	PacketMonitor thread.
875
	*	DataUpdater thread.
876
	*   The purpose of this thread is to request data from the server at regular intervals.
709 877
	*
710
	*	Currently, this counts the rate of token passes but will eventually 
711
	*	be modified to keep more important statistics.
712 878
	*/
713
	private class PacketMonitor extends Thread {
714
		final int PACKETMONITOR_DELAY = 1000;
879
	class DataUpdater extends Thread {
880
		final int DATAUPDATER_DELAY = 4000;
881
		
882
		public DataUpdater () {
883
			super("Colonet DataUpdater");
884
		}
885
		
886
		public void run () {
887
			String line;
888
			while (true) {
889
				try {
890
					//request more data
891
					if (csi != null && csi.isReady()) {
892
						csi.sendSensorDataRequest();
893
						csi.sendXBeeIDRequest();
894
						if (cmbRobotNum.getSelectedIndex() > 0)
895
							csi.sendBatteryRequest(cmbRobotNum.getSelectedIndex()-1);
896
					}
897
					Thread.sleep(DATAUPDATER_DELAY);
898
				} catch (InterruptedException e) {
899
					return;
900
				} 
901
			}
902
		}
903

  
904
	}
715 905
	
716
		boolean running;
717
		int tokenPasses;
906
	/*
907
	*	GraphicsPanel class
908
	*	Enables more efficient image handling in a component-controlled environment
909
	*/
910
	class GraphicsPanel extends JPanel {
911
		protected Image img;
718 912
	
719
		public PacketMonitor () {
720
			super("PacketMonitor");
721
			running = false;
722
			tokenPasses = 0;
913
		public GraphicsPanel (Image img) {
914
			super();
915
			this.img = img;
723 916
		}
724 917
		
725
		public void run () {
726
			running = true;
727
			while (running) {
728
				displayTokenPasses();
729
				try { 
730
					Thread.sleep(PACKETMONITOR_DELAY);
731
				} catch (InterruptedException e) { 
732
					running = false;
733
					return; 
734
				}
918
		public GraphicsPanel (boolean isDoubleBuffered, Image img) {
919
			super(isDoubleBuffered);
920
			this.img = img;
921
		}
922
		
923
		public void paint (Graphics g) {
924
			// Place the buffered image on the screen, inside the panel
925
			g.drawImage(img, 0, 0, Color.WHITE, this);
926
		}
927
	
928
	}
929
	
930
	/*
931
	*	WebcamPanel class
932
	*	Enables more efficient image handling in a component-controlled environment
933
	*/
934
	class WebcamPanel extends JPanel {
935
		int BORDER = 16;  // this is arbitrary. it makes the image look nice inside a border.
936
		int BOT_RADIUS = 40;
937
		volatile BufferedImage img;
938
		volatile Point [] points;
939
	
940
		public WebcamPanel () {
941
			super();
942
		}
943
		
944
		public synchronized void setImage (BufferedImage newimg) {
945
			if (img != null) {
946
				img.flush();
947
				img = null;
948
				img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
735 949
			}
950
			System.gc();
951
			img = newimg;
736 952
		}
737 953
		
738
		public synchronized void addTokenPass () {
739
			tokenPasses++;
954
		public synchronized void setPoints (Point [] newpoints) {
955
			this.points = newpoints;
740 956
		}
741 957
		
742
		public synchronized void displayTokenPasses () {
743
			lblTokenPasses.setText("" + tokenPasses);
744
			tokenPasses = 0;
958
		public synchronized void paint (Graphics g) {
959
			
960
			if (img == null)
961
				return;
962
			// Place the image on the screen, inside the panel
963
			g.drawImage(img, 
964
						BORDER,	//dx1 - the x coordinate of the first corner of the destination rectangle.
965
						BORDER,	//dy1 - the y coordinate of the first corner of the destination rectangle.
966
						this.getWidth() - BORDER, 	//dx2 - the x coordinate of the second corner of the destination rectangle.
967
						this.getHeight() - BORDER,	//dy2 - the y coordinate of the second corner of the destination rectangle.
968
						0,	//sx1 - the x coordinate of the first corner of the source rectangle.
969
						0,	//sy1 - the y coordinate of the first corner of the source rectangle.
970
						image.getWidth(),	//sx2 - the x coordinate of the second corner of the source rectangle.
971
						image.getHeight(),	//sy2 - the y coordinate of the second corner of the source rectangle.
972
						null	//observer - object to be notified as more of the image is scaled and converted.
973
						);
974
						
975
			// Draw Identifiers
976
			if (points == null)
977
				return;
978
			g.setColor(Color.RED);
979
			((Graphics2D)g).setStroke(new BasicStroke(2));
980
			for (int i = 0; i < points.length; i++) {
981
				g.drawOval(points[i].x - BOT_RADIUS, points[i].y - BOT_RADIUS, 2*BOT_RADIUS, 2*BOT_RADIUS);
982
			}
983
			
745 984
		}
746 985
	
747 986
	}
748 987
	
749 988
	/*
750
	*	DataListener thread.
751
	*
989
	*	WebcamLoader class
990
	*	Handles the loading of the webcam image.
752 991
	*/
753
	class DataListener extends Thread {
754
		final int DATALISTENER_DELAY = 666;
755
		BufferedReader reader;
992
	class WebcamLoader extends Thread 
993
	{
994
		final int WEBCAMLOADER_DELAY = 1000;
995
		final String IMAGE_PATH = "http://roboclub9.frc.ri.cmu.edu/colonet.jpg";
996
		final String LOCATIONS_PATH = "http://roboclub9.frc.ri.cmu.edu/colonet/locations.txt";
756 997
		
757
		public DataListener () {
758
			super("Colonet DataListener");
998
		URL imagePath;
999
		URI locationsPath;
1000
		
1001
		MediaTracker mt;
1002
		BufferedImage image;
1003
		
1004
		public WebcamLoader (JApplet applet)
1005
		{
1006
			super("ColonetWebcamLoader");
1007
			mt = new MediaTracker(applet);
1008
			ImageIO.setUseCache(false);
1009
			try {
1010
				imagePath = new URL(IMAGE_PATH);
1011
			} catch (MalformedURLException e) {
1012
				System.out.println("Malformed URL: could not form URL from: [" + IMAGE_PATH + "]\n");
1013
			}
1014
			try {
1015
				locationsPath = new URI(LOCATIONS_PATH);
1016
			} catch (URISyntaxException x) {
1017
				System.out.println("Malformed URI: could not form URI from: [" + LOCATIONS_PATH + "]\n");
1018
			}
1019
			
759 1020
		}
760 1021
		
761
		public void run () {
762
			String line;
1022
		public synchronized void run ()
1023
		{
763 1024
			while (true) {
764 1025
				try {
765
					if (csi == null) return;
766
					line = csi.getLine();
767
					if (line != null) {
768
						csi.msg("Incoming data: [" + line + "]");
769
						//TODO: parse incoming data here
770
					}
771
					Thread.sleep(DATALISTENER_DELAY);
1026
					Thread.sleep(WEBCAMLOADER_DELAY);
1027
					if (image != null) 
1028
						image.flush();
1029
					System.gc();
1030
					image = ImageIO.read(imagePath);
1031
					// The MediaTracker waitForID pauses the thread until the image is loaded.
1032
					// We don't want to display a half-downloaded image.
1033
					mt.addImage(image, 1);
1034
					mt.waitForID(1);
1035
					mt.removeImage(image);
1036
					// Save
1037
					panelWebcam.setImage(image);
1038
					parseLocations(locationsPath.toURL());
772 1039
				} catch (InterruptedException e) {
773 1040
					return;
774
				} 
1041
				} catch (java.security.AccessControlException e) {
1042
					csi.warn("java.security.AccessControlException in WebcamLoader.\n" + 
1043
						"The image cannot be loaded from the specified location.\n" + 
1044
						"Make sure you are accessing this applet from the correct server.");
1045
					return;
1046
				} catch (IOException e) {
1047
					log.append("IOException while trying to load image.");
1048
				}
775 1049
			}
776 1050
		}
1051
		
1052
		private void parseLocations (URL url) {
1053
			URLConnection conn = null;
1054
			DataInputStream data = null;
1055
			String line;
1056
			String [] lines = new String[30];
1057
			StringBuffer buf = new StringBuffer();
1058
			int i = 0;
1059
		
1060
			try {
1061
				conn = url.openConnection();
1062
				conn.connect();
1063
				data = new DataInputStream(new BufferedInputStream(conn.getInputStream()));
1064
				while ((line = data.readLine()) != null) {
1065
					buf.append(line + ";");
1066
					lines[i] = line;
1067
					i++;
1068
				}
1069
				data.close();
1070
			} catch (IOException e) {
1071
				System.out.println("IOException:" + e.getMessage());
1072
			}
1073
			//log.append("Got robot locations: " + buf + "\n");
1074
			
1075
			// Get Point values from strings
1076
			Point [] points = new Point[i];
1077
			for (int j = 0; j < i; j++) {
1078
				String [] parts = lines[j].split(",");
1079
				int xval = Integer.parseInt(parts[0]);
1080
				int yval = Integer.parseInt(parts[1]);
1081
				Point p = new Point(xval, yval);
1082
				points[j] = p;
1083
			}
1084
			if (points.length != 0)
1085
				panelWebcam.setPoints(points);
1086
			
1087
		}
1088
	}
777 1089

  
1090
	
1091
	/*
1092
	*	VectorController class
1093
	*	Manages robot motion control graphically
1094
	*/
1095
	class VectorController extends GraphicsPanel {
1096
		int x, y, cx, cy;
1097
		int width, height;
1098
		int side;
1099
		
1100
		public VectorController (Image img) {
1101
			super (img);
1102
			width = img.getWidth(null);
1103
			height = img.getHeight(null);
1104
			cx = img.getWidth(null)/2;
1105
			cy = img.getHeight(null)/2;
1106
			x = cx;
1107
			y = cy;
1108
			if (width < height)
1109
				side = width;
1110
			else
1111
				side = height;
1112
		}
1113
		
1114
		public void setPoint (int x, int y) {
1115
			if (!isValidPoint(x, y))
1116
				return;
1117
			this.x = x;
1118
			this.y = y;
1119
			repaint();
1120
		}
1121
		
1122
		public boolean isValidPoint (int x, int y) {
1123
			double xterm = Math.pow(1.0*(x - cx)/(side/2), 2);
1124
			double yterm = Math.pow(1.0*(y - cy)/(side/2), 2);
1125
			return (xterm + yterm <= 1);
1126
		}
1127
		
1128
		public void notifyMouseEvent (MouseEvent e, boolean send) {
1129
			if (!isValidPoint(e.getX(), e.getY()))
1130
				return;
1131
			vectorController.setPoint(e.getX(), e.getY());
1132
			vectorController.repaint();
1133
			if (send)
1134
				vectorController.sendToServer();
1135
		}
1136
		
1137
		public int getSpeed () {
1138
			int dx = x - cx;
1139
			int dy = y - cy;
1140
			int v = (int) Math.sqrt( Math.pow(dx, 2) + Math.pow(dy, 2) );
1141
			return v;
1142
		}
1143
		
1144
		public int getAngle () {
1145
			int dx = x - cx;
1146
			int dy = cy - y;
1147
			double theta = Math.atan2(Math.abs(dx), Math.abs(dy));
1148
			theta = (int) (1.0 * theta * 180 / Math.PI);  //transform to degrees
1149
			if (dy < 0)
1150
				theta = 180 - theta;
1151
			theta *= Math.signum(dx);
1152
			return (int) theta;
1153
		}
1154
		
1155
		public void paint (Graphics g) {
1156
			g.setColor(Color.BLACK);
1157
			g.fillRect(0, 0, width, height);
1158
			((Graphics2D)g).setStroke(new BasicStroke(1));
1159
			g.setColor(Color.RED);
1160
			g.drawOval(cx-side/2, cy-side/2, side, side);
1161
			((Graphics2D)g).setStroke(new BasicStroke(2));
1162
			g.setColor(Color.GREEN);
1163
			g.drawLine(cx, cy, x, y);
1164
			g.fillOval(x-3, y-3, 6, 6);
1165
		}
1166
		
1167
		public void setMaxForward () {
1168
			setPoint(cx, cy - (side/2) + 1);
1169
		}
1170
		
1171
		public void setMaxReverse () {
1172
			setPoint(cx, cy + (side/2) - 1);
1173
		}
1174
		
1175
		public void setMaxLeft () {
1176
			setPoint(cx - (side/2) + 1, cy);
1177
		}
1178
		
1179
		public void setMaxRight () {
1180
			setPoint(cx + (side/2) - 1, cy);
1181
		}
1182
		
1183
		public void setZero () {
1184
			setPoint(cx, cy);
1185
		}
1186
		
1187
		public void sendToServer () {
1188
			//log.append("Attempitng to send angle = " + vectorController.getAngle() + ", velocity = " + vectorController.getVelocity() + "\n");
1189
			String dest = ColonetServerInterface.GLOBAL_DEST;
1190
			if (cmbRobotNum != null && cmbRobotNum.getSelectedIndex() > 0)
1191
				dest = "" + (cmbRobotNum.getSelectedIndex()-1);
1192
			
1193
			if (csi != null) {
1194
				if (cx == 0 && cy == 0) {
1195
					csi.sendData(ColonetServerInterface.MOTORS_OFF, dest);
1196
				} else {
1197
					//Directional commands
1198
					/*
1199
					if (x > cx && y == cy) {  //move right
1200
						csi.sendData(ColonetServerInterface.MOTOR2_SET + " 0 200", dest);
1201
						csi.sendData(ColonetServerInterface.MOTOR1_SET + " 1 200", dest);
1202
					} else if (x < cx && y == cy) {  //move left
1203
						csi.sendData(ColonetServerInterface.MOTOR2_SET + " 1 200", dest);
1204
						csi.sendData(ColonetServerInterface.MOTOR1_SET + " 0 200", dest);
1205
					} else if (x == cx && y > cy) {  //move forward
1206
						csi.sendData(ColonetServerInterface.MOTOR2_SET + " 0 225", dest);
1207
						csi.sendData(ColonetServerInterface.MOTOR1_SET + " 0 225", dest);
1208
					} else if (x == cx && y < cy) {  //move backward
1209
						csi.sendData(ColonetServerInterface.MOTOR2_SET + " 1 225", dest);
1210
						csi.sendData(ColonetServerInterface.MOTOR1_SET + " 1 225", dest);
1211
					} else if (x == cx && y == cy) {  //stop!
1212
						csi.sendData(ColonetServerInterface.MOTOR2_SET + " 1 0", dest);
1213
						csi.sendData(ColonetServerInterface.MOTOR1_SET + " 1 0", dest);
1214
					}
1215
					*/
1216
					
1217
				}
1218
			}
1219
				
1220
			//The move command doesn't really work...or does it?
1221
			csi.sendData(ColonetServerInterface.MOVE + " " + 
1222
				vectorController.getSpeed() + " " + 
1223
				vectorController.getAngle(), dest);
1224
				
1225
			
1226
		}
1227
	
778 1228
	}
779

  
1229
	
1230
	/*
1231
	*	TaskAddWindow class
1232
	*	makes it easy to add tasks to the queue
1233
	*/
1234
	class TaskAddWindow extends JFrame implements ActionListener, ListSelectionListener {
1235
		JPanel panelButtons;
1236
		JPanel panelParameters;
1237
		JPanel panelSouth;
1238
		JPanel panelSelection;
1239
		JButton btnSubmit;
1240
		JButton btnCancel;
1241
		DefaultListModel availableListModel;
1242
		JList availableList;
1243
		JScrollPane spAvailableTasks;
1244
		JTextArea txtDescription;
1245
		JTextField txtParameters;
1246
		MouseListener mouseListener;
1247
		
1248
		public TaskAddWindow () {
1249
			super("Add a Task");
1250
			super.setSize(500,500);
1251
			super.setLayout(new BorderLayout());
1252
			
1253
			// set up buttons
1254
			btnSubmit = new JButton("Submit");
1255
			btnCancel = new JButton("Cancel");
1256
			panelButtons = new JPanel();
1257
			panelButtons.setLayout(new FlowLayout());
1258
			panelButtons.add(btnSubmit);
1259
			panelButtons.add(btnCancel);
1260
			this.getRootPane().setDefaultButton(btnSubmit);
1261
			
1262
			// set up task list
1263
			availableListModel = new DefaultListModel();
1264
			availableListModel.addElement("Map the Environment");
1265
			availableListModel.addElement("Clean Up Chemical Spill");
1266
			availableListModel.addElement("Grow Plants");
1267
			availableListModel.addElement("Save the Cheerleader");
1268
			availableListModel.addElement("Save the World");
1269
			availableList = new JList(availableListModel);
1270
			availableList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
1271
			availableList.setSelectedIndex(-1);
1272
			spAvailableTasks = new JScrollPane(availableList);
1273
			spAvailableTasks.setBorder(BorderFactory.createTitledBorder("Select A Task"));
1274
			txtDescription = new JTextArea();
1275
			txtDescription.setEditable(false);
1276
			txtDescription.setLineWrap(true);
1277
			txtDescription.setWrapStyleWord(true);
1278
			txtDescription.setBorder(BorderFactory.createTitledBorder("Description"));
1279
			
1280
			//set up parameter area
1281
			panelParameters = new JPanel();
1282
			panelParameters.setLayout(new BorderLayout());
1283
			txtParameters = new JTextField();
1284
			panelParameters.add(new JLabel("Optional parameters for this task: "), BorderLayout.WEST);
1285
			panelParameters.add(txtParameters);
1286
			
1287
			// assemble objects
1288
			panelSelection = new JPanel();
1289
			panelSelection.setLayout(new GridLayout(1,2));
1290
			panelSelection.add(spAvailableTasks);
1291
			panelSelection.add(txtDescription);
1292
			
1293
			panelSouth = new JPanel();
1294
			panelSouth.setLayout(new GridLayout(2,1));
1295
			panelSouth.add(panelParameters);
1296
			panelSouth.add(panelButtons);
1297
			
1298
			this.getContentPane().add(panelSouth, BorderLayout.SOUTH);
1299
			this.getContentPane().add(panelSelection, BorderLayout.CENTER);
1300
			this.setLocationRelativeTo(null);
1301
			
1302
			// add listeners here
1303
			availableList.addListSelectionListener(this);
1304
			btnSubmit.addActionListener(this);
1305
			btnCancel.addActionListener(this);
1306
		}
1307
		
1308
		public void prompt () {
1309
			this.setVisible(true);
1310
		}
1311
		
1312
		private String getDescription (int index) {
1313
			if (index < 0)
1314
				return "";
1315
			switch (index) {
1316
				case 0: return "SLAM and junk";
1317
				case 1: return "I'm not sure this works";
1318
				case 2: return "Push them into the light";
1319
				case 3: return "Watch out for clock repair guys";
1320
				case 4: return "But make sure he's dead, geez, why would you let him get away? I mean come on, "
1321
					+"he's just lying there and everyone's too busy looking at people flying through the sky to "
1322
					+"notice? Oh yeah, that's a good transition to a new season, let's make the audience think "
1323
					+"he's dead and then pull a fast one on them, they'll never see that coming.";
1324
			
1325
				default: return "Task not recognized";
1326
			}
1327
		}
1328
		
1329
		public void actionPerformed (ActionEvent e) {
1330
			Object source = e.getSource();
1331
			if (source == btnSubmit) {
1332
				txtParameters.setText(txtParameters.getText().trim());
1333
				
1334
				
1335
				this.setVisible(false);
1336
			} else if (source == btnCancel) {
1337
				this.setVisible(false);
1338
			}
1339
		}
1340
		
1341
		public void valueChanged (ListSelectionEvent e) {
1342
			int index = availableList.getSelectedIndex();
1343
			if (index >= 0)
1344
				txtDescription.setText(getDescription(index));
1345
		}
1346
	
1347
	}
1348
	
780 1349
	class BatteryIcon implements Icon{
781 1350
		private int width;
782 1351
	    private int height;
......
834 1403
	        return height;
835 1404
	    }
836 1405
	}
837
	
838 1406

  
1407

  
839 1408
}

Also available in: Unified diff