Setting Things Up¶
HolonomicLib uses Okapi’s OdomChassisController
for output. Thus, we must first create
a OdomChassisController
object as shown below.
Note
This assumes that you are using namespace okapi
1std::shared_ptr<OdomChassisController> chassis = ChassisControllerBuilder()
2 .withMotors(
3 1, // Top left
4 -2, // Top right (reversed)
5 -3, // Bottom right (reversed)
6 4 // Bottom left
7 )
8 .withSensors(
9 ADIEncoder{'A', 'B'}, // left encoder in ADI ports A & B
10 ADIEncoder{'C', 'D', true}, // right encoder in ADI ports C & D (reversed)
11 ADIEncoder{'E', 'F'} // middle encoder in ADI ports E & F
12 )
13 // specify the tracking wheels diameter (2.75 in), track (7 in), and TPR (360)
14 // specify the middle encoder distance (1 in) and diameter (2.75 in)
15 .withOdometry({{2.75_in, 7_in, 1_in, 2.75_in}, quadEncoderTPR})
16 .buildOdometry();
Note
For more details on Okapi’s OdomChassisController
,
please checkout the Okapi documentation.
Next, create an AsyncHolonomicChassisController
object using the AsyncHolonomicChassisControllerBuilder.
This will be used to control the robot.
The constructor takes an OdomChassisController that will be used to move the chassis.
std::shared_ptr<AsyncHolonomicChassisController> controller =
AsyncHolonomicChassisControllerBuilder(std::shared_ptr<okapi::OdomChassisController> ichassis)
Configure PID controllers - you need 2 controllers: one for turning and one for translation
One way you can configure the PID is by inputing the gains directly.
.withDistGains(const okapi::IterativePosPIDController::Gains &idistGains)
.withTurnGains(const okapi::IterativePosPIDController::Gains &iturnGains)
Another way is to supply the actual PID controller objects.
.withDistPID(std::unique_ptr<okapi::IterativePosPIDController> idistController)
.withTurnPID(std::unique_ptr<okapi::IterativePosPIDController> iturnController)
(Optional) Configure the settle parameters for the PID controllers.
.withDistSettleParameters(okapi::QLength imaxError,
okapi::QSpeed imaxDerivative,
okapi::QTime iwaitTime)
.withTurnSettleParameters(okapi::QLength imaxError,
okapi::QSpeed imaxDerivative,
okapi::QTime iwaitTime)
Finally, build the controller!
.build()
Here is a complete example of what you might do.
1std::shared_ptr<OdomChassisController> chassis = ChassisControllerBuilder()
2 .withMotors(
3 1, // Top left
4 -2, // Top right (reversed)
5 -3, // Bottom right (reversed)
6 4 // Bottom left
7 )
8 .withSensors(
9 ADIEncoder{'A', 'B'}, // left encoder in ADI ports A & B
10 ADIEncoder{'C', 'D', true}, // right encoder in ADI ports C & D (reversed)
11 ADIEncoder{'E', 'F'} // middle encoder in ADI ports E & F
12 )
13 // specify the tracking wheels diameter (2.75 in), track (7 in), and TPR (360)
14 // specify the middle encoder distance (1 in) and diameter (2.75 in)
15 .withOdometry({{2.75_in, 7_in, 1_in, 2.75_in}, quadEncoderTPR})
16 .buildOdometry();
17
18std::shared_ptr<AsyncHolonomicChassisController> controller =
19 AsyncHolonomicChassisControllerBuilder(chassis)
20 // PID gains (must be tuned for your robot)
21 .withDistGains(
22 {0.05, 0.0, 0.00065, 0.0} // Translation gains
23 )
24 .withTurnGains(
25 {0.05, 0.0, 0.00065, 0.0} // Turn gains
26 )
27 // Tolerance (how close the chassis must be to the target before stopping)
28 .withDistSettleParameters(
29 0.5_in, // Max error
30 2.0_in / 1_s, // Max derivative
31 100_ms // Wait time
32 )
33 .withTurnSettleParameters(
34 1.0_in, // Max error
35 2.0_in / 1_s, // Max derivative
36 100_ms // Wait time
37 )
38 .build();
More information regarding the HolonomicLib API can be found here