|
LightLib
PROS library for VEX V5: EKF/MCL localization, RAMSETE path following, high-level chassis API
|
This tutorial covers the bread-and-butter autonomous primitives: driving in a straight line, turning in place, and swing turns. Every LightLib auton is built from some combination of these three commands plus the pid_wait family.
A PID controller takes a setpoint (target) and a measurement (current position) and produces a motor command that drives the error toward zero:
kP (proportional) decides how hard the robot pushes against error. Too high → oscillation; too low → sluggish, doesn't reach the target.
kI (integral) accumulates past error so the robot doesn't get stuck a fraction of an inch short of the target. Almost always small (or zero). Large kI causes overshoot and windup.
kD (derivative) damps the response — it pushes back when error is shrinking fast, preventing overshoot. Tune kD up until the motion looks critically damped (lands on the target without oscillating).
LightLib runs four PIDs simultaneously during a drive motion:
pid_turn_set.Slew is layered on top: the drive PID's output is clamped to ramp from a small starting voltage up to its commanded max over the first few inches, so the wheels don't slip on launch.
Drives forward (or backward) by a distance in inches. The IMU heading PID holds the starting heading throughout.
Signature (one of several overloads — see drive.hpp):
p_target — distance with units. 24_in, 0.5_ft, 300_mm all work.speed — voltage scale, ±127. Sign of p_target decides direction; sign of speed is ignored.slew_on — ramp up from slew_drive_constants_set floor over the configured distance.toggle_heading — if false, heading correction is disabled (the IMU is ignored). Useful if the robot has just rammed a wall and the IMU measurement is unreliable for the next move.Forgetting pid_wait(). Without it, the next line runs immediately — your auton fires off six PID commands in a row and the chassis only executes the last one. Every motion command needs a pair:
Turns to an absolute field heading (or a relative one — see below). LightLib's IMU convention is 0° = facing the alliance wall it was zeroed at, CW positive.
Signature:
The e_angle_behavior enum values are: light::shortest (default), light::longest, light::cw, light::ccw, light::raw (signed delta as-is).
Use this when the auton "doesn't care" about absolute field heading — most of the time, honestly. Absolute turns make sense after setPose() resets or near features keyed to the field.
A swing turn locks one side of the drive and pivots around it. Half the turn radius of an in-place turn, useful for sweeping into a target without disturbing a mechanism on the locked side.
The opposite-speed overload is unique to swing. Most teams ignore it, but it can sharpen a sweeping intake into a stack — give the locked side a small reverse voltage to tighten the radius.
pid_wait() blocks until the active motion satisfies its exit conditions. There are four variants:
**pid_wait_quick_chain** is the magic one. It exits the current motion when error drops below pid_drive_chain_constant_set(...) (typically a few inches), so you can fire the next motion command without slowing the robot to a stop. Use it for fluid multi-move sequences:
The chain constants are configured in default_constants():
pid_wait_until(distance) is for triggering an action mid-motion — drop a piston at the 12-inch mark, then keep driving:
That's the entire vocabulary of "hand-crafted" autons in LightLib. Anything more elaborate — driving to an arbitrary field point, following a Jerryio path — uses the odom-based motion APIs covered in the next tutorial.