Project

General

Profile

Revision 531

more cleanup of client

View differences:

trunk/code/projects/colonet/robot/colonet_dragonfly/colonet_dragonfly.c
29 29

  
30 30
static int robot_x, robot_y;
31 31
static volatile int updated_robot_pos_ready;
32
#define ERROR_MAG_TO_MOTOR_DIFFENTIAL_CONST (10)
32
#define ERROR_MAG_TO_MOTOR_DIFFENTIAL_CONST (80)
33 33

  
34 34
/* Internal function prototypes */
35 35
static unsigned int two_bytes_to_int(char high, char low);
......
51 51

  
52 52
  robot_x = 0;
53 53
  robot_y = 0;
54
  updated_robot_pos_ready = 1;
54
  updated_robot_pos_ready = 0;
55 55

  
56 56
  return 0;
57 57
}
......
77 77
}
78 78

  
79 79
void request_abs_position() {
80
  //usb_puts("requesting_abs_position\n");
80
  usb_puts("requesting_abs_position\n");
81 81

  
82 82
  ColonetRobotServerPacket pkt;
83 83
  pkt.client_id = -1;
......
124 124
}
125 125

  
126 126
static void move_to_position_routine(int target_x, int target_y) {
127
 int last_x = robot_x, last_y = robot_y;
127
  int last_x = robot_x, last_y = robot_y;
128 128

  
129
 while (distsquared(robot_x, robot_y, target_x, target_y) >
129
  char buf[40];
130
  sprintf(buf, "cur dist is %d\n", distsquared(robot_x, robot_y, target_x, target_y));
131
  usb_puts(buf);
132
  sprintf(buf, "radius squared is %d\n", TARGET_POSITION_STOP_DISTANCE_THRESHOLD*TARGET_POSITION_STOP_DISTANCE_THRESHOLD);
133
  usb_puts(buf);
134

  
135
  while (distsquared(robot_x, robot_y, target_x, target_y) >
130 136
        TARGET_POSITION_STOP_DISTANCE_THRESHOLD*TARGET_POSITION_STOP_DISTANCE_THRESHOLD) {
137
    request_abs_position(); // While we're doing this computation, server can be reporting next position.
138

  
139
    int count = 0;
131 140
    while (!updated_robot_pos_ready) { // ghetto condition variable
132 141
      wl_do();
142

  
143
      if (count++ == 10000) { // in case the server missed it...
144
        request_abs_position();
145
        count = 0;
146
      }
133 147
    }
134 148

  
135 149
    int cur_robot_x = robot_x;
136 150
    int cur_robot_y = robot_y;
137 151

  
138
    char buf[40];
139
    sprintf(buf, "Position: %d %d\n", cur_robot_x, cur_robot_y);
152
    sprintf(buf, "Current position: %d %d\n", cur_robot_x, cur_robot_y);
140 153
    usb_puts(buf);
141 154

  
155
    sprintf(buf, "Target position: %d %d\n", target_x, target_y);
156
    usb_puts(buf);
157

  
142 158
    updated_robot_pos_ready = 0;
143 159
    request_abs_position(); // While we're doing this computation, server can be reporting next position.
144 160

  
......
158 174
    float e_y = r_y - v_y;
159 175
    float e_mag = sqrt_approx(e_x * e_x + e_y * e_y);
160 176

  
177
    sprintf(buf, "Error: <%f,%f>; mag: %f\n", e_x, e_y, e_mag);
178
    usb_puts(buf);
179

  
161 180
    /* Motor differential proportional to magnitude of directional error. */
162 181
    int motor_differential = (int)(e_mag * ERROR_MAG_TO_MOTOR_DIFFENTIAL_CONST);
163 182

  
......
181 200
      motor_differential = -motor_differential;
182 201
    }
183 202

  
203
    sprintf(buf, "motor_diff: %d\n", motor_differential);
204
    usb_puts(buf);
205

  
184 206
    last_x = cur_robot_x;
185 207
    last_y = cur_robot_y;
186 208

  
187

  
188
    sprintf(buf, "motor_diff: %d\n", motor_differential);
189
    usb_puts(buf);
190

  
191 209
    set_motors_with_differential(motor_differential);
192 210
  }
211
  
212
  usb_puts("reached destination!\n");
193 213
}
194 214

  
195 215
/* Private functions */
......
238 258
  int_args[2] = two_bytes_to_int(args[4], args[5]);
