# Feedforward Tuning
 Tuning the feedforward controller for accurate following is necessary for for accurate path following. Poor tuning of the feedforward controller will result in errors later along the line. Although the Road Runner quickstart comes with both an automatic tuner and a manual tuner, many find that the automatic tuner does not provide optimal results. The automatic tuner isn't able to properly calculate kA. However, you are free to try and run it and use the gains it produces. I would recommend manually tuning those results afterwards.
TIP
You can press X (on the Xbox and Logitech gamepads, square on the PS4 dualshock) to pause the tuning process and enter driver control.
Press A (on the Xbox and Logitech gamepads, X on the PS4 dualshock) to cede control back to the tuner.
If your bot drifts off path, simply enter driver control and drive your bot back to the initial position.
# Tuning
WARNING
It is likely that your robot will slowly drift off course throughout the tuning process, this is normal and will be fixed later during heading and translational pid tuning.
The first step is to run the
ManualFeedforwardTuneropmode via the RC.Then, connect to the RC phone's wifi network. The password to the network is located in the
Program and Managemenu.Navigate to
192.168.49.1:8080/dashwith a phone RC or192.168.43.1:8080/dashwith a Control Hub.
Your page should look something like this:
 (Ignore the graph content. This is just a sample of the page layout)
Run the opmode. The graph will not show up until you have started it.
- Make sure to click the graph button after you run the program. If the graph still doesn't show up, and instead shows a number of checkboxes, that's okay. Click the 
targetVelocityandposeVelocitycheckbox. 
- Make sure to click the graph button after you run the program. If the graph still doesn't show up, and instead shows a number of checkboxes, that's okay. Click the 
 In Dashboard, look for the
DriveConstantsdropdown on the right. Press it and it should open a drop down. Then, look for thekA,kV, andkStaticvariables. You will be tuning these in a second.
WARNING
This step is important. If you don't have a plateau, your kV is likely wrong and you will experience accuracy issues later. Increase distance until you have a relatively long velocity plateau on your graph.
- In the 
ManualFeedforwardTunerdrop down, ensure that theDISTANCEvariable is large enough so thetargetVelocityline has a plateau. If it resembles a series of triangles, increase theDISTANCE. 
TIP
If you do not have enough distance, you can increase your MAX_ACCEL in drive constants (if your robot is capable of it) or lower MAX_VEL in drive constants. This will affect the speed/acceleration of trajectories, so beware.
At this point, once you have run the opmode, the bot should be moving back and forth along the distance specified in the opmode file. The goal is for the
poseVelocityline to match thetargetVelocityline.Recommended tuning process:
kVshould initially be set to1 / max velocity. TheposeVelocityline should be touching the top of thetargetVelocityplateau. If not, increasekV.Increase
kAto try and get the slope of theposeVelocityline to matchtargetVelocity.Here is a reference to visualize what these gains should be doing.
 Tuning Tips These tips come from FRC Team 1712's Adaptive Pure Pursuit paper (opens new window)
That should be it! An example of a decently tuned feedforward controller can be found below.
Any adjustments in dashboard need to be copied over to the
DriveConstants.javafile under the equivalent variable name. Dashboard adjustments are temporary and will reset once you restart the opmode.Check the tuning simulator to see how each gain affects the behavior.
Note: The graph doesn't need to be perfect. Just "good enough." You can waste an infinite amount of time trying to perfect it. In addition to that, the Rev Hub's internal motor controller is a little odd and you will have a slight bump on deceleration that will be impossible to get rid of.
Decently tuned feedforward controller courtesy of Deetz from Team 14320:
 You may notice the asymmetry in the acceleration. Unfortunately, perfect velocity control is not yet achievable with a stock motor control model due to this asymmetry. Notice that the acceleration does not track well when decelerating. We suspect that this is due to weird Rev Hub's unique motor controller. For more details, or if you have a solution to this problem, please hit up the FTC Discord (opens new window).
TIP
The voltage that the REV Hub outputs will decrease as the battery level drops. Because of this, feedforward isn't guaranteed to be consistent throughout multiple matches. At this moment, Road Runner does not have explicit pose velocity closed loop control. There is a slight workaround to this. The translational PID controller's kD term is essentially equivalent to the kP term of a pose velocity PID controller. If you notice motion profile performance degradation along multiple matches, add a kD term to the translational PID (which you will tune in the follower PID page). Further questions or don't quite understand this concept? Hit up the FTC Discord (opens new window) and shoot a question in the programming channel!
WARNING
As mentioned prior, the REV Hub's motor controller has issues decelerating properly. This makes it impossible to properly tune the feedforward on the deceleration phases (when the velocity moves toward zero). This causes an overshoot every time. If you seem to be exhibiting a 10% overshoot, that is to be expected from the poor deceleration. Simply ignore it and move forward. The follower PIDs will take care of the issue. Ensure that you set kD to a non-zero value in the follower PID tuning steps.
# Troubleshooting
Your
MaxVelocityTuneris going backwards- Ensure that your wheels are reversed correctly. Check the goBILDA mecanum chart to use as a reference while debugging
 
The pose velocity line is going the opposite way and not following
targetVelocity:- Your localization is bonked. Run 
LocalizationTestand ensure that the reported pose matches the bot's actual pose. Ensure that thegetWheelVelocitiesfunction in your localizer (either inSampleMecanumDriveor the dead wheel localizers) match the signs in yourgetWheelPositionsfunction. 
- Your localization is bonked. Run 
 The StraightTest or ManualFeedforwardTuning opmode keeps overshooting and tweaking variables in
DriveConstants.javajust doesn't change anything:- Try lowering the 
MAX_VELinDriveConstants.java. Set it to a really low value at first to confirm that this is the problem. 
- Try lowering the 
 Miscellaneous motor direction problems:
- See reversing motor directions
 - Refer to the Motor Direction Debugger opmode (opens new window) if you are struggling to debug your motor config. The Motor Direction Debugger allows you to run your motors one by one. Remove the 
@Disabledlin on line41and follow the directions in the opmode comments. Use this to diagnose your motor config problem and fix appropriately. 
# Feedforward Tuning Simulator
time  | -- | 
|---|---|
targetVelocity  | -- | 
velocity0  | -- | 
Play around with the gains to see how each one affects the graph! Try and tune this simple example. This graph is very similar to what you will be doing while actually tuning the bot so having an understanding of how the process will go will be beneficial.
Tip: Press enter in the text input for your new gain to take effect (just like FTC-Dashboard!).
WARNING
This is a very very rudimentary "simulator." It is only meant to give you a basic high level understanding of how the gains affect the behavior of the graph. It is in no way trying to accurately simulate the Rev Hub's motor controller as that presents its own problems. This sim is based on a simple DC Motor model with arbitrary constants. The sim will not behave exactly like how your actual tuning will go but it is meant to give you a decent intuition of how it works. Also, I am very aware of the bugs it has. That's what the "reset" button is for 😛
# Temporary Informal Video
Temporary informal video while the polished, edited videos are in production. Quality is atrocious but hopefully it helps 😃