Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / colonet / client / Colonet.java @ 560

History | View | Annotate | Download (37.9 KB)

1
//
2
//        Colonet.java
3
//
4

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

    
15
/**
16
* The Colonet Graphical User Interface Applet for use locally and over an internet connection.
17
* @author Gregory Tress
18
*
19
* To generate javadoc on this file or other java files, use javadoc *.java -d doc, where doc
20
* is the name of the folder into which the files should be written.
21
*/
22
public class Colonet extends JApplet implements ActionListener, MouseInputListener, KeyListener {
23

    
24
        // Used for images
25
        final int CANVAS_SIZE = 500;        //the applet may be slow if the canvas gets too large
26
        final int BUFFER = 50;
27
        final int RADIUS = 30;
28

    
29
        //Used for the robot controller
30
        final int VECTOR_CONTROLLER_HEIGHT = 220;
31
        final int VECTOR_CONTROLLER_WIDTH = 350;
32

    
33
        // Connection
34
        JTextField txtHost;
35
        JTextField txtPort;
36
        JButton btnConnect;
37
        JButton btnGetXBeeIDs;
38
        JLabel lblConnectionStatus;
39
        JTextArea txtMatrix;
40
        JTextArea txtInfo;
41
        JPanel panelConnect;
42
        JPanel panelServerInterface;
43
        Socket socket;
44
        OutputStreamWriter out;
45
        DataUpdater dataUpdater;
46

    
47
        // South
48
        JPanel panelSouth;
49
        JTextArea log;
50
        JScrollPane spLog;
51

    
52
        // Control
53
        JPanel panelControl;
54
        JTabbedPane tabPaneControl;
55
        JPanel panelRobotControl;
56
        JPanel panelRobotDirection;
57
        JPanel panelRobotDirectionButtons;
58
        JPanel panelRobotCommands;
59
        JButton btnF, btnB, btnL, btnR, btnActivate;
60
        JComboBox cmbRobotNum;
61
        JLabel lblBattery;
62
        JLabel lblSelected;
63
        BatteryIcon batteryIcon;
64
        JPanel panelBattery;
65
        VectorController vectorController;
66
        BufferedImage imageVectorControl;
67
        JButton btnAssignID;
68
        boolean setWaypoint;
69
        int setWaypointID;
70
        JButton btnCommand_MoveTo;
71
        JButton btnCommand_MoveAll;
72
        JButton btnCommand_StopTask;
73
        JButton btnCommand_ResumeTask;
74
        JButton btnCommand_ChargeNow;
75
        JButton btnCommand_StopCharging;
76

    
77
        // Task Manager
78
        JPanel panelTaskManager;
79
        JScrollPane spTaskManager;
80
        JPanel panelTaskManagerControls;
81
        JPanel panelTaskManagerControlsPriority;
82
        DefaultListModel taskListModel;
83
        JList taskList;
84
        JButton btnAddTask;
85
        JButton btnRemoveTask;
86
        JButton btnMoveTaskUp;
87
        JButton btnMoveTaskDown;
88
        JButton btnUpdateTasks;
89
        TaskAddWindow taskAddWindow;
90

    
91
        //Webcam
92
        WebcamPanel panelWebcam;
93
        GraphicsPanel panelGraph;
94
        GraphicsConfiguration gc;
95
        volatile BufferedImage image;
96
        volatile Graphics2D canvas;
97
        int cx, cy;
98
        JTabbedPane tabPaneMain;
99

    
100
        Font botFont;
101
        volatile int numBots;
102
        volatile int selectedBot;         //the user has selected this bot graphically
103
        volatile java.util.Map <Integer, RobotIcon> robotIcons;         //contains boundary shapes around bots for click detection
104
        volatile int[] xbeeID;
105

    
106
        Colonet self = this;
107
        WebcamLoader webcamLoader;
108
        volatile ColonetServerInterface csi;
109

    
110
        public void init () {
111
                // Set the default look and feel - choose one
112
                //String laf = UIManager.getSystemLookAndFeelClassName();
113
                String laf = UIManager.getCrossPlatformLookAndFeelClassName();
114
                //String laf = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
115
                try {
116
                        UIManager.setLookAndFeel(laf);
117
                } catch (UnsupportedLookAndFeelException exc) {
118
                        System.err.println ("Warning: UnsupportedLookAndFeel: " + laf);
119
                } catch (Exception exc) {
120
                        System.err.println ("Error loading " + laf + ": " + exc);
121
                }
122

    
123
                // We should invoke and wait to avoid browser display difficulties
124
                Runnable r = new Runnable() {
125
                        public void run() {
126
                                createAndShowGUI();
127
                        }
128
                };
129

    
130
                try {
131
                        SwingUtilities.invokeAndWait(r);
132
                } catch (InterruptedException e) {
133
                        //Not really sure why we would be in this situation
134
                        System.out.println("InterruptedException in init: " + e);
135
                } catch (java.lang.reflect.InvocationTargetException e) {
136
                        //This could happen for various reasons if there is a problem in createAndShowGUI
137
                        e.printStackTrace();
138
                }
139
        }
140

    
141
        public void destroy () {
142
        }
143

    
144
        private synchronized void createAndShowGUI () {
145
                // init graphical elements
146
                // Get the graphics configuration of the screen to create a buffer
147
                gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
148
                image = gc.createCompatibleImage(CANVAS_SIZE,CANVAS_SIZE);
149
                canvas = image.createGraphics();
150
                canvas.setStroke(new BasicStroke(2));         //set pen width
151
                panelGraph = new GraphicsPanel(image, false);         //set automatic double-buffering to false. we are doing it manually.
152
                panelWebcam = new WebcamPanel();
153
                tabPaneMain = new JTabbedPane();
154
                tabPaneMain.setFont(new Font("arial", Font.PLAIN, 16));
155
                tabPaneMain.add(panelWebcam, "Webcam");
156
                //tabPaneMain.add(panelGraph, "Graph");
157

    
158
                // Calculate center of canvas
159
                cx = image.getWidth() / 2;
160
                cy = image.getHeight() / 2;
161

    
162
                // Set up robots
163
                botFont = new Font("arial", Font.PLAIN, 14);
164
                numBots = 0;
165
                selectedBot = -1;
166
                robotIcons = new HashMap <Integer, RobotIcon> ();
167

    
168
                // Connection area
169
                txtMatrix = new JTextArea();
170
                txtMatrix.setBorder(BorderFactory.createTitledBorder("Info"));
171
                txtInfo = new JTextArea();
172
                txtInfo.setBorder(BorderFactory.createTitledBorder("Info"));
173
                txtInfo.setEditable(false);
174
                txtHost = new JTextField(this.getDocumentBase().getHost());
175
                txtHost.setBorder(BorderFactory.createTitledBorder("Host"));
176
                txtPort = new JTextField("10123");
177
                txtPort.setBorder(BorderFactory.createTitledBorder("Port"));
178
                btnConnect = new JButton("Connect");
179
                btnConnect.setFont(new Font("arial", Font.BOLD, 16));
180
                btnGetXBeeIDs = new JButton("Get XBee IDs");
181
                getRootPane().setDefaultButton(btnConnect);
182
                lblConnectionStatus = new JLabel("Status: Offline");
183
                panelConnect = new JPanel();
184
                panelConnect.setLayout(new GridLayout(6,1));
185
                panelConnect.add(lblConnectionStatus);
186
                panelConnect.add(txtHost);
187
                panelConnect.add(txtPort);
188
                panelConnect.add(btnConnect);
189
                //panelConnect.add(btnGetXBeeIDs);
190
                panelServerInterface = new JPanel();
191
                panelServerInterface.setLayout(new GridLayout(2,1));
192
                panelServerInterface.add(panelConnect);
193
                panelServerInterface.add(txtMatrix);
194

    
195
                // Robot direction panel
196
                panelRobotDirection = new JPanel();
197
                panelRobotDirectionButtons = new JPanel();
198

    
199
                Font f = new Font(null, Font.PLAIN, 18);
200
                btnF = new JButton("\u2191");
201
                btnF.setFont(f);
202
                btnB = new JButton("\u2193");
203
                btnB.setFont(f);
204
                btnL = new JButton("\u2190");
205
                btnL.setFont(f);
206
                btnR = new JButton("\u2192");
207
                btnR.setFont(f);
208
                btnActivate = new JButton("\u25A0");
209
                btnActivate.setFont(new Font(null, Font.BOLD, 36));
210

    
211
                panelRobotDirectionButtons.setLayout(new GridLayout(1,5));
212
                panelRobotDirectionButtons.add(btnActivate);
213
                panelRobotDirectionButtons.add(btnF);
214
                panelRobotDirectionButtons.add(btnB);
215
                panelRobotDirectionButtons.add(btnL);
216
                panelRobotDirectionButtons.add(btnR);
217

    
218
                imageVectorControl = gc.createCompatibleImage(VECTOR_CONTROLLER_WIDTH, VECTOR_CONTROLLER_HEIGHT);
219
                vectorController = new VectorController(imageVectorControl);
220
                panelRobotDirection.setLayout(new BorderLayout());
221
                //panelRobotDirection.add(vectorController, BorderLayout.CENTER);
222
                panelRobotDirection.add(panelRobotDirectionButtons, BorderLayout.SOUTH);
223

    
224
                // Robot Control and Commands
225
                panelRobotCommands = new JPanel();
226
                panelRobotCommands.setLayout(new GridLayout(5,2));
227
                cmbRobotNum = new JComboBox();
228
                // Battery subset
229
                batteryIcon = new BatteryIcon(0);
230
                lblBattery = new JLabel(batteryIcon);
231
                lblSelected = new JLabel("None");
232
                // Command subset
233
                setWaypoint = false;
234
                setWaypointID = -1;
235
                btnAssignID = new JButton("Assign ID");
236
                btnCommand_MoveTo = new JButton("Move to ...");
237
                btnCommand_MoveAll = new JButton("Move all ...");
238
                btnCommand_StopTask = new JButton("Stop Current Task");
239
                btnCommand_ResumeTask = new JButton("Resume Current Task");
240
                btnCommand_ChargeNow = new JButton("Recharge Now");
241
                btnCommand_StopCharging = new JButton("Stop Recharging");
242
                panelRobotCommands.add(new JLabel("Select Robot to Control: "));
243
                panelRobotCommands.add(cmbRobotNum);
244
                panelRobotCommands.add(new JLabel("Battery Level: "));
245
                panelRobotCommands.add(lblBattery);
246
                panelRobotCommands.add(new JLabel("Selected Icon: "));
247
                panelRobotCommands.add(lblSelected);
248
                panelRobotCommands.add(btnAssignID);
249
                panelRobotCommands.add(new JLabel(""));
250
                panelRobotCommands.add(btnCommand_MoveTo);
251
                panelRobotCommands.add(btnCommand_MoveAll);
252
                //panelRobotCommands.add(btnCommand_StopTask);
253
                //panelRobotCommands.add(btnCommand_ResumeTask);
254
                //panelRobotCommands.add(btnCommand_ChargeNow);
255
                //panelRobotCommands.add(btnCommand_StopCharging);
256
                panelRobotControl = new JPanel();
257
                panelRobotControl.setLayout(new GridLayout(2,1));
258
                panelRobotControl.add(panelRobotDirection);
259
                panelRobotControl.add(panelRobotCommands);
260

    
261

    
262
                // Task Manager
263
                panelTaskManager = new JPanel();
264
                panelTaskManager.setLayout(new BorderLayout());
265
                taskListModel = new DefaultListModel();
266
                taskList = new JList(taskListModel);
267
                taskList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
268
                taskList.setSelectedIndex(0);
269
                spTaskManager = new JScrollPane(taskList);
270
                panelTaskManagerControls = new JPanel();
271
                panelTaskManagerControls.setLayout(new GridLayout(1,4));
272
                panelTaskManagerControlsPriority = new JPanel();
273
                panelTaskManagerControlsPriority.setLayout(new GridLayout(1,2));
274
                btnAddTask = new JButton("Add...");
275
                btnRemoveTask = new JButton("Remove");
276
                btnMoveTaskUp = new JButton("^");
277
                btnMoveTaskDown = new JButton("v");
278
                btnUpdateTasks = new JButton("Update");
279
                panelTaskManagerControlsPriority.add(btnMoveTaskUp);
280
                panelTaskManagerControlsPriority.add(btnMoveTaskDown);
281
                panelTaskManagerControls.add(btnAddTask);
282
                panelTaskManagerControls.add(btnRemoveTask);
283
                panelTaskManagerControls.add(btnUpdateTasks);
284
                panelTaskManagerControls.add(panelTaskManagerControlsPriority);
285
                panelTaskManager.add(spTaskManager, BorderLayout.CENTER);
286
                panelTaskManager.add(panelTaskManagerControls, BorderLayout.SOUTH);
287
                panelTaskManager.add(new JLabel("Current Task Queue"), BorderLayout.NORTH);
288
                taskAddWindow = new TaskAddWindow();
289

    
290
                // Message log
291
                log = new JTextArea();
292
                spLog = new JScrollPane(log, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
293
                        ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
294
                spLog.setBorder(BorderFactory.createTitledBorder("Log"));
295
                spLog.setPreferredSize(new Dimension(0, 120));
296
                log.setEditable(false);
297

    
298
                // Main control mechanism
299
                panelControl = new JPanel();
300
                panelControl.setLayout(new GridLayout(1,1));
301
                tabPaneControl = new JTabbedPane(JTabbedPane.TOP);
302
                tabPaneControl.setFont(new Font("arial", Font.PLAIN, 16));
303
                tabPaneControl.setPreferredSize(new Dimension(VECTOR_CONTROLLER_WIDTH, 0));
304
                tabPaneControl.addTab("Connection", panelServerInterface);
305
                tabPaneControl.addTab("Robots", panelRobotControl);
306
                //tabPaneControl.addTab("Tasks", panelTaskManager);
307
                panelControl.add(tabPaneControl);
308

    
309
                // Set up elements in the south
310
                panelSouth = new JPanel();
311
                panelSouth.setLayout(new GridLayout(1,2));
312
                //panelSouth.add(spLog);
313

    
314
                // Put all elements in the ContentPane
315
                this.getContentPane().setLayout(new BorderLayout());
316
                this.getContentPane().add(tabPaneMain, BorderLayout.CENTER);
317
                this.getContentPane().add(panelSouth, BorderLayout.SOUTH);
318
                this.getContentPane().add(panelControl, BorderLayout.EAST);
319
                this.setVisible(true);
320
                
321
                // Disable components before connecting
322
                btnConnect.setText("Connect");
323
        lblConnectionStatus.setText("Status: Disconnected");
324
        btnF.setEnabled(false);
325
        btnB.setEnabled(false);
326
        btnL.setEnabled(false);
327
        btnR.setEnabled(false);
328
        btnActivate.setEnabled(false);
329
        cmbRobotNum.setEnabled(false);
330
        btnAssignID.setEnabled(false);
331
        btnCommand_MoveTo.setEnabled(false);
332
        btnCommand_MoveAll.setEnabled(false);
333

    
334
                /* Add all listeners here */
335
                // Task Management
336
                btnAddTask.addActionListener(this);
337
                btnRemoveTask.addActionListener(this);
338
                btnMoveTaskUp.addActionListener(this);
339
                btnMoveTaskDown.addActionListener(this);
340
                btnUpdateTasks.addActionListener(this);
341
                // Robot Control
342
                btnF.addActionListener(this);
343
                btnB.addActionListener(this);
344
                btnL.addActionListener(this);
345
                btnR.addActionListener(this);
346
                btnF.addKeyListener(this);
347
                btnB.addKeyListener(this);
348
                btnL.addKeyListener(this);
349
                btnR.addKeyListener(this);
350
                btnActivate.addActionListener(this);
351
                btnActivate.addKeyListener(this);
352
                cmbRobotNum.addKeyListener(this);
353
                btnCommand_MoveTo.addActionListener(this);
354
                btnCommand_MoveAll.addActionListener(this);
355
                btnCommand_StopTask.addActionListener(this);
356
                btnCommand_ResumeTask.addActionListener(this);
357
                btnCommand_ChargeNow.addActionListener(this);
358
                btnCommand_StopCharging.addActionListener(this);
359
                // Other
360
                btnConnect.addActionListener(this);
361
                btnGetXBeeIDs.addActionListener(this);
362
                btnAssignID.addActionListener(this);
363
                panelWebcam.addMouseListener(this);
364
        }
365

    
366
        public void paint (Graphics g) {
367
                super.paint(g);
368
        }
369

    
370
        public void update (Graphics g) {
371
                paint(g);
372
        }
373

    
374
        /**
375
        * Gets the JTextArea used for storing the activity log. This method returns a reference to the
376
        * JTextArea that stores the log. The log can contain any activity that is revelant to the use
377
        * of the applet, and may optionally display debugging information.
378
        *
379
        * @return the JTextArea where BOM matrix information is stored.
380
        */
381
        public JTextArea getLog () {
382
                return log;
383
        }
384

    
385
        /**
386
        * Gets the JTextArea used for storing the BOM matrix data. This method returns a reference to the
387
        * JTextArea that stores the BOM matrix. The values in the matrix are stored as integers separated
388
        * by spaces, and the lines should be separated by a newline.
389
        *
390
        * @return the JTextArea where BOM matrix information is stored.
391
        */
392
        public JTextArea getMatrixInput () {
393
                return txtMatrix;
394
        }
395

    
396
        /**
397
        * Parses a String containing BOM matrix information.
398
        * The ColonetServerInterface receives lines of the BOM matrix.        (For encoding
399
        * information, see the ColonetServerInterface documentation.)         The entire matrix is passed
400
        * to the client when requested. This method takes a string of the form
401
        * "[command code] [command code] [number of robots] [data0] [data1] ..."
402
        * with tokens separated by spaces and containing no brackets.
403
        * The [command code]s are predefined values identifying this String as a BOM data
404
        * String, [number of robots] is an integer, and the values that follow are
405
        * the sensor readings of the robots in order, starting with robot 0.        Only [number of robots]^2
406
        * data entries will be read.        The matrix values are saved locally until the next String is parsed.
407
        *
408
        *
409
        * @param line the String containing BOM matrix information.
410
        * @throws ArrayIndexOutOfBoundsException if there are fewer than [number of robots]^2 data entries in the String
411
        */
412
        public void parseMatrix (String line) {
413
                txtMatrix.setText("");
414
                String [] str = line.split(" ");
415
                int num = Integer.parseInt(str[2]);
416
                for (int i = 0; i < num; i++) {
417
                        for (int j = 0; j < num; j++) {
418
                                String next = str[3 + i*num + j];
419
                                if (next.equals("-1")) {
420
                                        txtMatrix.append("-");
421
                                } else {
422
                                        txtMatrix.append(next);
423
                                }
424

    
425
                                if (j < num - 1) {
426
                                        txtMatrix.append(" ");
427
                                }
428
                        }
429

    
430
                        if (i < num - 1) {
431
                                txtMatrix.append("\n");
432
                        }
433
                }
434
                repaint();
435
        }
436

    
437
        public void connect () {
438
        if (csi != null)
439
                return;
440
        csi = new ColonetServerInterface(self);
441
        csi.connect(txtHost.getText(), txtPort.getText());
442
        if (!csi.isReady()) {
443
                csi = null;
444
                return;
445
        }
446
        webcamLoader = new WebcamLoader(self);
447
        dataUpdater = new DataUpdater();
448
        dataUpdater.start();
449
        webcamLoader.start();
450
        Runnable r = new Runnable() {
451
                public void run () {
452
                        btnConnect.setText("Disconnect");
453
                        lblConnectionStatus.setText("Status: Connected");
454
                btnF.setEnabled(true);
455
                btnB.setEnabled(true);
456
                btnL.setEnabled(true);
457
                btnR.setEnabled(true);
458
                btnActivate.setEnabled(true);
459
                cmbRobotNum.setEnabled(true);
460
                btnAssignID.setEnabled(true);
461
                btnCommand_MoveTo.setEnabled(true);
462
                btnCommand_MoveAll.setEnabled(true);
463
                    }
464
                };
465
                SwingUtilities.invokeLater(r);
466
        }
467

    
468
        public void disconnect () {
469
        dataUpdater.interrupt();
470
        csi = null;
471
                Runnable r = new Runnable() {
472
                public void run () {
473
                        btnConnect.setText("Connect");
474
                    lblConnectionStatus.setText("Status: Disconnected");
475
                btnF.setEnabled(false);
476
                btnB.setEnabled(false);
477
                btnL.setEnabled(false);
478
                btnR.setEnabled(false);
479
                btnActivate.setEnabled(false);
480
                cmbRobotNum.setEnabled(false);
481
                btnAssignID.setEnabled(false);
482
                btnCommand_MoveTo.setEnabled(false);
483
                btnCommand_MoveAll.setEnabled(false);
484
                    }
485
                };
486
                SwingUtilities.invokeLater(r);
487
        }
488

    
489
        /**
490
        * Parses a String containing a task queue update.
491
        * Format is currently not specified.
492
        * This method currently does nothing.
493
        *
494
        * @param line the String containing task queue update information.
495
        */
496
        public void parseQueue (String line) {
497
                log.append("Got queue update\n");
498
                //TODO: display new queue data in tasks tab
499
        }
500

    
501
        /**
502
        * Parses a String containing XBee ID values.
503
        * The ColonetServerInterface receives Strings of XBee information.        (For encoding
504
        * information, see the ColonetServerInterface documentation.)         This method takes
505
        * a string of the form "[command code] [command code] [number of robots] [id0] [id1] ..."
506
        * with tokens separated by spaces and containing no brackets.
507
        * The [command code]s are predefined values identifying this String as an XBee
508
        * ID String, [number of robots] is an integer, and the values that follow are
509
        * the IDs of the robots in order, starting with robot 0.        Only [number of robots]
510
        * will be read.         The ID values are saved locally until the next String is parsed.
511
        * The purpose of having this list is to ensure that robots are properly identified for control purposes.
512
        * This keeps robot identification consistent between sessions and prevents arbitrary assignment.
513
        *
514
        * @param line the String containing XBee ID information.
515
        * @throws ArrayIndexOutOfBoundsException if there are fewer than [number of robots] IDs in the String
516
        * @see ColonetServerInterface#sendXBeeIDRequest()
517
        */
518
        public void parseXBeeIDs (String line) {
519
                String [] str = line.split(" ");
520
                int num = Integer.parseInt(str[2]);
521
                xbeeID = new int[num];
522
                for (int i = 0; i < num; i++) {
523
                        xbeeID[i] = Integer.parseInt(str[i+3]);
524
                }
525

    
526
                //update the list of robots to control
527
                //but save the old value first
528
                Object oldSelection = cmbRobotNum.getSelectedItem();
529
                cmbRobotNum.removeAllItems();
530
                cmbRobotNum.addItem(new String("         All         "));
531
                for (int i = 0; i < num; i++) {
532
                        cmbRobotNum.addItem(new String("" + xbeeID[i]));
533
                }
534
                cmbRobotNum.setSelectedItem(oldSelection);
535
                repaint();
536
        }
537

    
538
        /**
539
        * Parses a String containing battery information.
540
        * The ColonetServerInterface receives Strings of battery information.         (For encoding
541
        * information, see the ColonetServerInterface documentation.)         This method takes
542
        * a string of the form "[command code] [command code] [robot ID] [value]"
543
        * with tokens separated by spaces and containing no brackets.
544
        * The [command code]s are predefined values identifying this String as a battery
545
        * information String, [robot ID] is an integer, and [value] is a battery measurement.
546
        * This updates the batery information for a single robot.
547
        *
548
        *
549
        * @param line the String containing battery information.
550
        * @see ColonetServerInterface#sendBatteryRequest(int)
551
        */
552
        public void parseBattery (String line) {
553
                String [] str = line.split(" ");
554
                int botNum = Integer.parseInt(str[2]);
555
                int level = Integer.parseInt(str[3]);
556
                int selected = -1;
557
                try {
558
                        selected = Integer.parseInt((String)cmbRobotNum.getSelectedItem());
559
                } catch (Exception e) {
560
                        System.out.println("Exception in parseBattery.");
561
                }
562

    
563
                if (selected == botNum) {
564
                        batteryIcon.setLevel(level);
565
                }
566
                repaint();
567
        }
568

    
569
        /**
570
        * Parses a String containing visual robot position information along with
571
        * canonical ID assignments.
572
        */
573
        public void parsePositions (String line) {
574
                String [] str = line.split(" ");
575
                java.util.Map <Integer, RobotIcon> newMap = new HashMap <Integer, RobotIcon> ();
576

    
577
                for (int i = 2; i < str.length; i+=3) {
578
                        int id = Integer.parseInt(str[i]);
579
                        int x = Integer.parseInt(str[i+1]);
580
                        int y = Integer.parseInt(str[i+2]);
581
                        RobotIcon newIcon = new RobotIcon(id, x, y);
582
                        if (newIcon.id >= 0) {
583
                                newIcon.color = Color.GREEN;
584
                        }
585
                        newMap.put(id, newIcon);
586
                }
587
                robotIcons = newMap;
588
                repaint();
589
        }
590

    
591
        //
592
        // MouseListener methods
593
        //
594
        public void mousePressed(MouseEvent e) {
595
                //Start a new Thread to handle the MouseEvent
596
                (new MouseHandler(e)).start();
597
        }
598
        public void mouseExited(MouseEvent e) {
599
        }
600
        public void mouseEntered(MouseEvent e) {
601
        }
602
        public void mouseReleased(MouseEvent e) {
603
        }
604
        public void mouseClicked(MouseEvent e) {
605
        }
606
        public void mouseDragged(MouseEvent e) {
607
        }
608
        public void mouseMoved(MouseEvent e) {
609
        }
610

    
611
        //
612
        // KeyListener methods
613
        //
614
        public void keyPressed (KeyEvent e) {
615
                //Start a new Thread to handle the KeyEvent
616
                (new KeyHandler(e)).start();
617
        }
618
        public void keyReleased (KeyEvent e) {
619
        }
620
        public void keyTyped (KeyEvent e) {
621
        }
622

    
623
        //
624
        // ActionListener method
625
        //
626
        public void actionPerformed (ActionEvent e) {
627
                // Start a new Thread to handle the ActionEvent
628
                (new ActionHandler(e)).start();
629
        }
630

    
631
        class MouseHandler extends Thread {
632
                MouseEvent e;
633

    
634
                public MouseHandler (MouseEvent event) {
635
                        super("MouseHandler");
636
                        this.e = event;
637
                }
638

    
639
                public void run () {
640
                        Point pt = panelWebcam.convertClick(e);
641

    
642
                        // If we are selecting a waypoint (destination) for a specific bot
643
                        if (setWaypoint && setWaypointID >= 0) {
644
                                setWaypoint = false;
645
                                panelWebcam.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
646
                                if (selectedBot < 0) {
647
                                        return;
648
                                }
649
                                
650
                                RobotIcon r = robotIcons.get(selectedBot);
651
                                if (r != null) {
652
                                        r.destx = pt.x;
653
                                        r.desty = pt.y;
654
                                        if (csi != null) {
655
                                                csi.sendAbsoluteMove(r.id, r.destx, r.desty);
656
                                        }
657
                                }
658

    
659
                                return;
660
                        }
661

    
662
                        // Right-click also means we are moving a robot
663
                        if (e.getButton() == MouseEvent.BUTTON2 || e.getButton() == MouseEvent.BUTTON3) {
664
                                if (selectedBot < 0) {
665
                                        return;
666
                                }
667

    
668
                                RobotIcon r = robotIcons.get(selectedBot);
669
                                if (r != null) {
670
                                        r.destx = pt.x;
671
                                        r.desty = pt.y;
672
                                        if (csi != null) {
673
                                                csi.sendAbsoluteMove(r.id, r.destx, r.desty);
674
                                        }
675
                                }
676

    
677
                                return;
678
                        }
679

    
680
                        // If we are setting all waypoints
681
                        if (setWaypoint) {
682
                                setWaypoint = false;
683
                                panelWebcam.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
684
                                for (int i = 0; i < robotIcons.size(); i++) {
685
                                        RobotIcon r = robotIcons.get(i);
686
                                        r.destx = pt.x;
687
                                        r.desty = pt.y;
688
                                }
689
                                
690
                                return;
691
                        }
692

    
693
                        // Otherwise, we are selecting a bot, or doing nothing
694
                        for (int i = 0; i < robotIcons.size(); i++) {
695
                                RobotIcon r = robotIcons.get(i);
696
                                if (r.contains(pt.x, pt.y)) {
697
                                        selectedBot = r.id;
698
                                        lblSelected.setText("" + r.id);
699
                                        // Try to select the clicked bot, if its XBee ID is detected.
700
                                        for (int j = 1; j < cmbRobotNum.getItemCount(); j++) {
701
                                                if (Integer.parseInt(cmbRobotNum.getItemAt(j).toString()) == selectedBot) {
702
                                                        cmbRobotNum.setSelectedIndex(j);
703
                                                }
704
                                        }
705
                                        return;
706
                                }
707
                        }
708

    
709
                        repaint();
710
                }
711
        }
712

    
713
        class KeyHandler extends Thread {
714
                KeyEvent e;
715

    
716
                public KeyHandler (KeyEvent event) {
717
                        super("KeyHandler");
718
                        this.e = event;
719
                }
720

    
721
                public void run () {
722
                        int code = e.getKeyCode();
723
                        if (code == KeyEvent.VK_UP) {
724
                                vectorController.setMaxForward();
725
                                vectorController.sendToServer();
726
                        } else if (code == KeyEvent.VK_DOWN) {
727
                                vectorController.setMaxReverse();
728
                                vectorController.sendToServer();
729
                        } else if (code == KeyEvent.VK_LEFT) {
730
                                vectorController.setMaxLeft();
731
                                vectorController.sendToServer();
732
                        } else if (code == KeyEvent.VK_RIGHT) {
733
                                vectorController.setMaxRight();
734
                                vectorController.sendToServer();
735
                        } else if (code == KeyEvent.VK_S) {
736
                                vectorController.setZero();
737
                                vectorController.sendToServer();
738
                        }
739
                        repaint();
740
                }
741
        }
742

    
743
        class ActionHandler extends Thread {
744
                ActionEvent e;
745

    
746
                public ActionHandler (ActionEvent event) {
747
                        super("ActionHandler");
748
                        this.e = event;
749
                }
750

    
751
                public void run () {
752
                        Object source = e.getSource();
753

    
754
                        // General Actions
755
                        if (source == btnConnect) {
756
                                if (csi == null) {
757
                                        connect();
758
                                } else {
759
                                        disconnect();
760
                                }
761
                        } else if (source == btnGetXBeeIDs) {
762
                                csi.sendXBeeIDRequest();
763
                        } else if (source == btnAssignID) {
764
                                String message;
765
                                if (selectedBot < 0) {
766
                                        message = "That robot is unidentified. Please specify its ID.";
767
                                } else {
768
                                        message = "That robot has ID " + selectedBot + ". You may reassign it now.";
769
                                }
770
                                String result = JOptionPane.showInputDialog(self, message, "Robot Identification", JOptionPane.QUESTION_MESSAGE);
771
                                if (result == null) {
772
                                        return;
773
                                }
774
                                int newID = -1;
775
                                try {
776
                                        newID = Integer.parseInt(result);
777
                                } catch (Exception ex) {
778
                                        csi.warn("Invalid ID.");
779
                                        return;
780
                                }
781
                                // Assign new ID and update display
782
                                if (csi != null) {
783
                                        csi.sendIDAssignment(selectedBot, newID);
784
                                }
785
                                selectedBot = newID;
786
                                lblSelected.setText("" + newID);
787
                        } else if (source == btnF) { // Robot Movement Controls
788
                                vectorController.setMaxForward();
789
                                vectorController.sendToServer();
790
                        } else if (source == btnB) {
791
                                vectorController.setMaxReverse();
792
                                vectorController.sendToServer();
793
                        } else if (source == btnL) {
794
                                vectorController.setMaxLeft();
795
                                vectorController.sendToServer();
796
                        } else if (source == btnR) {
797
                                vectorController.setMaxRight();
798
                                vectorController.sendToServer();
799
                        } else if (source == btnActivate) {
800
                                vectorController.setZero();
801
                                vectorController.sendToServer();
802
                        } else if (source == btnCommand_MoveTo) { // Robot Commands (non-movement)
803
                                if (selectedBot < 0) {
804
                                        return;
805
                                }
806
                                panelWebcam.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
807
                                setWaypoint = true;
808
                                setWaypointID = selectedBot;
809
                        } else if (source == btnCommand_MoveAll) {
810
                                panelWebcam.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
811
                                setWaypoint = true;
812
                                setWaypointID = -1;
813
                        } else if (source == btnCommand_StopTask) {
814

    
815
                        } else if (source == btnCommand_ResumeTask) {
816

    
817
                        } else if (source == btnCommand_ChargeNow) {
818

    
819
                        } else if (source == btnCommand_StopCharging) {
820

    
821
                        } else if (source == btnAddTask) { // Queue Management
822
                                taskAddWindow.prompt();
823
                        } else if (source == btnRemoveTask) {
824
                                if (taskList.getSelectedIndex() >= 0) {
825
                                        csi.sendQueueRemove(taskList.getSelectedIndex());
826
                                }
827
                                csi.sendQueueUpdate();
828
                        } else if (source == btnMoveTaskUp) {
829
                                csi.sendQueueReorder(taskList.getSelectedIndex(), taskList.getSelectedIndex() - 1);
830
                                csi.sendQueueUpdate();
831
                        } else if (source == btnMoveTaskDown) {
832
                                csi.sendQueueReorder(taskList.getSelectedIndex(), taskList.getSelectedIndex() + 1);
833
                                csi.sendQueueUpdate();
834
                        } else if (source == btnUpdateTasks) {
835
                                csi.sendQueueUpdate();
836
                        }
837

    
838
                        repaint();
839
                }
840
        }
841

    
842
        /*
843
        * DataUpdater thread.
844
        *                The purpose of this thread is to request data from the server at regular intervals.
845
        *
846
        */
847
        class DataUpdater extends Thread {
848
                final int DATAUPDATER_DELAY = 250;
849

    
850
                public DataUpdater () {
851
                        super("Colonet DataUpdater");
852
                }
853

    
854
                public void run () {
855
                        String line;
856
                        while (true) {
857
                                try {
858
                                        //request more data
859
                                        if (csi != null && csi.isReady()) {
860
                                                csi.sendPositionRequest();
861
                                                csi.sendXBeeIDRequest();
862
                                                if (cmbRobotNum.getSelectedIndex() > 0) {
863
                                                        String sel = (String) cmbRobotNum.getSelectedItem();
864
                                                        int num = Integer.parseInt(sel);
865
                                                        csi.sendBatteryRequest(num);
866
                                                }
867
                                        }
868
                                        Thread.sleep(DATAUPDATER_DELAY);
869
                                } catch (InterruptedException e) {
870
                                        return;
871
                                }
872
                        }
873
                }
874
        }
875

    
876
        /*
877
        * GraphicsPanel class
878
        * An extension of JPanel, designed for holding an image that will be repainted regularly.
879
        */
880
        class GraphicsPanel extends JPanel {
881
                protected Image img;
882

    
883
                public GraphicsPanel (Image img) {
884
                        this(img, true);
885
                }
886

    
887
                public GraphicsPanel (Image img, boolean isDoubleBuffered) {
888
                        super(isDoubleBuffered);
889
                        this.img = img;
890
                }
891

    
892
                public void paint (Graphics g) {
893
                        // Place the buffered image on the screen, inside the panel
894
                        g.drawImage(img, 0, 0, Color.WHITE, this);
895
                }
896
        }
897

    
898
        /*
899
        * WebcamPanel class
900
        * Enables more efficient image handling in a component-controlled environment
901
        */
902
        class WebcamPanel extends JPanel {
903
                int BORDER = 16;        // this is arbitrary. it makes the image look nice inside a border.
904
                int BOT_RADIUS = 40;
905
                volatile BufferedImage img;
906
                BufferedImage buffer;
907

    
908
                public WebcamPanel () {
909
                        super(true);
910
                }
911

    
912
                public synchronized void setImage (BufferedImage newimg) {
913
                        if (img != null) {
914
                                img.flush();
915
                        }
916
                        System.gc();
917
                        img = newimg;
918
                        repaint();
919
                }
920

    
921
                public synchronized void paint (Graphics g) {
922
                        if (img == null) {
923
                                return;
924
                        }
925

    
926
                        // Calculate scaling
927
                        int maxWidth = getWidth() - 2*BORDER;
928
                        int maxHeight = getHeight() - 2*BORDER;
929
                        double widthRatio = 1.0 * maxWidth / img.getWidth();
930
                        double heightRatio = 1.0 * maxHeight / img.getHeight();
931
                        double scale = 0;
932
                        int newWidth = 0;
933
                        int newHeight = 0;
934
                        int x = 0;
935
                        int y = 0;
936

    
937
                        if (widthRatio > heightRatio) {         //height is the limiting factor
938
                                scale = heightRatio;
939
                                newHeight = maxHeight;
940
                                newWidth = (int) (img.getWidth() * scale);
941
                                y = BORDER;
942
                                x = (maxWidth - newWidth) / 2 + BORDER;
943
                        } else {        //width is the limiting factor
944
                                scale = widthRatio;
945
                                newWidth = maxWidth;
946
                                newHeight = (int) (img.getHeight() * scale);
947
                                x = BORDER;
948
                                y = (maxHeight - newHeight) / 2 + BORDER;
949
                        }
950

    
951
                        // Draw everything onto the buffer
952
                        buffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
953
                        Graphics2D bufferedGraphics = (Graphics2D)buffer.getGraphics();
954
                        bufferedGraphics.setColor(Color.GRAY);
955
                        bufferedGraphics.fillRect(0, 0, this.getWidth(), this.getHeight());
956
                        Image imgScaled = img.getScaledInstance(newWidth, newHeight, Image.SCALE_FAST);
957
                        bufferedGraphics.drawImage(imgScaled, x, y, this);
958

    
959

    
960
                        // Draw Identifiers and battery levels
961
                        if (robotIcons != null) {
962
                                bufferedGraphics.setStroke(new BasicStroke(2));
963
                                Iterator <Map.Entry<Integer,RobotIcon>> it = robotIcons.entrySet().iterator();
964
                                while (it.hasNext()) {
965
                                        RobotIcon r = it.next().getValue();
966
                                        bufferedGraphics.setColor(r.color);
967
                                        // Identifier circle
968
                                        int px = (int) (x + r.x * scale);
969
                                        int py = (int) (y + r.y * scale);
970
                                        bufferedGraphics.drawOval(px-RADIUS, py-RADIUS, 2*r.RADIUS, 2*r.RADIUS);
971
                                        // Battery
972
                                        //if (r.battery >= 0) {
973
                                                bufferedGraphics.setColor(Color.GREEN);
974
                                                bufferedGraphics.fillRect(px+20, py+20, 30, 10);
975
                                                bufferedGraphics.setColor(Color.BLACK);
976
                                                bufferedGraphics.drawRect(px+20, py+20, 50, 10);
977
                                        //}
978
                                        // If the robot has a destination, draw the vector
979
                                        if (r.destx >= 0) {
980
                                                bufferedGraphics.drawLine(px, py, (int)(x + r.destx * scale), (int)(y + r.desty * scale));
981
                                        }
982
                                }
983
                        }
984

    
985
                        // Identify currently-selected robot
986
                        RobotIcon r = robotIcons.get(selectedBot);
987
                        if (r != null) {
988
                                int px = (int) (x + r.x * scale);
989
                                int py = (int) (y + r.y * scale);
990
                                bufferedGraphics.setColor(Color.BLACK);
991
                                bufferedGraphics.drawOval(px-RADIUS-6, py-RADIUS-6, 2*r.RADIUS+12, 2*r.RADIUS+12);
992
                        }
993

    
994
                        //Display buffered content
995
                        g.drawImage(buffer, 0, 0, this);
996
                }
997

    
998
                /*
999
                * Convert a click on the webcam panel to a coordinate that is consistent with the
1000
                * original size of the image that the panel contains.
1001
                */
1002
                public Point convertClick (MouseEvent e) {
1003
                        if (img == null) {
1004
                                return new Point(e.getX(), e.getY());
1005
                        }
1006

    
1007
                        // Calculate scaling
1008
                        int clickx = e.getX();
1009
                        int clicky = e.getY();
1010
                        int maxWidth = getWidth() - 2*BORDER;
1011
                        int maxHeight = getHeight() - 2*BORDER;
1012
                        double widthRatio = 1.0 * maxWidth / img.getWidth();
1013
                        double heightRatio = 1.0 * maxHeight / img.getHeight();
1014
                        double scale = 0;
1015
                        int newWidth = 0;
1016
                        int newHeight = 0;
1017
                        int px = 0;
1018
                        int py = 0;
1019

    
1020
                        if (widthRatio > heightRatio) {         //height is the limiting factor
1021
                                scale = heightRatio;
1022
                                newHeight = maxHeight;
1023
                                newWidth = (int) (img.getWidth() * scale);
1024
                                py = clicky - BORDER;
1025
                                px = clickx - BORDER - (maxWidth - newWidth) / 2;
1026
                        } else {        //width is the limiting factor
1027
                                scale = widthRatio;
1028
                                newWidth = maxWidth;
1029
                                newHeight = (int) (img.getHeight() * scale);
1030
                                px = clickx - BORDER;
1031
                                py = clicky - BORDER - (maxHeight - newHeight) / 2;
1032
                        }
1033
                        py = (int) (py / scale);
1034
                        px = (int) (px / scale);
1035

    
1036
                        txtMatrix.setText("(" + clickx + "," + clicky + ") => (" + px + "," + py + ")");
1037
                        return new Point(px, py);
1038
                }
1039
        }
1040

    
1041
        /*
1042
        * WebcamLoader class
1043
        * Handles the loading of the webcam image.
1044
        */
1045
        class WebcamLoader extends Thread
1046
        {
1047
                final int WEBCAMLOADER_DELAY = 400;
1048
                final String IMAGE_PATH = "http://roboclub9.frc.ri.cmu.edu/colonet.jpg";
1049

    
1050
                URL imagePath;
1051

    
1052
                MediaTracker mt;
1053
                BufferedImage image;
1054
                Random rand;
1055

    
1056
                public WebcamLoader (JApplet applet)
1057
                {
1058
                        super("ColonetWebcamLoader");
1059
                        mt = new MediaTracker(applet);
1060
                        ImageIO.setUseCache(false);
1061
                        rand = new Random();
1062
                }
1063

    
1064
                public void run ()
1065
                {
1066
                        while (true) {
1067
                                try {
1068
                                        Thread.sleep(WEBCAMLOADER_DELAY);
1069
                                        if (image != null)
1070
                                                image.flush();
1071
                                        System.gc();
1072
                                        try {
1073
                                                imagePath = new URL(IMAGE_PATH + "?rand=" + rand.nextInt(50000));
1074
                                        } catch (MalformedURLException e) {
1075
                                                System.out.println("Malformed URL: could not form URL from: [" + IMAGE_PATH + "]\n");
1076
                                        }
1077
                                        image = ImageIO.read(imagePath);
1078
                                        // The MediaTracker waitForID pauses the thread until the image is loaded.
1079
                                        // We don't want to display a half-downloaded image.
1080
                                        mt.addImage(image, 1);
1081
                                        mt.waitForID(1);
1082
                                        mt.removeImage(image);
1083
                                        // Save
1084
                                        panelWebcam.setImage(image);
1085
                                } catch (InterruptedException e) {
1086
                                        return;
1087
                                } catch (java.security.AccessControlException e) {
1088
                                        csi.warn("Could not load webcam.\n" + e);
1089
                                        return;
1090
                                } catch (IOException e) {
1091
                                        log.append("IOException while trying to load image.");
1092
                                }
1093
                        }
1094
                }
1095
        }
1096

    
1097
        /*
1098
        * VectorController class
1099
        * Manages robot motion control graphically
1100
        */
1101
        class VectorController extends GraphicsPanel implements MouseListener, MouseMotionListener {
1102
                int x, y, cx, cy;
1103
                int width, height;
1104
                int side;
1105

    
1106
                public VectorController (Image img) {
1107
                        super (img);
1108
                        width = img.getWidth(null);
1109
                        height = img.getHeight(null);
1110
                        cx = img.getWidth(null)/2;
1111
                        cy = img.getHeight(null)/2;
1112
                        x = cx;
1113
                        y = cy;
1114
                        if (width < height) {
1115
                                side = width;
1116
                        } else {
1117
                                side = height;
1118
                        }
1119
                        this.addMouseListener(this);
1120
                        this.addMouseMotionListener(this);
1121
                }
1122

    
1123
                public void setPoint (int x, int y) {
1124
                        if (isValidPoint(x, y)) {
1125
                                this.x = x;
1126
                                this.y = y;
1127
                        }
1128
                }
1129

    
1130
                public boolean isValidPoint (int x, int y) {
1131
                        double xterm = Math.pow(1.0*(x - cx)/(side/2), 2);
1132
                        double yterm = Math.pow(1.0*(y - cy)/(side/2), 2);
1133
                        return (xterm + yterm <= 1);
1134
                }
1135

    
1136
                public void notifyMouseEvent (MouseEvent e, boolean send) {
1137
                        if (!isValidPoint(e.getX(), e.getY())) {
1138
                                return;
1139
                        }
1140
                        setPoint(e.getX(), e.getY());
1141
                repaint();
1142
                        if (send) {
1143
                                sendToServer();
1144
                        }
1145
                }
1146

    
1147
                public void mouseExited(MouseEvent e) {
1148
                }
1149
                public void mouseEntered(MouseEvent e) {
1150
                }
1151
                public void mouseReleased(MouseEvent e) {
1152
                        this.notifyMouseEvent(e, true);
1153
                }
1154
                public void mouseClicked(MouseEvent e) {
1155
                        this.notifyMouseEvent(e, false);
1156
                }
1157
                public void mousePressed(MouseEvent e) {
1158
                }
1159
                public void mouseDragged(MouseEvent e) {
1160
                        vectorController.notifyMouseEvent(e, false);
1161
                }
1162
                public void mouseMoved(MouseEvent e) {
1163
                }
1164

    
1165
                public int getSpeed () {
1166
                        int dx = x - cx;
1167
                        int dy = y - cy;
1168
                        int v = (int) Math.sqrt( Math.pow(dx, 2) + Math.pow(dy, 2) );
1169
                        return v;
1170
                }
1171

    
1172
                /**
1173
                * Returns the angle of the control vector in positive degrees west of north,
1174
                * or negative degrees east of north, whichever is less than or equal to
1175
                * 180 degrees total.
1176
                */
1177
                public int getAngle () {
1178
                        int dx = x - cx;
1179
                        int dy = cy - y;
1180
                        // find reference angle in radians
1181
                        double theta = Math.atan2(Math.abs(dx), Math.abs(dy));
1182
                        // transform to degrees
1183
                        theta = theta * 180 / Math.PI;
1184
                        // adjust for quadrant
1185
                        if (dx < 0 && dy < 0)
1186
                                theta = 90 + theta;
1187
                        else if (dx < 0 && dy >= 0)
1188
                                theta = 90 - theta;
1189
                        else if (dx >= 0 && dy < 0)
1190
                                theta = -90 - theta;
1191
                        else
1192
                                theta = -90 + theta;
1193
                        return (int) theta;
1194
                }
1195

    
1196
                public void paint (Graphics g) {
1197
                        g.setColor(Color.BLACK);
1198
                        g.fillRect(0, 0, width, height);
1199
                        ((Graphics2D)g).setStroke(new BasicStroke(1));
1200
                        g.setColor(Color.RED);
1201
                        g.drawOval(cx-side/2, cy-side/2, side, side);
1202
                        ((Graphics2D)g).setStroke(new BasicStroke(2));
1203
                        g.setColor(Color.GREEN);
1204
                        g.drawLine(cx, cy, x, y);
1205
                        g.fillOval(x-3, y-3, 6, 6);
1206
                }
1207

    
1208
                public void setMaxForward () {
1209
                        setPoint(cx, cy - (side/2) + 1);
1210
                }
1211

    
1212
                public void setMaxReverse () {
1213
                        setPoint(cx, cy + (side/2) - 1);
1214
                }
1215

    
1216
                public void setMaxLeft () {
1217
                        setPoint(cx - (side/2) + 1, cy);
1218
                }
1219

    
1220
                public void setMaxRight () {
1221
                        setPoint(cx + (side/2) - 1, cy);
1222
                }
1223

    
1224
                public void setZero () {
1225
                        setPoint(cx, cy);
1226
                }
1227

    
1228
                public void sendToServer () {
1229
                        System.out.println("Attempting to send angle = " + getAngle() + ", speed = " + getSpeed() + "");
1230
                        String dest = ColonetServerInterface.GLOBAL_DEST;
1231
                        if (cmbRobotNum != null && cmbRobotNum.getSelectedIndex() > 0) {
1232
                                dest = (String)cmbRobotNum.getSelectedItem();
1233
                        }
1234

    
1235
                        if (csi != null) {
1236
                                /*
1237
                                csi.sendData(ColonetServerInterface.MOVE + " " + getSpeed() + " " + getAngle(), dest);
1238
                                */
1239

    
1240
                                //Directional commands
1241
                                if (x > cx && y == cy) {        //move right
1242
                                        csi.sendData(ColonetServerInterface.MOTOR2_SET + " 0 200", dest);
1243
                                        csi.sendData(ColonetServerInterface.MOTOR1_SET + " 1 200", dest);
1244
                                } else if (x < cx && y == cy) {         //move left
1245
                                        csi.sendData(ColonetServerInterface.MOTOR2_SET + " 1 200", dest);
1246
                                        csi.sendData(ColonetServerInterface.MOTOR1_SET + " 0 200", dest);
1247
                                } else if (x == cx && y > cy) {         //move forward
1248
                                        csi.sendData(ColonetServerInterface.MOTOR2_SET + " 0 225", dest);
1249
                                        csi.sendData(ColonetServerInterface.MOTOR1_SET + " 0 225", dest);
1250
                                } else if (x == cx && y < cy) {         //move backward
1251
                                        csi.sendData(ColonetServerInterface.MOTOR2_SET + " 1 225", dest);
1252
                                        csi.sendData(ColonetServerInterface.MOTOR1_SET + " 1 225", dest);
1253
                                } else if (x == cx && y == cy) {        //stop!
1254
                                        csi.sendData(ColonetServerInterface.MOTOR2_SET + " 1 0", dest);
1255
                                        csi.sendData(ColonetServerInterface.MOTOR1_SET + " 1 0", dest);
1256
                                }
1257
                        }
1258
                }
1259

    
1260
        }
1261

    
1262

    
1263

    
1264
}