Releases: EZ-Robotics/EZ-Template
🐛v3.2.1🍠edamame
Minor bug fix, swings will now work as expected when the autonomous routine is mirrored.
🎡TRACKING WHEELS🎡
🚗ODOM DRIVE SYNTAX🚗
🐷PURE PURSUIT🐷
🪀BOOMERANG🪀
🪀🐷BOOMERANG INJECTED INTO PURE PURSUITS🪀🐷
👉TURN TO POINT👉
💄MIRRORED AUTONS💄
🩰TURN BEHAVIOR🩰
🛹GLOBAL SLEW🛹
📺BLANK LCD PAGES📺
Download and Installation
Learn how to install and setup EZ-Template here!
Discord Server
Need extra assistance using EZ-Template? Feel free to join our Discord Server!
What's Changed
- 🐛Swings flip correctly by @ssejrog in #234
- 📝Fixed mistakes in all swing motion comments by @ssejrog in #235
Full Changelog: v3.2.0...v3.2.1
v3.2.0 ‼️ODOMETRY‼️
🥳🥳🥳EZ-TEMPLATE'S LARGEST FEATURE UPGRADE🥳🥳🥳
🎡TRACKING WHEELS🎡
🚗ODOM DRIVE SYNTAX🚗
🐷PURE PURSUIT🐷
🪀BOOMERANG🪀
🪀🐷BOOMERANG INJECTED INTO PURE PURSUITS🪀🐷
👉TURN TO POINT👉
💄MIRRORED AUTONS💄
🩰TURN BEHAVIOR🩰
🛹GLOBAL SLEW🛹
📺BLANK LCD PAGES📺
Download and Installation
Learn how to install and setup EZ-Template here!
Discord Server
Need extra assistance using EZ-Template? Feel free to join our Discord Server!
What's Changed
- Feature/odom by @ssejrog in #173
- PID Tuner Cusotmization by @ssejrog in #160
- Fixed tracking inconsistencies by @ssejrog in #187
- Fixed border typo by @jemminiz in #183
- Added arcade vector scaling #185 by @ssejrog in #188
- Opcontrol speed limit by @ssejrog in #189
- Fixed segfault #186 by @ssejrog in #190
- Turn to point now respects angle behavior by @ssejrog in #193
- Bug/we hate quadrant 3 by @ssejrog in #194
- Can now relative drive after odom motions by @ssejrog in #196
- Can now flip angle #161 by @ssejrog in #197
- Added units to wait_until (#199) by @ssejrog in #200
- Added
pid_wait_until_index_started
(#198) by @ssejrog in #201 - Path smoothing doesn't override lookahead #202 by @ssejrog in #203
- Drive isn't slow in opcontrol by @ssejrog in #204
- Simplified PID tuner by @ssejrog in #206
- Fix linter errors by @ssejrog in #208
- Limited decimal points by @ssejrog in #211
- Added unique vibration when imu fails by @ssejrog in #212
- Set xy without requiring angle by @ssejrog in #213
- Added xyt set by @ssejrog in #214
- Added motor group exit condition wrapper by @ssejrog in #210
- Front tracker works now by @ssejrog in #217
- Commenting for documentation and fixing up drive.hpp by @jemminiz in #218
- Added constants for path smoothing by @ssejrog in #221
- Active brake uses PID class and doesn't reset drive sensors by @ssejrog in #220
- Default pid_odom_set is no longer forced to boomerang by @ssejrog in #222
- Clarifying code comments by @ssejrog in #225
- Relative odom works with axis flipped by @ssejrog in #227
New Contributors
- @jemminiz made their first contribution in #183
- @aayala04 was the cause of beta.4, beta.5, beta.6, beta.7, beta.8, and rc.1. Too good at finding bugs
- Thank you @8pxl for the original measuring offsets function!
Full Changelog: v3.1.0...v3.2.0
v3.2.0-rc.2
Very minor update. Example project now contains a screen task and has been simplified further, general documentation clean up, and a bug fix for relative odom when x or y axis is flipped.
Full 3.2.0 will be released very shortly
What's Changed
- Clarifying code comments by @ssejrog in #225
- Relative odom works with axis flipped by @ssejrog in #227
Full Changelog: v3.2.0-rc.1...v3.2.0-rc.2
🎉ODOMETRY🎉
EZ-Template has odometry!! The easiest way to start messing with this is to start messing with it by downloading the example project below! You can also see the example project here.
🎡Tracking Wheels
You can create tracking wheels with EZ-Template using ADI Encoders (or 3rd party digital encoders) and rotation sensors.
// Are you using tracking wheels? Comment out which ones you're using here!
// `2.75` is the wheel diameter
// `4.0` is the distance from the center of the wheel to the center of the robot
ez::tracking_wheel right_tracker({-'A', -'B'}, 2.75, 4.0); // ADI Encoders
ez::tracking_wheel left_tracker(1, {'C', 'D'}, 2.75, 4.0); // ADI Encoders plugged into a Smart port
ez::tracking_wheel horiz_tracker(1, 2.75, 4.0); // Rotation sensors
To enable them, you'll need these lines of code in void initialize()
// Are you using tracking wheels? Comment out which ones you're using here!
chassis.odom_tracker_right_set(&right_tracker);
chassis.odom_tracker_left_set(&left_tracker);
chassis.odom_tracker_back_set(&horiz_tracker); // Replace `back` to `front` if your tracker is in the front!
🚗Odom Drive Syntax
If you have previous actions that you're porting over to 3.2.0 but you're not quite ready to retune odom stuff, you can try replacing .pid_drive_set
with .pid_odom_set
and it'll make your normal autons use odometry.
void drive_and_turn() {
chassis.pid_odom_set(24_in, DRIVE_SPEED, true);
chassis.pid_wait();
chassis.pid_turn_set(45_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_turn_set(-45_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_turn_set(0_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_odom_set(-24_in, DRIVE_SPEED, true);
chassis.pid_wait();
}
🐷Pure Pursuit
EZ-Template's Pure Pursuit is all done on the robot. chassis.pid_odom_set()
will be your main function and covers all aspects of odom. You can input as many points as you'd like here and the robot will path through all of them.
// Drive to 0, 30 and pass through 6, 10 and 0, 20 on the way, with slew
chassis.pid_odom_set({{{6_in, 10_in}, fwd, 110},
{{0_in, 20_in}, fwd, 110},
{{0_in, 30_in}, fwd, 110}},
true);
chassis.pid_wait();
You can combine going forward and reverse in the same motion
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait();
And you can pid_wait_until
a point has been reached
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{{12_in, 24_in}, rev, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
🪀Boomerang
Boomerang will try to go to a point at a specific angle. You use this by specifying an angle while using pid_odom_set()
chassis.pid_odom_set({{0_in, 24_in, 45_deg}, fwd, 110},
true);
chassis.pid_wait();
🪀🐷Boomerang Injected into Pure Pursuits
Any point that the robot goes to, if you specify the angle it'll become a boomerang motion, even if it's during a pure pursuit path!
chassis.pid_odom_set({{{0_in, 24_in, 45_deg}, fwd, 110},
{{12_in, 24_in}, fwd, 110},
{{24_in, 24_in}, fwd, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
👉Turn to Point
You can turn to face a point! All of the syntax for normal turning applies here, so you can do this:
chassis.pid_turn_set({12_in, 12_in}, fwd, 110, ez::longest, true);
Or you can keep it simple and do this
chassis.pid_turn_set({12_in, 12_in}, fwd, 110);
💄Mirrored Field Problem
To help with making unique autons for the left and right side of the field, EZ-Template 3.2.0 has a feature to flip what direction the X and Y axis face. By flipping these you're allowing 1 autonomous routine to work for red and blue.
odom_y_flip();
odom_x_flip();
odom_theta_flip();
odom_y_direction_get(); // True = down is positive Y, False = up is positive Y
odom_x_direction_get(); // True = left is positive X, False = right is positive X
odom_theta_direction_get(); // True = positive is counterclockwise, False = positive is counterclockwise
It is still suggested to make minor tweaks for both sides, nothing is perfect, but it'll be much easier to maintain with one base function.
void base() {
ez::united_pose start_intaking_here;
if (chassis.odom_x_direction_get() == false)
start_intaking_here = {12_in, 24_in}; // If red
else
start_intaking_here = {15_in, 24_in}; // If blue
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{start_intaking_here, rev, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
chassis.pid_odom_set({{24_in, 48_in, 45_deg}, fwd, 110},
true);
chassis.pid_wait();
chassis.pid_turn_set(90_deg, 110, true);
chassis.pid_wait();
}
void red() {
base();
}
void blue() {
chassis.odom_x_flip();
chassis.odom_theta_flip();
base();
}
🩰Turn Behavior
In every previous version of EZ-Template, turning used the raw IMU values. This was confusing to teams as turning to 360 and 0 were the same angle but would do different things. In 3.2.0 you can change the default behavior of turning for turns, swings, and odoms. You can choose between:
ez::raw
- this is the behavior prior to 3.2.0
ez::left_turn
/ ez::ccw
- this will always turn counterclockwise
ez::right_turn
/ ez::cw
- this will always turn clockwise
ez::longest
- this will always take the longest path there, capped at 360deg
ez::shortest
- this will always take the shortest path there
You can call these in default_constants()
in src/autons.cpp
to change what the default behavior is. The 3.2.0 example project has it as ez::shortest
.
pid_turn_behavior_set(ez::shortest);
pid_swing_behavior_set(ez::shortest);
pid_odom_behavior_set(ez::shortest);
Now you can change how the robot behaves in turns
void turn() {
chassis.pid_turn_behavior_set(ez::shortest);
chassis.pid_turn_set(90_deg, TURN_SPEED, ez::left_turn);
chassis.pid_wait();
chassis.pid_turn_set(45_deg, TURN_SPEED, ez::right_turn);
chassis.pid_wait();
chassis.pid_turn_set(0_deg, TURN_SPEED, ez::longest);
chassis.pid_wait();
// This will take the shortest route because that's the default behavior
chassis.pid_turn_set(359_deg, TURN_SPEED);
chassis.pid_wait();
}
🛹Global Slew
If you're tired of having true
at the end of all of your motions, you can now globally enable slew for each motion type! You can override the default in each motion, but it won't change the default unless you explicitly change it.
slew_drive_set(true)
slew_swing_set(true)
slew_turn_set
🎸Adding PIDs to PID Tuner
ez::PID liftPID{0.45};
Adding this line of code to initialize()
will add your PID to the tuner!
chassis.pid_tuner_pids.push_back({"Lift PID", &liftPID.constants});
🏃Opcontrol Max Speed
By calling this function before the while loop in opcontrol(0
, you'll retain the full range of motion of the joystick but your maximum speed will be 63. This can be a number from 0 to 127.
chassis.opcontrol_speed_max_set(63);
📺Blank LCD Pages
All blank pages will come after the autonomous selector. You can check if you're on them with page_blank_is_on(x)
and by doing so it'll create the page when you get to it on the selector.
if (ez::as::page_blank_is_on(0))
ez::screen_print("this is our first blank page", 1);
else if (ez::as::page_blank_is_on(1))
ez::screen_print("this is our second blank page", 1);
v3.2.0-rc.1
3.2.0-beta.8 has been stable for teams using it so we're ready for the first release candidate!
Notable Changes
- front trackers now work
chassis.pid_odom_set(24_in, 110);
now isn't boomerang and is way faster- much more complete example project
measuring_offsets()
function that calculates your tracking wheel offsets for you. run the autonmeasuring offsets
in driver control, and check the blank page after. the offsets you see there are the offsets you should use in code.
All Changes
- Fix linter errors by @ssejrog in #208
- Limited decimal points by @ssejrog in #211
- Added unique vibration when imu fails by @ssejrog in #212
- Set xy without requiring angle by @ssejrog in #213
- Added xyt set by @ssejrog in #214
- Added motor group exit condition wrapper by @ssejrog in #210
- Front tracker works now by @ssejrog in #217
- Commenting for documentation and fixing up drive.hpp by @jemminiz in #218
- Added constants for path smoothing by @ssejrog in #221
- Active brake uses PID class and doesn't reset drive sensors by @ssejrog in #220
- Default pid_odom_set is no longer forced to boomerang by @ssejrog in #222
Thank you @8pxl for the original measuring offsets function!
Full Changelog: v3.2.0-beta.8...v3.2.0-rc.1
🎉ODOMETRY🎉
EZ-Template has odometry!! The easiest way to start messing with this is to start messing with it by downloading the example project below! You can also see the example project here.
🎡Tracking Wheels
You can create tracking wheels with EZ-Template using ADI Encoders (or 3rd party digital encoders) and rotation sensors.
// Are you using tracking wheels? Comment out which ones you're using here!
// `2.75` is the wheel diameter
// `4.0` is the distance from the center of the wheel to the center of the robot
ez::tracking_wheel right_tracker({-'A', -'B'}, 2.75, 4.0); // ADI Encoders
ez::tracking_wheel left_tracker(1, {'C', 'D'}, 2.75, 4.0); // ADI Encoders plugged into a Smart port
ez::tracking_wheel horiz_tracker(1, 2.75, 4.0); // Rotation sensors
To enable them, you'll need these lines of code in void initialize()
// Are you using tracking wheels? Comment out which ones you're using here!
chassis.odom_tracker_right_set(&right_tracker);
chassis.odom_tracker_left_set(&left_tracker);
chassis.odom_tracker_back_set(&horiz_tracker); // Replace `back` to `front` if your tracker is in the front!
🚗Odom Drive Syntax
If you have previous actions that you're porting over to 3.2.0 but you're not quite ready to retune odom stuff, you can try replacing .pid_drive_set
with .pid_odom_set
and it'll make your normal autons use odometry.
void drive_and_turn() {
chassis.pid_odom_set(24_in, DRIVE_SPEED, true);
chassis.pid_wait();
chassis.pid_turn_set(45_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_turn_set(-45_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_turn_set(0_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_odom_set(-24_in, DRIVE_SPEED, true);
chassis.pid_wait();
}
🐷Pure Pursuit
EZ-Template's Pure Pursuit is all done on the robot. chassis.pid_odom_set()
will be your main function and covers all aspects of odom. You can input as many points as you'd like here and the robot will path through all of them.
// Drive to 0, 30 and pass through 6, 10 and 0, 20 on the way, with slew
chassis.pid_odom_set({{{6_in, 10_in}, fwd, 110},
{{0_in, 20_in}, fwd, 110},
{{0_in, 30_in}, fwd, 110}},
true);
chassis.pid_wait();
You can combine going forward and reverse in the same motion
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait();
And you can pid_wait_until
a point has been reached
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{{12_in, 24_in}, rev, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
🪀Boomerang
Boomerang will try to go to a point at a specific angle. You use this by specifying an angle while using pid_odom_set()
chassis.pid_odom_set({{0_in, 24_in, 45_deg}, fwd, 110},
true);
chassis.pid_wait();
🪀🐷Boomerang Injected into Pure Pursuits
Any point that the robot goes to, if you specify the angle it'll become a boomerang motion, even if it's during a pure pursuit path!
chassis.pid_odom_set({{{0_in, 24_in, 45_deg}, fwd, 110},
{{12_in, 24_in}, fwd, 110},
{{24_in, 24_in}, fwd, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
👉Turn to Point
You can turn to face a point! All of the syntax for normal turning applies here, so you can do this:
chassis.pid_turn_set({12_in, 12_in}, fwd, 110, ez::longest, true);
Or you can keep it simple and do this
chassis.pid_turn_set({12_in, 12_in}, fwd, 110);
💄Mirrored Field Problem
To help with making unique autons for the left and right side of the field, EZ-Template 3.2.0 has a feature to flip what direction the X and Y axis face. By flipping these you're allowing 1 autonomous routine to work for red and blue.
odom_y_flip();
odom_x_flip();
odom_theta_flip();
odom_y_direction_get(); // True = down is positive Y, False = up is positive Y
odom_x_direction_get(); // True = left is positive X, False = right is positive X
odom_theta_direction_get(); // True = positive is counterclockwise, False = positive is counterclockwise
It is still suggested to make minor tweaks for both sides, nothing is perfect, but it'll be much easier to maintain with one base function.
void base() {
ez::united_pose start_intaking_here;
if (chassis.odom_x_direction_get() == false)
start_intaking_here = {12_in, 24_in}; // If red
else
start_intaking_here = {15_in, 24_in}; // If blue
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{start_intaking_here, rev, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
chassis.pid_odom_set({{24_in, 48_in, 45_deg}, fwd, 110},
true);
chassis.pid_wait();
chassis.pid_turn_set(90_deg, 110, true);
chassis.pid_wait();
}
void red() {
base();
}
void blue() {
chassis.odom_x_flip();
chassis.odom_theta_flip();
base();
}
🩰Turn Behavior
In every previous version of EZ-Template, turning used the raw IMU values. This was confusing to teams as turning to 360 and 0 were the same angle but would do different things. In 3.2.0 you can change the default behavior of turning for turns, swings, and odoms. You can choose between:
ez::raw
- this is the behavior prior to 3.2.0
ez::left_turn
/ ez::ccw
- this will always turn counterclockwise
ez::right_turn
/ ez::cw
- this will always turn clockwise
ez::longest
- this will always take the longest path there, capped at 360deg
ez::shortest
- this will always take the shortest path there
You can call these in default_constants()
in src/autons.cpp
to change what the default behavior is. The 3.2.0 example project has it as ez::shortest
.
pid_turn_behavior_set(ez::shortest);
pid_swing_behavior_set(ez::shortest);
pid_odom_behavior_set(ez::shortest);
Now you can change how the robot behaves in turns
void turn() {
chassis.pid_turn_behavior_set(ez::shortest);
chassis.pid_turn_set(90_deg, TURN_SPEED, ez::left_turn);
chassis.pid_wait();
chassis.pid_turn_set(45_deg, TURN_SPEED, ez::right_turn);
chassis.pid_wait();
chassis.pid_turn_set(0_deg, TURN_SPEED, ez::longest);
chassis.pid_wait();
// This will take the shortest route because that's the default behavior
chassis.pid_turn_set(359_deg, TURN_SPEED);
chassis.pid_wait();
}
🛹Global Slew
If you're tired of having true
at the end of all of your motions, you can now globally enable slew for each motion type! You can override the default in each motion, but it won't change the default unless you explicitly change it.
slew_drive_set(true)
slew_swing_set(true)
slew_turn_set
🎸Adding PIDs to PID Tuner
ez::PID liftPID{0.45};
Adding this line of code to initialize()
will add your PID to the tuner!
chassis.pid_tuner_pids.push_back({"Lift PID", &liftPID.constants});
🏃Opcontrol Max Speed
By calling this function before the while loop in opcontrol(0
, you'll retain the full range of motion of the joystick but your maximum speed will be 63. This can be a number from 0 to 127.
chassis.opcontrol_speed_max_set(63);
📺Blank LCD Pages
All blank pages will come after the autonomous selector. You can check if you're on them with ...
v3.2.0-beta.8
Default constants have changed in this version to make pointing towards angles less "mushy". You can upgrade your beta 7 project with no breaking changes.
What's Changed
Full Changelog: v3.2.0-beta.7...v3.2.0-beta.8
🎉ODOMETRY🎉
EZ-Template has odometry!! The easiest way to start messing with this is to start messing with it by downloading the example project below! You can also see the example project here.
🎡Tracking Wheels
You can create tracking wheels with EZ-Template using ADI Encoders (or 3rd party digital encoders) and rotation sensors.
// Are you using tracking wheels? Comment out which ones you're using here!
// `2.75` is the wheel diameter
// `4.0` is the distance from the center of the wheel to the center of the robot
ez::tracking_wheel right_tracker({-'A', -'B'}, 2.75, 4.0); // ADI Encoders
ez::tracking_wheel left_tracker(1, {'C', 'D'}, 2.75, 4.0); // ADI Encoders plugged into a Smart port
ez::tracking_wheel horiz_tracker(1, 2.75, 4.0); // Rotation sensors
To enable them, you'll need these lines of code in void initialize()
// Are you using tracking wheels? Comment out which ones you're using here!
chassis.odom_tracker_right_set(&right_tracker);
chassis.odom_tracker_left_set(&left_tracker);
chassis.odom_tracker_back_set(&horiz_tracker); // Replace `back` to `front` if your tracker is in the front!
🚗Odom Drive Syntax
If you have previous actions that you're porting over to 3.2.0 but you're not quite ready to retune odom stuff, you can try replacing .pid_drive_set
with .pid_odom_set
and it'll make your normal autons use odometry.
void drive_and_turn() {
chassis.pid_odom_set(24_in, DRIVE_SPEED, true);
chassis.pid_wait();
chassis.pid_turn_set(45_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_turn_set(-45_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_turn_set(0_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_odom_set(-24_in, DRIVE_SPEED, true);
chassis.pid_wait();
}
🐷Pure Pursuit
EZ-Template's Pure Pursuit is all done on the robot. chassis.pid_odom_set()
will be your main function and covers all aspects of odom. You can input as many points as you'd like here and the robot will path through all of them.
// Drive to 0, 30 and pass through 6, 10 and 0, 20 on the way, with slew
chassis.pid_odom_set({{{6_in, 10_in}, fwd, 110},
{{0_in, 20_in}, fwd, 110},
{{0_in, 30_in}, fwd, 110}},
true);
chassis.pid_wait();
You can combine going forward and reverse in the same motion
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait();
And you can pid_wait_until
a point has been reached
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{{12_in, 24_in}, rev, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
🪀Boomerang
Boomerang will try to go to a point at a specific angle. You use this by specifying an angle while using pid_odom_set()
chassis.pid_odom_set({{0_in, 24_in, 45_deg}, fwd, 110},
true);
chassis.pid_wait();
🪀🐷Boomerang Injected into Pure Pursuits
Any point that the robot goes to, if you specify the angle it'll become a boomerang motion, even if it's during a pure pursuit path!
chassis.pid_odom_set({{{0_in, 24_in, 45_deg}, fwd, 110},
{{12_in, 24_in}, fwd, 110},
{{24_in, 24_in}, fwd, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
👉Turn to Point
You can turn to face a point! All of the syntax for normal turning applies here, so you can do this:
chassis.pid_turn_set({12_in, 12_in}, fwd, 110, ez::longest, true);
Or you can keep it simple and do this
chassis.pid_turn_set({12_in, 12_in}, fwd, 110);
💄Mirrored Field Problem
To help with making unique autons for the left and right side of the field, EZ-Template 3.2.0 has a feature to flip what direction the X and Y axis face. By flipping these you're allowing 1 autonomous routine to work for red and blue.
odom_y_flip();
odom_x_flip();
odom_theta_flip();
odom_y_direction_get(); // True = down is positive Y, False = up is positive Y
odom_x_direction_get(); // True = left is positive X, False = right is positive X
odom_theta_direction_get(); // True = positive is counterclockwise, False = positive is counterclockwise
It is still suggested to make minor tweaks for both sides, nothing is perfect, but it'll be much easier to maintain with one base function.
void base() {
ez::united_pose start_intaking_here;
if (chassis.odom_x_direction_get() == false)
start_intaking_here = {12_in, 24_in}; // If red
else
start_intaking_here = {15_in, 24_in}; // If blue
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{start_intaking_here, rev, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
chassis.pid_odom_set({{24_in, 48_in, 45_deg}, fwd, 110},
true);
chassis.pid_wait();
chassis.pid_turn_set(90_deg, 110, true);
chassis.pid_wait();
}
void red() {
base();
}
void blue() {
chassis.odom_x_flip();
chassis.odom_theta_flip();
base();
}
🩰Turn Behavior
In every previous version of EZ-Template, turning used the raw IMU values. This was confusing to teams as turning to 360 and 0 were the same angle but would do different things. In 3.2.0 you can change the default behavior of turning for turns, swings, and odoms. You can choose between:
ez::raw
- this is the behavior prior to 3.2.0
ez::left_turn
/ ez::ccw
- this will always turn counterclockwise
ez::right_turn
/ ez::cw
- this will always turn clockwise
ez::longest
- this will always take the longest path there, capped at 360deg
ez::shortest
- this will always take the shortest path there
You can call these in default_constants()
in src/autons.cpp
to change what the default behavior is. The 3.2.0 example project has it as ez::shortest
.
pid_turn_behavior_set(ez::shortest);
pid_swing_behavior_set(ez::shortest);
pid_odom_behavior_set(ez::shortest);
Now you can change how the robot behaves in turns
void turn() {
chassis.pid_turn_behavior_set(ez::shortest);
chassis.pid_turn_set(90_deg, TURN_SPEED, ez::left_turn);
chassis.pid_wait();
chassis.pid_turn_set(45_deg, TURN_SPEED, ez::right_turn);
chassis.pid_wait();
chassis.pid_turn_set(0_deg, TURN_SPEED, ez::longest);
chassis.pid_wait();
// This will take the shortest route because that's the default behavior
chassis.pid_turn_set(359_deg, TURN_SPEED);
chassis.pid_wait();
}
🛹Global Slew
If you're tired of having true
at the end of all of your motions, you can now globally enable slew for each motion type! You can override the default in each motion, but it won't change the default unless you explicitly change it.
slew_drive_set(true)
slew_swing_set(true)
slew_turn_set
🎸Adding PIDs to PID Tuner
ez::PID liftPID{0.45};
Adding this line of code to initialize()
will add your PID to the tuner!
chassis.pid_tuner_pids.push_back({"Lift PID", &liftPID.constants});
🏃Opcontrol Max Speed
By calling this function before the while loop in opcontrol(0
, you'll retain the full range of motion of the joystick but your maximum speed will be 63. This can be a number from 0 to 127.
chassis.opcontrol_speed_max_set(63);
📺Blank LCD Pages
All blank pages will come after the autonomous selector. You can check if you're on them with page_blank_is_on(x)
and by doing so it'll create the page when you get to it on the selector.
if (ez::as::page_blank_is_on(0))
ez::screen_print("this is our first blank page", 1);
else if (ez::as::page_blank_is_on(1))
ez::screen_print("this is our second blank page", 1);
v3.2.0-beta.7
What do you do with your code?
There is a breaking change! odom_x_direction_flip
and odom_y_direction_flip
have been renamed to odom_x_flip
and odom_y_flip
. Besides that, you won't have to change anything else with your project.
What's Changed
Bugs
- Can now use relative drive after odom motions by @ssejrog in #196
- Path smoothing doesn't override lookahead (#202) by @ssejrog in #203
Features
- Can now flip angle (#161) by @ssejrog in #197
- Added units to wait_until (#199) by @ssejrog in #200
- Added
pid_wait_until_index_started
(#198) by @ssejrog in #201
Full Changelog: v3.2.0-beta.6...v3.2.0-beta.7
🎉ODOMETRY🎉
EZ-Template has odometry!! The easiest way to start messing with this is to start messing with it by downloading the example project below! You can also see the example project here.
🎡Tracking Wheels
You can create tracking wheels with EZ-Template using ADI Encoders (or 3rd party digital encoders) and rotation sensors.
// Are you using tracking wheels? Comment out which ones you're using here!
// `2.75` is the wheel diameter
// `4.0` is the distance from the center of the wheel to the center of the robot
ez::tracking_wheel right_tracker({-'A', -'B'}, 2.75, 4.0); // ADI Encoders
ez::tracking_wheel left_tracker(1, {'C', 'D'}, 2.75, 4.0); // ADI Encoders plugged into a Smart port
ez::tracking_wheel horiz_tracker(1, 2.75, 4.0); // Rotation sensors
To enable them, you'll need these lines of code in void initialize()
// Are you using tracking wheels? Comment out which ones you're using here!
chassis.odom_tracker_right_set(&right_tracker);
chassis.odom_tracker_left_set(&left_tracker);
chassis.odom_tracker_back_set(&horiz_tracker); // Replace `back` to `front` if your tracker is in the front!
🚗Odom Drive Syntax
If you have previous actions that you're porting over to 3.2.0 but you're not quite ready to retune odom stuff, you can try replacing .pid_drive_set
with .pid_odom_set
and it'll make your normal autons use odometry.
void drive_and_turn() {
chassis.pid_odom_set(24_in, DRIVE_SPEED, true);
chassis.pid_wait();
chassis.pid_turn_set(45_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_turn_set(-45_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_turn_set(0_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_odom_set(-24_in, DRIVE_SPEED, true);
chassis.pid_wait();
}
🐷Pure Pursuit
EZ-Template's Pure Pursuit is all done on the robot. chassis.pid_odom_set()
will be your main function and covers all aspects of odom. You can input as many points as you'd like here and the robot will path through all of them.
// Drive to 0, 30 and pass through 6, 10 and 0, 20 on the way, with slew
chassis.pid_odom_set({{{6_in, 10_in}, fwd, 110},
{{0_in, 20_in}, fwd, 110},
{{0_in, 30_in}, fwd, 110}},
true);
chassis.pid_wait();
You can combine going forward and reverse in the same motion
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait();
And you can pid_wait_until
a point has been reached
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{{12_in, 24_in}, rev, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
🪀Boomerang
Boomerang will try to go to a point at a specific angle. You use this by specifying an angle while using pid_odom_set()
chassis.pid_odom_set({{0_in, 24_in, 45_deg}, fwd, 110},
true);
chassis.pid_wait();
🪀🐷Boomerang Injected into Pure Pursuits
Any point that the robot goes to, if you specify the angle it'll become a boomerang motion, even if it's during a pure pursuit path!
chassis.pid_odom_set({{{0_in, 24_in, 45_deg}, fwd, 110},
{{12_in, 24_in}, fwd, 110},
{{24_in, 24_in}, fwd, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
👉Turn to Point
You can turn to face a point! All of the syntax for normal turning applies here, so you can do this:
chassis.pid_turn_set({12_in, 12_in}, fwd, 110, ez::longest, true);
Or you can keep it simple and do this
chassis.pid_turn_set({12_in, 12_in}, fwd, 110);
💄Mirrored Field Problem
To help with making unique autons for the left and right side of the field, EZ-Template 3.2.0 has a feature to flip what direction the X and Y axis face. By flipping these you're allowing 1 autonomous routine to work for red and blue.
odom_y_flip();
odom_x_flip();
odom_theta_flip();
odom_y_direction_get(); // True = down is positive Y, False = up is positive Y
odom_x_direction_get(); // True = left is positive X, False = right is positive X
odom_theta_direction_get(); // True = positive is counterclockwise, False = positive is counterclockwise
It is still suggested to make minor tweaks for both sides, nothing is perfect, but it'll be much easier to maintain with one base function.
void base() {
ez::united_pose start_intaking_here;
if (chassis.odom_x_direction_get() == false)
start_intaking_here = {12_in, 24_in}; // If red
else
start_intaking_here = {15_in, 24_in}; // If blue
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{start_intaking_here, rev, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
chassis.pid_odom_set({{24_in, 48_in, 45_deg}, fwd, 110},
true);
chassis.pid_wait();
chassis.pid_turn_set(90_deg, 110, true);
chassis.pid_wait();
}
void red() {
base();
}
void blue() {
chassis.odom_x_flip();
chassis.odom_theta_flip();
base();
}
🩰Turn Behavior
In every previous version of EZ-Template, turning used the raw IMU values. This was confusing to teams as turning to 360 and 0 were the same angle but would do different things. In 3.2.0 you can change the default behavior of turning for turns, swings, and odoms. You can choose between:
ez::raw
- this is the behavior prior to 3.2.0
ez::left_turn
/ ez::ccw
- this will always turn counterclockwise
ez::right_turn
/ ez::cw
- this will always turn clockwise
ez::longest
- this will always take the longest path there, capped at 360deg
ez::shortest
- this will always take the shortest path there
You can call these in default_constants()
in src/autons.cpp
to change what the default behavior is. The 3.2.0 example project has it as ez::shortest
.
pid_turn_behavior_set(ez::shortest);
pid_swing_behavior_set(ez::shortest);
pid_odom_behavior_set(ez::shortest);
Now you can change how the robot behaves in turns
void turn() {
chassis.pid_turn_behavior_set(ez::shortest);
chassis.pid_turn_set(90_deg, TURN_SPEED, ez::left_turn);
chassis.pid_wait();
chassis.pid_turn_set(45_deg, TURN_SPEED, ez::right_turn);
chassis.pid_wait();
chassis.pid_turn_set(0_deg, TURN_SPEED, ez::longest);
chassis.pid_wait();
// This will take the shortest route because that's the default behavior
chassis.pid_turn_set(359_deg, TURN_SPEED);
chassis.pid_wait();
}
🛹Global Slew
If you're tired of having true
at the end of all of your motions, you can now globally enable slew for each motion type! You can override the default in each motion, but it won't change the default unless you explicitly change it.
slew_drive_set(true)
slew_swing_set(true)
slew_turn_set
🎸Adding PIDs to PID Tuner
ez::PID liftPID{0.45};
Adding this line of code to initialize()
will add your PID to the tuner!
chassis.pid_tuner_pids.push_back({"Lift PID", &liftPID.constants});
🏃Opcontrol Max Speed
By calling this function before the while loop in opcontrol(0
, you'll retain the full range of motion of the joystick but your maximum speed will be 63. This can be a number from 0 to 127.
chassis.opcontrol_speed_max_set(63);
📺Blank LCD Pages
All blank pages will come after the autonomous selector. You can check if you're on them with page_blank_is_on(x)
and by doing so it'll create the page when you get to it on the selector.
if (ez::as::page_blank_is_on(0))
ez::screen_print("this is our first blank page", 1);
else if (ez::as::page_blank_is_on(1))
ez::screen_print("this is our second blank page", 1);
v3.2.0-beta.6
Small bug fixes. beta.5 seems like it's performing very well with teams, this should be one of the last releases before a full 3.2.0 release!
What do you do with your code?
If you tuned PID constants for beta 5, you might have to adjust them slightly for beta 6. Making odom_turn_bias(0.5)
a larger number, like 0.8 or 0.9, will probably fix it for you. xyPID during pure pursuit now calculates derivative correctly, so it has "larger brakes". Increasing turn bias will lower the brakes that EZ-Template applies to xyPID when entering a turn.
What's Changed Changed since beta.5
- Turn to point now respects angle behavior by @ssejrog in #193
- Robot will now successfully face points in quadrant 3 @ssejrog in #194
Special thank you to @aayala04 for helping debug and spend time testing beta.3, beta.4, and beta.5!
Full Changelog: v3.2.0-beta.5...v3.2.0-beta.6
🎉ODOMETRY🎉
EZ-Template has odometry!! The easiest way to start messing with this is to start messing with it by downloading the example project below! You can also see the example project here.
🎡Tracking Wheels
You can create tracking wheels with EZ-Template using ADI Encoders (or 3rd party digital encoders) and rotation sensors.
// Are you using tracking wheels? Comment out which ones you're using here!
// `2.75` is the wheel diameter
// `4.0` is the distance from the center of the wheel to the center of the robot
ez::tracking_wheel right_tracker({-'A', -'B'}, 2.75, 4.0); // ADI Encoders
ez::tracking_wheel left_tracker(1, {'C', 'D'}, 2.75, 4.0); // ADI Encoders plugged into a Smart port
ez::tracking_wheel horiz_tracker(1, 2.75, 4.0); // Rotation sensors
To enable them, you'll need these lines of code in void initialize()
// Are you using tracking wheels? Comment out which ones you're using here!
chassis.odom_tracker_right_set(&right_tracker);
chassis.odom_tracker_left_set(&left_tracker);
chassis.odom_tracker_back_set(&horiz_tracker); // Replace `back` to `front` if your tracker is in the front!
🚗Odom Drive Syntax
If you have previous actions that you're porting over to 3.2.0 but you're not quite ready to retune odom stuff, you can try replacing .pid_drive_set
with .pid_odom_set
and it'll make your normal autons use odometry.
void drive_and_turn() {
chassis.pid_odom_set(24_in, DRIVE_SPEED, true);
chassis.pid_wait();
chassis.pid_turn_set(45_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_turn_set(-45_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_turn_set(0_deg, TURN_SPEED);
chassis.pid_wait();
chassis.pid_odom_set(-24_in, DRIVE_SPEED, true);
chassis.pid_wait();
}
🐷Pure Pursuit
EZ-Template's Pure Pursuit is all done on the robot. chassis.pid_odom_set()
will be your main function and covers all aspects of odom. You can input as many points as you'd like here and the robot will path through all of them.
// Drive to 0, 30 and pass through 6, 10 and 0, 20 on the way, with slew
chassis.pid_odom_set({{{6_in, 10_in}, fwd, 110},
{{0_in, 20_in}, fwd, 110},
{{0_in, 30_in}, fwd, 110}},
true);
chassis.pid_wait();
You can combine going forward and reverse in the same motion
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait();
And you can pid_wait_until
a point has been reached
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{{12_in, 24_in}, rev, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
🪀Boomerang
Boomerang will try to go to a point at a specific angle. You use this by specifying an angle while using pid_odom_set()
chassis.pid_odom_set({{0_in, 24_in, 45_deg}, fwd, 110},
true);
chassis.pid_wait();
🪀🐷Boomerang Injected into Pure Pursuits
Any point that the robot goes to, if you specify the angle it'll become a boomerang motion, even if it's during a pure pursuit path!
chassis.pid_odom_set({{{0_in, 24_in, 45_deg}, fwd, 110},
{{12_in, 24_in}, fwd, 110},
{{24_in, 24_in}, fwd, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
👉Turn to Point
You can turn to face a point! All of the syntax for normal turning applies here, so you can do this:
chassis.pid_turn_set({12_in, 12_in}, fwd, 110, ez::longest, true);
Or you can keep it simple and do this
chassis.pid_turn_set({12_in, 12_in}, fwd, 110);
💄Mirrored Field Problem
To help with making unique autons for the left and right side of the field, EZ-Template 3.2.0 has a feature to flip what direction the X and Y axis face. By flipping these you're allowing 1 autonomous routine to work for red and blue.
odom_y_direction_flip();
odom_x_direction_flip();
odom_y_direction_get(); // True = down is positive Y, false = up is positive Y
odom_x_direction_get(); // True = left is positive x, false = right is positive x
It is still suggested to make minor tweaks for both sides, nothing is perfect, but it'll be much easier to maintain with one base function.
void base() {
ez::united_pose start_intaking_here;
if (chassis.odom_x_direction_get() == false)
start_intaking_here = {12_in, 24_in}; // If red
else
start_intaking_here = {15_in, 24_in}; // If blue
chassis.pid_odom_set({{{0_in, 24_in}, fwd, 110},
{start_intaking_here, rev, 110},
{{24_in, 24_in}, rev, 110}},
true);
chassis.pid_wait_until_index(1); // Waits until the robot passes 12, 24
Intake.move(127);
chassis.pid_wait();
}
void red() {
base();
}
void blue() {
chassis.odom_x_direction_flip();
base();
}
🩰Turn Behavior
In every previous version of EZ-Template, turning used the raw IMU values. This was confusing to teams as turning to 360 and 0 were the same angle but would do different things. In 3.2.0 you can change the default behavior of turning for turns, swings, and odoms. You can choose between:
ez::raw
- this is the behavior prior to 3.2.0
ez::left_turn
/ ez::ccw
- this will always turn counterclockwise
ez::right_turn
/ ez::cw
- this will always turn clockwise
ez::longest
- this will always take the longest path there, capped at 360deg
ez::shortest
- this will always take the shortest path there
You can call these in default_constants()
in src/autons.cpp
to change what the default behavior is. The 3.2.0 example project has it as ez::shortest
.
pid_turn_behavior_set(ez::shortest);
pid_swing_behavior_set(ez::shortest);
pid_odom_behavior_set(ez::shortest);
Now you can change how the robot behaves in turns
void turn() {
chassis.pid_turn_behavior_set(ez::shortest);
chassis.pid_turn_set(90_deg, TURN_SPEED, ez::left_turn);
chassis.pid_wait();
chassis.pid_turn_set(45_deg, TURN_SPEED, ez::right_turn);
chassis.pid_wait();
chassis.pid_turn_set(0_deg, TURN_SPEED, ez::longest);
chassis.pid_wait();
// This will take the shortest route because that's the default behavior
chassis.pid_turn_set(359_deg, TURN_SPEED);
chassis.pid_wait();
}
🛹Global Slew
If you're tired of having true
at the end of all of your motions, you can now globally enable slew for each motion type! You can override the default in each motion, but it won't change the default unless you explicitly change it.
slew_drive_set(true)
slew_swing_set(true)
slew_turn_set
🎸Adding PIDs to PID Tuner
ez::PID liftPID{0.45};
Adding this line of code to initialize()
will add your PID to the tuner!
chassis.pid_tuner_pids.push_back({"Lift PID", &liftPID.constants});
🏃Opcontrol Max Speed
By calling this function before the while loop in opcontrol(0
, you'll retain the full range of motion of the joystick but your maximum speed will be 63. This can be a number from 0 to 127.
chassis.opcontrol_speed_max_set(63);
📺Blank LCD Pages
All blank pages will come after the autonomous selector. You can check if you're on them with page_blank_is_on(x)
and by doing so it'll create the page when you get to it on the selector.
if (ez::as::page_blank_is_on(0))
ez::screen_print("this is our first blank page", 1);
else if (ez::as::page_blank_is_on(1))
ez::screen_print("this is our second blank page", 1);
v3.2.0-beta.5 - Tracking Wheels! (frfr this time)
beta.4 worked great with IMEs, but as soon as you stated to use trackers it became hit or miss. beta.5 solves this and aims to give consistent behavior between using trackers and imes.
This includes breaking changes from beta.4
PID constants for odom will have to be retuned along with trackers being renamed from odom_left_tracker
to odom_tracker_left
. If you have autons on previous betas, I would suggest testing the beta.5 example project out before you upgrade your main project.
What's Changed since beta.4
- Fixed tracking inconsistencies by @ssejrog in #187
- Fixed border typo by @jemminiz in #183
- Added arcade vector scaling #185 by @ssejrog in #188
- Opcontrol speed limit by @ssejrog in #189
- Fixed segfault #186 by @ssejrog in #190
New Contributors
Full Changelog: v3.2.0-beta.4...v3.2.0-beta.5
v3.2.0-beta.4 - Tracking Wheels! (fr this time)
Full Changelog: v3.2.0-beta.3...v3.2.0-beta.4
v3.2.0-beta.4
This version is stable
This is very close to what RC1 will be. This is being released now for testing while extra documentation is made in drive.hpp
. There is still a chance breaking changes happen between this and RC1 / the full 3.2.0 release.
Features since beta.3
- you can now remove blank pages
Bug fixed since beta.3
- rotation sensors will actually reverse in tracking wheels
- fixed typos in example project
Refactoring
- drive.hpp now has comments
Missing Features
Once this bug is fixed/figured out, the new drive constructor will work and will allow you to input track width into the constructor. Additional comments are needed in drive.hpp
, and new example autonomous routines are needed to show how odom works.
What should you test?
Something cool about this version is pid_odom_set
now supports the same syntax as pid_drive_set
. So you can take one of your autos from a previous 3.x version, change pid_drive_set
to pid_odom_set
, and you'd have tracking in your autons! This will not be as good as telling the robot what points to go to, as accumulative error will still happen, but each motion should be more accurate with this.
v3.2.0-beta.3 - Tracking Wheels!
Full Changelog: v3.2.0-beta.2...v3.2.0-beta.3
v3.2.0-beta.3
This version is stable
This is very close to what RC1 will be. This is being released now for testing while extra documentation is made in drive.hpp
. There is still a chance breaking changes happen between this and RC1 / the full 3.2.0 release.
Features since beta.2
- tracking wheel support
- turn directions
pid_drive_set
syntax is compatible withpid_odom_set
- blank pages can be added to the auton selector
- "mirrored field problem" is solved
- blanket enables for slew
- odom units
clamp()
now has an option for 2 parameters- slew reenables when speed increases during pure pursuits
- you can add custom stuff to pid tuner
Bug fixed since beta.2
- disabling PID now turns the drive motors off
Missing Features
Once this bug is fixed/figured out, the new drive constructor will work and will allow you to input track width into the constructor. Additional comments are needed in drive.hpp
, and new example autonomous routines are needed to show how odom works.
What should you test?
Something cool about this version is pid_odom_set
now supports the same syntax as pid_drive_set
. So you can take one of your autos from a previous 3.x version, change pid_drive_set
to pid_odom_set
, and you'd have tracking in your autons! This will not be as good as telling the robot what points to go to, as accumulative error will still happen, but each motion should be more accurate with this.