Open ethanmusser opened 2 years ago
I was thinking these are the functions and variables that could be in abstract class
I was thinking these are the functions and variables that could be in abstract class
Some thoughts:
Start
, Run
, and Stop
methods are intended to do here.Init
only really makes sense as a factory constructor a la this.set_gains
function generic to any kind of controller gains (different controller implementations will have different types and numbers of gains).So I was thinking there could be times when we want to shift from one controller scheme to another. So in that case we would require to start, run and stop. Which is why I kept these items. If I am not wrong if we were to template the function we would be able to send n number of parameters. Or we could send a vector and then do a check based on the number of parameters. Also we could use a 2-dimensional array that has the names as well.
So I was thinking there could be times when we want to shift from one controller scheme to another. So in that case we would require to start, run and stop. Which is why I kept these items. If I am not wrong if we were to template the function we would be able to send n number of parameters. Or we could send a vector and then do a check based on the number of parameters. Also we could use a 2-dimensional array that has the names as well.
std::vector
alone could word, but might be more confusing since your gains are unlabelled. Not sure what you mean with the 2D array.Init
vs. constructor comment.In general, you should definitely start small with this and build up more complicated functionality as you go.
- Sorry missed the Init part, I was thinking that if we were to use different controllers then a separate init would be required. However, I don't if it is required honestly.
- When I mean by a 2D array, I mean one row will specify the name of the gain and the second row will contain the value. Something like a dictionary in python. Or even 2 1D std:vectors.
- So if I assume we don't require a hybrid control then Start, Stop, Run are not required correct?
ControllerBase
child to implement their own initialization, you have the following options:
ControllerBase
base class constructor. I.e., the user would always need to write one of the following into their derived class (note C.52):
class UserController : public ControllerBase {
public:
using ControllerBase::ControllerBase; // This simply calls the child class constructor
UserController() : ControllerBase(/* ... */) {} // This calls the parent class constructor in the initialization
}
Initialize
method (as you described). In this case, the user would have to manually call the Initialize
method in their code. Initialize
cannot be called in the abstract class constructor as this may cause undefined behavior (this is very rightfully discouraged in this style guide section). ControllerBase
to handle the virtual initialization behavior. This is the method recommended by the ISO C++ Core Guidlines (check out C.50).std::map
and std::unordered_map
. These structures and internal algorithms are much better than the 2D array approach described here.I have a question, when I am writing the update function. How would I make it generic to the inputs I can take into the function? Is it possible?
I have a question, when I am writing the update function. How would I make it generic to the inputs I can take into the function? Is it possible?
This question depends on how you have made PIDController
. Building on that, generic to what anticipated inputs?
If PIDController
is a...
int
, double,
float), then your
Update` method should simply accept a parameter of that same scalar type, which you can write into your class template with the scalar template parameter.Eigen::Matrix<Scalar, 1, X>
, where Scalar
is a scalar type, and X
is the vector size), then the procedure is largely the same as above, but your Update
should use the class template parameter for the Eigen vector type.I am asking for the update function within the pidcontroller. The number of variables that we give to the update function could vary based on the controller we are using. So I wanted to generalise.
I am asking for the update function within the pidcontroller. The number of variables that we give to the update function could vary based on the controller we are using. So I wanted to generalise.
I would start with SISO and figure out MISO/MIMO implementations later.
Feature request for a proportional-derivative (or perhaps proportional-integral-derivative) controller class.
Desired Behavior
Users can utilize the PD/PID controller class for applicable use-cases, or implement their own, more advanced controllers through child classes.
Minimal Proposed Implementation
ControllerBase
: An abstract class template that is templated for input type. Contains generic functions applicable to controllers, including:ControllerBase
- Default constructor.Update
- Pure virtual method that computes the controller output from the latest signal and set-point.set_set_point
set_gains
(maybe, might live in the child classes)PIDController
: A child class toController
that implements a discrete-time PID controller.Desired Features
ControllerBase
:std::vector
, andstd::array
.PIDController
:e^2
,sqrt(e)
) via a function handledt
)Later Features
ControllerBase
child classes for more controllers, including:BandBangController
ActiveDampingController
References
This code might be a good jumping-off point for the PID controller.