I have been tasked with representing a simple cruise control system with a PID controller as an ordinary differential equation and estimating KP, KI, and KD parameters (I use torchdiffeq library for differentiation and simulation). I know, I can add error to the state to calculate the integral, however, I struggle with the implementation of the derivative. I believe there is a better way to represent the system without the use of ‘global’ variables.
Here is my current code:
def forward(self, t, x):
y, E = x
dydt = torch.zeros_like(x)
workaround_int = y + y.trunc().detach() - y.detach()
error = self.Setpoint - workaround_int
inte = E
div = (error - self.Error_previous)/self.Dt
pid = self.Params[0]*error + self.Params[1]*inte + self.Params[2]*div
F_ego = pid
D_ego = self.CdA*(y ** 2)
if y > 0:
F_net = F_ego - D_ego
else:
F_net = F_ego + D_ego
dydt[0] = F_net/self.M
dydt[1] = error
self.Error_previous = error
return dydt
If you need any additional information, I am happy to provide!
I have tried to change the system to be of a more correct ‘ODE’ form by setting the setpoint to 0. This however resulted in an inaccurate system, because of the trunctuated velocity when calculating error. Moreover, it did not solve the issue of having to approximate the derivative term with a finite difference.
I looked at similar problems but they all were related to the higher-order differential equations. I think that technically velocity is of second order but with applied control, it is regarded as first(?).
Unfortunately, I am not very familiar with the control theory and Laplace transform thus any help would be welcomed.
It is strange that you compute a force and thus acceleration, but then only have a first-order DE. // Instead of hacking the integration method, which is not reliable, you can also rewrite the DE to avoid derivatives of the error, see stackoverflow.com/questions/58810439/….