Motion Profiling with Pathfinder and Talon SRX

This week was very productive for my programming team. We managed to implement motion profiling two different ways using Jaci’s Pathfinder and Talon SRX motor controllers.

One team managed to create integrate via Jaci’s instructions to varying results and generated a command to drive the path. the other team used the path generated by Pathfinder and commanded via the Talon MPE interface.

Both had varying results because we didn’t spend any time tuning the PIDF parameters of their respective drive trains, which we will hopefully have time with this week on our practice bot.

I do have one question with respect to the Talon Control Mode for Jaci’s integration using SRX’s. After watching it run several times (rather inconsistently). They have the control mode set for the Talons in “PercentVbus”. Am not entirely sure looking through the integration steps but would the Talon “Speed” control mode be the better closed loop control for the implementation using the Talon SRX?

Any guidance you could provide would be greatly appreciated.

PercentVbus is not closed loop at all, it is raw 0-100% power of the talon SRX with no PID control.

Speed control on the Talon SRX eliminates the need for any closed loop control by the roboRIO. If you’ve configured your talon SRX with encoders hooked up to it, in speed control, you can feed it a target wheel speed (in rotations per minute I believe) and the Talon SRX will perform its own on board closed loop control to maintain a target wheel speed (need to configure the Talon’s PID values through the roboRIO web based configuration tool). Motion profiling and using the on board closed loop function in PercentVbus is not recommended as that will make the talon target a “Percent” of the “Voltage (V)” that is available to the robot from its battery. As the battery voltage changes, your profile will behave completely different. It is better to have the talon target a set wheel speed by setting it to speed control mode since closed looping to a wheel speed will make your system independent of the charge on your battery, and therefore, much more consistent.

Using the Talon SRX MPE interface is certainly possible, and I believe some teams have done it with some success. In this case, you’d want the MotionProfile control mode.

My integration (here) uses the RoboRIO to calculate the closed loop control of the motor (Perr + D(derr/dt)+Vvel+Aacc). This integration does NOT use closed loop control on the SRX, meaning it stays in PercentVBus mode.

You may be seeing inconsistencies because your PDVA values are not chosen correctly. P and D are the same as any other PID loop, however, V must be the reciprocal of your robot’s max speed (1/max_vel). Our tested values were P=0.8, D=0.0, V=1/max_vel, A=0.0, however your milage may vary. Also be sure that you have set your encoder offset properly, as well as your ticks per revolution and wheel diameter.

Also, be certain your SRX’s encoder is updating the RoboRIO fast enough. We use

srx.setStatusFrameRateMs(CANTalon.StatusFrameRate.QuadEncoder, 20)

for this.

1 Like

I think you misunderstand the phrasing of the question.

I believe OP is asking how to setup control modes for Pathfinder’s Integration of Path Following (seen here). In this case, the calculation of closed-loop gains is done on the RoboRIO in order to fit with the constraints provided (e.g. max velocity, desired P and D values etc).

What you’re suggesting is to run another closed loop on the SRX to adjust the speed going to the motor as set by pathfinder’s own closed loop. This is asking for trouble.

The desired control mode IS PercVBus, as Pathfinder’s control loop will account for dips in speed due to battery voltage as it sees a larger error.

Running in speed mode will give you one closed-loop controlling another closed-loop. Pathfinder’s follower outputs a percentage throttle, and so PercVBus is what you should be using.

This is exactly the answer that I was looking for. Thank you for clarifying that with your integration, we need that RIO implementation to stay in PercentVbus.

As I mentioned, we have both implementations working independently of each other (Jaci’s on RIO and MPE on Talon) and I knew that we still had to tune the controller whichever direction they wish to use.

With respect to your other points, since they have configured the Talon SRX with the properly (CPR set in the Talon), they have implemented using a DistanceFollower. In the DistanceFollower class, I didn’t see any configuration methods to set the wheel diameter. Since the Talon returns distance in Revolutions and speed in RPM, I made sure that they included the conversion for Revs–>Inches and RPM → Inches/sec (I’m from an imperialistic country, what can I say :stuck_out_tongue: ).

I will have them check the encoder frame rate this evening as you suggest.

With respect to the gyro integration in your wiki, was there any reasoning why you implemented:

double turn = 0.8 * (-1.0/80.0) * angleDifference;

Or is that merely you Pgain * correction_factor if you Pgain = 0.8?

Thanks for your guidance.

  1. The DistanceFollower takes in the distance your robot has traveled on the ground (e.g. in metres or feet), hence it doesn’t know the concept of wheel diameter. You can find the distance traveled on the ground by finding the arc circumference. For example, for a single 1/4 rotation:
distance = (1/4)*3.1415*diameter
  1. The turn gain can either be linked to the Pgain, or independent. 0.8 * (-1.0/80.0) * angleDifference comes from Team 254’s TrajectoryLib, and we found it works very well in most cases. Increasing this will cause the robot to turn faster, but may oscillate more.

My bad. I’m not familiar with the Pathfinder Library. I assumed it worked similar to 254’s TrajectoryLib for motion profile generation which is what we use.

Both TrajectoryLib and Pathfinder use the same following logic. Generation is slightly different, but the following of the path is practically identical between the libraries.

In both cases, the closed-loop adjustment is done on the roborio. While there’s nothing stopping you running a second control loop on the SRX, it can often be unstable as you will have 2 loops running at different speeds. It is also important to note that in many cases the rio control loop will have the ‘error’ calculated with respect to the desired distance travelled, however the SRX will calculate in respect to the set speed (if we’re talking about the Speed closed-loop mode).

