Add my old ultra-simplistic PI controller. The fancy PID controller doesn't
seem to be fully deterministic in P-only mode. This old simple controller does what I expect, so it's good for calulating stage #1's of multi-stage controllers.
This commit is contained in:
parent
869aa997a5
commit
bffca78da4
2 changed files with 40 additions and 58 deletions
|
@ -296,13 +296,13 @@ void FGPIDController::update( double dt ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FGSimplePIController::FGSimplePIController( SGPropertyNode *node ):
|
FGPISimpleController::FGPISimpleController( SGPropertyNode *node ):
|
||||||
proportional( false ),
|
proportional( false ),
|
||||||
factor( 0.0 ),
|
Kp( 0.0 ),
|
||||||
offset_prop( NULL ),
|
offset_prop( NULL ),
|
||||||
offset_value( 0.0 ),
|
offset_value( 0.0 ),
|
||||||
integral( false ),
|
integral( false ),
|
||||||
gain( 0.0 ),
|
Ki( 0.0 ),
|
||||||
int_sum( 0.0 ),
|
int_sum( 0.0 ),
|
||||||
clamp( false ),
|
clamp( false ),
|
||||||
debug( false ),
|
debug( false ),
|
||||||
|
@ -318,6 +318,8 @@ FGSimplePIController::FGSimplePIController( SGPropertyNode *node ):
|
||||||
string cval = child->getStringValue();
|
string cval = child->getStringValue();
|
||||||
if ( cname == "name" ) {
|
if ( cname == "name" ) {
|
||||||
name = cval;
|
name = cval;
|
||||||
|
} else if ( cname == "debug" ) {
|
||||||
|
debug = child->getBoolValue();
|
||||||
} else if ( cname == "enable" ) {
|
} else if ( cname == "enable" ) {
|
||||||
// cout << "parsing enable" << endl;
|
// cout << "parsing enable" << endl;
|
||||||
SGPropertyNode *prop = child->getChild( "prop" );
|
SGPropertyNode *prop = child->getChild( "prop" );
|
||||||
|
@ -331,8 +333,6 @@ FGSimplePIController::FGSimplePIController( SGPropertyNode *node ):
|
||||||
if ( val != NULL ) {
|
if ( val != NULL ) {
|
||||||
enable_value = val->getStringValue();
|
enable_value = val->getStringValue();
|
||||||
}
|
}
|
||||||
} else if ( cname == "debug" ) {
|
|
||||||
debug = child->getBoolValue();
|
|
||||||
} else if ( cname == "input" ) {
|
} else if ( cname == "input" ) {
|
||||||
SGPropertyNode *prop = child->getChild( "prop" );
|
SGPropertyNode *prop = child->getChild( "prop" );
|
||||||
if ( prop != NULL ) {
|
if ( prop != NULL ) {
|
||||||
|
@ -345,7 +345,7 @@ FGSimplePIController::FGSimplePIController( SGPropertyNode *node ):
|
||||||
} else {
|
} else {
|
||||||
prop = child->getChild( "value" );
|
prop = child->getChild( "value" );
|
||||||
if ( prop != NULL ) {
|
if ( prop != NULL ) {
|
||||||
r_n_value = prop->getDoubleValue();
|
r_n = prop->getDoubleValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ( cname == "output" ) {
|
} else if ( cname == "output" ) {
|
||||||
|
@ -356,64 +356,43 @@ FGSimplePIController::FGSimplePIController( SGPropertyNode *node ):
|
||||||
output_list.push_back( tmp );
|
output_list.push_back( tmp );
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
prop = child->getChild( "clamp" );
|
} else if ( cname == "config" ) {
|
||||||
|
SGPropertyNode *prop;
|
||||||
|
|
||||||
|
prop = child->getChild( "Kp" );
|
||||||
if ( prop != NULL ) {
|
if ( prop != NULL ) {
|
||||||
|
Kp = prop->getDoubleValue();
|
||||||
|
proportional = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop = child->getChild( "Ki" );
|
||||||
|
if ( prop != NULL ) {
|
||||||
|
Ki = prop->getDoubleValue();
|
||||||
|
integral = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop = child->getChild( "u_min" );
|
||||||
|
if ( prop != NULL ) {
|
||||||
|
u_min = prop->getDoubleValue();
|
||||||
clamp = true;
|
clamp = true;
|
||||||
|
|
||||||
SGPropertyNode *tmp;
|
|
||||||
|
|
||||||
tmp = prop->getChild( "min" );
|
|
||||||
if ( tmp != NULL ) {
|
|
||||||
u_min = tmp->getDoubleValue();
|
|
||||||
// cout << "min = " << u_min << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = prop->getChild( "max" );
|
|
||||||
if ( tmp != NULL ) {
|
|
||||||
u_max = tmp->getDoubleValue();
|
|
||||||
// cout << "max = " << u_max << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ( cname == "proportional" ) {
|
|
||||||
proportional = true;
|
|
||||||
|
|
||||||
SGPropertyNode *prop;
|
|
||||||
|
|
||||||
prop = child->getChild( "factor" );
|
|
||||||
if ( prop != NULL ) {
|
|
||||||
factor = prop->getDoubleValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prop = child->getChild( "offset" );
|
prop = child->getChild( "u_max" );
|
||||||
if ( prop != NULL ) {
|
if ( prop != NULL ) {
|
||||||
SGPropertyNode *sub = prop->getChild( "prop" );
|
u_max = prop->getDoubleValue();
|
||||||
if ( sub != NULL ) {
|
clamp = true;
|
||||||
offset_prop = fgGetNode( sub->getStringValue(), true );
|
|
||||||
// cout << "offset prop = " << sub->getStringValue() << endl;
|
|
||||||
} else {
|
|
||||||
sub = prop->getChild( "value" );
|
|
||||||
if ( sub != NULL ) {
|
|
||||||
offset_value = sub->getDoubleValue();
|
|
||||||
// cout << "offset value = " << offset_value << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ( cname == "integral" ) {
|
|
||||||
integral = true;
|
|
||||||
|
|
||||||
SGPropertyNode *prop;
|
|
||||||
prop = child->getChild( "gain" );
|
|
||||||
if ( prop != NULL ) {
|
|
||||||
gain = prop->getDoubleValue();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in autopilot config logic" );
|
SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in autopilot config logic" );
|
||||||
|
if ( name.length() ) {
|
||||||
|
SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FGSimplePIController::update( double dt ) {
|
void FGPISimpleController::update( double dt ) {
|
||||||
if (enable_prop != NULL && enable_prop->getStringValue() == enable_value) {
|
if (enable_prop != NULL && enable_prop->getStringValue() == enable_value) {
|
||||||
if ( !enabled ) {
|
if ( !enabled ) {
|
||||||
// we have just been enabled, zero out int_sum
|
// we have just been enabled, zero out int_sum
|
||||||
|
@ -454,11 +433,11 @@ void FGSimplePIController::update( double dt ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( proportional ) {
|
if ( proportional ) {
|
||||||
prop_comp = error * factor + offset;
|
prop_comp = error * Kp + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( integral ) {
|
if ( integral ) {
|
||||||
int_sum += error * gain * dt;
|
int_sum += error * Ki * dt;
|
||||||
} else {
|
} else {
|
||||||
int_sum = 0.0;
|
int_sum = 0.0;
|
||||||
}
|
}
|
||||||
|
@ -554,6 +533,9 @@ bool FGXMLAutopilot::build() {
|
||||||
if ( name == "pid-controller" ) {
|
if ( name == "pid-controller" ) {
|
||||||
FGXMLAutoComponent *c = new FGPIDController( node );
|
FGXMLAutoComponent *c = new FGPIDController( node );
|
||||||
components.push_back( c );
|
components.push_back( c );
|
||||||
|
} else if ( name == "pi-simple-controller" ) {
|
||||||
|
FGXMLAutoComponent *c = new FGPISimpleController( node );
|
||||||
|
components.push_back( c );
|
||||||
} else {
|
} else {
|
||||||
SG_LOG( SG_ALL, SG_ALERT, "Unknown top level section: "
|
SG_LOG( SG_ALL, SG_ALERT, "Unknown top level section: "
|
||||||
<< name );
|
<< name );
|
||||||
|
|
|
@ -137,19 +137,19 @@ public:
|
||||||
* A simplistic P [ + I ] PID controller
|
* A simplistic P [ + I ] PID controller
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class FGSimplePIController : public FGXMLAutoComponent {
|
class FGPISimpleController : public FGXMLAutoComponent {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// proportional component data
|
// proportional component data
|
||||||
bool proportional;
|
bool proportional;
|
||||||
double factor;
|
double Kp;
|
||||||
SGPropertyNode *offset_prop;
|
SGPropertyNode *offset_prop;
|
||||||
double offset_value;
|
double offset_value;
|
||||||
|
|
||||||
// integral component data
|
// integral component data
|
||||||
bool integral;
|
bool integral;
|
||||||
double gain;
|
double Ki;
|
||||||
double int_sum;
|
double int_sum;
|
||||||
|
|
||||||
// post functions for output
|
// post functions for output
|
||||||
|
@ -168,8 +168,8 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FGSimplePIController( SGPropertyNode *node );
|
FGPISimpleController( SGPropertyNode *node );
|
||||||
~FGSimplePIController() {}
|
~FGPISimpleController() {}
|
||||||
|
|
||||||
void update( double dt );
|
void update( double dt );
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue