Skip to content

Drive Train Control

Jeffrey Shen edited this page Nov 14, 2017 · 9 revisions

This functionality requires the use of the Sensor struct and the PID Struct.

This library provides functionality to control the movement of the drive train (say, move it forward by 2 inches), and also contains a field positioning system (say, to access the current position of the robot on the field).

Setup

In config.c:

#define USE_MOVE 1

Next, initialize all relevant values (in pre-autonomous, usually):

initializeDrive(float d2r, sensor* leftS, sensor* rightS, sensor* gyroS)

leftS is a pointer to the sensor on the left side of the drive train, rightS is for the right side, and gyroS is for the robot's gyroscope. The scaling factor for leftS and rightS must convert ticks to 0.1 inches, and the scaling factor for gyroS must convert ticks to 0.1 degrees.

[insert explanation on d2r].

Finally, in config.c, create the method void move(int V, int H, int X). This method should move the drive train based on V (forwards/backwards voltage), H (rotational voltage), and X (strafing voltage).

For example:

void move(int V, int H, int X){
  motorReq[M_WHEEL_L1] = BOUND(V + H, -127, 127);
  motorReq[M_WHEEL_L2] = BOUND(V + H, -127, 127);
  motorReq[M_WHEEL_R1] = BOUND(V - H, -127, 127);
  motorReq[M_WHEEL_R2] = BOUND(V - H, -127, 127);
}

Usage

Movement Control

This library has been built to provide as much flexibility as possible when moving. So, to do a move (say, rotate 90 degrees), you need to:

  1. Refresh the wheels
  2. Start a movement function
  3. Start a tracking function
  4. End the movement

This will all make sense in a second! Just read the examples below, and the explanation of why the code was structured this way.

The movement functions:

  • void moveStop(): Halts the drive train.
  • void moveVertical(int vol): Moves vertically at the specified voltage.
  • void moveFwd(): Moves forward at full speed.
  • void moveBkwd(): Moves backward at full speed.
  • void rotate(int vol): Rotates at voltage vol (positive is clockwise).
  • void strafe(int vol): Strafes at voltage vol.
  • void moveCurve(int level): Moves the robot in a curved motion based on the level. Level can be a number from -10 to 10, inclusive. A positive level curves the robot right, and a negative level curves the robot left. The larger the level's magnitude, the more it curves.
  • void moveCurveBkwd(int level): Moves the robot in a backwards curved motion. Level can be a number from -10 to 10, inclusive. A positive level curves the robot left, and a negative level curves the robot right. The larger the level's magnitude, the more it curves.
  • Of course, you can also use void move(int V, int H, int X) or any other thing that moves the wheels.

The tracking functions:

  • void moveBy(int dist, int tlimit): dist is in 0.1 inches and tlimit is in milliseconds. Holds the robot in a loop until the robot has moved a vertical distance of dist, or tlimit milliseconds have passed.
  • void strafeBy(int dist, int tlimit): dist is in 0.1 inches and tlimit is in milliseconds. Holds the robot in a loop until the robot has moved a lateral distance of dist, or tlimit milliseconds have passed.
  • void rotateBy(int ang, int tlimit): ang is in 0.1 degrees and tlimit is in milliseconds. Holds the robot in a loop until the robot has rotated ang degrees, or tlimit milliseconds have passed.

Examples:

//A simple move (move 20 inches forward)
MOVE_MONITOR = START;
refreshDrive(); //Refresh
moveFwd(); //Movement Function
moveBy(200, 5000); //Tracker Function
moveStop(); //End the movement 
MOVE_MONITOR = STOP;

Moves can be chained together:

//Move forward by 10 inches, then rotate 90 degrees clockwise:
MOVE_MONITOR = START;
refreshDrive(); //Refresh
moveFwd(); //Movement Function
moveBy(100, 5000); //Tracker Function
//Movement doesn't always need to be ended by a stop

refreshDrive(); //Refresh before each move
rotate(127);  //Movement Function
rotateBy(900, 5000); //Tracker Function
moveStop(); //End the movement
MOVE_MONITOR = STOP;

Why this way?
The system was designed in this way to be asynchronous and flexible. You can do any type of movement you desire (even non-linear movement like moveCurve()), and still have it be tracked using our tracker functions. Moreover, the system is asynchronous because it allows you to perform actions while moving at the same time. For example:

MOVE_MONITOR = START;
refreshDrive(); 
moveFwd();

//LIFT YOUR ROBOT'S LIFT UP
 
moveBy(200, 5000); 
moveStop();
MOVE_MONITOR = STOP;

In this example, the robot will still move 20 inches, but it will also starting lifting the robot's lift up. In autonomous, this saves tons of time.

Advanced Movements

The functions illustrated above do not provide any braking logic. Thus, they are fine for less precise movements, but will not be accurate for moving small distances, or moving precise amounts. The following functions are used in the same way as above, except they use a PID control for accurate movement:

  • void moveByPID(int dist, int dir, int tlimit)
  • void strafe(int dist, int dir, int tlimit)
  • void rotate(int ang, int dir, int tlimit)

In order for these functions to work, each base sensor must be initialized with a PID struct. Notice how each function has an extra parameter dir. This just specifies the direction the robot is moving in. So, if the robot is moving forward, moveByPID should be called with a dir of 1. If it is moving backwards, dir should be -1. Then, use them in the same way:

//A simple ACCURATE move (move 20 inches forward)
MOVE_MONITOR = START;
refreshDrive(); //Refresh
moveFwd(); //Movement Function
moveByPID(200, 1, 5000); //Tracker Function 
MOVE_MONITOR = STOP;

Notice how there is no longer moveStop(). This is because PID functions automatically stop after they are completed.

Field Positioning System

To use the field positioning system, you first need to set the robot's initial position (this is the coordinate it starts at). Call this (in autonomous, or pre autonomous, usually):

resetDrive(x, y, r);

X and Y are integers in units of 0.1 inches, and R is an integer in units of 0.1 degrees. This method can also be called later to manually reset the robot's position. Be careful: This position needs to be correct otherwise the rest of the field positioning system will be wrong. If not called, the default values will all be 0.

To get the robot's position:

driveGetX(); //Get the X position in 0.1 inches
driveGetY(); //Get the Y position in 0.1 inches
driveGetDegrees(); //Get the rotation in 0.1 degrees