Assuming your trajectory generation library is generating a left wheel and right wheel trajectory, you know precisely the desired position (x), velocity (v), and acceleration (a) of each wheel at any given moment in time. As has already been enumerated in this thread, there are a bunch of different ways you could go about ensuring your robot follows the trajectory as generated (using the Talon).

  • PercentVBus: In this mode, the Talon interprets your command as a % of full throttle (which is roughly proportional to voltage). The RoboRIO controller would take your trajectory setpoint as an input and generates a % of full throttle as an output.
  • Voltage: In this mode, the Talon interprets your commands as an absolute voltage. A little bit better than PercentVBus in most cases since battery voltage is actively being compensated. The RoboRIO controller takes a trajectory setpoint as an input and generates a voltage as an output.
  • Speed: In this mode, the Talon interprets your commands as a velocity (RPM if you tell your Talon the specs of your sensor). A little bit better than Voltage because the Talon actively tries to achieve the speed you commanded. The RoboRIO controller takes a trajectory setpoint as an input and generates a velocity as an output.
  • Position: In this mode, the Talon interprets your commands as a desired position. However, the Talon (at least the ‘D’ gain) assumes that you want to stop at the desired position, whereas your trajectory will have points with non-zero velocity. As a result this doesn’t work great for this application. The RoboRIO controller takes a trajectory setpoint as an input and generates a position as an output. There’s also a Motion Magic mode that is basically position control + acceleration and velocity limits, but it suffers from the same issues.
  • Profile: In this mode, the Talon takes both a desired position AND velocity command. Fantastic! However, this mode is a bit more complicated - you need to stream trajectory points to the Talon on the fly at whatever resolution you’d like.

So generally, PercentVBus, Voltage, Speed, and Profile are the modes that work, in order of increasing complexity but also increased performance.

As for the RoboRIO side controller, the exact formulation depends on the Talon control mode, but in general your command should be something like:

output = Fvelocity(t) + FAacceleration(t) + KPpos_error(t) + KIerror_sum(t) + KD*vel_error(t)

The meanings/units of the five constants change depending on control mode. For example, in Voltage mode, I’d expect F to be roughly (12V / free speed of the motor), but in Speed mode I would expect it to be 1 (or a unit conversion if your trajectory is not in RPM). Also note that in many cases, some gains are zero! Start with F, add FA if necessary, then do P, I, and D as in any other PID controller.

Do this for both the left and right sides and you should track pretty well! But you still may have some heading issues and drift.

Adding in a gyro term (even just proportional) can help a lot to ensure you don’t inevitably drift off course. (Alternatively, what 254 does these days is to re-generate a trajectory every control cycle based on our measured encoders + gyro position, so if we are drifting off course the new trajectory will compensate for it).

Thank you very much for the insight, Jared.

We had a last night to test the Motion Profile Executor that is integrated into the Talon. I had the kids follow the tuning method that is called out in the Software Reference Manual and the Motion Profile Manual released by CTRE. (Set the F gain based on max velocity, calculate the Pgain based on the error between command and actual, etc.)

When they demonstrated their straight driving implementation to me, it was very consistent with only a minor drift off to the left (3 inches over 10 feet) while maintaining the heading.

However, the concerning thing for me, it seemed that after the motors are turned OFF (talon were in brake mode), the robot every time veers left sharply and ends with a -10-20 degree heading. It doesn’t make sense that it does this motion profile causes the issue (as I said, the drift appears to occur after the command has finished executing. Could this be caused by mechanical lash in the drive train?

I think it will be very difficult to tune this behavior out with closed loop feedback.

Thanks.

We’re using Motion Magic successfully with Talon SRX control, which calculates the profile for you, given the desired end position, max velocity, and max acceleration. The control is completely off-loaded to the processor on the Talon, which operates with a 1 ms control loop.

We simulate control loops, motor loading, and sensor feedback using SystemVision Cloud. This can help with tuning the PIDF values.

See my blog for more detail if you want to try it. It’s completely online and free. I’ve characterized the most common FRC motors so the models are easy for you to use.

Consider adding a ramp down to stop in your motion profile code, such that the robot should have come to a complete stop before the profile completes in a controlled fashion.

Bit off topic for this thread, but it looks like a group of MP experts so I will ask.

We spent this weekend working on MP with Talon SRX, using the CTRE example code as a base. This is the first time we have worked with MP.

The profile is running, but we do not seem to get any indication that the profile has completed. The main control loop relies on the status returned from the Talon having the 'isLast" flag set true, and it never seems to come true.

Is this a know issue, or are we doing something incorrectly?

Secondly, currently looking at Jaci’s code for MP - looks pretty good to me. Comments on this approach versus using the Talon local MP?

Regards

David

The isLast flag needs to be marked on the individual TrajectoryPoint that terminates the trajectory.

Thanks Eli

I should have mentioned that we checked this.

Is there any possibility of a timing issue where the status being read from the Talon is incorrect if we miss the final point?

Thanks Eli

I should have mentioned that we checked this, and even tried setting teh last 10-20 points as “isLast”

Clearly we are doing something wrong, but bit confused.

Any chance there is a timing issue, where if the status is not checked at the right time the “isLast” goes back to false?

Hard to diagnose without being able to see your code; is it possible you are telling the controller to start running a profile in a periodic method and thus as soon as it hits the “last” point it tries to start running again?

Good thought Eli

It is being called in periodic, but I thought we had guarded against running again. Will go back and check.

So as far as you are concerned, the isLast status does update correctly?

It has worked fine for us, yes.