Package lejos.pc.comm

Source Code of lejos.pc.comm.MCLFrame

package lejos.pc.comm;

import javax.swing.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.*;
import java.io.*;

import lejos.robotics.Pose;
import lejos.robotics.RangeReadings;
import lejos.robotics.localization.*;
import lejos.geom.*;
import lejos.robotics.mapping.*;

/**
* A panel that can be opened in a frame to control a robot
* that implements the MCL algorithm. The panel displays the particles and
* has buttons to move the robot and take readings.
*
* The line map, size and color of the frame is supplied by classes
* that extend this class.
*
* @author Lawrie Griffiths
*
*/
public class MCLFrame extends RemoteFrame{
  private static final long serialVersionUID = 1L;
  public static final float PIXELS_PER_CM = 2f;
  public static final float X_OFFSET = 66f;
  public static final float Y_OFFSET = 56f;
  private static final float ARROW_LENGTH = 10f;

  // Commands sent to the NXT
  private static final byte GET_PARTICLES = 0;
  private static final byte READINGS = 1;
  private static final byte RANDOM_MOVE = 2;
  private static final byte STOP = 3;
  private static final byte FIND_CLOSEST = 4;
 
  // The maximum size of a cluster of particles for a located robot (in cm)
  private static final int MAX_CLUSTER_SIZE = 25;

  // Array of lines for the map
  private Line[] lines;
  private LineMap map; // the map
  private MCLParticleSet particles; // the particle set
  private RangeReadings readings;  
  private int closest = -1;
  private int numParticles;
 
  // GUI Buttons
  private JButton readingsButton, moveButton, stopButton;
 
  /**
   * Paint the map and particles
   */
  public void paintComponent(Graphics g) {
    clear(g);
    Graphics2D g2d = (Graphics2D) g;
    paintMap(g2d);
    paintParticles(g2d);
    paintLocation(g2d);
  }
 
  /**
   * Paint the particles
   * @param g2d the Graphics2D object
   */
  private void paintParticles(Graphics2D g2d) {
    g2d.setColor(Color.red);
    for (int i = 0; i < numParticles; i++) {
      MCLParticle part = particles.getParticle(i);
      if (part != null) {
        if (i == closest) g2d.setColor(Color.green);
        paintPose(g2d, new Pose(part.getPose().getX(), part.getPose().getY(), part.getPose().getHeading()));
        g2d.setColor(Color.red);
      }
    }   
  }

  /**
   * Draw the map using Line2D objects
   *
   * @param g2d the Graphics2D object
   */
  private void paintMap(Graphics2D g2d) {
  g2d.setColor(Color.black);
    for (int i = 0; i < lines.length; i++) {
      Line2D line = new Line2D.Float(X_OFFSET + lines[i].x1 * PIXELS_PER_CM, Y_OFFSET + lines[i].y1 * PIXELS_PER_CM,
          X_OFFSET + lines[i].x2 * PIXELS_PER_CM, Y_OFFSET + lines[i].y2 * PIXELS_PER_CM);
      g2d.draw(line);
    }
  }

  /**
   * Paint the pose using Ellipse2D
   *
   * @param g2d the Graphics2D object
   */
  private void paintPose(Graphics2D g2d, Pose pose) {
    Ellipse2D c = new Ellipse2D.Float(X_OFFSET + pose.getX() * PIXELS_PER_CM - 1, Y_OFFSET + pose.getY() * PIXELS_PER_CM - 1, 2, 2);
    Line rl = getArrowLine(pose);
    Line2D l2d = new Line2D.Float(rl.x1, rl.y1, rl.x2, rl.y2);
    g2d.draw(l2d);
    g2d.draw(c);
  }
 
