Understanding and Tuning Smart Motion for an arm

I’m trying to program our arm to reach a particular angle setpoint. I’ve already looked at the smart motion example code but I am a bit confused about how to tune it and how exactly it works. What exactly is smart motion and how can I tune it for an arm? What I understand so far is that it is just a modified version of a PIDF control loop. Any tips on how to tune smart motion and how it works are greatly appreciated. Thanks in advance.

You might need to provide more info about what you’re looking for. Start by reading about motion profiles in the WPILib docs.

Since you said “Smart Motion”, not “Motion Magic” or “ProfiledPID”, I’m guessing you’re using a REV Spark Max. Here is REV’s example: Smart Motion example. Here is a link to our wrist code, our wrist is just an arm on a stick.

I think CTRE’s documentation is a little more complete than REV’s in describing motion profiles, take a look at the Gravity Offset Arm documentation.

1 Like

Do not use SmartMotion. It has some poor choices in how it is implemented that make it rather ineffective as an option for position control.


Can you elaborate on those poor choices?

The profile setpoints are piped to the velocity controller instead of the position controller.


What is the resulting effect?

1 Like

Measurement delay and accumulating steady-state position error.


Do you still get these effects when using a through bore encoder wired directly to the spark max and running Smart Motion on the spark max? I was under the impression that the velocity delay was being caused by noisy velocity data that was then being smoothed with a moving average that would cause inherent latency.

EDIT: I remember reading somewhere that generating motion profiles on the Rio and running pid from there was roughly equivalent to running spark max onboard control with the delayed data. Thoughts?

Do you have an example of alternative code you are willing to share? I think it would be helpful to the original poster if they were provided some additional direction and support


I haven’t tried it but could you run PI with smart motion? Probably wouldn’t be as good as closing the loop on the position trajectory like motion magic does but maybe it would mitigate some of the steady-state error. Or maybe a rio control loop is still better…

Are there any alternatives besides motion magic that we can use on a spark max? The method needs to accurate as our arm is our primary way to score

You will only be able to run the rev provided control systems if you are looking to run onboard the spark max. We are using smart motion on our wrist which is a very robust system and haven’t necessarily noticed the accumulation of steady state error, but its also not running very fast or going very far. It was a breeze to tune which was also nice. For my teams shoulder joint we are using a rio control loop that’s running a trapezoidal motion profile with pid(profiled pid controller) and it works alright, but because of the larger time scales with which it calculates at, it is less smooth than I would have otherwise hoped. For the mechanisms that use falcons for our team motion magic is a go to because it just works, once you understand what it’s doing. In your case, with this flaw of the rev controller though, I would suggest a profiled pid controller if I were you.

You mean use something like this and compensate for gravity using an arbitrary feedforward? Could that work?

Yes exactly, but you can obtain your feedforward coefficients from sysid which would be easier.

1 Like

Any finitely-differenced velocity measurement is inherently lagged, so i don’t think there’s a way around this entirely. You can make it better or worse by toying with the filtering settings.

The best bet is to use a trapezoid profile on the RIO and the motor controller’s onboard position controller.

1 Like

As we are switching to SparkMaxes, and have heard the Neo encoders are no great for closed loop position control, looking for advice:

  • For position control, is alternate encoded required?
  • Can someone provide a good example of java code for doing position closed loop with SparkMax / NEO?

The NEO encoders are fine for position control. They’re questionable for velocity control.


The biggest downsides to SmartMotion using velocity control are:

  1. If your system over or undershoots, position control won’t keep trying to correct it. When you use position control, at the end of a profile it will keep correcting any error automatically, whereas with velocity control the last setpoint it gets is just “set velocity = 0”. You can get around this by switching from SmartMotion to Position mode on the RIO once it finishes, but that’s extra code to write.
  2. The biggest one in my opinion: you have to tune a velocity control loop on a position based mechanism. Tuning a velocity loop is pretty straightforward on a drivetrain or especially something like a flywheel, where it can keep spinning forever. But on a mechanism like an arm with limited extension, it’s not as easy to figure out max speed, feedforward constants, etc. It’s way more intuitive to tune small movements via position control mode, and then tune motion profiles via MotionMagic on CTRE devices, or by setting up profiles on the RIO and sending setpoints in Position mode for REV devices.
1 Like

Feeding it setpoints in a sense and letting it interpolate between those?

1 Like

Yes, plus appropriate feedforward to drive the dynamics.