Driving a Simple Robot
Lessons 2, 3, and 4 gave you the pieces: controller input, motor controllers, and sensors. This lesson puts them together into a working differential drive robot — a two-side drivetrain that can move forward, turn, and stop reliably under driver control. It is the first complete system you will build in this course.
By the end of this lesson, you will:
- Implement arcade drive and tank drive by computing left/right motor outputs from controller input
- Use WPILib's
DifferentialDriveclass for safe, clamp-protected drive output - Add a speed scaling (slow mode) feature using a held button modifier
- Implement a ramp rate to prevent sudden full-speed starts that stress the drivetrain
- Build a complete, deployment-ready drive subsystem with all protections in place
Differential Drive: How Two Motors Produce Motion
A differential drive (also called a tank drive or skid-steer) controls direction by running the left and right sides of the robot at different speeds. Both sides forward at the same speed = drive straight. Left faster than right = turn right. Left backward, right forward = spin in place. All of motion planning in a differential drive reduces to calculating two numbers: the left motor output and the right motor output.
Drive Style Visualizer
There are three common input patterns for differential drive. Select each to see how it maps controller inputs to motor outputs — and which situations each is best for.
One stick controls forward/backward speed (throttle); a second stick (or the same stick's X-axis) controls left/right rotation (turn).left = throttle + turnright = throttle − turn
Both outputs are clamped to [−1, 1].
Most intuitive for new drivers — feels like a video game. Left stick forward = go forward, right stick sideways = turn. Recommended for any team whose driver didn't grow up playing tank games. Trade-off: diagonal stick movements can produce unexpected outputs at the output boundaries.
Left stick Y-axis directly controls the left motors; right stick Y-axis directly controls the right motors.left = leftStickYright = rightStickY
The driver has independent control over each side.
Gives experienced drivers maximum mechanical intuition — they can feel exactly what each side is doing. Good for defense-heavy robots where precise lateral positioning matters. Trade-off: requires both thumbs simultaneously; novice drivers often make the robot shake trying to hold both sticks at the same position.
Forward speed on one axis, curvature (turning radius) on another. At higher speeds, turning input produces a wider arc. At zero speed (with quick-turn enabled), it rotates in place.
WPILib's DifferentialDrive.curvatureDrive() handles the math.
Feels like driving a car — large turning radius at speed, tight turns when slow. Good for robots that need to hold straight lines at high speed while still being maneuverable. Used by many championship-level teams. Requires more practice to feel natural than arcade drive.
Drive Output Calculator
Adjust the forward and rotation inputs to see how arcade drive and tank drive compute left/right motor outputs. Watch the outputs clamp when the sum exceeds 1.0.
WPILib's DifferentialDrive Class
You could compute arcade/tank drive manually — the math is simple. But WPILib's DifferentialDrive class adds output clamping, motor safety (stops motors if no command is sent for 100ms), and WPILib telemetry. Using it is a good default for any two-sided robot.
DifferentialDrive applies a default deadband of 0.02 to inputs. That's usually not enough for joystick noise — apply MathUtil.applyDeadband() with 0.05 before passing values to the drive methods. The internal deadband does not replace your manual deadband application.
Speed Scaling and Turbo Mode
Running at full speed in the pit during calibration, or bumping into field elements at 5 m/s because a driver accidentally full-sticked, are both common and both preventable. Speed scaling lets you reduce maximum output by default and unlock full speed with a held button — or the reverse (default full speed, slow mode with a bumper).
A ramp rate limits how fast the motor output can change per second. Without a ramp rate, a driver going from 0 to full speed in one stick movement slams the full output onto the motors in one 20ms cycle — 50 output units per second. A 0.2-second ramp limits acceleration to manageable levels for the drivetrain hardware.
The TalonFX's hardware ramp applies to all output modes including feedforward and closed-loop. A software ramp only applies in code that explicitly uses it. For simple open-loop teleop driving, the hardware ramp is cleaner. For mechanisms where you need full control of the ramp behavior across modes, use the software version.
A Complete Drive Subsystem
The single most reliable indicator of a team's drive software quality during inspection is whether I see a speed scale. A robot with no speed limiting that can drive at full speed in any mode is a robot that will hit field elements, alliance partners, or volunteers the first time a driver is startled. It is also a robot whose drivers have no way to practice fine positioning. Default-limited with a bumper for turbo is the right model: safe by default, full capability when intentionally engaged.
- Verify inversion physically before competition. Deploy, enable, push forward — robot should move forward. If it spins, check which side is inverted. If it moves backward, both sides are inverted or the Y-axis isn't negated.
- Apply deadband before any drive calculation, not after. Computing arcade drive output then applying a deadband to the result is wrong — you'd be deadbanding the combined output, not the source axes individually.
- Use a speed limiter as default. Default to 60–70% speed in teleop. Document that the right bumper unlocks full speed. Tell drivers. Write it in your drive team notes.
- Configure ramp rate in motor controller, not only in software. The hardware ramp applies even if your software sends a step change due to a code bug. Software ramp alone can be bypassed; hardware ramp cannot.
- Monitor stator current during pushing matches. Current spikes on drive motors during defense indicate when your gearbox and chain are being stressed. A drive motor consistently pulling above its current limit is a mechanism maintenance warning.
Knowledge Check
Build and Drive Your First Robot
- In your
Robot.java, add twoTalonFXmotors for left and right drive. Configure both with 50A current limit and a 0.15s ramp rate. Invert the right motor. - Implement arcade drive using
DifferentialDrive. Apply a 0.05 deadband and negate the left Y. Deploy to a robot (or simulate) and confirm forward stick drives the robot forward. - Add a speed scale: default 0.6, hold right bumper for 1.0. Print the scale factor to SmartDashboard. Drive both with and without the bumper held and feel the difference.
- Switch from arcade to curvature drive using
drive.curvatureDrive(). Try driving at high speed and low speed. Note how the turning radius changes with speed. - In
disabledInit(), switch to Coast. InteleopInit(), switch to Brake. Verify: push the robot forward when disabled (should coast), then push when enabled in brake (should resist). - Bonus: Implement tank drive and have your drive team test all three modes (arcade, tank, curvature) on the same robot. Write a paragraph explaining which mode your team would choose for competition and why based on your observation session.