239 259

  
240 260
  if (type == COLONET_REQUEST) {
241
    usb_puts("received a COLONET_REQUEST\n");
261
    sprintf(buf, "received colonet request: pkt msgcode is %d\n", pkt->msg_code);
262
    usb_puts(buf);
242 263

  
243 264
    switch (pkt->msg_code) {
244 265
      //Sharp
......
279 300
      break;
280 301
    }
281 302
  } else if (type == COLONET_COMMAND) {
282
    usb_puts("colonet command ... %d\n", pkt->msg_code);
303
    sprintf(buf, "colonet command ... pkt->msg_code=%d\n", pkt->msg_code);
304
    usb_puts(buf);
283 305

  
284 306
/* TODO uncomment this stuff */
285 307
/*     if (pkt.msg_code >= USER_DEFINED_MSG_ID_START && */
......
301 323
      robot_x = int_args[0];
302 324
      robot_y = int_args[1];
303 325

  
304
      updated_robot_pos_ready;
326
      updated_robot_pos_ready = 1;
305 327

  
306 328
      sprintf(buf, "pos is: %d %d\n", robot_x, robot_y);
307 329
      usb_puts(buf);
308 330
      break;
309 331

  
310 332
    case MOVE_TO_ABSOLUTE_POSITION:
311
      usb_puts("move to abs position!\n");
333
      usb_puts("move to abs position2!\n");
312 334
      move_to_position_routine(int_args[0], int_args[1]);
313 335
      break;
314 336

  
trunk/code/projects/colonet/server/vision/vision.c
14 14
#include <stdio.h>
15 15
#include <stdlib.h>
16 16

  
17
#define MINH 100 //min threshold level
18
#define MAXH 220 //max threshold level
17
#define MINH 150 //min threshold level
18
#define MAXH 200 //max threshold level
19 19
#define DEBUG 0 //Debug to find threshold level
20 20

  
21 21
struct CenterP {
trunk/code/projects/colonet/client/Colonet.java
1 1
//
2
//  Colonet.java
2
//	Colonet.java
3 3
//
4 4

  
5 5
import javax.swing.*;
......
12 12
import java.io.*;
13 13
import java.util.*;
14 14

  
15

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

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

  
......
31 30
	final int VECTOR_CONTROLLER_HEIGHT = 220;
32 31
	final int VECTOR_CONTROLLER_WIDTH = 350;
33 32

  
34

  
35 33
	// Connection
36 34
	JTextField txtHost;
37 35
	JTextField txtPort;
......
101 99

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

  
108 106
	Colonet self = this;
......
110 108
	WebcamLoader webcamLoader;
111 109
	ColonetServerInterface csi;
112 110

  
113

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

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

  
132 131
		try {
133 132
			SwingUtilities.invokeAndWait(r);
134 133
		} catch (InterruptedException e) {
......
150 149
		gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
151 150
		image = gc.createCompatibleImage(CANVAS_SIZE,CANVAS_SIZE);
152 151
		canvas = image.createGraphics();
153
		canvas.setStroke(new BasicStroke(2));  //set pen width
154
		panelGraph = new GraphicsPanel(image, false);  //set automatic double-buffering to false. we are doing it manually.
152
		canvas.setStroke(new BasicStroke(2));	 //set pen width
153
		panelGraph = new GraphicsPanel(image, false);	 //set automatic double-buffering to false. we are doing it manually.
155 154
		panelWebcam = new WebcamPanel();
156 155
		tabPaneMain = new JTabbedPane();
157 156
		tabPaneMain.add(panelWebcam, "Webcam");
......
282 281

  
283 282
		// Message log
284 283
		log = new JTextArea();
285
		spLog = new JScrollPane(log,
286
			ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
284
		spLog = new JScrollPane(log, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
287 285
			ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
288 286
		spLog.setBorder(BorderFactory.createTitledBorder("Log"));
289 287
		spLog.setPreferredSize(new Dimension(0, 120));
......
341 339
		btnGetXBeeIDs.addActionListener(this);
342 340
		btnAssignID.addActionListener(this);
343 341
		panelWebcam.addMouseListener(this);
344

  
345 342
	}
346 343

  
347 344
	public void run () {
......
356 353
	}
357 354

  
358 355
	public void paint (Graphics g) {
359
	    super.paint(g);
356
		super.paint(g);
360 357
	}
361 358

  
362 359
	public void update (Graphics g) {
363
	    paint(g);
360
		paint(g);
364 361
	}
365 362

  
366 363
	/**
......
387 384

  
388 385
	/**
389 386
	* Parses a String containing BOM matrix information.
390
	* The ColonetServerInterface receives lines of the BOM matrix.  (For encoding
391
	* information, see the ColonetServerInterface documentation.)  The entire matrix is passed
387
	* The ColonetServerInterface receives lines of the BOM matrix.	(For encoding
388
	* information, see the ColonetServerInterface documentation.)	 The entire matrix is passed
392 389
	* to the client when requested. This method takes a string of the form
393 390
	* "[command code] [command code] [number of robots] [data0] [data1] ..."
394 391
	* with tokens separated by spaces and containing no brackets.
395 392
	* The [command code]s are predefined values identifying this String as a BOM data
396 393
	* String, [number of robots] is an integer, and the values that follow are
397
	* the sensor readings of the robots in order, starting with robot 0.  Only [number of robots]^2
398
	* data entries will be read.  The matrix values are saved locally until the next String is parsed.
394
	* the sensor readings of the robots in order, starting with robot 0.	Only [number of robots]^2
395
	* data entries will be read.	The matrix values are saved locally until the next String is parsed.
399 396
	*
400 397
	*
401 398
	* @param line the String containing BOM matrix information.
......
408 405
		for (int i = 0; i < num; i++) {
409 406
			for (int j = 0; j < num; j++) {
410 407
				String next = str[3 + i*num + j];
411
				if (next.equals("-1"))
408
				if (next.equals("-1")) {
412 409
					txtMatrix.append("-");
413
				else
410
				} else {
414 411
					txtMatrix.append(next);
415
				if (j < num - 1)
412
				}
413

  
414
				if (j < num - 1) {
416 415
					txtMatrix.append(" ");
416
				}
417 417
			}
418
			if (i < num - 1)
418

  
419
			if (i < num - 1) {
419 420
				txtMatrix.append("\n");
421
			}
420 422
		}
421 423
		repaint();
422 424
	}
423 425

  
424 426
	public void connect () {
425
	    lblConnectionStatus.setText("Status: Connecting...");
426
	    webcamLoader = new WebcamLoader(this);
427
		lblConnectionStatus.setText("Status: Connecting...");
428
		webcamLoader = new WebcamLoader(this);
427 429
		dataUpdater = new DataUpdater();
428 430
		csi = new ColonetServerInterface(this);
429 431
		csi.connect(txtHost.getText(), txtPort.getText());
430 432
		if (!csi.isReady()) {
431
		    lblConnectionStatus.setText("Status: Offline");
432
			return;
433
	    }
434
		btnConnect.setText("Disconnect");
435
		lblConnectionStatus.setText("Status: Connected");
436
		dataUpdater.start();
437
		webcamLoader.start();
433
			lblConnectionStatus.setText("Status: Offline");
434
		} else {
435
			btnConnect.setText("Disconnect");
436
			lblConnectionStatus.setText("Status: Connected");
437
			dataUpdater.start();
438
			webcamLoader.start();
439
		}
438 440
	}
439 441

  
440 442
	public void disconnect () {
441
	    lblConnectionStatus.setText("Status: Disconnecting...");
442
	    dataUpdater.interrupt();
443
	    csi.disconnect();
444
	    csi = null;
445
	    btnConnect.setText("Connect");
446
	    lblConnectionStatus.setText("Status: Disconnected");
443
		lblConnectionStatus.setText("Status: Disconnecting...");
444
		dataUpdater.interrupt();
445
		csi.disconnect();
446
		csi = null;
447
		btnConnect.setText("Connect");
448
		lblConnectionStatus.setText("Status: Disconnected");
447 449
	}
448 450

  
449 451
	/**
......
460 462

  
461 463
	/**
462 464
	* Parses a String containing XBee ID values.
463
	* The ColonetServerInterface receives Strings of XBee information.  (For encoding
464
	* information, see the ColonetServerInterface documentation.)  This method takes
465
	* The ColonetServerInterface receives Strings of XBee information.	(For encoding
466
	* information, see the ColonetServerInterface documentation.)	 This method takes
465 467
	* a string of the form "[command code] [command code] [number of robots] [id0] [id1] ..."
466 468
	* with tokens separated by spaces and containing no brackets.
467 469
	* The [command code]s are predefined values identifying this String as an XBee
468 470
	* ID String, [number of robots] is an integer, and the values that follow are
469
	* the IDs of the robots in order, starting with robot 0.  Only [number of robots]
470
	* will be read.  The ID values are saved locally until the next String is parsed.
471
	* the IDs of the robots in order, starting with robot 0.	Only [number of robots]
472
	* will be read.	 The ID values are saved locally until the next String is parsed.
471 473
	* The purpose of having this list is to ensure that robots are properly identified for control purposes.
472 474
	* This keeps robot identification consistent between sessions and prevents arbitrary assignment.
473 475
	*
......
479 481
		String [] str = line.split(" ");
480 482
		int num = Integer.parseInt(str[2]);
481 483
		xbeeID = new int[num];
482
		for (int i = 0; i < num; i++)
484
		for (int i = 0; i < num; i++) {
483 485
			xbeeID[i] = Integer.parseInt(str[i+3]);
486
		}
484 487

  
485 488
		//update the list of robots to control
486 489
		//but save the old value first
487 490
		Object oldSelection = cmbRobotNum.getSelectedItem();
488 491
		cmbRobotNum.removeAllItems();
489
		cmbRobotNum.addItem(new String("   All   "));
490
		for (int i = 0; i < num; i++)
492
		cmbRobotNum.addItem(new String("	 All	 "));
493
		for (int i = 0; i < num; i++) {
491 494
			cmbRobotNum.addItem(new String("" + xbeeID[i]));
495
		}
492 496
		cmbRobotNum.setSelectedItem(oldSelection);
493 497
		repaint();
494 498
	}
495 499

  
496 500
	/**
497 501
	* Parses a String containing battery information.
498
	* The ColonetServerInterface receives Strings of battery information.  (For encoding
499
	* information, see the ColonetServerInterface documentation.)  This method takes
502
	* The ColonetServerInterface receives Strings of battery information.	 (For encoding
503
	* information, see the ColonetServerInterface documentation.)	 This method takes
500 504
	* a string of the form "[command code] [command code] [robot ID] [value]"
501 505
	* with tokens separated by spaces and containing no brackets.
502 506
	* The [command code]s are predefined values identifying this String as a battery
......
513 517
		int level = Integer.parseInt(str[3]);
514 518
		int selected = -1;
515 519
		try {
516
		    selected = Integer.parseInt((String)cmbRobotNum.getSelectedItem());
520
			selected = Integer.parseInt((String)cmbRobotNum.getSelectedItem());
517 521
		} catch (Exception e) {
522
			System.out.println("Exception in parseBattery.");
518 523
		}
524

  
519 525
		if (selected == botNum) {
520 526
			batteryIcon.setLevel(level);
521 527
		}
......
535 541
			int x = Integer.parseInt(str[i+1]);
536 542
			int y = Integer.parseInt(str[i+2]);
537 543
			RobotIcon newIcon = new RobotIcon(id, x, y);
538
            if (newIcon.id >= 0)
539
                newIcon.color = Color.GREEN;
544
			if (newIcon.id >= 0) {
545
				newIcon.color = Color.GREEN;
546
			}
540 547
			newList.add(newIcon);
541 548
		}
542 549
		robotIcons = newList;
543 550
		repaint();
544 551
	}
545 552

  
546

  
547 553
	//
548 554
	// MouseListener methods
549 555
	//
550 556
	public void mousePressed(MouseEvent e) {
551
	    //Start a new Thread to handle the MouseEvent
552
	    (new MouseHandler(e)).start();
557
		//Start a new Thread to handle the MouseEvent
558
		(new MouseHandler(e)).start();
553 559
	}
554 560
	public void mouseExited(MouseEvent e) {
555 561
	}
......
569 575
	//
570 576
	public void keyPressed (KeyEvent e) {
571 577
		//Start a new Thread to handle the KeyEvent
572
	    (new KeyHandler(e)).start();
578
		(new KeyHandler(e)).start();
573 579
	}
574 580
	public void keyReleased (KeyEvent e) {
575 581
	}
......
585 591
	}
586 592

  
587 593
	class MouseHandler extends Thread {
594
		MouseEvent e;
588 595

  
589
	    MouseEvent e;
596
		public MouseHandler (MouseEvent event) {
597
			super("MouseHandler");
598
			this.e = event;
599
		}
590 600

  
591
	    public MouseHandler (MouseEvent event) {
592
	        super("MouseHandler");
593
	        this.e = event;
594
	    }
601
		public void run () {
602
			Point pt = panelWebcam.convertClick(e);
595 603

  
596
	    public void run () {
604
			// If we are selecting a waypoint (destination) for a specific bot
605
			if (setWaypoint && setWaypointID	>= 0) {
606
				setWaypoint = false;
607
				panelWebcam.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
608
				if (selectedBot < 0) {
609
					return;
610
				}
597 611

  
598
	        Point pt = panelWebcam.convertClick(e);
612
				RobotIcon r = robotIcons.get(selectedBot);
613
				r.destx = pt.x;
614
				r.desty = pt.y;
599 615

  
600
	        // If we are selecting a waypoint (destination) for a specific bot
601
	        if (setWaypoint && setWaypointID  >= 0) {
602
	            setWaypoint = false;
603
	            panelWebcam.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
604
	            if (selectedBot < 0)
605
	                return;
616
				if (csi != null) {
617
					csi.sendAbsoluteMove(r.id, r.destx, r.desty);
606 618

  
607
	            RobotIcon r = robotIcons.get(selectedBot);
608
	            r.destx = pt.x;
609
	            r.desty = pt.y;
619
				}
620
				
621
				return;
622
			}
610 623

  
611
	            if (csi != null)
612
	                csi.sendAbsoluteMove(r.id, r.destx, r.desty);
624
			// Right-click also means we are moving a robot
625
			if (e.getButton() == MouseEvent.BUTTON2 || e.getButton() == MouseEvent.BUTTON3) {
626
				if (selectedBot < 0) {
627
					return;
628
				}
613 629

  
614
	            return;
615
	        }
630
				RobotIcon r = robotIcons.get(selectedBot);
631
				r.destx = pt.x;
632
				r.desty = pt.y;
616 633

  
617
	        // Right-click also means we are moving a robot
618
	        if (e.getButton() == MouseEvent.BUTTON2 || e.getButton() == MouseEvent.BUTTON3) {
619
	            if (selectedBot < 0)
620
	                return;
634
				if (csi != null) {
635
					csi.sendAbsoluteMove(r.id, r.destx, r.desty);
636
				}
621 637

  
622
	            RobotIcon r = robotIcons.get(selectedBot);
623
	            r.destx = pt.x;
624
	            r.desty = pt.y;
638
				return;
639
			}
625 640

  
626
	            if (csi != null)
627
	                csi.sendAbsoluteMove(r.id, r.destx, r.desty);
641
			// If we are setting all waypoints
642
			if (setWaypoint) {
643
				setWaypoint = false;
644
				panelWebcam.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
645
				for (int i = 0; i < robotIcons.size(); i++) {
646
					RobotIcon r = robotIcons.get(i);
647
					r.destx = pt.x;
648
					r.desty = pt.y;
649
				}
650
				
651
				return;
652
			}
628 653

  
629
	            return;
630
	        }
631

  
632
	        // If we are setting all waypoints
633
	        if (setWaypoint) {
634
	            setWaypoint = false;
635
	            panelWebcam.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
636
	            for (int i = 0; i < robotIcons.size(); i++) {
637
	                RobotIcon r = robotIcons.get(i);
638
	                r.destx = pt.x;
639
	                r.desty = pt.y;
640
	            }
641
	            return;
642
	        }
643

  
644
	        // Otherwise, we are selecting a bot, or doing nothing
645
		    for (int i = 0; i < robotIcons.size(); i++) {
646
		        RobotIcon r = robotIcons.get(i);
647
		        if (r.contains(pt.x, pt.y)) {
648
		            selectedBot = i;
649
		            lblSelected.setText(" " + r.id);
654
			// Otherwise, we are selecting a bot, or doing nothing
655
			for (int i = 0; i < robotIcons.size(); i++) {
656
				RobotIcon r = robotIcons.get(i);
657
				if (r.contains(pt.x, pt.y)) {
658
					selectedBot = i;
659
					lblSelected.setText(" " + r.id);
650 660
					// Try to select the clicked bot, if its XBee ID is detected.
651 661
					for (int j = 1; j < cmbRobotNum.getItemCount(); j++) {
652
						if (Integer.parseInt(cmbRobotNum.getItemAt(j).toString()) == robotIcons.get(selectedBot).id)
662
						if (Integer.parseInt(cmbRobotNum.getItemAt(j).toString()) == robotIcons.get(selectedBot).id) {
653 663
							cmbRobotNum.setSelectedIndex(j);
664
						}
654 665
					}
655 666
					return;
656
		        }
657
		    }
667
				}
668
			}
658 669

  
659
		    repaint();
660
	    }
670
			repaint();
671
		}
661 672
	}
662 673

  
663 674
	class KeyHandler extends Thread {
664

  
665 675
		KeyEvent e;
666 676

  
667 677
		public KeyHandler (KeyEvent event) {
......
692 702
	}
693 703

  
694 704
	class ActionHandler extends Thread {
705
		ActionEvent e;
695 706

  
696
	    ActionEvent e;
707
		public ActionHandler (ActionEvent event) {
708
			super("ActionHandler");
709
			this.e = event;
710
		}
697 711

  
698
	    public ActionHandler (ActionEvent event) {
699
	        super("ActionHandler");
700
	        this.e = event;
701
	    }
712
		public void run () {
713
			Object source = e.getSource();
702 714

  
703
	    public void run () {
704
	        Object source = e.getSource();
715
			// General Actions
716
			if (source == btnConnect) {
717
				if (csi == null) {
718
					connect();
719
				} else {
720
					disconnect();
721
				}
722
			} else if (source == btnGetXBeeIDs) {
723
				csi.sendXBeeIDRequest();
724
			} else if (source == btnAssignID) {
725
				String message;
726
				if (selectedBot < 0) {
727
					return;
728
				}
729
				int curID = robotIcons.get(selectedBot).id;
705 730

  
706
		    // General Actions
707
		    if (source == btnConnect) {
708
		        if (csi == null)
709
			        connect();
710
			    else
711
			        disconnect();
712
		    } else if (source == btnGetXBeeIDs) {
713
			    csi.sendXBeeIDRequest();
714
		    } else if (source == btnAssignID) {
715
		        String message;
716
		        if (selectedBot < 0)
717
		            return;
718
		        int curID = robotIcons.get(selectedBot).id;
719
		        if (curID < 0)
720
		            message = "That robot is unidentified. Please specify its ID.";
721
		        else
722
		            message = "That robot has ID " + curID + ". You may reassign it now.";
723
		        String result = JOptionPane.showInputDialog(self, message, "Robot Identification", JOptionPane.QUESTION_MESSAGE);
724
		        if (result == null)
725
		            return;
726
	            int newID = -1;
727
		        try {
728
		            newID = Integer.parseInt(result);
729
		        } catch (Exception ex) {
730
		            csi.warn("Invalid ID.");
731
		            return;
732
		        }
733
		        // Assign new ID and update display
734
			    csi.sendIDAssignment(curID, newID);
735
		        robotIcons.get(selectedBot).id = newID;
736
		        robotIcons.get(selectedBot).color = Color.GREEN;
737
		        lblSelected.setText(" " + newID);
731
				if (curID < 0) {
732
					message = "That robot is unidentified. Please specify its ID.";
733
				} else {
734
					message = "That robot has ID " + curID + ". You may reassign it now.";
735
				}
736
				String result = JOptionPane.showInputDialog(self, message, "Robot Identification", JOptionPane.QUESTION_MESSAGE);
737
				if (result == null) {
738
					return;
739
				}
740
				int newID = -1;
741
				try {
742
					newID = Integer.parseInt(result);
743
				} catch (Exception ex) {
744
					csi.warn("Invalid ID.");
745
					return;
746
				}
747
				// Assign new ID and update display
748
				csi.sendIDAssignment(curID, newID);
749
				robotIcons.get(selectedBot).id = newID;
750
				robotIcons.get(selectedBot).color = Color.GREEN;
751
				lblSelected.setText(" " + newID);
752
			} else if (source == btnF) { // Robot Movement Controls
753
				vectorController.setMaxForward();
754
				vectorController.sendToServer();
755
			} else if (source == btnB) {
756
				vectorController.setMaxReverse();
757
				vectorController.sendToServer();
758
			} else if (source == btnL) {
759
				vectorController.setMaxLeft();
760
				vectorController.sendToServer();
761
			} else if (source == btnR) {
762
				vectorController.setMaxRight();
763
				vectorController.sendToServer();
764
			} else if (source == btnActivate) {
765
				vectorController.setZero();
766
				vectorController.sendToServer();
767
			} else if (source == btnCommand_MoveTo) { // Robot Commands (non-movement)
768
				if (selectedBot < 0) {
769
					return;
770
				}
771
				panelWebcam.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
772
				setWaypoint = true;
773
				setWaypointID = selectedBot;
774
			} else if (source == btnCommand_MoveAll) {
775
				panelWebcam.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
776
				setWaypoint = true;
777
				setWaypointID = -1;
778
			} else if (source == btnCommand_StopTask) {
738 779

  
780
			} else if (source == btnCommand_ResumeTask) {
739 781

  
740
		    }
782
			} else if (source == btnCommand_ChargeNow) {
741 783

  
742
		    // Robot Movement Controls
743
		    else if (source == btnF) {
744
			    vectorController.setMaxForward();
745
			    vectorController.sendToServer();
746
		    } else if (source == btnB) {
747
			    vectorController.setMaxReverse();
748
			    vectorController.sendToServer();
749
		    } else if (source == btnL) {
750
			    vectorController.setMaxLeft();
751
			    vectorController.sendToServer();
752
		    } else if (source == btnR) {
753
			    vectorController.setMaxRight();
754
			    vectorController.sendToServer();
755
		    } else if (source == btnActivate) {
756
			    vectorController.setZero();
757
			    vectorController.sendToServer();
758
		    }
759
		    // Robot Commands (non-movement)
760
		    else if (source == btnCommand_MoveTo) {
761
		        if (selectedBot < 0)
762
		            return;
763
		        panelWebcam.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
764
		        setWaypoint = true;
765
		        setWaypointID = selectedBot;
784
			} else if (source == btnCommand_StopCharging) {
766 785

  
767
		    } else if (source == btnCommand_MoveAll) {
768
		        panelWebcam.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
769
		        setWaypoint = true;
770
		        setWaypointID = -1;
786
			} else if (source == btnAddTask) { // Queue Management
787
				taskAddWindow.prompt();
788
			} else if (source == btnRemoveTask) {
789
				if (taskList.getSelectedIndex() >= 0) {
790
					csi.sendQueueRemove(taskList.getSelectedIndex());
791
				}
792
				csi.sendQueueUpdate();
793
			} else if (source == btnMoveTaskUp) {
794
				csi.sendQueueReorder(taskList.getSelectedIndex(), taskList.getSelectedIndex() - 1);
795
				csi.sendQueueUpdate();
796
			} else if (source == btnMoveTaskDown) {
797
				csi.sendQueueReorder(taskList.getSelectedIndex(), taskList.getSelectedIndex() + 1);
798
				csi.sendQueueUpdate();
799
			} else if (source == btnUpdateTasks) {
800
				csi.sendQueueUpdate();
801
			}
771 802

  
772
		    } else if (source == btnCommand_StopTask) {
773

  
774
		    } else if (source == btnCommand_ResumeTask) {
775

  
776
		    } else if (source == btnCommand_ChargeNow) {
777

  
778
		    } else if (source == btnCommand_StopCharging) {
779

  
780
		    }
781

  
782
		    // Queue Management
783
		    else if (source == btnAddTask) {
784
			    taskAddWindow.prompt();
785
		    } else if (source == btnRemoveTask) {
786
			    if (taskList.getSelectedIndex() >= 0);
787
				    csi.sendQueueRemove(taskList.getSelectedIndex());
788
			    csi.sendQueueUpdate();
789
		    } else if (source == btnMoveTaskUp) {
790
			    csi.sendQueueReorder(taskList.getSelectedIndex(), taskList.getSelectedIndex() - 1);
791
			    csi.sendQueueUpdate();
792
		    } else if (source == btnMoveTaskDown) {
793
			    csi.sendQueueReorder(taskList.getSelectedIndex(), taskList.getSelectedIndex() + 1);
794
			    csi.sendQueueUpdate();
795
		    } else if (source == btnUpdateTasks) {
796
			    csi.sendQueueUpdate();
797
		    }
798

  
799
	        repaint();
800
	    }
801

  
803
			repaint();
804
		}
802 805
	}
803 806

  
804 807
	/*
805
	*	DataUpdater thread.
806
	*   The purpose of this thread is to request data from the server at regular intervals.
808
	* DataUpdater thread.
809
	*		The purpose of this thread is to request data from the server at regular intervals.
807 810
	*
808 811
	*/
809 812
	class DataUpdater extends Thread {
......
819 822
				try {
820 823
					//request more data
821 824
					if (csi != null && csi.isReady()) {
822
                        csi.sendPositionRequest();
825
												csi.sendPositionRequest();
823 826
						csi.sendXBeeIDRequest();
824 827
						if (cmbRobotNum.getSelectedIndex() > 0) {
825
						    String sel = (String) cmbRobotNum.getSelectedItem();
826
						    int num = Integer.parseInt(sel);
828
								String sel = (String) cmbRobotNum.getSelectedItem();
829
								int num = Integer.parseInt(sel);
827 830
							csi.sendBatteryRequest(num);
828 831
						}
829 832
					}
......
837 840
	}
838 841

  
839 842
	/*
840
	*	GraphicsPanel class
841
	*	An extension of JPanel, designed for holding an image that will be repainted regularly.
843
	* GraphicsPanel class
844
	* An extension of JPanel, designed for holding an image that will be repainted regularly.
842 845
	*/
843 846
	class GraphicsPanel extends JPanel {
844 847
		protected Image img;
......
856 859
			// Place the buffered image on the screen, inside the panel
857 860
			g.drawImage(img, 0, 0, Color.WHITE, this);
858 861
		}
859

  
860 862
	}
861 863

  
862 864
	/*
863
	*	WebcamPanel class
864
	*	Enables more efficient image handling in a component-controlled environment
865
	* WebcamPanel class
866
	* Enables more efficient image handling in a component-controlled environment
865 867
	*/
866 868
	class WebcamPanel extends JPanel {
867
		int BORDER = 16;  // this is arbitrary. it makes the image look nice inside a border.
869
		int BORDER = 16;	// this is arbitrary. it makes the image look nice inside a border.
868 870
		int BOT_RADIUS = 40;
869 871
		volatile BufferedImage img;
870 872
		BufferedImage buffer;
......
897 899
			int x = 0;
898 900
			int y = 0;
899 901

  
900
			if (widthRatio > heightRatio) {  //height is the limiting factor
901
			    scale = heightRatio;
902
			    newHeight = maxHeight;
903
			    newWidth = (int) (img.getWidth() * scale);
904
			    y = BORDER;
905
			    x = (maxWidth - newWidth) / 2 + BORDER;
906
			} else {  //width is the limiting factor
907
			    scale = widthRatio;
908
			    newWidth = maxWidth;
909
			    newHeight = (int) (img.getHeight() * scale);
910
			    x = BORDER;
911
			    y = (maxHeight - newHeight) / 2 + BORDER;
902
			if (widthRatio > heightRatio) {	 //height is the limiting factor
903
					scale = heightRatio;
904
					newHeight = maxHeight;
905
					newWidth = (int) (img.getWidth() * scale);
906
					y = BORDER;
907
					x = (maxWidth - newWidth) / 2 + BORDER;
908
			} else {	//width is the limiting factor
909
					scale = widthRatio;
910
					newWidth = maxWidth;
911
					newHeight = (int) (img.getHeight() * scale);
912
					x = BORDER;
913
					y = (maxHeight - newHeight) / 2 + BORDER;
912 914
			}
913 915

  
914 916
			// Draw everything onto the buffer
......
922 924

  
923 925
			// Draw Identifiers and battery levels
924 926
			if (robotIcons != null) {
925
			    bufferedGraphics.setStroke(new BasicStroke(2));
926
			    for (int i = 0; i < robotIcons.size(); i++) {
927
				    RobotIcon r = robotIcons.get(i);
928
				    bufferedGraphics.setColor(r.color);
929
				    // Identifier circle
930
				    int px = (int) (x + r.x * scale);
931
				    int py = (int) (y + r.y * scale);
932
				    bufferedGraphics.drawOval(px-RADIUS, py-RADIUS, 2*r.RADIUS, 2*r.RADIUS);
933
				    // Battery
934
				    //if (r.battery >= 0) {
935
				        bufferedGraphics.setColor(Color.GREEN);
936
				        bufferedGraphics.fillRect(px+20, py+20, 30, 10);
937
				        bufferedGraphics.setColor(Color.BLACK);
938
				        bufferedGraphics.drawRect(px+20, py+20, 50, 10);
939
				    //}
940
				    // If the robot has a destination, draw the vector
941
				    if (r.destx >= 0) {
942
				        bufferedGraphics.drawLine(px, py, (int)(x + r.destx * scale), (int)(y + r.desty * scale));
943
				    }
944
			    }
927
					bufferedGraphics.setStroke(new BasicStroke(2));
928
					for (int i = 0; i < robotIcons.size(); i++) {
929
						RobotIcon r = robotIcons.get(i);
930
						bufferedGraphics.setColor(r.color);
931
						// Identifier circle
932
						int px = (int) (x + r.x * scale);
933
						int py = (int) (y + r.y * scale);
934
						bufferedGraphics.drawOval(px-RADIUS, py-RADIUS, 2*r.RADIUS, 2*r.RADIUS);
935
						// Battery
936
						//if (r.battery >= 0) {
937
								bufferedGraphics.setColor(Color.GREEN);
938
								bufferedGraphics.fillRect(px+20, py+20, 30, 10);
939
								bufferedGraphics.setColor(Color.BLACK);
940
								bufferedGraphics.drawRect(px+20, py+20, 50, 10);
941
						//}
942
						// If the robot has a destination, draw the vector
943
						if (r.destx >= 0) {
944
								bufferedGraphics.drawLine(px, py, (int)(x + r.destx * scale), (int)(y + r.desty * scale));
945
						}
946
					}
945 947
			}
946 948

  
947 949
			// Identify currently-selected robot
948 950
			if (selectedBot >= 0) {
949
			    bufferedGraphics.setColor(Color.BLACK);
950
			    RobotIcon r = robotIcons.get(selectedBot);
951
			    int px = (int) (x + r.x * scale);
952
			    int py = (int) (y + r.y * scale);
953
			    bufferedGraphics.drawOval(px-RADIUS-6, py-RADIUS-6, 2*r.RADIUS+12, 2*r.RADIUS+12);
951
					bufferedGraphics.setColor(Color.BLACK);
952
					RobotIcon r = robotIcons.get(selectedBot);
953
					int px = (int) (x + r.x * scale);
954
					int py = (int) (y + r.y * scale);
955
					bufferedGraphics.drawOval(px-RADIUS-6, py-RADIUS-6, 2*r.RADIUS+12, 2*r.RADIUS+12);
954 956
			}
955 957

  
956 958
			//Display buffered content
......
964 966
		public Point convertClick (MouseEvent e) {
965 967
			// Calculate scaling
966 968
			int clickx = e.getX();
967
		    int clicky = e.getY();
969
				int clicky = e.getY();
968 970
			int maxWidth = getWidth() - 2*BORDER;
969 971
			int maxHeight = getHeight() - 2*BORDER;
970 972
			double widthRatio = 1.0 * maxWidth / img.getWidth();
......
975 977
			int px = 0;
976 978
			int py = 0;
977 979

  
978
			if (widthRatio > heightRatio) {  //height is the limiting factor
979
			    scale = heightRatio;
980
			    newHeight = maxHeight;
981
			    newWidth = (int) (img.getWidth() * scale);
982
			    py = clicky - BORDER;
983
			    px = clickx - BORDER - (maxWidth - newWidth) / 2;
984
			    py *= scale;
985
			    px *= scale;
986
			} else {  //width is the limiting factor
987
			    scale = widthRatio;
988
			    newWidth = maxWidth;
989
			    newHeight = (int) (img.getHeight() * scale);
990
			    px = clickx - BORDER;
991
			    py = clicky - BORDER - (maxHeight - newHeight) / 2;
992
			    px *= scale;
993
			    py *= scale;
980
			if (widthRatio > heightRatio) {	 //height is the limiting factor
981
					scale = heightRatio;
982
					newHeight = maxHeight;
983
					newWidth = (int) (img.getWidth() * scale);
984
					py = clicky - BORDER;
985
					px = clickx - BORDER - (maxWidth - newWidth) / 2;
986
					py *= scale;
987
					px *= scale;
988
			} else {	//width is the limiting factor
989
					scale = widthRatio;
990
					newWidth = maxWidth;
991
					newHeight = (int) (img.getHeight() * scale);
992
					px = clickx - BORDER;
993
					py = clicky - BORDER - (maxHeight - newHeight) / 2;
994
					px *= scale;
995
					py *= scale;
994 996
			}
995 997

  
996
		    return new Point(px, py);
998
				return new Point(px, py);
997 999

  
998 1000
		}
999 1001

  
1000 1002
	}
1001 1003

  
1002 1004
	/*
1003
	*	WebcamLoader class
1004
	*	Handles the loading of the webcam image.
1005
	* WebcamLoader class
1006
	* Handles the loading of the webcam image.
1005 1007
	*/
1006 1008
	class WebcamLoader extends Thread
1007 1009
	{
......
1031 1033
						image.flush();
1032 1034
					System.gc();
1033 1035
					try {
1034
				        imagePath = new URL(IMAGE_PATH + "?rand=" + rand.nextInt(50000));
1035
			        } catch (MalformedURLException e) {
1036
				        System.out.println("Malformed URL: could not form URL from: [" + IMAGE_PATH + "]\n");
1037
			        }
1036
								imagePath = new URL(IMAGE_PATH + "?rand=" + rand.nextInt(50000));
1037
							} catch (MalformedURLException e) {
1038
								System.out.println("Malformed URL: could not form URL from: [" + IMAGE_PATH + "]\n");
1039
							}
1038 1040
					image = ImageIO.read(imagePath);
1039 1041
					// The MediaTracker waitForID pauses the thread until the image is loaded.
1040 1042
					// We don't want to display a half-downloaded image.
......
1057 1059
	}
1058 1060

  
1059 1061
	/*
1060
	*  RobotIcon class
1061
	*  Provides a means for graphically representing and keeping track of webcam bots.
1062
	*	 RobotIcon class
1063
	*	 Provides a means for graphically representing and keeping track of webcam bots.
1062 1064
	*/
1063 1065
	class RobotIcon {
1064 1066
		public final int RADIUS = 30;
......
1068 1070
		public int destx, desty;
1069 1071
		public int id;
1070 1072
		public Color color;
1071
        public int battery;
1073
				public int battery;
1072 1074

  
1073 1075
		public RobotIcon (int id, int x, int y) {
1074 1076
			this.color = Color.RED;
......
1081 1083
		}
1082 1084

  
1083 1085
		/**
1084
		*  Relocates this RobotIcon to a new coordinate point.
1086
		*	 Relocates this RobotIcon to a new coordinate point.
1085 1087
		*
1086 1088
		*/
1087 1089
		public void move (int newX, int newY) {
......
1090 1092
		}
1091 1093

  
1092 1094
		/**
1093
		*  Determines if a given point is within a reasonable range of the current location
1094
		*  to be considered the same robot when moving. The threshold is determined by the
1095
		*  CLOSE value.
1095
		*	 Determines if a given point is within a reasonable range of the current location
1096
		*	 to be considered the same robot when moving. The threshold is determined by the
1097
		*	 CLOSE value.
1096 1098
		*
1097
		*  @returns Whether or not the given point is reasonably close to the current location.
1099
		*	 @returns Whether or not the given point is reasonably close to the current location.
1098 1100
		*
1099 1101
		*/
1100 1102
		public boolean isClose (int nx, int ny) {
......
1103 1105
		}
1104 1106

  
1105 1107
		/**
1106
		*  Determines whether a given point is within the rectangle that circumscribes the
1107
		*  robot's circlular icon. Used for clicking on robots in webcam view.
1108
        *
1109
        */
1108
		*	 Determines whether a given point is within the rectangle that circumscribes the
1109
		*	 robot's circlular icon. Used for clicking on robots in webcam view.
1110
				*
1111
				*/
1110 1112
		public boolean contains (int px, int py) {
1111
		    Rectangle rect = new Rectangle(x-RADIUS, y-RADIUS, 2*RADIUS, 2*RADIUS);
1112
		    return rect.contains(px, py);
1113
				Rectangle rect = new Rectangle(x-RADIUS, y-RADIUS, 2*RADIUS, 2*RADIUS);
1114
				return rect.contains(px, py);
1113 1115
		}
1114 1116

  
1115 1117
		public String toString () {
......
1121 1123

  
1122 1124

  
1123 1125
	/*
1124
	*	VectorController class
1125
	*	Manages robot motion control graphically
1126
	* VectorController class
1127
	* Manages robot motion control graphically
1126 1128
	*/
1127 1129
	class VectorController extends GraphicsPanel implements MouseListener, MouseMotionListener {
1128 1130
		int x, y, cx, cy;
......
1262 1264
				*/
1263 1265

  
1264 1266
				//Directional commands
1265
				if (x > cx && y == cy) {  //move right
1267
				if (x > cx && y == cy) {	//move right
1266 1268
					csi.sendData(ColonetServerInterface.MOTOR2_SET + " 0 200", dest);
1267 1269
					csi.sendData(ColonetServerInterface.MOTOR1_SET + " 1 200", dest);
1268
				} else if (x < cx && y == cy) {  //move left
1270
				} else if (x < cx && y == cy) {	 //move left
1269 1271
					csi.sendData(ColonetServerInterface.MOTOR2_SET + " 1 200", dest);
1270 1272
					csi.sendData(ColonetServerInterface.MOTOR1_SET + " 0 200", dest);
1271
				} else if (x == cx && y > cy) {  //move forward
1273
				} else if (x == cx && y > cy) {	 //move forward
1272 1274
					csi.sendData(ColonetServerInterface.MOTOR2_SET + " 0 225", dest);
1273 1275
					csi.sendData(ColonetServerInterface.MOTOR1_SET + " 0 225", dest);
1274
				} else if (x == cx && y < cy) {  //move backward
1276
				} else if (x == cx && y < cy) {	 //move backward
1275 1277
					csi.sendData(ColonetServerInterface.MOTOR2_SET + " 1 225", dest);
1276 1278
					csi.sendData(ColonetServerInterface.MOTOR1_SET + " 1 225", dest);
1277
				} else if (x == cx && y == cy) {  //stop!
1279
				} else if (x == cx && y == cy) {	//stop!
1278 1280
					csi.sendData(ColonetServerInterface.MOTOR2_SET + " 1 0", dest);
1279 1281
					csi.sendData(ColonetServerInterface.MOTOR1_SET + " 1 0", dest);
1280 1282
				}
......
1284 1286
	}
1285 1287

  
1286 1288
	/*
1287
	*	TaskAddWindow class
1288
	*	A window that provides a simple way to add tasks to a task queue.
1289
	* TaskAddWindow class
1290
	* A window that provides a simple way to add tasks to a task queue.
1289 1291
	*/
1290 1292
	class TaskAddWindow extends JFrame implements ActionListener, ListSelectionListener {
1291 1293
		JPanel panelButtons;
......
1399 1401
	}
1400 1402

  
1401 1403
	/*
1402
	*  BatteryIcon class
1403
	*  Graphical representation of battery level
1404
	*	 BatteryIcon class
1405
	*	 Graphical representation of battery level
1404 1406
	*/
1405 1407
	class BatteryIcon implements Icon {
1406 1408
		private int width;
1407
	    private int height;
1408
	    private int level;
1409
			private int height;
1410
			private int level;
1409 1411

  
1410 1412
		/**
1411 1413
		* Constructs a new BatteryIcon with all default parameters.
1412 1414
		* Default width and height are 50.
1413 1415
		* Default level is 100.
1414 1416
		*/
1415
	    public BatteryIcon(){
1416
	    	this(100, 50, 50);
1417
	    }
1417
			public BatteryIcon(){
1418
				this(100, 50, 50);
1419
			}
1418 1420

  
1419 1421
		/**
1420 1422
		* Constructs a new BatteryIcon with default width and height, and with the specified level.
1421 1423
		* Default width and height are 50.
1422 1424
		*/
1423
	    public BatteryIcon(int startLevel){
1424
	    	this(startLevel, 50, 50);
1425
	    }
1425
			public BatteryIcon(int startLevel){
1426
				this(startLevel, 50, 50);
1427
			}
1426 1428

  
1427 1429
		/**
1428 1430
		* Constructs a new BatteryIcon with the specified level, width, and height.
1429 1431
		*/
1430
	    public BatteryIcon(int startLevel, int w, int h){
1431
	    	level = startLevel;
1432
	    	width = w;
1433
	    	height = h;
1434
	    }
1432
			public BatteryIcon(int startLevel, int w, int h){
1433
				level = startLevel;
1434
				width = w;
1435
				height = h;
1436
			}
1435 1437

  
1436
	    public void paintIcon(Component c, Graphics g, int x, int y) {
1437
	        Graphics2D g2d = (Graphics2D) g.create();
1438
	        //clear the background
1439
	        g2d.setColor(Color.WHITE);
1440
	        g2d.fillRect(x + 1, y + 1, width - 2, height - 2);
1441
	        //outline
1442
	        g2d.setColor(Color.BLACK);
1443
	        g2d.drawRect((int)(x + width*.3), y + 2, (int)(width*.4), height - 4);
1444
	        //battery life rectangle
1438
			public void paintIcon(Component c, Graphics g, int x, int y) {
1439
					Graphics2D g2d = (Graphics2D) g.create();
1440
					//clear the background
1441
					g2d.setColor(Color.WHITE);
1442
					g2d.fillRect(x + 1, y + 1, width - 2, height - 2);
1443
					//outline
1444
					g2d.setColor(Color.BLACK);
1445
					g2d.drawRect((int)(x + width*.3), y + 2, (int)(width*.4), height - 4);
1446
					//battery life rectangle
1445 1447
			if (level > 50)
1446 1448
				g2d.setColor(Color.GREEN);
1447 1449
			else if (level > 25)
1448 1450
				g2d.setColor(Color.YELLOW);
1449 1451
			else
1450 1452
				g2d.setColor(Color.RED);
1451
	        int greenX = (int)(x + 1 + width*.3);
1452
	        int greenY = (int)((y+3) + Math.abs(level-100.0)*(height-6)/(100));
1453
	        int greenWidth = (int)(width*.4 - 2)+1;
1454
	        int greenHeight = 1+(int)(level-0.0)*(height-6)/(100);
1455
	        g2d.fillRect(greenX, greenY, greenWidth, greenHeight);
1456
	        //text
1457
	        g2d.setColor(Color.BLACK);
1458
	        g2d.drawString(level + "%", greenX + greenWidth/2 - 10, greenY + greenHeight/2 + 5);
1453
					int greenX = (int)(x + 1 + width*.3);
1454
					int greenY = (int)((y+3) + Math.abs(level-100.0)*(height-6)/(100));
1455
					int greenWidth = (int)(width*.4 - 2)+1;
1456
					int greenHeight = 1+(int)(level-0.0)*(height-6)/(100);
1457
					g2d.fillRect(greenX, greenY, greenWidth, greenHeight);
1458
					//text
1459
					g2d.setColor(Color.BLACK);
1460
					g2d.drawString(level + "%", greenX + greenWidth/2 - 10, greenY + greenHeight/2 + 5);
1459 1461

  
1460
	        g2d.dispose();
1461
	    }
1462
					g2d.dispose();
1463
			}
1462 1464

  
1463 1465
		/**
1464 1466
		* Sets the battery level for this BatteryIcon. The level should be given in raw form, i.e. 0-255 directly
......
1466 1468
		*
1467 1469
		* @param newLevel the new battery reading from the robot that this BatteryIcon will display.
1468 1470
		*/
1469
	    public void setLevel(int newLevel) {
1470
	    	level = convert(newLevel);
1471
	    	repaint();
1472
	    	System.out.println("Updated level to " + level);
1473
	    }
1471
			public void setLevel(int newLevel) {
1472
				level = convert(newLevel);
1473
				repaint();
1474
				System.out.println("Updated level to " + level);
1475
			}
1474 1476

  
1475
	    public int getIconWidth() {
1476
	        return width;
1477
	    }
1477
			public int getIconWidth() {
1478
					return width;
1479
			}
1478 1480

  
1479
	    public int getIconHeight() {
1480
	        return height;
1481
	    }
1481
			public int getIconHeight() {
1482
					return height;
1483
			}
1482 1484

  
1483 1485
		/**
1484 1486
		* Converts a robot battery reading into representable form.
trunk/code/projects/colonet/client/ColonetServerInterface.java
27 27
*/
28 28
public class ColonetServerInterface
29 29
{
30
	/* STATIC FIELDS
31
	 * Eugene Marinelli, Fan
32
	 * 10/27/06
33
	 *
34
	 * Colonet Definitions - common definitions and structs used in all colonet
35
	 * applications
30
/*	Old packet structure:
36 31

  
37
	Old packet structure:
38

  
39 32
    COMMAND PACKET STRUCTURE
40 33
	1:  SEND_TO_ROBOT
41 34
	2:  # of robot, or GLOBAL_DEST
......
107 100
	public static final String ORB_SET_NUM = "21"; //0x15
108 101
	public static final String ORB_SEND = "22"; //0x16
109 102

  
110

  
111 103
	Colonet colonet;  //save reference to the entire applet locally
112 104
	Socket socket;
113 105
	OutputStreamWriter out;
......
115 107
	DataListener dataListener;
116 108
	JTextArea log, txtMatrix;
117 109

  
118

  
119 110
	/*
120 111
	*	FUNCTION IMPLEMENTATIONS
121 112
	*/
......
125 116
	* reference must be provided to ensure that data is routed correctly.
126 117
	*
127 118
	* @param colonet The Colonet object to save locally. This reference cannot be changed once the
128
	*		ColonetSreverInterface has been contsructed.
119
	*   ColonetSreverInterface has been contsructed.
129 120
	* @throws NullPointerException if colonet is null
130 121
	*
131 122
	*/

Also available in: Unified diff