Unable to push motion profile to Talon SRX

Hey guys,

Were having an issue pushing a motion profile to our talon SRX’s. They all are on the 3.3 phoenix frame work, roboRio is on 2018v17, and I’ve put the phoenix web dashboard through lifeboat.

When I push a point to the srx, I UnsatisfiedLinkError. I’m not sure what other updates I need, or what files I need.

Here is some of the stack trace:

ERROR  1  Unhandled exception: java.lang.UnsatisfiedLinkError: com.ctre.phoenix.motorcontrol.can.MotControllerJNI.PushMotionProfileTrajectory2(JDDDIIZZI)I  com.ctre.phoenix.motorcontrol.can.MotControllerJNI.PushMotionProfileTrajectory2(Native Method)
	at com.ctre.phoenix.motorcontrol.can.MotControllerJNI.PushMotionProfileTrajectory2(Native Method)
	at com.ctre.phoenix.motorcontrol.can.BaseMotorController.pushMotionProfileTrajectory(BaseMotorController.java:1250)


Any help would be nice!

Thank you

Send CTRE an email for the best support :slight_smile:

support@ctr-electronics.com

That would be the next option, I just first wanted to see if this was a common/known issue, or if I was doing something obviously wrong

Including the code that you are using could be very helpful.
Are other commands to the Talons succeeding?
Has your code worked in the past, or are you trying motion profiling for the first time?

I am trying motion profiling for the first time. I am able to run closed loop, including motion magic perfectly fine. I’m trying to write to two talons (I want a seperate profile for the left and right drives), and neither worked.

Here is the parts of the code that I feel is most important, but I’ll also give the entire method in case it helps



TrajectoryPoint outerPoint = new TrajectoryPoint();
		TrajectoryPoint innerPoint = new TrajectoryPoint();

		double timer = 0;
		double stepSize = 10;

		double outerCurrentVel = inVelOuter;
		double innerCurrentVel = inVelInner;
		double outerCurrentPos = outer.getSelectedSensorPosition(0);
		double innerCurrentPos = inner.getSelectedSensorPosition(0);

		boolean isFirst = true;

		inner.clearMotionProfileTrajectories();
		outer.clearMotionProfileTrajectories();

		outerPoint.profileSlotSelect0 = 0;
		innerPoint.profileSlotSelect0 = 0;
		outerPoint.headingDeg = 0;
		innerPoint.profileSlotSelect0 = 0;
		outerPoint.profileSlotSelect1 = 1;
		innerPoint.profileSlotSelect1 = 1;
		
		
		ProfileNotifier pNotifier = new ProfileNotifier(10, innerDist, outerDist, inner, outer);

		
		while (timer < time) {
			timer += .1;

			if (timer < firstAccelerationTime) {

				outerCurrentVel += firstAccelerationOuter * stepSize;
				outerCurrentPos += outerCurrentVel * stepSize;
				innerCurrentVel += firstAccelerationInner * stepSize;
				innerCurrentPos += outerCurrentVel * stepSize;

				outerPoint.isLastPoint = false;
				outerPoint.zeroPos = false;
				outerPoint.velocity = outerCurrentVel;
				outerPoint.position = outerCurrentPos;
				outerPoint.timeDur = TrajectoryDuration.Trajectory_Duration_10ms;

				innerPoint.isLastPoint = false;
				outerPoint.zeroPos = false;
				innerPoint.velocity = innerCurrentVel;
				innerPoint.position = innerCurrentPos;
				innerPoint.timeDur = TrajectoryDuration.Trajectory_Duration_10ms;

				if (isFirst) {
					outerPoint.zeroPos = true;
					innerPoint.zeroPos = true;
					isFirst = false;
				}

				pNotifier.addPoint();

			}  //Other conditions removed for simplicity	
			
			
			inner.pushMotionProfileTrajectory(innerPoint);
			outer.pushMotionProfileTrajectory(outerPoint);
		}


Here my entire code:



