Closed Loop Control on a Rotating Arm


I have a few questions in terms of closed-loop control, specifically for an arm which rotates 180 degrees.

  1. Using the TalonSRX + the SRX magnetic encoder, which application would work best in terms of inputting a setpoint angle and having the arm move to said angle: Motion Magic, Motion Profiling, or Position Closed Loop?

  2. I understand how PID works, but I am confused when it comes to PIDf. I read nickbrickmaster’s post (Velocity Limiting PID) on determining the feedforward value through physics, but am confused on how you would apply it in the case of using closed-loop control with the TalonSRX’s and setting the gains. Assuming that the voltage necessary to hold the arm is FF = (Arm Weight) * (Distance to arm center of mass) / (Motor stall torque) * (Number of motors) * (Gear Ratio) ] * cos(theta) (taken from nick’s post), this implies that the feedforward value changes as the arm moves.

In order to use this, wouldn’t you have to change the kF gain as the arm moves? Am I missing something?


(cool, new CD notifies you when your post is linked)

(2) is correct. Feedforward in this case is a function of robot state. It’s alright to update this from your robot loop, as the 20ms lag on FF value isn’t that significant. Make sure you divide out the setpoint.

For 1, it matters on how much time you’re willing to invest to get marginal improvements. I would go with motion magic, as the Motion Profile mode is the same thing, but you have to generate the trajectory instead. Motion Magic will have a smoother motion than position closed loop because it’s a motion profile- that is, speed up, cruise, slow down smoothly to a stop. Position closed loop doesn’t limit acceleration, so if you have a massive arm you will have overshoot and a long settling time at best, and tear your robot apart at worst.


So assuming I use motion magic, would this work?

write a function to calculate the angle of the arm, plug the angle into the feedforward equation, then return the calculated gain.

put talon.config_kF(feedForward()); in robotPeriodic().


I would instead use the Arbitrary Feed Forward function, as during Motion Magic kF gets multiplied by the target velocity. Make sure you use the correct units as well.


I would recommend starting with classic Motion Magic, particularly if you are unfamiliar with the tech, with a conservative acceleration value.

You likely will still want to dial kF since it profiles target-velocity. Even if you plan on using arbFeedFwd later. Otherwise you many need to include velocity/accel/etc in addition to your gravity compensation.

Then you can leverage the arbFeedFwd for your gravity compensation, basically use the 4-param set and calculate your feed-forward as you like. You can poll the current sensor position - which you will likely need for your math.

And you can always set kF to zero if you only want your calculated feed-forward portion of the math. This allows for great experimentation, so you can connect software-changes to your results.

Doc section for posterity

FeedForward for Arm motion

If I do Plan to use ArbitraryFeedForward should I Zero the kF on the PID0 Slot?


See if the stuff on this thread helps: Motion Magic with an Arm

TL;DR Because motion magic generates the velocity setpoints internally, you have to use kF for the velocity-proportional part of the feedforward. Arbitrary feedforward is probably best used just to compensate for external forces.


That is what is happening in the case of an arm. At the top We only need minimal if not near zero feed forward but at 90 deg we need the full value. So in the PID-Slot[0] do we set to zero and in the ArbitraryFeedForward do we use the COS[currentAngle] * Full_FeedForward.


See this post from a while ago:

And this snippet:

And finally this post:

Let me know if I am misinterpreting your question and linking unhelpful responses.


I have read all(most) of the threads and papers. It seems to me that in the case of an arm with the variable of gravity acting on it having a static FeedForward term is not necessary. When ever we have attempted to tune up an arm we have troubles with it being either to hot raising crashing into stops or not enough power to raise it. I’ve been thinking the relatively large kF needed to get it past horizontal is driving the arm into the top stop because the arm weight near nothing at that time and leading me to think we only need arbitraryFF so at 0 deg we use all the kF term but at 90 we use none.
It seem like this would allow us to chase our bicycle friend as we go up and down the hills. I visualize the FeedForward term as needed to keep up while on flat ground but with an arm it feels like we are either chasing up hill (Arm at 0 deg COS(0)=1) or going down hill (Arm at 90 COS(90)=0)
Maybe I need to input some D-term to hold the reins in. Since we spend nearly no time on flat ground.

A Good practical video is need with someone tuning up an arm. Then if needed a follow up going into the theory. The read my code links has many of us lost


You are correct that with an arm, you want to factor in the current angle of the arm when calculating the arbitrary feedforward to compensate for gravity. The calculation should be (output required to hold arm at horizontal) * cos(angle to horizontal).


While I haven’t worked through too many examples, I also think you’d want a combination of arbitrary and velocity feed forward. One will depend on the position of the arm, the other on how fast you want the arm to move. Sure, you could do all the math to combine them into a single term, but why go through the extra effort?

Imagine the arm were laying on its side, making the effects of gravity constant throughout the rotation. In that case, you’d want some (estimated) mapping between motor input and output rotation speed. That’s what Kf does. It gets you most of the way to the correct motor input given the desired output.

Now flip the arm back upright. Gravity now matters. The goal of arb FF in that case is to work against gravity to make it behave as-if it were on its side again. That is, it would try to balance out gravity and hold the arm steady (at any orientation) so that any other forces make it easy to move in either direction. One of those forces would be the ones applied by closed loop Kf feed forward term.

My approach would be to use % output to get the value needed to barely hold the arm straight out. Use this as the constant term mentioned in the post above me multiplied by cos(theta), and have my Set() call constantly update the demand1 value in arb feed forward mode.

Then switch to motion magic mode. Run the arm while plotting encoder speed vs. the profile desired velocity. Tune Kf until they line up during steady state. Yes, this can be scary when the arm has a limited range of motion … turn down cruise velocity and acceleration to something that can be stopped in time in case of danger then work up slowly.

After that, you’re like 90% of the way there. Add some moderate P gain and likely it’ll be good. Fine tune as needed. But as mentioned above, if both arb FF and Kf are solid the error term is going to be small so PID won’t have a huge impact on the overall behavior of the system.


Thank you a light just came on with the visualization of first turning the system on the side to remove gravity then putting it up right. Arbitrary FeedForward is a counter balance spring proportional to the angle of the arm.