  /**
   * If we are down to one small cluster show the
   * location of the robot.
   *
   * @param g2d the Graphics2D object
   */
  private void paintLocation(Graphics2D g2d) {
    float minX = particles.getMinX();
    float maxX = particles.getMaxX();
    float minY = particles.getMinY();
    float maxY = particles.getMaxY();
    Pose estimatedPose = particles.getEstimatedPose();
    if (maxX - minX > 0 && maxX - minX <= MAX_CLUSTER_SIZE &&
        maxY - minY > 0 && maxY - minY <= MAX_CLUSTER_SIZE) {
        Ellipse2D c = new Ellipse2D.Float(X_OFFSET + minX * PIXELS_PER_CM, Y_OFFSET + minY * PIXELS_PER_CM, (maxX - minX* PIXELS_PER_CM, (maxY - minY* PIXELS_PER_CM);
        g2d.setColor(Color.blue);
        g2d.draw(c);
        paintPose(g2d,estimatedPose);
    }
  }

  /**
   * Create a Line that represents the direction of the pose
   *
   * @param pose the pose
   * @return the arrow line
   */
  private Line getArrowLine(Pose pose) {
    return new Line(X_OFFSET + pose.getX() * PIXELS_PER_CM,
                Y_OFFSET + pose.getY() * PIXELS_PER_CM,
                X_OFFSET + pose.getX() * PIXELS_PER_CM + ARROW_LENGTH * (float) Math.cos(Math.toRadians(pose.getHeading())),
                Y_OFFSET + pose.getY() * PIXELS_PER_CM + ARROW_LENGTH * (float) Math.sin(Math.toRadians(pose.getHeading())));
  }

  /**
   * Create the GUI elements the map and the particle set, connect to the
   * NXT and then process button events.
   */
  public MCLFrame(String nxt, Line[] lines, Rectangle bound, int numParticles, int numReadings) throws IOException {
  // Connect to the NXT
  super(nxt);
  this.lines = lines;
    // Create a map of the environment
    map = new LineMap(lines, bound);
    this.numParticles = numParticles;
    particles = new MCLParticleSet(map,numParticles, 10);

    // Create some buttons
    readingsButton = createButton("Readings");
    moveButton = createButton("Move");
    stopButton = createButton("Stop");
   
    //Send Map
    map.dumpMap(dos);
   
    // Send the number of particles 
    dos.writeInt(numParticles);
    dos.flush();

    // Retrieve the particles
    getParticles();
   
    readings = new RangeReadings(numReadings);
  }

  /**
   * Process buttons
   */
  public void actionPerformed(ActionEvent e) {
  try {
      // Readings button; take readings and calculate weights
      if (e.getSource() == readingsButton) {
        sendCommand(READINGS);
        // Get range readings
        readings.loadReadings(dis);
        readings.printReadings();
        System.out.println("Max weight = " + dis.readFloat());
        getParticles();
        repaint();
      }
 
      // Move Button: apply a random move
      if (e.getSource() == moveButton) {
        sendCommand(RANDOM_MOVE);
        getParticles();     
        repaint();
      }
 
      // Stop Button: shut down
      if (e.getSource() == stopButton) {
        close();
      }
    } catch (IOException ioe) {
        error("IOException");
   
  }
 
  /**
   * Find the particle closest to the specified coordinates
   *
   * @param x the x coordinate
   * @param y the y coordinate
   * @return the index of the particle
   *
   */
  private int findClosest(int x, int y) {
    sendCommand(FIND_CLOSEST);
    try {
      dos.writeFloat((float) x);
      dos.writeFloat((float) y);
      dos.flush();
      int closest = dis.readInt();
      for(int i=0;i<3;i++) {
      float reading = dis.readFloat();
        System.out.println("Reading " + i + " = " + (reading < 0 ? "Invalid" : reading));
      }
      System.out.println("Weight = " + dis.readFloat());
      return closest;
    } catch (IOException ioe) {
      error("IOException");
      return -1;
    }
  }
 
  /**
   * Get current state of the particles from the NXT.
   */
  private void getParticles() throws IOException {
    sendCommand(GET_PARTICLES);
    particles.loadParticles(dis);
    particles.loadEstimation(dis);
  }
 
  /**
   * Send a command to the NXT
   */
  private void sendCommand(byte command) {
    try {
      dos.writeByte(command);
      dos.flush();
    } catch (IOException ioe) {
      error("IO Exception");
    }
  }

  /**
   * Close down the program and the NXT
   */
  private void close() {
    try {
      dos.writeByte(STOP);
      dos.flush();
      Thread.sleep(1000);
      System.exit(0);
    } catch (Exception ioe) {
      error("IO Exception");
    }
  }

  /**
   * Find the closest particle to the mouse click
   */
  public void mouseClicked(MouseEvent me) {
    int x = (int) ((me.getX()- X_OFFSET) /PIXELS_PER_CM );
    int y = (int) ((me.getY() - Y_OFFSET) / PIXELS_PER_CM);
    System.out.println("X = " + x + ", Y = " + y);
    closest = findClosest(x,y);
    repaint();
  }
}

TOP

Related Classes of lejos.pc.comm.MCLFrame

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.