40#include "FGFCSComponent.h"
41#include "models/FGFCS.h"
42#include "math/FGParameterValue.h"
43#include "input_output/FGLog.h"
55 Input = Output = delay_time = 0.0;
58 clip = cyclic_clip =
false;
59 dt = fcs->GetChannelDeltaT();
61 auto PropertyManager = fcs->GetPropertyManager();
62 if (element->
GetName() ==
string(
"lag_filter")) {
64 }
else if (element->
GetName() ==
string(
"lead_lag_filter")) {
65 Type =
"LEAD_LAG_FILTER";
66 }
else if (element->
GetName() ==
string(
"washout_filter")) {
67 Type =
"WASHOUT_FILTER";
68 }
else if (element->
GetName() ==
string(
"second_order_filter")) {
69 Type =
"SECOND_ORDER_FILTER";
70 }
else if (element->
GetName() ==
string(
"integrator")) {
72 }
else if (element->
GetName() ==
string(
"summer")) {
74 }
else if (element->
GetName() ==
string(
"pure_gain")) {
76 }
else if (element->
GetName() ==
string(
"scheduled_gain")) {
77 Type =
"SCHEDULED_GAIN";
78 }
else if (element->
GetName() ==
string(
"aerosurface_scale")) {
79 Type =
"AEROSURFACE_SCALE";
80 }
else if (element->
GetName() ==
string(
"switch")) {
82 }
else if (element->
GetName() ==
string(
"kinematic")) {
84 }
else if (element->
GetName() ==
string(
"deadband")) {
86 }
else if (element->
GetName() ==
string(
"fcs_function")) {
87 Type =
"FCS_FUNCTION";
88 }
else if (element->
GetName() ==
string(
"pid")) {
90 }
else if (element->
GetName() ==
string(
"sensor")) {
92 }
else if (element->
GetName() ==
string(
"accelerometer")) {
93 Type =
"ACCELEROMETER";
94 }
else if (element->
GetName() ==
string(
"magnetometer")) {
95 Type =
"MAGNETOMETER";
96 }
else if (element->
GetName() ==
string(
"gyro")) {
98 }
else if (element->
GetName() ==
string(
"actuator")) {
100 }
else if (element->
GetName() ==
string(
"waypoint_heading")) {
101 Type =
"WAYPOINT_HEADING";
102 }
else if (element->
GetName() ==
string(
"waypoint_distance")) {
103 Type =
"WAYPOINT_DISTANCE";
104 }
else if (element->
GetName() ==
string(
"angle")) {
106 }
else if (element->
GetName() ==
string(
"distributor")) {
107 Type =
"DISTRIBUTOR";
115 while (init_element) {
117 PropertyManager, init_element));
122 while (input_element) {
124 PropertyManager, input_element));
132 bool node_exists = PropertyManager->HasNode(output_node_name);
133 SGPropertyNode* OutputNode = PropertyManager->GetNode( output_node_name,
true );
136 err <<
" Unable to process property: " << output_node_name <<
"\n";
139 OutputNodes.push_back(OutputNode);
153 delay_time = delayParam.GetValue();
155 if (delayType.length() > 0) {
156 if (delayType ==
"time") {
157 delay = (
unsigned int)(delay_time / dt);
158 }
else if (delayType ==
"frames") {
159 delay = (
unsigned int)delay_time;
162 log <<
"Unallowed delay type\n";
165 delay = (
unsigned int)(delay_time / dt);
167 output_array.resize(delay);
168 for (
unsigned int i=0; i<delay; i++) output_array[i] = 0.0;
176 log <<
"Element <min> is missing, <clipto> is ignored.\n";
185 log <<
"Element <max> is missing, <clipto> is ignored.\n";
210void FGFCSComponent::ResetPastStates(
void)
213 for (
auto &elm: output_array)
219void FGFCSComponent::CheckInputNodes(
size_t MinNodes,
size_t MaxNodes, Element* el)
221 size_t num = InputNodes.size();
223 if (num < MinNodes) {
224 XMLLogException err(el);
225 err <<
" Not enough <input> nodes are provided\n"
226 <<
" Expecting " << MinNodes <<
" while " << num
227 <<
" are provided.\n";
231 if (num > MaxNodes) {
232 FGXMLLogging log(el, LogLevel::ERROR);
233 log <<
" Too many <input> nodes are provided\n"
234 <<
" Expecting " << MaxNodes <<
" while " << num
235 <<
" are provided.\n"
236 <<
" The last " << num-MaxNodes <<
" input nodes will be ignored.\n";
242void FGFCSComponent::SetOutput(
void)
244 for (
auto node: OutputNodes)
245 node->setDoubleValue(Output);
250void FGFCSComponent::Delay(
void)
252 if (fcs->GetTrimStatus()) {
255 std::fill(output_array.begin(), output_array.end(), Output);
258 output_array[index] = Output;
259 if ((
unsigned int)index == delay-1) index = 0;
261 Output = output_array[index];
267void FGFCSComponent::Clip(
void)
270 double vmin = ClipMin->GetValue();
271 double vmax = ClipMax->GetValue();
272 double range = vmax - vmin;
275 FGLogging log(LogLevel::ERROR);
276 log <<
"Trying to clip with a max value (" << fixed << vmax <<
") from "
277 << ClipMax->GetName() <<
" lower than the min value (" << vmin
278 <<
") from " << ClipMin->GetName() <<
".\n"
279 <<
"Clipping is ignored.\n";
283 if (cyclic_clip && range != 0.0) {
284 double value = Output - vmin;
285 Output = fmod(value, range) + vmin;
303void FGFCSComponent::bind(Element* el, FGPropertyManager* PropertyManager)
306 if (Name.find(
"/") == string::npos)
307 tmp =
"fcs/" + PropertyManager->mkPropertyName(Name,
true);
311 bool node_exists = PropertyManager->HasNode(tmp);
315 OutputNodes.push_back(node);
324 FGXMLLogging log(el, LogLevel::ERROR);
325 log <<
"Could not get or create property " << tmp <<
"\n";
348void FGFCSComponent::Debug(
int from)
350 if (debug_lvl <= 0)
return;
354 FGLogging log(LogLevel::DEBUG);
355 log <<
"\n Loading Component \"" << Name << fixed
356 <<
"\" of type: " << Type <<
"\n";
359 log <<
" Minimum limit: " << ClipMin->GetName() <<
"\n";
360 log <<
" Maximum limit: " << ClipMax->GetName() <<
"\n";
362 if (delay > 0) log <<
" Frame delay: " << delay << fixed
363 << setprecision(4) <<
" frames (" << delay*dt <<
" sec)\n";
366 if (debug_lvl & 2 ) {
367 FGLogging log(LogLevel::DEBUG);
368 if (from == 0) log <<
"Instantiated: FGFCSComponent\n";
369 if (from == 1) log <<
"Destroyed: FGFCSComponent\n";
371 if (debug_lvl & 4 ) {
373 if (debug_lvl & 8 ) {
375 if (debug_lvl & 16) {
377 if (debug_lvl & 64) {
Element * FindElement(const std::string &el="")
Searches for a specified element.
const std::string & GetName(void) const
Retrieves the element name.
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
std::string GetDataLine(unsigned int i=0)
Gets a line of data belonging to an element.
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
virtual ~FGFCSComponent()
Destructor.
FGFCSComponent(FGFCS *fcs, Element *el)
Constructor.
Encapsulates the Flight Control System (FCS) functionality.
static constexpr double Constrain(double min, double value, double max)
Constrain a value between a minimum and a maximum value.
Represents a either a real value or a property value.
Represents a property value which can use late binding.
A node in a property tree.
bool setDoubleValue(double value)
Set a double value for this node.
Main namespace for the JSBSim Flight Dynamics Model.