39 #include "math/FGParameterValue.h"
49 FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
54 Input_prev = Input_prev2 = 0.0;
56 ProcessVariableDot =
nullptr;
60 CheckInputNodes(1, 1, element);
62 string pid_type = element->GetAttributeValue(
"type");
64 if (pid_type ==
"standard") IsStandard =
true;
66 el = element->FindElement(
"kp");
68 Kp =
new FGParameterValue(el, PropertyManager);
70 Kp =
new FGRealValue(0.0);
72 el = element->FindElement(
"ki");
74 string integ_type = el->GetAttributeValue(
"type");
75 if (integ_type ==
"rect") {
77 }
else if (integ_type ==
"trap") {
78 IntType = eTrapezoidal;
79 }
else if (integ_type ==
"ab2") {
80 IntType = eAdamsBashforth2;
81 }
else if (integ_type ==
"ab3") {
82 IntType = eAdamsBashforth3;
84 IntType = eAdamsBashforth2;
87 Ki =
new FGParameterValue(el, PropertyManager);
90 Ki =
new FGRealValue(0.0);
93 el = element->FindElement(
"kd");
95 Kd =
new FGParameterValue(el, PropertyManager);
97 Kd =
new FGRealValue(0.0);
99 el = element->FindElement(
"pvdot");
101 ProcessVariableDot =
new FGPropertyValue(el->GetDataLine(), PropertyManager);
103 el = element->FindElement(
"trigger");
105 Trigger =
new FGPropertyValue(el->GetDataLine(), PropertyManager);
112 void FGPID::bind(Element *el)
114 FGFCSComponent::bind(el);
117 if (Name.find(
"/") == string::npos) {
122 typedef double (FGPID::*PMF)(void)
const;
123 PropertyManager->
Tie(tmp+
"/initial-integrator-value",
this, (PMF)
nullptr,
124 &FGPID::SetInitialOutput);
137 delete ProcessVariableDot;
143 void FGPID::ResetPastStates(
void)
145 FGFCSComponent::ResetPastStates();
147 Input_prev = Input_prev2 = Output = I_out_total = 0.0;
152 bool FGPID::Run(
void )
154 double I_out_delta = 0.0;
157 Input = InputNodes[0]->getDoubleValue();
159 if (ProcessVariableDot) {
160 Dval = ProcessVariableDot->getDoubleValue();
162 Dval = (Input - Input_prev)/dt;
171 if (Trigger) test = Trigger->getDoubleValue();
173 if (fabs(test) < 0.000001) {
179 I_out_delta = 0.5 * (Input + Input_prev);
181 case eAdamsBashforth2:
182 I_out_delta = 1.5*Input - 0.5*Input_prev;
184 case eAdamsBashforth3:
185 I_out_delta = (23.0*Input - 16.0*Input_prev + 5.0*Input_prev2) / 12.0;
194 if (test < 0.0) I_out_total = 0.0;
196 I_out_total += Ki->GetValue() * dt * I_out_delta;
199 Output = Kp->GetValue() * (Input + I_out_total + Kd->GetValue()*Dval);
201 Output = Kp->GetValue()*Input + I_out_total + Kd->GetValue()*Dval;
203 Input_prev2 = test < 0.0 ? 0.0:Input_prev;
231 void FGPID::Debug(
int from)
233 if (debug_lvl <= 0)
return;
237 cout <<
" INPUT: " << InputNodes[0]->GetNameWithSign() << endl;
239 for (
auto node: OutputNodes)
240 cout <<
" OUTPUT: " << node->getNameString() << endl;
243 if (debug_lvl & 2 ) {
244 if (from == 0) cout <<
"Instantiated: FGPID" << endl;
245 if (from == 1) cout <<
"Destroyed: FGPID" << endl;
247 if (debug_lvl & 4 ) {
249 if (debug_lvl & 8 ) {
251 if (debug_lvl & 16) {
253 if (debug_lvl & 64) {