Hardware Setup
How to declare motors, sensors, pneumatics, and the drivetrain in PROS—using the Push Back robot as a reference.
The Pattern: Declare Once, Use Everywhere
PROS hardware objects (motors, sensors, etc.) are just C++ objects. The convention used in this codebase is:
- Define them once in
src/robot.cpp - Declare them as
externininclude/robot.hpp - Include
robot.hppwherever you need them
This avoids multiple-definition linker errors and keeps everything organised.
Drivetrain Motors
This robot uses a 6-motor tank drivetrain (three per side) with
blue (600 RPM) cartridges geared down externally.
Motors are grouped into pros::MotorGroup objects.
Negative port numbers reverse the motor direction in software.
src/robot.cpp// Negative port = motor is physically reversed pros::MotorGroup leftMotorGroup({-9, -19, -20}, pros::v5::MotorGears::blue); pros::MotorGroup rightMotorGroup({16, 12, 11}, pros::v5::MotorGears::blue);
Intake & Scoring Mechanisms
The Push Back robot has a two-stage intake and several pneumatic mechanisms:
| Variable | Type | Purpose |
|---|---|---|
firstStageIntake | pros::Motor (green, port 18) | Picks blocks up from the floor / loaders (flex wheels) |
secondStageIntake | pros::Motor (blue, port −5) | Feeds blocks up into the basket or scores into goals |
slideMechanismLeft/Right | pros::adi::DigitalOut H / G | Deploys a slide that channels blocks from loaders to the intake |
descoreMechanism | pros::adi::DigitalOut E | Pops blocks out of opponent long goals |
aligner | pros::adi::DigitalOut F | Triangle-shaped wedge for aligning with long goals |
src/robot.cpppros::adi::DigitalOut slideMechanismLeft('H'); pros::adi::DigitalOut slideMechanismRight('G'); // Helper: fire both solenoids together void slideMechanism(bool value) { slideMechanismLeft.set_value(value); slideMechanismRight.set_value(value); } pros::adi::DigitalOut descoreMechanism('E'); pros::adi::DigitalOut aligner('F'); pros::Motor firstStageIntake(18, pros::MotorGears::green); pros::Motor secondStageIntake(-5, pros::MotorGears::blue);
Sensors
Sensors are the eyes of the robot. Here is every sensor on this robot and why it exists:
| Variable | Type / Port | Role |
|---|---|---|
inertial | IMU, port 10 | Tracks absolute heading; primary input for odometry |
verticalEncoder | Rotation sensor, port −14 | Vertical tracking wheel for forward/backward odometry |
distanceRight | Distance sensor, port 15 | Measures distance to the right field wall → resets X or Y pose |
distanceBack | Distance sensor, port 2 | Measures distance to the back field wall → resets X or Y pose |
optical | Optical sensor, port 7 | Detects block hue; used for color-sorting / anti-jam |
gps | GPS sensor, port 13 | Global position via field tape (backup for long skills runs) |
src/robot.cpppros::Imu inertial(10); pros::Gps gps(13); pros::Optical optical(7); pros::Distance distanceRight(15); pros::Distance distanceBack(2); // Rotation sensor on the vertical tracking wheel pros::Rotation verticalEncoder(-14); // negative = reversed
chassis.calibrate() at startup zeros it out
for that run, but mid-run drift is why distance resets exist.
LemLib Drivetrain Configuration
LemLib needs a lemlib::Drivetrain struct that describes the physical geometry.
These values must match your real robot—they affect how far the robot thinks it moves.
src/robot.cpplemlib::Drivetrain drivetrain( &leftMotorGroup, &rightMotorGroup, 11.5, // track width (inches, center-to-center) lemlib::Omniwheel::NEW_325, // 3.25" omni wheels 450, // RPM at the wheel 2 // horizontal drift factor (2 for omni/drift, 8 for traction) );
Tracking Wheel
A tracking wheel is a free-spinning wheel with an encoder. It is not driven—it only measures movement—so it has no wheel slip from motor torque. This robot uses one vertical tracker:
src/robot.cpp// Tracking wheel: 1.97" diameter, 0" offset from center lemlib::TrackingWheel verticalTracker(&verticalEncoder, 1.97, 0); lemlib::OdomSensors sensors( &verticalTracker, // vertical tracking wheel #1 nullptr, // vertical #2 (not used) nullptr, // horizontal tracking wheel (not used) nullptr, // horizontal #2 &inertial // IMU for heading );
Putting It Together: Chassis
All the pieces above are assembled into a single Chassis object.
This object is used everywhere in the codebase for movement.
src/robot.cppChassis chassis( drivetrain, lateral_controller, // see PID chapter angular_controller, // see PID chapter sensors, &throttle_curve, // expo curve for driver control &steer_curve );