Programming the differential drive

With the LeJOS project set up and tested, it is now time to implement the software that controls the differential drive. This is where the modular approach to programming comes in. From an implementation standpoint, the differential drive is simply one part of the robot, the part that controls its motion.

We already know that we require only four controls in our drive: forward, stop, rotate clockwise, and rotate counterclockwise. These four types of motion are achieved by controlling the two motors, left and right. With this in mind, we write a separate DifferenentialDrive class (in a separate Java file src/DifferentialDrive.java) that has four methods corresponding to the four types of motion. Each method when called sends the appropriate commands to the two motors that constitute the drive, to perform the required motion.

The differential drive code

I will present the src/DifferentialDrive.java file in full before explaining it in detail:

import lejos.hardware.motor.EV3LargeRegulatedMotor;
import lejos.hardware.port.Port;

public class DifferentialDrive
{
    private EV3LargeRegulatedMotor mLeftMotor;
    private EV3LargeRegulatedMotor mRightMotor;

    private final static int SPEED = 200;

    public DifferentialDrive(Port left_port, Port right_port)
    {
        mLeftMotor = new EV3LargeRegulatedMotor(left_port);
        mRightMotor = new EV3LargeRegulatedMotor(right_port);

        mLeftMotor.setSpeed(SPEED);
        mRightMotor.setSpeed(SPEED);
    }

    public void forward()
    {
        mLeftMotor.forward();
        mRightMotor.forward();
    }

    public void stop()
    {
        mLeftMotor.stop();
        mRightMotor.stop();
    }

    public void rotateClockwise()
    {
        mLeftMotor.forward();
        mRightMotor.backward();
    }

    public void rotateCounterClockwise()
    {
        mLeftMotor.backward();
        mRightMotor.forward();
    }
}

As always, the Java class starts with the import statements to pull in objects required by the code that will follow. We import the hardware Port and EV3LargeRegulatedMotor objects that we will use to gain access to the two motors:

import lejos.hardware.motor.EV3LargeRegulatedMotor;
import lejos.hardware.port.Port;

The next step is to define the class and its members (variables):

public class DifferentialDrive
{
    private EV3LargeRegulatedMotor mLeftMotor;
    private EV3LargeRegulatedMotor mRightMotor;

    private final static int SPEED = 200;

The first line names the DifferentialDrive class. When we need to control the robot's differential drive, we will create an object of this class and then issue commands to it. The next two lines define members of the DifferentialDrive class, variables that are associated with any object of this class. These members are of the type EV3LargeRegulatedMotor and will store handlers to the right and left Large Motors. We will use them to control each motor.

The third (nonempty, nonsimple) line declares a final static variable SPEED and sets is value to 200 (a pretty slow speed, arrived at empirically, which will allow the robot to analyze its environment and react in plenty of time—the faster the robot, the more it will deviate from the line whenever it encounters a turn). The final declaration means that this variable's value cannot be changed afterwards.

Constructors

The first method declared in the class is the constructor. It is called when an object of this class is created, and it is used to carry out the initialization of the object. In the case of the DifferentialDrive class, this consists of gaining access to the left and right Large Motors:

   public DifferentialDrive(Port left_port, Port right_port)
    {
        mLeftMotor = new EV3LargeRegulatedMotor(left_port);
        mRightMotor = new EV3LargeRegulatedMotor(right_port);

        mLeftMotor.setSpeed(SPEED);
        mRightMotor.setSpeed(SPEED);
    }

The arguments required by the constructor are two Port values, where we specify which ports the left and right motors are attached to, as follows:

    public DifferentialDrive(Port left_port, Port right_port)

The values that are passed are determined by how you constructed the Line-follower robot, in particular, which ports you connected the motors to using cables.

The constructor uses this information to create two EV3LargeRegulatedMotor objects with the ports specified. These are stored in the mLeftMotor and mRightMotor members/variables, which we defined earlier:

    mLeftMotor = new EV3LargeRegulatedMotor(left_port);
    mRightMotor = new EV3LargeRegulatedMotor(right_port);

Storing them as members allows other methods/functions of the class to access them. This is the essence of object-oriented programming; a class is a collection of members (variables) and methods (functions) that have access to the data stored in the members.

The final initialization step is to set the speed of both the motors to the final value that was defined earlier and stored in the variable SPEED:

    mLeftMotor.setSpeed(SPEED);
    mRightMotor.setSpeed(SPEED);

The constructor, therefore, creates objects to control the left and right Large Motors and sets their speed. The DifferentialDrive object is now ready to receive commands and, in turn, translate them into commands for the Large Motors.

Commands

As specified in the scenario we discussed for the Line-follower robot, the differential drive only needs to carry out four types of motion: forward, stop, rotate clockwise, and rotate counterclockwise. These are the commands that are expected and accepted by the differential drive, and it is only natural to implement them as methods in the class. Once the DifferentialDrive object has been created (instantiated using the constructor), we can call these methods to carry out these motion commands.

Forward

The forward command is implemented as the forward() method:

   public void forward()
   {
      mLeftMotor.forward();
      mRightMotor.forward();
   }

To make a differential drive move forward in a straight line, both the motors must rotate in the forward direction. This simple insight is translated into two lines of code, which simply instruct the left and right Large Motors to start rotating in the forward direction. The speed has already been specified in the constructor. Note how we issue commands to the motors by using the EV3LargeRegulatedMotor objects that we created in the constructor and stored in the mLeftMotor and mRightMotor members.

Stop

The stop() method is pretty self-explanatory. To stop the differential drive, one must simply order both motors to come to a stop:

   public void stop()
    {
        mLeftMotor.stop();
        mRightMotor.stop();
    }

Rotate clockwise

The direction of rotation is observed by looking at the robot from above. Therefore, clockwise rotation corresponds to the robot turning towards the right. Since we want the robot to pivot in its place, this is achieved by rotating the left motor forward and the right motor in reverse. This is exactly what the rotateClockwise() method does:

   public void rotateClockwise()
    {
        mLeftMotor.forward();
        mRightMotor.backward();
    }

Rotate counterclockwise

Counterclockwise rotation is achieved by doing the exact opposite of the rotateClockwise() method:

   public void rotateCounterClockwise()
    {
        mLeftMotor.backward();
        mRightMotor.forward();
    }
..................Content has been hidden....................

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