public static ProfileNotifier generateTurnMotionControl(double cruzV, double outV, double turnR, double turnAngle,
			boolean right, TalonSRX leftT2, TalonSRX rightT2) {
		
		System.out.println("Generating profile");
		
		if (Config.robotWidth == 0) {
			throw new RuntimeException("measure the robot width");
		}
		TalonSRX outer = (right ? leftT2 : rightT2);
		TalonSRX inner = (right ? rightT2 : leftT2);
		double angle = Math.toRadians(turnAngle);
		DriveTrain drive = (DriveTrain) Robot.getSubsystem(SubsystemNames.DRIVE_TRAIN);
		double outerDist = drive.inchesToCycles(turnR + Config.robotWidth) * angle;
		double innerDist = drive.inchesToCycles(turnR) * angle;

		double inVelOuter = outer.getSelectedSensorVelocity(0);
		double inVelInner = inner.getSelectedSensorPosition(0);

		double v1 = (inVelOuter + cruzV) / 8d;
		double v2 = cruzV / 2d;
		double v3 = (cruzV + outV) / 8d;

		double time = outerDist / (v1 + v2 + v3) * 100; // cycles / (cycles / 100ms) -> 100ms

		double firstAccelerationTime = time / 4d;
		double cruzTime = time / 2d;
		double secondAccelerationTime = time / 4d;

		double innerCruzVel = 4 * ((innerDist / time) - (inVelInner / 8d) - (outV / 8d)) / 3d;

		double firstAccelerationOuter = (cruzV - inVelOuter) / firstAccelerationTime;
		double secondAccelerationOuter = (outV - cruzV) / secondAccelerationTime;

		double firstAccelerationInner = (innerCruzVel - inVelInner) / firstAccelerationTime;
		double secondAccelerationInner = (outV - innerCruzVel) / secondAccelerationTime;

		TrajectoryPoint outerPoint = new TrajectoryPoint();
		TrajectoryPoint innerPoint = new TrajectoryPoint();

		double timer = 0;
		double stepSize = 10;

		double outerCurrentVel = inVelOuter;
		double innerCurrentVel = inVelInner;
		double outerCurrentPos = outer.getSelectedSensorPosition(0);
		double innerCurrentPos = inner.getSelectedSensorPosition(0);

		boolean isFirst = true;

		inner.clearMotionProfileTrajectories();
		outer.clearMotionProfileTrajectories();

		outerPoint.profileSlotSelect0 = 0;
		innerPoint.profileSlotSelect0 = 0;
		outerPoint.headingDeg = 0;
		innerPoint.profileSlotSelect0 = 0;
		outerPoint.profileSlotSelect1 = 1;
		innerPoint.profileSlotSelect1 = 1;
		
		
		ProfileNotifier pNotifier = new ProfileNotifier(10, innerDist, outerDist, inner, outer);

		//leftT2.configMotionProfileTrajectoryPeriod(0, 10);
		//rightT2.configMotionProfileTrajectoryPeriod(0, 10);
		
		
		System.out.println("first acc time: " + firstAccelerationTime);
		System.out.println("first acc time: " + cruzTime);
		System.out.println("first acc time: " + secondAccelerationTime);

		
		while (timer < time) {
			System.out.println("happy face one");
			timer += .1;

			if (timer < firstAccelerationTime) {
				System.out.println("happy face two");

				outerCurrentVel += firstAccelerationOuter * stepSize;
				outerCurrentPos += outerCurrentVel * stepSize;
				innerCurrentVel += firstAccelerationInner * stepSize;
				innerCurrentPos += outerCurrentVel * stepSize;

				outerPoint.isLastPoint = false;
				outerPoint.zeroPos = false;
				outerPoint.velocity = outerCurrentVel;
				outerPoint.position = outerCurrentPos;
				outerPoint.timeDur = TrajectoryDuration.Trajectory_Duration_10ms;

				innerPoint.isLastPoint = false;
				outerPoint.zeroPos = false;
				innerPoint.velocity = innerCurrentVel;
				innerPoint.position = innerCurrentPos;
				innerPoint.timeDur = TrajectoryDuration.Trajectory_Duration_10ms;

				if (isFirst) {
					outerPoint.zeroPos = true;
					innerPoint.zeroPos = true;
					isFirst = false;
				}

				pNotifier.addPoint();

			} else if (timer < firstAccelerationTime + cruzTime) {
				outerCurrentVel += cruzV;
				outerCurrentPos += outerCurrentVel * stepSize;
				innerCurrentVel += innerCruzVel;
				innerCurrentPos += outerCurrentVel * stepSize;

				outerPoint.isLastPoint = false;
				outerPoint.zeroPos = false;
				outerPoint.velocity = outerCurrentVel;
				outerPoint.position = outerCurrentPos;
				outerPoint.timeDur = TrajectoryDuration.Trajectory_Duration_10ms;

				innerPoint.isLastPoint = false;
				outerPoint.zeroPos = false;
				innerPoint.velocity = innerCurrentVel;
				innerPoint.position = innerCurrentPos;
				innerPoint.timeDur = TrajectoryDuration.Trajectory_Duration_10ms;

				pNotifier.addPoint();

			} else if (timer < firstAccelerationTime + cruzTime + secondAccelerationTime) {
				outerCurrentVel += secondAccelerationOuter * stepSize;
				outerCurrentPos += outerCurrentVel * stepSize;
				innerCurrentVel += secondAccelerationInner * stepSize;
				innerCurrentPos += outerCurrentVel * stepSize;

				outerPoint.isLastPoint = false;
				outerPoint.zeroPos = false;
				outerPoint.velocity = outerCurrentVel;
				outerPoint.position = outerCurrentPos;
				outerPoint.timeDur = TrajectoryDuration.Trajectory_Duration_10ms;

				innerPoint.isLastPoint = false;
				outerPoint.zeroPos = false;
				innerPoint.velocity = innerCurrentVel;
				innerPoint.position = innerCurrentPos;
				innerPoint.timeDur = TrajectoryDuration.Trajectory_Duration_10ms;

				pNotifier.addPoint();

			} else if (timer >= time) {
				innerPoint.isLastPoint = true;
				innerPoint.isLastPoint = true;

				pNotifier.addPoint();

			}
			
			System.out.println("generating " + (inner == null) + " " + (innerPoint==null));
			
			printPoint(innerPoint);
			
			
			
			inner.pushMotionProfileTrajectory(innerPoint);
			outer.pushMotionProfileTrajectory(outerPoint);
		}
		
		System.out.println("done generating profile");

		return pNotifier;
	}

[third time im replying really not sure why it isnt showing]

This is the first time I’m trying motion profiling, but we have closed loop control working and motion magic. I’m trying to push to two talons, as I want a seperate profile for the left and right drives.

My goal is to get the robot to turn in a smooth arc in auto as opposed to drive, stop, turn, start. I’m not sure if there is a better way to achieve this, other than calculating the required profile for the left and right.

I would provide code but that may be why my replies are not going through?

Any help would be nice thanks!

This is an interesting approach. How do you plan on calculating the profiles? We are using Pathfinder which uses a gyro to correct for angles. This could be a cool approach if you can get it to work. I know CTRE is going to add motion magic arc in a later update.

Right now it is just an arc so its not too hard to do the math on paper. Im basically calculating x(t), v(t), and a(t), assuming we accelerate/decelerate for 1/4th the time and cruise for 1/2 the time. If i get this working I’d be pretty happy

Motion Profile Arc is available. New firmware 3.8. Trying to implement tonight. Not working yet.:frowning: