Quote:
Originally Posted by Kruuzr
We've just coded this last night and hope to try it tonight. You need to derive your own class from the PIDSource class. In PIDSource.h, notice that there is one method defined:
virtual double PIDGet() = 0;
This is what's known as a pure virtual method; There is no default implementation This means you can't create a PIDSource object, only one derived from it with this method overridden with your own. The code looks something like this:
// .h file
#include <WPILib.h>
class MyPIDSource : public PIDSource
{
public:
double PIDGet();
}
// .cpp file
#include "MyPIDSource.h"
double MyPIDSource:  IDGet()
{
double pidSourceValue;
// calculate 'double' value that you want compared to the set point
// feel free to format it the same as you expect with your set point
pidSourceValue = ...
// return value
return pidSourceValue;
}
Before you create your controller object, you must create an instance of your class. Pass this pointer as a parameter to PIDController for the PIDSource arg.
Now, every 50 ms (assuming you've started it going), the PIDController will read the PID source, compare the value to the set point, do it's PID calculations, and write the new value to the PID output device.
With our setup, we are turning a turret that has a camera mounted on it to track the vision target. My PID Source uses the X component of the Particle report to get the error value. So our set point is permanently set to 0 (centered in the camera). But we have to take into account the position of the turret with respect to our two end stops. As we get closer to one of our stops (as read from our 10 turn pot attached to the turret gears) we have to supply a smaller number until it gets to 0 at the end, assuming we're driving it in that direction. We can also disable our 'auto tracking' by just returning a 0, and allow manual control by just passing back the z component of a joystick to represent the value. It's actually quite powerful.
I'll let you know how it works.
Hope this helped...
Steve
|
I have coded something up as well, but won't get a chance to test it till tonight either. I think this will work, but if any code guru's see something wrong let me know. I am also using a 10 turn pot on a turret gear and want to do exactly what you are talking about.
----------------------------------------
I have a CamSource.h which is:
----------------------------------------
#include "WPILib.h"
class CamSource : public PIDSource
{
public:
CamSource();
double PIDGet();
void SetSource(double);
private:
double source;
};
------------------------------------------------
My CamSource.cpp file is:
----------------------------------------
#include "CamSource.h"
CamSource :: CamSource()
{}
void CamSource :: SetSource (double sourcedum)
{
source = sourcedum;
}
double CamSource :: PIDGet()
{
return source;
}
----------------------------------------
Then in my main code I do the following to use it. Basically I set the CamSource to what the X difference on the camera is, and then feed it to my PIDController.
RobotCode.h:
----------------------------------------
PIDController *turretCamControl;
CamSource *CameraBrains;
RobotCode.cpp
----------------------------------------
CameraBrains = new CamSource();
turretCamControl = new PIDController(CamP, CamI, CamD, CameraBrains, TurretPIDMotor);
Then in my teleoperated periodic:
turretCamControl->Enable();
CameraBrains->SetSource(horizontalDestination);
turretCamControl->SetSetpoint(0);
-----------------------------------------
I think it will work, at least it compiles fine. horizontalDestination is the normalized X parameter from the camera. Thanks for your help, what you have outlined is pretty much the route I went as well. I don't know why, WPI couldn't just write a controller that allows us to just input a dang variable. It would be much easier.