CTRE Phoenix - Motion Profiling with Gyro questions

CTRE released an update allowing, from what I know, a gyro (Pigeon) to assist motion profiling to go where it wants to go. I’m looking at the example code here: https://github.com/CrossTheRoadElec/Phoenix-Examples-Languages/tree/master/Java/RemoteClosedLoop

I’m confused at a lot of things, such as:

_talonRght.configRemoteFeedbackFilter(_talonLeft.getDeviceID(), RemoteSensorSource.TalonSRX_SelectedSensor,Constants.REMOTE_0, Constants.kTimeoutMs);

Why is the Talon configuring a remote sensor as the other Talon?

_talonRght.config_kP(Constants.kSlot_Turning, Constants.kGains_Turning.kP, Constants.kTimeoutMs);

Why does CTRE have a PID for turning? How does that work?

What I want to implement is two-axis motion profiling, as shown in the function called “two_Axis_MotionProfile”. Example implementation:

void two_Axis_MotionProfile(boolean bFirstCall, ButtonEvent bExecuteAction, double joyForward, double joyTurn) {

			/* calculate targets from gamepad inputs */
			boolean bMoveForward = (joyForward >= 0) ? true : false;
			double finalHeading_units = Constants.kTurnTravelUnitsPerRotation * joyTurn * -1.0; /* positive right stick => negative heading target (turn to right) */

			if (bFirstCall) {
				System.out.print("[13]two_Axis_MotionProfile selected, ");
				System.out.println("Press Button 6 to fire the profile. ");
				neutralMotors("Target not set yet.

				/* slots are selected in the profile, not via selectProfileSlot() */

			} else if (bExecuteAction == ButtonEvent.ButtonOnToOff) {

			} else if (bExecuteAction == ButtonEvent.ButtonOffToOn) {
				neutralMotors("Button let go
				_motProfExample.start(finalHeading_units, bMoveForward);
			} else if (bExecuteAction == ButtonEvent.ButtonOn) {

				_talonRght.set(ControlMode.MotionProfileArc, _motProfExample.getSetValue().value);
				_talonLeft.follow(_talonRght, FollowerType.AuxOutput1);
			/* call this periodically, and catch the output.  Only apply it if user wants to run MP. */


What I don’t get it why is finalHeading_units calculated by the joystick turn value? Shouldn’t it use the Pigeon gyro somewhere to get the current yaw value?

And finally, in MotionProfileExample.java, there’s a variable called endHeading that’s used during motion profiling. Why is only the end heading specified? Shouldn’t the heading and gyro yaw value be pulled periodically to ensure exact angles during motion profiling?


I could be wrong, but there seem to be a few things going on here.

1, I think it has the 1 talon pull the pigeon from the other Talon’s dataport as a remote pull.

2, If the pigeon is working and the button is pressed, the desired angle becomes the set point.

3, If either of the above statements is false, then it reverts to joystick control.

Normally, I would assume that running a specific trajectory on the left and right sides of the talons will be most intuitive for people, especially those using libraries such as Pathfinder which includes a TankModifier to generate separate trajectories.

However, CTRE takes a slightly different approach to this problem. The issue with running separate trajectories on each talon is that the PID loop for the encoders (primary PID) and the gyro (auxiliary PID) will end up fighting against each other. For example, if the gyro detects that your robot needs to turn more to the right, it will output more power to your left drivetrain and reduce power on your right drivetrain. This would in turn increase the encoder position on your left side and reduce the position on the right side. However, your primary PID loop will do just the opposite (decrease left power, increase right power) to attempt to correct the encoder positions.

To solve this, motion profiling is run on a single master talon (in CTRE’s example, it’s the right master talon). Instead of having each side follow its own position setpoint, the entire drivetrain follows the sum of the left and right encoders. The theory behind this is that your robot is free to zero-turn throughout the entire trajectory without affecting the position setpoint (increasing one side’s output and decreasing another side’s output by an equal magnitude will result in the encoder differences cancelling each other out).

When CTRE’s code is using _talonRght.configRemoteFeedbackFilter(), it’s not configuring a remote sensor as another Talon. Rather, it’s setting FeedbackDevice.Remote0 as the selected sensor on the other talon (which in this case, would be the encoder). If you look down a bit further in the code, configSensorTerm() is used to sum up the local encoder and the remote encoder to FeedbackDevice.SensorSum.

You would need PID for gyro (the auxiliary loop) to maintain your robot’s heading throughout the entire trajectory. With something such as Pathfinder’s TankModifier, the velocity feed-forward and the position setpoint for the left and right sides are already calculated. During a turn, the velocities of both sides of the drivetrain will be different. However, with the Sensor Sum configuration, both sides will be going at the same velocity throughout the entire trajectory. The auxiliary gyro loop is what accounts for the heading error by increasing the output on one side and decreasing the output on the other.

Thank you!! I’m still confused on one thing – why is only the final heading specified, and not the gyro yaw value specified every loop?

Also, three more questions:

  1. How do I tune PID for a gyro?

  2. How would I specify the final heading, if it’s different for different trajectories?

  3. In the example code, they only have one master talon. In our code, we have the two front motors as masters and the two back as followers to their respective master. How would doing this auxiliary stuff change this? Would I need to specify one talon as master and the rest three as followers?