How to Program a ProfiledPidController?

Hello, I’m trying to use a ProfiledPidController instead of a normal PidController, I wrote a simple code, but the motors do not respond, and I can’t figure out what I’m doing wrong, with a regular PidController everything works fine, but I need a soft start and a soft stop

1 Like
  • What unit is your max velocity constraint?
  • What unit is your average encoder distance?
  • How are you running the command?
  • Always output values to debug. What is the controller setpoint when running? The goal? PID output?
  1. 1.5 - velocity , 0.5 - acceleration (test values ​​as I can’t test this on a robot)
  2. average distance calculated by encoders is used in millimeters
  3. goal is 1000 millimeters ,pid output i could not view
  4. I run the command using the class on the inheriting SequentialCommandGroup.

Your velocity and acceleration constraints need to be in the same units as your measurement/goal. If those are your values then the generated profile has a maximum speed of 1.5 millimeters per second.

You can override the execute method from ProfiledPIDCommand to log your pid output and setpoint.

1 Like

could you show what you mean?

You can override the execute() of ProfiledPIDCommand, but this is kinda messy. Personally, I dislike using PIDCommands because you are separating so much control logic from the subsystem and putting it in the command.


Looking at your example, you can just edit your useOutput function from the constructor to do this much cleaner.
image

1 Like

This method doesn’t build a proper motion profile either, my engine just starts oscillating back and forth.
In general, I decided to implement this controller simply in a subsystem, and based on this subsystem, I created a command that should already control the engine, but the engine still does not move.
(Below is a link to PasteBin, where I provided the subsystem and command code : Trap - Pastebin.com)

Your PID gains and profile constraint values are non-final, but you initialize the controller outside of the constructor. You should do this inside the constructor(instead of using your setControllerSettings method) or all of your values will be 0.


Also, did you change the measurement/goal units to meters?

1 Like

Wait, this controller requires me to assign distances to it only in meters, so I can’t use millimeters, inches, etc.?

he must be in the same units

correct

how can I use different coefficients in one subsystem for different commands?

I can’t really imagine a good reason to dynamically change your settings, but if you look at the ProfiledPIDController class you can see there’s a setPID and setConstraints method.

i don’t want to dynamically change the settings of the pid controller, i just want to use the same subsystem for different commands, for example move left and forward, they will have different coefficients

Is this for driving a mecanum/swerve robot a certain distance autonomously? If so, it doesn’t really make sense to place your pidcontroller in a separate subsystem. You should place it in your drivetrain and then require the drivetrain subsystem for those commands using it.

This is actually already addressed in WPILib-- using a PIDController on X position, a PIDController on Y position, and a ProfiledPIDController on theta angle, the HolonomicDriveController lets you follow trajectories. You can ignore the velocity reference (feedforward) if you just want to use feedback control towards a target pose, or you create some simple TrapezoidProfile implementation that feeds you poses and velocities along some arbitrary straight path in any direction.

1 Like

I would be very happy to use the speed controllers implemented in wpilib, but they are not suitable for a tricycle omni base

tricycle omni base

oh… good luck with that. I see you have a holonomicDrive method; You should still be able to do this, given you are just receiving ChassisSpeeds, no? The difficulty with that kind of drivebase would be how you are translating ChassisSpeeds to individual wheel speeds.

The controller started to build a trapezoidal profile, which is cool, but now my question is how to set it up?
The question is how to set it up using the chart provided in the shuffle board? How do I plot an ideal profile plot and then equate the actual values ​​to it?
My maximum speed will be equal to the maximum linear speed of the motor, right?

The controller

This is kind of ambiguous… what controller?
I believe PIDControllers are automatically published to LiveWindow, but you might log numbers yourself by simply using SmartDashboard.putNumber; for example, SmartDashboard.putNumber("Controller Setpoint", controller.getSetpoint().position) would show the controller setpoint. I would recommend using the Glass tool instead since the plots look nicer, but you can visualize multiple values in one shuffleboard plot by using SmartDashboard.putNumberArray.

My maximum speed will be equal to the maximum linear speed of the motor, right?

Do you mean the constraint given to the ProfiledPIDController? You should use whatever speed is appropriate for the mechanism. You probably don’t want to use the maximum possible speed because that removes a lot of room for error.

Weird, I can’t run Glass from wpilib, it doesn’t exist at all.
Can it be installed separately?