39#include "models/FGFCS.h"
40#include "math/FGParameterValue.h"
41#include "input_output/FGLog.h"
51FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
56 Input_prev = Input_prev2 = 0.0;
58 ProcessVariableDot =
nullptr;
62 CheckInputNodes(1, 1, element);
64 auto PropertyManager = fcs->GetPropertyManager();
65 string pid_type = element->GetAttributeValue(
"type");
67 if (pid_type ==
"standard") IsStandard =
true;
69 el = element->FindElement(
"kp");
71 Kp =
new FGParameterValue(el, PropertyManager);
73 Kp =
new FGRealValue(0.0);
75 el = element->FindElement(
"ki");
77 string integ_type = el->GetAttributeValue(
"type");
78 if (integ_type ==
"rect") {
80 }
else if (integ_type ==
"trap") {
81 IntType = eTrapezoidal;
82 }
else if (integ_type ==
"ab2") {
83 IntType = eAdamsBashforth2;
84 }
else if (integ_type ==
"ab3") {
85 IntType = eAdamsBashforth3;
87 IntType = eAdamsBashforth2;
90 Ki =
new FGParameterValue(el, PropertyManager);
93 Ki =
new FGRealValue(0.0);
96 el = element->FindElement(
"kd");
98 Kd =
new FGParameterValue(el, PropertyManager);
100 Kd =
new FGRealValue(0.0);
102 el = element->FindElement(
"pvdot");
104 ProcessVariableDot =
new FGPropertyValue(el->GetDataLine(), PropertyManager, el);
106 el = element->FindElement(
"trigger");
108 Trigger =
new FGPropertyValue(el->GetDataLine(), PropertyManager, el);
110 bind(el, PropertyManager.get());
115void FGPID::bind(Element *el, FGPropertyManager* PropertyManager)
117 FGFCSComponent::bind(el, PropertyManager);
120 if (Name.find(
"/") == string::npos) {
121 tmp =
"fcs/" + PropertyManager->mkPropertyName(Name,
true);
125 PropertyManager->Tie<FGPID,
double>(tmp+
"/initial-integrator-value",
this,
126 nullptr, &FGPID::SetInitialOutput);
139 delete ProcessVariableDot;
145void FGPID::ResetPastStates(
void)
147 FGFCSComponent::ResetPastStates();
149 Input_prev = Input_prev2 = Output = I_out_total = 0.0;
154bool FGPID::Run(
void )
156 double I_out_delta = 0.0;
159 Input = InputNodes[0]->getDoubleValue();
161 if (ProcessVariableDot) {
162 Dval = ProcessVariableDot->getDoubleValue();
164 Dval = (Input - Input_prev)/dt;
173 if (Trigger) test = Trigger->getDoubleValue();
175 if (fabs(test) < 0.000001) {
181 I_out_delta = 0.5 * (Input + Input_prev);
183 case eAdamsBashforth2:
184 I_out_delta = 1.5*Input - 0.5*Input_prev;
186 case eAdamsBashforth3:
187 I_out_delta = (23.0*Input - 16.0*Input_prev + 5.0*Input_prev2) / 12.0;
196 if (test < 0.0) I_out_total = 0.0;
198 I_out_total += Ki->GetValue() * dt * I_out_delta;
201 Output = Kp->GetValue() * (Input + I_out_total + Kd->GetValue()*Dval);
203 Output = Kp->GetValue()*Input + I_out_total + Kd->GetValue()*Dval;
205 Input_prev2 = test < 0.0 ? 0.0:Input_prev;
233void FGPID::Debug(
int from)
235 if (debug_lvl <= 0)
return;
238 FGLogging log(LogLevel::DEBUG);
240 log <<
" INPUT: " << InputNodes[0]->GetNameWithSign() <<
"\n";
242 for (
auto node: OutputNodes)
243 log <<
" OUTPUT: " << node->getNameString() <<
"\n";
246 if (debug_lvl & 2 ) {
247 FGLogging log(LogLevel::DEBUG);
248 if (from == 0) log <<
"Instantiated: FGPID\n";
249 if (from == 1) log <<
"Destroyed: FGPID\n";
251 if (debug_lvl & 4 ) {
253 if (debug_lvl & 8 ) {
255 if (debug_lvl & 16) {
257 if (debug_lvl & 64) {
Main namespace for the JSBSim Flight Dynamics Model.