![]() |
JSBSim Flight Dynamics Model 1.0 (23 February 2013)
An Open Source Flight Dynamics and Control Software Library in C++
|
Encapsulates a kinematic (mechanical) component for the flight control system. More...
#include <FGKinemat.h>
Inheritance diagram for FGKinemat:
Collaboration diagram for FGKinemat:Public Member Functions | |
| FGKinemat (FGFCS *fcs, Element *element) | |
| Constructor. | |
| ~FGKinemat () | |
| Destructor. | |
| double | GetOutputPct () const |
| Kinematic component output value. | |
| bool | Run (void) |
| Run method, overrides FGModel::Run(). | |
This component models the action of a moving effector, such as an aerosurface or other mechanized entity such as a landing gear strut for the purpose of effecting vehicle control or configuration. The form of the component specification is:
<kinematic name="Gear Control"> <input> [-]property </input> <traverse> <setting> <position> number </position> <time> number </time> </setting> ... </traverse> [<clipto> <min> {[-]property name | value} </min> <max> {[-]property name | value} </max> </clipto>] [<gain> {property name | value} </gain>] [<output> {property} </output>] </kinematic>
The detent is the position that the component takes, and the lag is the time it takes to get to that position from an adjacent setting. For example:
<kinematic name="Gear Control">
<input>gear/gear-cmd-norm</input>
<traverse>
<setting>
<position>0</position>
<time>0</time>
</setting>
<setting>
<position>1</position>
<time>5</time>
</setting>
</traverse>
<output>gear/gear-pos-norm</output>
</kinematic>
In this case, it takes 5 seconds to get to a 1 setting. As this is a software mechanization of a servo-actuator, there should be an output specified.
Definition at line 111 of file FGKinemat.h.
| fcs | A reference to the current flight control system. |
| element | reference to the current configuration file node. |
Definition at line 56 of file FGKinemat.cpp.
References Element::FindElement(), Element::FindElementValueAsNumber(), and Element::FindNextElement().
: FGFCSComponent(fcs, element) { Element *traverse_element, *setting_element; double tmpDetent; double tmpTime; Detents.clear(); TransitionTimes.clear(); Output = OutputPct = 0; DoScale = true; if (element->FindElement("noscale")) DoScale = false; traverse_element = element->FindElement("traverse"); setting_element = traverse_element->FindElement("setting"); while (setting_element) { tmpDetent = setting_element->FindElementValueAsNumber("position"); tmpTime = setting_element->FindElementValueAsNumber("time"); Detents.push_back(tmpDetent); TransitionTimes.push_back(tmpTime); setting_element = traverse_element->FindNextElement("setting"); } NumDetents = Detents.size(); if (NumDetents <= 1) { cerr << "Kinematic component " << Name << " must have more than 1 setting element" << endl; exit(-1); } FGFCSComponent::bind(); // treenode->Tie("output-norm", this, &FGKinemat::GetOutputPct ); Debug(0); }
Here is the call graph for this function:| double GetOutputPct | ( | void | ) | const [inline, virtual] |
Reimplemented from FGFCSComponent.
Definition at line 124 of file FGKinemat.h.
{ return OutputPct; }
| bool Run | ( | void | ) | [virtual] |
Reimplemented from FGFCSComponent.
Definition at line 102 of file FGKinemat.cpp.
References FGJSBBase::EqualToRoundoff().
{
double dt0 = dt;
Input = InputNodes[0]->getDoubleValue() * InputSigns[0];
if (DoScale) Input *= Detents[NumDetents-1];
if (IsOutput) Output = OutputNodes[0]->getDoubleValue();
if (Input < Detents[0])
Input = Detents[0];
else if (Detents[NumDetents-1] < Input)
Input = Detents[NumDetents-1];
// Process all detent intervals the movement traverses until either the
// final value is reached or the time interval has finished.
while ( dt0 > 0.0 && !EqualToRoundoff(Input, Output) ) {
// Find the area where Output is in
int ind;
for (ind = 1; (Input < Output) ? Detents[ind] < Output : Detents[ind] <= Output ; ++ind)
if (NumDetents <= ind)
break;
// A transition time of 0.0 means an infinite rate.
// The output is reached in one step
if (TransitionTimes[ind] <= 0.0) {
Output = Input;
break;
} else {
// Compute the rate in this area
double Rate = (Detents[ind] - Detents[ind-1])/TransitionTimes[ind];
// Compute the maximum input value inside this area
double ThisInput = Input;
if (ThisInput < Detents[ind-1]) ThisInput = Detents[ind-1];
if (Detents[ind] < ThisInput) ThisInput = Detents[ind];
// Compute the time to reach the value in ThisInput
double ThisDt = fabs((ThisInput-Output)/Rate);
// and clip to the timestep size
if (dt0 < ThisDt) {
ThisDt = dt0;
if (Output < Input)
Output += ThisDt*Rate;
else
Output -= ThisDt*Rate;
} else
// Handle this case separate to make shure the termination condition
// is met even in inexact arithmetics ...
Output = ThisInput;
dt0 -= ThisDt;
}
}
OutputPct = (Output-Detents[0])/(Detents[NumDetents-1]-Detents[0]);
Clip();
if (IsOutput) SetOutput();
return true;
}
Here is the call graph for this function: