39 #include "input_output/FGXMLElement.h" 47 IDENT(IdSrc,
"$Id: FGPID.cpp,v 1.24 2014/01/13 10:46:09 ehofman Exp $");
54 FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
56 string kp_string, ki_string, kd_string;
66 Input_prev = Input_prev2 = 0.0;
68 ProcessVariableDot = 0;
72 string pid_type = element->GetAttributeValue(
"type");
74 if (pid_type ==
"standard") IsStandard =
true;
76 if ( element->FindElement(
"kp") ) {
77 kp_string = element->FindElementValue(
"kp");
78 if (!is_number(kp_string)) {
79 if (kp_string[0] ==
'-') {
80 KpPropertySign = -1.0;
83 KpPropertyNode = PropertyManager->GetNode(kp_string);
85 Kp = element->FindElementValueAsNumber(
"kp");
89 if ( element->FindElement(
"ki") ) {
90 ki_string = element->FindElementValue(
"ki");
92 string integ_type = element->FindElement(
"ki")->GetAttributeValue(
"type");
93 if (integ_type ==
"rect") {
95 }
else if (integ_type ==
"trap") {
96 IntType = eTrapezoidal;
97 }
else if (integ_type ==
"ab2") {
98 IntType = eAdamsBashforth2;
99 }
else if (integ_type ==
"ab3") {
100 IntType = eAdamsBashforth3;
102 IntType = eAdamsBashforth2;
105 if (!is_number(ki_string)) {
106 if (ki_string[0] ==
'-') {
107 KiPropertySign = -1.0;
108 ki_string.erase(0,1);
110 KiPropertyNode = PropertyManager->GetNode(ki_string);
112 Ki = element->FindElementValueAsNumber(
"ki");
116 if ( element->FindElement(
"kd") ) {
117 kd_string = element->FindElementValue(
"kd");
118 if (!is_number(kd_string)) {
119 if (kd_string[0] ==
'-') {
120 KdPropertySign = -1.0;
121 kd_string.erase(0,1);
123 KdPropertyNode = PropertyManager->GetNode(kd_string);
125 Kd = element->FindElementValueAsNumber(
"kd");
129 if (element->FindElement(
"pvdot")) {
130 ProcessVariableDot = PropertyManager->GetNode(element->FindElementValue(
"pvdot"));
133 if (element->FindElement(
"trigger")) {
134 Trigger = PropertyManager->GetNode(element->FindElementValue(
"trigger"));
137 FGFCSComponent::bind();
139 if (Name.find(
"/") == string::npos) {
140 tmp =
"fcs/" + PropertyManager->mkPropertyName(Name,
true);
144 typedef double (FGPID::*PMF)(void)
const;
145 PropertyManager->Tie(tmp+
"/initial-integrator-value",
this, (PMF)0, &FGPID::SetInitialOutput);
159 void FGPID::ResetPastStates(
void)
161 FGFCSComponent::ResetPastStates();
163 Input_prev = Input_prev2 = Output = I_out_total = 0.0;
168 bool FGPID::Run(
void )
170 double I_out_delta = 0.0;
173 Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
175 if (KpPropertyNode != 0) Kp = KpPropertyNode->getDoubleValue() * KpPropertySign;
176 if (KiPropertyNode != 0) Ki = KiPropertyNode->getDoubleValue() * KiPropertySign;
177 if (KdPropertyNode != 0) Kd = KdPropertyNode->getDoubleValue() * KdPropertySign;
179 if (ProcessVariableDot) {
180 Dval = ProcessVariableDot->getDoubleValue();
182 Dval = (Input - Input_prev)/dt;
191 if (Trigger != 0) test = Trigger->getDoubleValue();
193 if (fabs(test) < 0.000001) {
196 I_out_delta = Ki * dt * Input;
199 I_out_delta = (Ki/2.0) * dt * (Input + Input_prev);
201 case eAdamsBashforth2:
202 I_out_delta = Ki * dt * (1.5*Input - 0.5*Input_prev);
204 case eAdamsBashforth3:
205 I_out_delta = (Ki/12.0) * dt * (23.0*Input - 16.0*Input_prev + 5.0*Input_prev2);
214 if (test < 0.0) I_out_total = 0.0;
216 I_out_total += I_out_delta;
219 Output = Kp * (Input + I_out_total + Kd*Dval);
221 Output = Kp*Input + I_out_total + Kd*Dval;
225 Input_prev2 = Input_prev;
228 if (IsOutput) SetOutput();
252 void FGPID::Debug(
int from)
254 if (debug_lvl <= 0)
return;
258 if (InputSigns[0] < 0)
259 cout <<
" INPUT: -" << InputNodes[0]->GetName() << endl;
261 cout <<
" INPUT: " << InputNodes[0]->GetName() << endl;
264 for (
unsigned int i=0; i<OutputNodes.size(); i++)
265 cout <<
" OUTPUT: " << OutputNodes[i]->getName() << endl;
269 if (debug_lvl & 2 ) {
270 if (from == 0) cout <<
"Instantiated: FGPID" << endl;
271 if (from == 1) cout <<
"Destroyed: FGPID" << endl;
273 if (debug_lvl & 4 ) {
275 if (debug_lvl & 8 ) {
277 if (debug_lvl & 16) {
279 if (debug_lvl & 64) {
281 cout << IdSrc << endl;
282 cout << IdHdr << endl;