JSBSim Flight Dynamics Model  1.1.11 (13 Feb 2022)
An Open Source Flight Dynamics and Control Software Library in C++
FGKinemat.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Module: FGKinemat.cpp
4  Author: Tony Peden, for flight control system authored by Jon S. Berndt
5  Date started: 12/02/01
6 
7  ------------- Copyright (C) 2000 Anthony K. Peden -------------
8 
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free
11  Software Foundation; either version 2 of the License, or (at your option) any
12  later version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
17  details.
18 
19  You should have received a copy of the GNU Lesser General Public License along
20  with this program; if not, write to the Free Software Foundation, Inc., 59
21  Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 
23  Further information about the GNU Lesser General Public License can also be
24  found on the world wide web at http://www.gnu.org.
25 
26 FUNCTIONAL DESCRIPTION
27 --------------------------------------------------------------------------------
28 
29 HISTORY
30 --------------------------------------------------------------------------------
31 
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33 COMMENTS, REFERENCES, and NOTES
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 INCLUDES
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39 
40 #include "FGKinemat.h"
41 #include "input_output/FGXMLElement.h"
42 #include "models/FGFCS.h"
43 
44 using namespace std;
45 
46 namespace JSBSim {
47 
48 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
49 CLASS IMPLEMENTATION
50 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
51 
52 FGKinemat::FGKinemat(FGFCS* fcs, Element* element)
53  : FGFCSComponent(fcs, element)
54 {
55  CheckInputNodes(1, 1, element);
56 
57  Output = 0;
58  DoScale = true;
59 
60  if (element->FindElement("noscale")) DoScale = false;
61 
62  Element* traverse_element = element->FindElement("traverse");
63  Element* setting_element = traverse_element->FindElement("setting");
64  while (setting_element) {
65  double tmpDetent = setting_element->FindElementValueAsNumber("position");
66  double tmpTime = setting_element->FindElementValueAsNumber("time");
67  Detents.push_back(tmpDetent);
68  TransitionTimes.push_back(tmpTime);
69  setting_element = traverse_element->FindNextElement("setting");
70  }
71 
72  if (Detents.size() <= 1) {
73  stringstream s;
74  s << "Kinematic component " << Name
75  << " must have more than 1 setting element";
76  cerr << element->ReadFrom() << endl << s.str() << endl;
77  throw BaseException(s.str());
78  }
79 
80  bind(element);
81 
82  Debug(0);
83 }
84 
85 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
86 
88 {
89  Debug(1);
90 }
91 
92 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93 
94 bool FGKinemat::Run(void )
95 {
96  double dt0 = dt;
97 
98  Input = InputNodes[0]->getDoubleValue();
99 
100  if (DoScale) Input *= Detents.back();
101 
102  if (!OutputNodes.empty())
103  Output = OutputNodes[0]->getDoubleValue();
104 
105  Input = Constrain(Detents.front(), Input, Detents.back());
106 
107  if (fcs->GetTrimStatus())
108  // When trimming the output must be reached in one step
109  Output = Input;
110  else {
111  // Process all detent intervals the movement traverses until either the
112  // final value is reached or the time interval has finished.
113  while ( dt0 > 0.0 && !EqualToRoundoff(Input, Output) ) {
114 
115  // Find the area where Output is in
116  unsigned int ind;
117  for (ind = 1; (Input < Output) ? Detents[ind] < Output : Detents[ind] <= Output ; ++ind)
118  if (ind >= Detents.size())
119  break;
120 
121  // A transition time of 0.0 means an infinite rate.
122  // The output is reached in one step
123  if (TransitionTimes[ind] <= 0.0) {
124  Output = Input;
125  break;
126  } else {
127  // Compute the rate in this area
128  double Rate = (Detents[ind] - Detents[ind-1])/TransitionTimes[ind];
129  // Compute the maximum input value inside this area
130  double ThisInput = Constrain(Detents[ind-1], Input, Detents[ind]);
131  // Compute the time to reach the value in ThisInput
132  double ThisDt = fabs((ThisInput-Output)/Rate);
133 
134  // and clip to the timestep size
135  if (dt0 < ThisDt) {
136  ThisDt = dt0;
137  if (Output < Input)
138  Output += ThisDt*Rate;
139  else
140  Output -= ThisDt*Rate;
141  } else
142  // Handle this case separate to make shure the termination condition
143  // is met even in inexact arithmetics ...
144  Output = ThisInput;
145 
146  dt0 -= ThisDt;
147  }
148  }
149  }
150 
151  Clip();
152  SetOutput();
153 
154  return true;
155 }
156 
157 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158 // The bitmasked value choices are as follows:
159 // unset: In this case (the default) JSBSim would only print
160 // out the normally expected messages, essentially echoing
161 // the config files as they are read. If the environment
162 // variable is not set, debug_lvl is set to 1 internally
163 // 0: This requests JSBSim not to output any messages
164 // whatsoever.
165 // 1: This value explicity requests the normal JSBSim
166 // startup messages
167 // 2: This value asks for a message to be printed out when
168 // a class is instantiated
169 // 4: When this value is set, a message is displayed when a
170 // FGModel object executes its Run() method
171 // 8: When this value is set, various runtime state variables
172 // are printed out periodically
173 // 16: When set various parameters are sanity checked and
174 // a message is printed out when they go out of bounds
175 
176 void FGKinemat::Debug(int from)
177 {
178  if (debug_lvl <= 0) return;
179 
180  if (debug_lvl & 1) { // Standard console startup message output
181  if (from == 0) { // Constructor
182  cout << " INPUT: " << InputNodes[0]->GetName() << endl;
183  cout << " DETENTS: " << Detents.size() << endl;
184  for (unsigned int i=0;i<Detents.size();i++) {
185  cout << " " << Detents[i] << " " << TransitionTimes[i] << endl;
186  }
187  for (auto node: OutputNodes)
188  cout << " OUTPUT: " << node->getNameString() << endl;
189  if (!DoScale) cout << " NOSCALE" << endl;
190  }
191  }
192  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
193  if (from == 0) cout << "Instantiated: FGKinemat" << endl;
194  if (from == 1) cout << "Destroyed: FGKinemat" << endl;
195  }
196  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
197  }
198  if (debug_lvl & 8 ) { // Runtime state variables
199  }
200  if (debug_lvl & 16) { // Sanity checking
201  }
202  if (debug_lvl & 64) {
203  if (from == 0) { // Constructor
204  }
205  }
206 }
207 }
JSBSim::FGJSBBase::EqualToRoundoff
static bool EqualToRoundoff(double a, double b)
Finite precision comparison.
Definition: FGJSBBase.h:301
JSBSim::Element::FindElement
Element * FindElement(const std::string &el="")
Searches for a specified element.
Definition: FGXMLElement.cpp:389
JSBSim::Element::FindElementValueAsNumber
double FindElementValueAsNumber(const std::string &el="")
Searches for the named element and returns the data belonging to it as a number.
Definition: FGXMLElement.cpp:429
JSBSim::FGKinemat::~FGKinemat
~FGKinemat()
Destructor.
Definition: FGKinemat.cpp:87
JSBSim::BaseException
Definition: FGJSBBase.h:59
JSBSim::FGFCSComponent
Base class for JSBSim Flight Control System Components.
Definition: FGFCSComponent.h:84
JSBSim::FGJSBBase::Constrain
static constexpr double Constrain(double min, double value, double max)
Constrain a value between a minimum and a maximum value.
Definition: FGJSBBase.h:333
JSBSim::FGFCS
Encapsulates the Flight Control System (FCS) functionality.
Definition: FGFCS.h:187
JSBSim::FGKinemat::Run
bool Run(void) override
Run method, overrides FGModel::Run().
Definition: FGKinemat.cpp:94
JSBSim::Element::ReadFrom
std::string ReadFrom(void) const
Return a string that contains a description of the location where the current XML element was read fr...
Definition: FGXMLElement.cpp:738
JSBSim::Element::FindNextElement
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
Definition: FGXMLElement.cpp:407
JSBSim::Element
Definition: FGXMLElement.h:143