39#include "models/FGFCS.h"
40#include "math/FGParameterValue.h"
50FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
55 Input_prev = Input_prev2 = 0.0;
57 ProcessVariableDot =
nullptr;
61 CheckInputNodes(1, 1, element);
63 auto PropertyManager = fcs->GetPropertyManager();
64 string pid_type = element->GetAttributeValue(
"type");
66 if (pid_type ==
"standard") IsStandard =
true;
68 el = element->FindElement(
"kp");
70 Kp =
new FGParameterValue(el, PropertyManager);
72 Kp =
new FGRealValue(0.0);
74 el = element->FindElement(
"ki");
76 string integ_type = el->GetAttributeValue(
"type");
77 if (integ_type ==
"rect") {
79 }
else if (integ_type ==
"trap") {
80 IntType = eTrapezoidal;
81 }
else if (integ_type ==
"ab2") {
82 IntType = eAdamsBashforth2;
83 }
else if (integ_type ==
"ab3") {
84 IntType = eAdamsBashforth3;
86 IntType = eAdamsBashforth2;
89 Ki =
new FGParameterValue(el, PropertyManager);
92 Ki =
new FGRealValue(0.0);
95 el = element->FindElement(
"kd");
97 Kd =
new FGParameterValue(el, PropertyManager);
99 Kd =
new FGRealValue(0.0);
101 el = element->FindElement(
"pvdot");
103 ProcessVariableDot =
new FGPropertyValue(el->GetDataLine(), PropertyManager, el);
105 el = element->FindElement(
"trigger");
107 Trigger =
new FGPropertyValue(el->GetDataLine(), PropertyManager, el);
109 bind(el, PropertyManager.get());
114void FGPID::bind(Element *el, FGPropertyManager* PropertyManager)
116 FGFCSComponent::bind(el, PropertyManager);
119 if (Name.find(
"/") == string::npos) {
120 tmp =
"fcs/" + PropertyManager->mkPropertyName(Name,
true);
124 PropertyManager->Tie<FGPID,
double>(tmp+
"/initial-integrator-value",
this,
125 nullptr, &FGPID::SetInitialOutput);
138 delete ProcessVariableDot;
144void FGPID::ResetPastStates(
void)
146 FGFCSComponent::ResetPastStates();
148 Input_prev = Input_prev2 = Output = I_out_total = 0.0;
153bool FGPID::Run(
void )
155 double I_out_delta = 0.0;
158 Input = InputNodes[0]->getDoubleValue();
160 if (ProcessVariableDot) {
161 Dval = ProcessVariableDot->getDoubleValue();
163 Dval = (Input - Input_prev)/dt;
172 if (Trigger) test = Trigger->getDoubleValue();
174 if (fabs(test) < 0.000001) {
180 I_out_delta = 0.5 * (Input + Input_prev);
182 case eAdamsBashforth2:
183 I_out_delta = 1.5*Input - 0.5*Input_prev;
185 case eAdamsBashforth3:
186 I_out_delta = (23.0*Input - 16.0*Input_prev + 5.0*Input_prev2) / 12.0;
195 if (test < 0.0) I_out_total = 0.0;
197 I_out_total += Ki->GetValue() * dt * I_out_delta;
200 Output = Kp->GetValue() * (Input + I_out_total + Kd->GetValue()*Dval);
202 Output = Kp->GetValue()*Input + I_out_total + Kd->GetValue()*Dval;
204 Input_prev2 = test < 0.0 ? 0.0:Input_prev;
232void FGPID::Debug(
int from)
234 if (debug_lvl <= 0)
return;
238 cout <<
" INPUT: " << InputNodes[0]->GetNameWithSign() << endl;
240 for (
auto node: OutputNodes)
241 cout <<
" OUTPUT: " << node->getNameString() << endl;
244 if (debug_lvl & 2 ) {
245 if (from == 0) cout <<
"Instantiated: FGPID" << endl;
246 if (from == 1) cout <<
"Destroyed: FGPID" << endl;
248 if (debug_lvl & 4 ) {
250 if (debug_lvl & 8 ) {
252 if (debug_lvl & 16) {
254 if (debug_lvl & 64) {