The limited sweep

In this iteration of the Controller class, we attempt to resolve two issues, namely limiting the sweep to a specified maximum angle and keeping the robot from deviating from a straight-line segment.

Code changes (Controller.java)

This solution involves modifications to sweepClockwise() as a prototype. I will only present the parts of the code that have changed since the last iteration. The first change we made is to introduce two new members (variables) in the class:

   private final static float DELAYS_PER_DEG = 100.0f / 180;
   private final static int SMALL_ROT = 10;

The first variable DELAYS_PER_DEG encapsulates our empirical knowledge that 100 delays roughly corresponds to 180 degrees of rotation (this number may be different for your robot, the previous section discusses how to determine it empirically). We use this information to calculate the fractional amount of delays that correspond to 1 degree of rotation by using simple division. The f at the end of 100.0f tells Java that it is to be treated as a float and not double, that is, it is to be stored using the smaller data type since the correspondence between 100 and 180 isn't exact to begin with.

The second variable simply declares a small rotation to be equal to 10 degrees. Both variables are defined as final since they are meant to be constant and not changed at any point by the program.

The sweepClockwise() method is modified to give it the ability to limit the rotation. By limiting the rotation, we will specify the maximum allowed angle of rotation. Also, if the path is not detected before that limit, the rotation will be stopped. The method will return false to indicate this eventuality. The code is as follows:

private boolean sweepClockwise(int rot_limit)
    {
        log("Sweeping clockwise. Limit: " + rot_limit + " degrees.");

        drive.rotateClockwise();

        for (int i = 0; i < (rot_limit * DELAYS_PER_DEG); i++)
        {
            delay();

            if (sensor.onPath())
            {
                log("Path Detected");

                drive.stop();

                return true;
            }
        }

        log("Path not detected. Rotation limit exceeded.");

        drive.stop();

        return false;
    }

The first change we made to the sweepClockwise() function was the addition of an argument to the function body, rot_limit. This value is passed in when we call the function and specifies the limit for the current rotation in degrees. We set it up this way because it will allow us to specify different limits under different conditions.

The drive.rotateClockwise() command is unchanged and simply starts the clockwise rotation. We then replaced the indefinite while loop with a for loop:

   for (int i = 0; i < (rot_limit * DELAYS_PER_DEG); i++)

The for loop is used where we want the loop to iterate a specified number of times. The loop variable is the integer i, which is set to start at 0, increment by 1 on each loop (i++), and stop when its value equals or exceeds rot_limit * DELAYS_PER_DEG. By multiplying rot_limit = 10 with DELAYS_PER_DEG = 100.0f / 180, we get the number of delays that correspond to 10 degrees of rotation. So, the for loop will iterate for as many delays as are required for the rotation limit to be achieved. In this way, the rotation is automatically limited.

Inside the for loop, we have a delay() method to pause the execution and a test to see whether the path has been detected or not:

      delay();

      if (sensor.onPath())
             {
                 log("Path Detected");

                 drive.stop();

                 return true;
             }

The if statement is used to check whether the sensor has detected the path. If it evaluates to true, we stop the rotation and return true to indicate that the path has been found. A return statement anywhere inside the body of a function immediately exits the function without executing any more lines of code inside it.

If the path is not found in the time it takes for the for loop to count up to the maximum value, the for loop will terminate normally and execution will move on to the next lines of code:

      drive.stop();

              return false;

The limit has been reached, so we stop the rotation. However, this time we return false because we failed to find the path. The returned value of false indicates to the calling method that the sweep has failed.

The seek() method is slightly modified to make use of the new sweepClockwise() method:

    private boolean seek()
    {
        log("Seeking Path.");

        return sweepClockwise(SMALL_ROT);
    }

The only change is that when sweepClockwise() is called, we pass in the rotation limit that we set to be the SMALL_ROT variable we defined earlier.

Finally, we modify the run() method slightly to make use of the new seek() method. We simply remove the second (and last) move() method call from it. So, the body of the run() method now consists of the following:

   move();
   seek();
   end();

Testing

When we execute this code on EV3, the move() method call will make it move in a straight line until it moves off of the path. This triggers the seek() method, which performs a limited clockwise sweep up to 10 degrees. If the path is reacquired within 10 degrees, the robot will stop rotating immediately. Otherwise, it will sweep through the 10 degrees and come to a halt.

The success of this test will validate this implementation and its ability to limit the rotation of the robot. The 10 degree small rotation is meant to be used in the scenario where the robot may have left the straight-line segment before the segment ends, by drifting out of the edge due to alignment issues or slight imperfections in the path or surface. We will consider this possibility in more detail in coming sections.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.214.32