# Autonomous Driving Tutorial for VEX V5 Robots

## A complete tutorial with code

The 15 second autonomous period is a critical part of VEX Robotics games. You have a short amount of time to control the robot without a human driver and score as many points as possible.

During this time, it is critical that you are able to control the robot precisely. The fundamental part of this control is being able to drive the robot around the field with precision.

Driving is composed of two actions: driving (forward/backward) and turning (left/right). If you are able to these two actions autonomously with reasonable accuracy, you can move your robot practically anywhere on the field confidently. First, let’s look at driving forward and backward.

# Driving (forward/backward)

`// Right motor reversed because it is facing the opposite directionvex::motor LeftMotor  = vex::motor(vex::PORT10, false);vex::motor RightMotor = vex::motor(vex::PORT1, true);`

Now in `main.cpp` we can make a function to drive the robot forward or backward by a specific distance, and then call that function from the autonomous function.

That function can be something like this:

`void driveForward( float inches ) {    float inchesPerDegree = WHEEL_CIRCUMFERENCE / 360;    float degrees = inches / inchesPerDegree;    // startRotate doesn't wait for completion    // this way, the other wheel can turn at same time    LeftMotor.startRotateFor(        degrees * GEAR_RATIO, vex::rotationUnits::deg,         AUTON_DRIVE_PCT, vex::velocityUnits::pct    );    RightMotor.rotateFor(        degrees * GEAR_RATIO, vex::rotationUnits::deg,        AUTON_DRIVE_PCT, vex::velocityUnits::pct    );}`

The key here is that we need some way to convert between the linear distance moved by the robot and the rotational angle swept by the drive motor. To do that, we find the circumferential inches per degree of the wheel, by dividing the wheel’s circumference by the 360 total degrees.

From there, taking the inches needed to move divided by the inches moved per degree yields the degrees needed to move. This can be seen through dimensional analysis:

`(inches) / (inches / degree)=> degrees`

The last thing to consider is the gear ratio. If you directly connect the motor to the wheel, the gear ratio is 1 (1 motor rotation : 1 wheel rotation). If you have gear(s) between the motor and the wheel, you may end up creating a different gear ratio, such as 0.5, (0.5 motor rotation : 1 wheel rotation). Multiplying the degrees to rotate the wheel by this gear ratio finally gives the degrees to rotate the motor. This can be seen through dimensional analysis:

`  (wheel degrees) * (gear ratio)= (wheel degrees) * (motor degrees / wheel degrees)=> motor degrees`

It is also worth mentioning that this function uses a few constants that need to be declared earlier in the file, preferably near the top by convention. These declarations will look something like this:

`const float WHEEL_DIAMETER = 4.125; // inchesconst float WHEEL_CIRCUMFERENCE = WHEEL_DIAMETER * 3.1416;const float GEAR_RATIO = 0.5; // 0.5 turn of motor = 1 turn of wheelconst int  AUTON_DRIVE_PCT = 50; // motors at 50% power during auton`

Now the autonomous function can call the driveForward function like the following:

`void autonomous( void ) {    driveForward( 1.2 * 12 ); // drive 1.2 ft forwards    driveForward(-1.2 * 12 ); // drive 1.2 ft backwards}`

# Turning (left/right)

This can be done with another helper function like this:

`void turn( float degrees ) {    // Note: +90 degrees is a right turn    float turningRatio = TURNING_DIAMETER / WHEEL_DIAMETER;    float wheelDegrees = turningRatio * degrees;        // Divide by two because each wheel provides half the rotation    LeftMotor.startRotateFor(        wheelDegrees * gearRatio / 2, vex::rotationUnits::deg,         AUTON_DRIVE_PCT, vex::velocityUnits::pct    );    RightMotor.rotateFor(        wheelDegrees * gearRatio / 2, vex::rotationUnits::deg,        AUTON_DRIVE_PCT, vex::velocityUnits::pct    );}`

Turning the robot is a little less straightforward than simple linear driving because we have to consider the turning radius of the robot. In this case, a four-wheeled robot has a turning diameter approximated by the diagonal distance between the wheels. This distance can simply be measured on the robot as the distance between the upper left and lower right wheels at the points where they contact the ground.

Once the turning diameter is known, the ratio a rotation of the robot as a whole and the rotation of a wheel is given by dividing the turning diameter by the wheel diameter. Then multiplying by the desired degrees of rotation from the robot gives the degrees to rotate the wheel.

To translate that to motor rotation, we do the same as we did above, multiplying by the gear ratio, and then dividing by two because we are getting rotation from both the left and right sides.

The constant turning diameter also needs to be declared like so:

`// distance (in inches) from top-left wheel to bottom-right wheelconst float turningDiameter = 19.0;`

From there, you can call the turn function from the autonomous function like this:

`void autonomous( void ) {        turn( 90); // right turn    turn(-90); // left turn}`

## Possible Solutions

You could also decide to use a gyroscope for turning and an accelerometer for moving linearly.

Such a solution would be a little more complicated, so you should probably try implementing a simpler system that just uses motor encoders (like that described above) before involving other sensors like gyroscopes.

Hope this helps. Good luck!

Written by

## The Floating Point

#### Programming and more

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just \$5/month. Upgrade