Package

Source Code of Homer

import java.awt.Rectangle;
import java.io.PrintStream;
import java.util.Collection;
import lejos.geom.Line;
import lejos.nxt.Button;
import lejos.nxt.Motor;
import lejos.nxt.SensorPort;
import lejos.nxt.UltrasonicSensor;
import lejos.nxt.comm.RConsole;
import lejos.robotics.Pose;
import lejos.robotics.RangeReadings;
import lejos.robotics.RangeScanner;
import lejos.robotics.localization.MCLParticleSet;
import lejos.robotics.mapping.LineMap;
import lejos.robotics.mapping.RangeMap;
import lejos.robotics.proposal.ArcPoseController;
import lejos.robotics.proposal.DestinationUnreachableException;
import lejos.robotics.proposal.DifferentialPilot;
import lejos.robotics.localization.MCLPoseProvider;
import lejos.robotics.proposal.MapPathFinder;
import lejos.robotics.proposal.PathFinder;
import lejos.robotics.proposal.PoseController;
import lejos.robotics.proposal.WayPoint;

/**
* Test of Monte Carlo Localisation, Pose Controllers and Path finders.
*
* The robot is put down in a random position in the mapped area.
* It makes random moves until if works out where it is.
* It then uses a path finder to find a route home.
* A pose controller is used to follow the route.
*
* The robot is an robot that is supported by the DifferentialPilot class.
* A range scanner located above the robot's center of rotation is required.
*
* @author Lawrie Griffiths
*
*/
public class Homer implements RangeScanner {
  // Tyre diameter and wheel base
  private static final float TYRE_DIAMETER = 5.6f;
  private static final float WHEEL_BASE = 16.0f;

  private static int BORDER = 10;
  private static int NUM_PARTICLES = 200;
  private static int MAX_RELIABLE_RANGE_READING = 150;
  private static float RANGE_READING_ANGLE = 45;
  private static int FORWARD_READING = 1;
  private static int MAX_DISTANCE = 40;
 
  // Distance from ultrasonic sensor to front of robot in cm
  private static final float PROJECTION = 10.0f;
 
  private static UltrasonicSensor range = new UltrasonicSensor(SensorPort.S1);
  private static RangeReadings readings = new RangeReadings(3);
 
  // Array of lines for the map
  private static final Line[] lines = {
        new Line(32, 0, 32, 88), new Line(32, 88, 0, 88),
        new Line(0, 88, 0, 340), new Line(0, 340, 95, 340),
        new Line(95, 340, 95, 294), new Line(95, 294, 132, 294),
        new Line(132, 294, 132, 0), new Line(132, 0, 32, 0)};
 
  private static final Rectangle bound = new Rectangle(0,0,132,340);
  private static RangeMap map = new LineMap(lines, bound);
  private static DifferentialPilot pilot;
  private static MCLParticleSet particles;
  private static MCLPoseProvider mcl;
 
  public static void main(String[] args) {
    Homer simpson = new Homer();
    simpson.run();
  }
 
  public void run() { 
    //RConsole.openBluetooth(0);
    //System.setOut(new PrintStream(RConsole.openOutputStream()));
   
    // Create the robot and MCL pose provider and get its particle set
    pilot = new DifferentialPilot(
        TYRE_DIAMETER, WHEEL_BASE, Motor.B, Motor.C, true);
    mcl = new MCLPoseProvider(pilot,this, map, NUM_PARTICLES, BORDER);
    particles = mcl.getParticles();
    particles.setDebug(true);
   
    // Make random moves until we know where we are
    Pose start = localize();
 
    // Find a route home
    Pose home = new Pose(50, 300, -90);
    PathFinder pf = new MapPathFinder(map, readings);
    PoseController pc = new  ArcPoseController(pilot, mcl);
   
    System.out.println("Located: (" + (int) start.getX() + "," + (int) start.getY() + ")");
   
    // Go home
    try {
      Collection<WayPoint> route = pf.findRoute(start, home);
     
      for(WayPoint wp: route) {
        System.out.println("Go to (" + (int) wp.x + "," + (int) wp.y + ")");
        Pose pose = pc.goTo(wp);
        goodEstimate(pose); // Just for diagnostics
        // Pose controller should have a goTo(Pose) method to do this
        pilot.rotate(wp.getHeading() - pose.getHeading());
      }
    } catch (DestinationUnreachableException e) {
      System.out.println("Unreachable");
    }
    Button.waitForPress();
  }

  @Override
  public RangeReadings getRangeValues() {
    takeReadings();
    return readings;
  }
 
  /**
   * Take a single range reading
   *
   */
  private void takeReading(float angle, int i) {
    int rangeByte = (int) range.getRange();
    float range;

    if (rangeByte > MAX_RELIABLE_RANGE_READING) range = -1f;
    else range = ((float) rangeByte);
    readings.setRange(i,angle, range);
  }
 
  /**
   * Take a set of 3 readings
   */
  public void takeReadings() {
    // Take forward reading
    takeReading(0f, FORWARD_READING);

    // Take left reading
    pilot.rotate(-RANGE_READING_ANGLE);
    takeReading(-RANGE_READING_ANGLE, 0);

    // Take right reading
    pilot.rotate(2 * RANGE_READING_ANGLE);
    takeReading(RANGE_READING_ANGLE, 2);
    pilot.rotate(-RANGE_READING_ANGLE);
  }
 
  /**
   * Make a random move
   */
  public void randomMove() {
    float angle = (float) Math.random() * 360;
    float distance = (float) Math.random() * MAX_DISTANCE;
   
    if (angle > 180f) angle -= 360f;

    // Get forward range
    float forwardRange = readings.getRange(1);

    // Don't move forward if we are near a wall
    if (forwardRange < 0
        || distance + BORDER + PROJECTION < forwardRange)
      pilot.travel(distance);
   
    pilot.rotate(angle);
  }
 
  /**
   * Check if estimated pose is accurate enough
   */
  boolean goodEstimate(Pose pose) {
    int width = particles.getErrorRect().width;
    int height = particles.getErrorRect().height;
    System.out.println("At " + (int) pose.getX() + "," + (intpose.getY() + " Error: " + width + "," + height + " Weight: " + particles.getMaxWeight());
    return width < 50 && height < 50;
  }
 
  /**
   * Make random moves until the estimated pose is good enough
   */
  private Pose localize() {
    for(;;) {
      Pose pose = mcl.getPose();
      if (goodEstimate(pose)) return pose;
      else randomMove();
    }
  }
}

TOP

Related Classes of Homer

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.