# FeedForward for Arm motion

There are a few thread active on feedforward gains for Arms. They all have great information. To attempt to not snipe the thread or get lost here is a new on stemmed from what I believe I learned.

https://www.chiefdelphi.com/t/paper-understanding-feedforward-models-for-frc/169109

FeedForward will change as an arm swings through it motion.
The Algorithm may look something like this for a PID

Subsystem

``````private void calculateFF(double currentAngle){
double armLenght = 10.0; //inches
double armWeight = 10.0; //lbs

//Redline motor
double mortorOhms = .112; //internal Resistance
double motorTorqe = 5.55; //Inch*lbs
double motorStallCurrent = 106.9; //amps

//Total Gear Reduction
double gearBox = 200;
double Kt = (motorTorqe/motorStallCurrent);

double kF = ( (armLenght*armWeight*mortorOhms) / (Kt*gearBox) ) * Math.cos(Math.toRadians(currentAngle));

getPIDController().setF(kF);
}
``````

Now What?

There is no periodic method in a PIDSubsystem (When using a PID

controller on the RoboRio to call this function. Maybe the returnPIDInput() method could call this calculateFF() before returning the input.

If using the a TalonSRX the command that set the setpoint could call this calculateFF() in its execute() method untill its complete setting the kf value of the affected motor controller.

The few name I recall that got me to this point @ozrien @dydx @NewtonCrosby @krf

This is exactly why I would not use the WPILib PIDSubsystem in particular- it is very inflexible for more advanced controllers.

When using the PIDController class, you can override the calculateFeedForward function to do this math.

When using the Talon SRX, you can use the arbitraryFeedForward term to do this (calculate it on execute loop)

Correct.

@cpapplefamily, I’m currently working on the same problem. This is what I intend to do. I’d be interested if anyone else has comments on this approach.

1. Use a default command for the arm subsystem so that the execute function is called periodically.
2. Store the current mode in a variable (Percent-Out or Motion-Magic or Position Closed Loop, etc…) in your subsystem along with the set-point.
3. Depending on the mode, give the Talon the correct output including the calculated AFF value.
It appears to be OK to set the Motion-Magic target multiple times. This should answer your main question.
4. Create a command which sets the MM set-point of the subsystem and switches modes.
5. Check for joy-stick input periodically and switch to percent-out if any is read as a manual override.
6. Check for the end of your closed-loop motion by comparing the current position against your set point. Switch back to percent-out when close enough, or no motion for some N tics.
7. If returning to your starting position, consider resetting your encoder to zero after ending the closed-loop mode.

So a standard Subsystem with a PIDController would be best thanks I will look at that.

x

@ozrien
Will my issues of using a potentiometer like on my elevator with the 10turn pot creep into this being to low of a resolution? Or since in this case I would be using ~100 deg of a 170deg pot be ok. The Elevator was the first time we used a pot on the TalonSRX as feedback and it was not a great experience.

We are starting into the Black Magic of controls. I thought I understood but after creating a Subsystem with my Motor, Pot and a PIDController I began to poke into the PIDController.class. I don’t see a calculateFeedForward function.

It ended up in PIDBase, maybe after the rewrite this season.

So do I need to create my own PIDController that extends PIDBase … Basically copy and rename the WPILib PIDController?

``````public class myPIDController extends PIDBase implements Controller {

//Copy all the code of the WPILibs PIDControlller
@Override
public double calculateFeedForward(double currentAngle){
double armLenght = 10.0; //inches
double armWeight = 10.0; //lbs

//Redline motor
double mortorOhms = .112; //internal Resistance
double motorTorqe = 5.55; //Inch*lbs
double motorStallCurrent = 106.9; //amps

//Total Gear Reduction
double gearBox = 200;
double Kt = (motorTorqe/motorStallCurrent);

return  ( (armLenght*armWeight*mortorOhms) / (Kt*gearBox) ) * Math.cos(Math.toRadians(currentAngle));

}
``````

All so I can expose and utilize the function? Seems like a lot of work but even then the TalonSRX option I have not seen much about how that works either.

You can just extend PIDController and override calculateFeedForward, which re-uses the PIDController code with your custom feed-forward.

You can also do all of this in a PIDCommand, which is my preferred method, and calculate your feedforward in the useOutput method.

If that’s the case then Adding some code to the PIDSubsystem useOutput() like I shared above would work too.

`private void calculateFF(double currentAngle){`

My recommendation is to use motionMagic + arbFF.

Any issues with using an analog potentiometer here for feed back? I ask because of the issue I had using one on our elevator and not having enough resolution to smooth the motion Profile.

Yep, that should do it!

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.