|
HoloLib
High-performance holonomic (X-Drive) control library for VEX V5
|
A feature-rich PROS template, with first-class holonomic drivetrain support.
HoloLib is a highly extensible, feature-rich PROS template, using the Eigen linear-algebra library for vectorization. It handles the hard parts of programming an X-Drive well: knowing where the robot is, getting it where you want it, and keeping it from running into things.
Create the chassis, odometry, and tuning objects in your main.cpp by giving them the motors, the IMU, and the physical dimensions of your robot.
Keep the names below exactly as they are. include/hololib/config.hpp declares this set as extern, and every motion function falls back to them by default, so renaming one or leaving it out breaks the build:
Once the chassis is set up, autonomous moves read like instructions. Calling a motion directly blocks until it finishes; wrapping it in chassisAsync runs it on the motion handler, so your code keeps going until you ask for the next move:
In opcontrol, hand the controller inputs to the chassis. This example matches the driver-control in main.cpp:
HoloLib is five systems that work together. Each one solves a specific problem you hit when you try to make an X-Drive do something precise:
| System | The problem it solves |
|---|---|
| Encoder EKF odometry | Knowing where the robot is, even when wheels slip |
| Obstacle avoidance | Getting around things in the way |
| Gain scheduling | One PID tune can't do everything well |
| Holonomic motion | Driving and following paths in any direction |
| Driver replay | Turning a practice run into an autonomous routine |
The rest of this page walks through each one. For the hands-on side, function by function, with code and tuning advice, see the Usage Guide.
To do anything in autonomous, the robot has to know where it is on the field. The usual approach is to count wheel rotations and add them up. That works until a wheel slips, the sensor reads a little noisy, or small errors pile up over a long run. After a few seconds the robot's idea of "where I am" has drifted away from reality.
HoloLib's odometry layer, EncoderEKFOdometry, fixes this by not trusting any single sensor. It blends what it has available, while PoseEKF handles the actual Kalman filter math:
addTrackingWheel (vertical and horizontal layouts are both supported).Out of the box it runs on the motor encoders and the IMU. Adding tracking wheels switches the position half over to them, since unpowered wheels don't slip the way driven ones do.
An Extended Kalman Filter does this in two repeating steps. First it predicts where the robot should be now, using the holonomic motion model. Then it corrects that guess by comparing it against what the sensors actually read, and nudges the estimate toward the more trustworthy ones.
Think of it like figuring out where you are on a walk by combining a pedometer that's slightly off with a compass that's slightly off. Neither is right on its own, but together they beat either one alone. That's the whole idea, run a few hundred times a second.
Heads up: the EKF stack is the most involved part of the library to tune. If you're not comfortable adjusting filter noise values, leave it off until you are. A badly tuned filter is worse than no filter.
Sometimes the straight line to where you want to go runs through something you can't drive over. HoloLib has two ways to deal with that, depending on how much control you want.
Recursive waypoint generation is the planned approach. Before the robot moves, ObstacleManager checks whether the straight path to the target crosses any obstacle you've defined (each one a circle on the field). If it does, the library inserts a waypoint that clears the obstacle, then checks the new path again, and keeps going until the whole route is clear. It's like rerouting around a building on a map before you start driving.
Artificial Potential Fields (APF) is the reactive approach. The target pulls the robot toward it like a magnet, and every obstacle pushes the robot away. Add those forces together each tick and you get a direction to drive. HoloLib also adds a sideways "tangential" push so the robot glides around an obstacle instead of stalling against it head-on.
Heads up: this is meant to keep you from crashing into things you didn't plan for. For tight, repeatable autonomous routines you'll usually want the planned waypoints, and APF may need extra tuning before it behaves the way you want.
A PID controller has gains (kP, kI, kD) that decide how hard it pushes to close the gap between where the robot is and where it should be. The trouble is that one set of gains can't be good at everything. Tune it to sprint across the field and it overshoots on small moves. Tune it to settle gently on small moves and it crawls across long ones.
HoloLib's GainScheduler lets you define several sets of gains, each tied to a range of error (how far you still are from the target). As the robot closes in, the controller transitions between those sets: aggressive gains when there's a lot of distance to cover, gentle gains as it settles in on the target. The slew rate (how fast the output is allowed to change) scales the same way.
The result is a single movement that accelerates hard at the start and settles without overshooting at the end, which is hard to get from a fixed tune.
An X-Drive can move in any direction and rotate at the same time, which is what makes it worth the trouble. HoloLib gives you that control directly through the hololib::motions API instead of making you think about individual wheels.
FollowPath, HoldAngle, or CustomAngles.A good driver run is itself a kind of autonomous routine, you just have to capture it. DriverReplay::logReplayData prints the robot's pose while you drive a practice run, and runDriverReplay drives those points back during autonomous. It splits the run into segments wherever you reversed direction, so a back-and-forth run plays back the same way.
Heads up: the replay only captures the path the robot took. Button presses aren't recorded into it, on purpose, to keep the log from overflowing the buffer, so mechanisms still need to be scripted separately.
Chassis & motion
| Path | What it does |
|---|---|
include/hololib/chassis.hpp | Public interface for the chassis controller |
src/robot/chassis.cpp | Core chassis controller and holonomic kinematics |
include/hololib/localization/odometry.hpp, src/localization/odometry.cpp | Encoder EKF odometry and pose tracking |
include/hololib/motions/motions.hpp, src/motions/*.cpp | Path-following and point-to-point movement routines |
include/hololib/motions/motion_handler.hpp, src/motions/MotionHandler.cpp | Queues and manages async movements |
include/hololib/motions/motion_cancel_helper.hpp, src/motions/MotionCancelHelper.cpp | Shared cancellation helpers for async motion |
Control & estimation
| Path | What it does |
|---|---|
include/hololib/util/PID.hpp, src/motions/controllers/PID.cpp | The custom PID controller |
include/hololib/util/GainScheduler.hpp, src/util/GainScheduler.cpp | Error-threshold-based PID gain scheduling |
include/hololib/util/PoseEKF.hpp, src/util/PoseEKF.cpp | Extended Kalman Filter for robot pose estimation |
include/hololib/localization/odometry.hpp | Tracking-wheel configuration, chassis config, and pose access |
include/hololib/util/Timer.hpp, src/util/Timer.cpp | Small timing helper used by motion control |
Localization & paths
| Path | What it does |
|---|---|
include/hololib/localization/odometry.hpp | Pose, velocity, chassis config, and tracking wheel types |
include/hololib/localization/distanceReset.hpp, src/localization/distanceReset.cpp | Distance-sensor-based odometry reset |
include/hololib/util/obstacle_manager.hpp, src/util/obstacle_manager.cpp | Field obstacle representation and avoidance |
include/hololib/util/replay.hpp, src/util/replay.cpp | Driver replay capture and playback |
Subsystems & utilities
| Path | What it does |
|---|---|
include/hololib/config.hpp | Chassis dimension and hardware constants |
include/hololib/util/util.hpp, src/util/util.cpp | Small shared utility helpers |
include/hololib/util/modular_lift.hpp, src/motions/controllers/modular_lift.cpp | Configurable lift subsystem with background control task |
tools/sim_auton.py | Python tool to visualize and debug autonomous routes in the browser |
HoloLib ships with a Python tool for designing and checking autonomous paths before you run them on a real robot:
It reads the motion calls out of src/main.cpp and writes bin/auton_viewer.html. Open that file in a browser to step through the path and watch for overshoot.
This is a one-person project, so contributions, issues, and pull requests are welcome!
HoloLib is released under the Apache 2.0 license. If your robot uses this template, please abide by the terms of the license.
This project includes software developed by the LemLib project, licensed under the MIT License. The copyright of those helper components belong to the LemLib project. Their work inspired HoloLib, so please check them out!
View the terms of the Eigen License.
The PROS operating system is licensed under the Mozilla Public License Version 2.0.