Uploading Map Data
The RCX brick is great for collecting real-world data, but it is not so good at displaying and analyzing that data. A PC is the best platform for this, so it's useful to be able to send data results back to the PC. For data transmission to take place there must be a program running on the RCX and a separate program running on the PC (Figure 115).
The following project creates a robot that will map the coordinates of objects it bumps into. The strategy of the robot is to store the coordinates in two arrays; one for x values and one for y values. Once it has encountered 10 objects the robot's movement should be stopped by pressing the Run button,
Figure 115 Basic communication with an RCX brick.
then the robot should be placed in front of the IR tower. When the PC side program is up and running, the user can press the View button to begin transmission. Once all data has been uploaded, the PC displays a simple approximation of the robot's trail.
NOTE
Theoretically this code will work on any robot using the Navigation interface (Trilobot, Tippy Senior, or Mozer). However, this code uses a total of 47 classes (displayed using verbose option of lejos.exe), which pushes the RCX to the limit. I was only able to use TimingNavigator without running out of memory.
1. import josx.platform.rcx.*; 2. import josx.platform.rcx.comm.*; 3. import josx.robotics.*; 4. import java.io.*; 5. 6. class DataSender implements SensorListener { 7. 8. Navigator robot; 9. static final byte ARRAY_SIZE = 10; 10. public short [] xCoords; 11. public short [] yCoords; 12. byte count = 0; 13. 14. public DataSender(Navigator robot) { 15. this.robot = robot; 16. 17. xCoords = new short [ARRAY_SIZE]; 18. yCoords = new short [ARRAY_SIZE]; 19. 20. Sensor.S2.addSensorListener(this); 21. } 22. 23. public static void main(String [] args) throws IOException { 24. TimingNavigator robot = new TimingNavigator(Motor.C, Motor.A, 4.475f, 1.61f); 25. robot.forward(); 26. 27. DataSender ds = new DataSender(robot); 28. try{ 29. Button.RUN.waitForPressAndRelease(); 30. robot.stop(); 31. Button.VIEW.waitForPressAndRelease(); 32. }catch(InterruptedException ie){} 33. 34. // Send data: 35. RCXDataPort port = new RCXDataPort(); 36. DataOutputStream out = new DataOutput- Stream(port.getOutputStream()); 37. out.writeShort(0); 38. out.writeShort(0); 39. for(byte i=0;i<ARRAY_SIZE;++i) { 40. out.writeShort(ds.xCoords[i]); 41. out.writeShort(ds.yCoords[i]); 42. } 43. out.flush(); 44. } 45. 46. /** Records the x, y position when bumper hits an object.*/ 47. public void stateChanged(Sensor bumper, int oldVal, intnewVal) { 48. if(bumper.readBooleanValue() == true) { 49. robot.stop(); 50. if(count < ARRAY_SIZE) { 51. xCoords[count] = (short)robot.getX(); 52. yCoords[count] = (short)robot.getY(); 53. ++count; 54. } 55. robot.travel(-20); 56. robot.rotate((float)(Math.random() * 180)); 57. robot.forward(); 58. } 59. } 60 }
This code creates a Navigator object called robot and starts moving forward. A listener is added to the bumper sensor, so every time the robot comes into contact with an object it can react accordingly (Lines 4961). The reaction of the robot is simply to record the coordinates of the collision, back up, and turn a random amount. The main() method contains the code to initialize the object, wait for the user to press the Run button, and wait for the user to press the View button. When the View button is pressed, it sends the data back to the PC.
Now that the robot code is complete we need some code on the PC side to receive the data and display it on the monitor. The code to do this is quite Chapter 11 RCX Communications brief considering it uses the Java Abstract Window Toolkit (AWT). To make things simple, this code begins waiting for input from the IR tower in the constructor. Once the data has been received it displays it in a window (Figure 116).
1. import java.io.*; 2. import pc.irtower.comm.*; 3. import java.awt.*; 4. import java.awt.event.*; 5. 6. public class MapData extends Canvas{ 7. int ARRAY_SIZE = 10; 8. short [] xCoords; 9. short [] yCoords; 10. 11. public MapData() { 12. xCoords = new short[ARRAY_SIZE]; 13. yCoords = new short[ARRAY_SIZE]; 14. PCDataPort port = null; 15. try { 16. port = new PCDataPort("COM2"); 17. DataInputStream in = new DataInputStream(port.getInputStream()); 18. for(int i=0;i<ARRAY_SIZE;++i) { 19. xCoords[i] = in.readShort(); 20. System.out.println("x = " + xCoords[i]); 21. yCoords[i] = in.readShort(); 22. System.out.println("y = " + yCoords[i]); 23. } 24. } catch(IOException ioe) { 25. ioe.printStackTrace(); 26. } 27. } 28. 29. public static void main(String [] args) { 30. 31. Frame mainFrame = new Frame("Explorer Command Center"); 32. mainFrame.addWindowListener(new WindowAdapter() { 33. public void windowClosing(WindowEvent e) { 34. System.exit(0); 35. } 36. }); 37. mainFrame.setSize(400, 300); 38. mainFrame.add(new MapData()); 39. mainFrame.setVisible(true); 40. } 41. 42. public void paint(Graphics g) { 43. int height = this.getSize().height; 44. int width = this.getSize().width; 45. g.setColor(Color.orange); 46. g.drawLine(width/2,0,width/2, height); 47. g.drawLine(0,height/2, width, height/2); 48. g.setColor(Color.black); 49. for(int i=0;i<ARRAY_SIZE-1;++i) { 50. g.drawLine(xCoords[i] + width/2, yCoords[i] + height/2, 51. xCoords[i+1] + width/2, yCoords[i + 1]+height/2); 52. } 53. } 54. }
NOTE
Line 16 must specify the port to contact your IR tower (e.g., COM1 or USB).
Figure 11-6 PC display of map data
Most of the code is devoted to AWT display, but the interesting code for receiving data is found between Lines 15 and 28.>
To test this project out I used Tippy Senior (Chapter 8, "Navigation with Rotation Sensors"). First, let the robot wander around until it has hit at least 10 objects. Once this is done press the Run button to stop the motors and place the robot in front of the IR tower. Execute the PC program and the green light on the IR tower will turn on, indicating you can press View to start sending data. Once all the data has been uploaded it displays a map similar to Figure 116.