JSBSim Flight Dynamics Model  1.1.11 (13 Feb 2022)
An Open Source Flight Dynamics and Control Software Library in C++
FGGroundReactions.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Module: FGGroundReactions.cpp
4  Author: Jon S. Berndt
5  Date started: 09/13/00
6  Purpose: Encapsulates the ground reaction forces (gear and collision)
7 
8  ------------- Copyright (C) 2000 Jon S. Berndt (jon@jsbsim.org) -------------
9 
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU Lesser General Public License as published by the Free
12  Software Foundation; either version 2 of the License, or (at your option) any
13  later version.
14 
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18  details.
19 
20  You should have received a copy of the GNU Lesser General Public License along
21  with this program; if not, write to the Free Software Foundation, Inc., 59
22  Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24  Further information about the GNU Lesser General Public License can also be
25  found on the world wide web at http://www.gnu.org.
26 
27 FUNCTIONAL DESCRIPTION
28 --------------------------------------------------------------------------------
29 
30 HISTORY
31 --------------------------------------------------------------------------------
32 09/13/00 JSB Created
33 
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 INCLUDES
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
37 
38 #include <iomanip>
39 
40 #include "FGGroundReactions.h"
41 #include "FGAccelerations.h"
42 #include "input_output/FGXMLElement.h"
43 
44 using namespace std;
45 
46 namespace JSBSim {
47 
48 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
49 CLASS IMPLEMENTATION
50 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
51 
52 FGGroundReactions::FGGroundReactions(FGFDMExec* fgex) :
53  FGModel(fgex),
54  FGSurface(fgex),
55  DsCmd(0.0)
56 {
57  Name = "FGGroundReactions";
58 
59  bind();
60 
61  Debug(0);
62 }
63 
64 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
65 
66 FGGroundReactions::~FGGroundReactions(void)
67 {
68  for (unsigned int i=0; i<lGear.size();i++) delete lGear[i];
69  lGear.clear();
70 
71  Debug(1);
72 }
73 
74 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75 
76 bool FGGroundReactions::InitModel(void)
77 {
78  if (!FGModel::InitModel()) return false;
79 
80  vForces.InitMatrix();
81  vMoments.InitMatrix();
82  DsCmd = 0.0;
83 
84  multipliers.clear();
85 
86  for (unsigned int i=0; i<lGear.size(); i++)
87  lGear[i]->ResetToIC();
88 
89  return true;
90 }
91 
92 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93 
94 bool FGGroundReactions::Run(bool Holding)
95 {
96  if (FGModel::Run(Holding)) return true;
97  if (Holding) return false;
98 
99  RunPreFunctions();
100 
101  vForces.InitMatrix();
102  vMoments.InitMatrix();
103 
104  multipliers.clear();
105 
106  // Sum forces and moments for all gear, here.
107  // Some optimizations may be made here - or rather in the gear code itself.
108  // The gear ::Run() method is called several times - once for each gear.
109  // Perhaps there is some commonality for things which only need to be
110  // calculated once.
111  for (unsigned int i=0; i<lGear.size(); i++) {
112  vForces += lGear[i]->GetBodyForces(this);
113  vMoments += lGear[i]->GetMoments();
114  }
115 
116  RunPostFunctions();
117 
118  return false;
119 }
120 
121 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122 
123 bool FGGroundReactions::GetWOW(void) const
124 {
125  bool result = false;
126  for (unsigned int i=0; i<lGear.size(); i++) {
127  if (lGear[i]->IsBogey() && lGear[i]->GetWOW()) {
128  result = true;
129  break;
130  }
131  }
132  return result;
133 }
134 
135 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 
138 {
139  DsCmd = cmd;
140  for (unsigned int i=0; i<lGear.size(); ++i)
141  lGear[i]->SetSteerCmd(cmd);
142 }
143 
144 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145 
146 bool FGGroundReactions::Load(Element* document)
147 {
148  int num=0;
149 
150  Name = "Ground Reactions Model: " + document->GetAttributeValue("name");
151 
152  Debug(2);
153 
154  // Perform base class Pre-Load
155  if (!FGModel::Upload(document, true))
156  return false;
157 
158  unsigned int numContacts = document->GetNumElements("contact");
159  lGear.resize(numContacts);
160  Element* contact_element = document->FindElement("contact");
161  for (unsigned int idx=0; idx<numContacts; idx++) {
162  lGear[idx] = new FGLGear(contact_element, FDMExec, num++, in);
163  contact_element = document->FindNextElement("contact");
164  }
165 
166  for (unsigned int i=0; i<lGear.size();i++) lGear[i]->bind();
167 
168  PostLoad(document, FDMExec);
169 
170  return true;
171 }
172 
173 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174 
175 string FGGroundReactions::GetGroundReactionStrings(string delimeter) const
176 {
177  std::ostringstream buf;
178 
179  for (unsigned int i=0;i<lGear.size();i++) {
180  if (lGear[i]->IsBogey()) {
181  string name = lGear[i]->GetName();
182  buf << name << " WOW" << delimeter
183  << name << " stroke (ft)" << delimeter
184  << name << " stroke velocity (ft/sec)" << delimeter
185  << name << " compress force (lbs)" << delimeter
186  << name << " wheel side force (lbs)" << delimeter
187  << name << " wheel roll force (lbs)" << delimeter
188  << name << " body X force (lbs)" << delimeter
189  << name << " body Y force (lbs)" << delimeter
190  << name << " wheel velocity vec X (ft/sec)" << delimeter
191  << name << " wheel velocity vec Y (ft/sec)" << delimeter
192  << name << " wheel rolling velocity (ft/sec)" << delimeter
193  << name << " wheel side velocity (ft/sec)" << delimeter
194  << name << " wheel slip (deg)" << delimeter;
195  } else {
196  string name = lGear[i]->GetName();
197  buf << name << " WOW" << delimeter
198  << name << " stroke (ft)" << delimeter
199  << name << " stroke velocity (ft/sec)" << delimeter
200  << name << " compress force (lbs)" << delimeter;
201  }
202  }
203 
204  buf << " Total Gear Force_X (lbs)" << delimeter
205  << " Total Gear Force_Y (lbs)" << delimeter
206  << " Total Gear Force_Z (lbs)" << delimeter
207  << " Total Gear Moment_L (ft-lbs)" << delimeter
208  << " Total Gear Moment_M (ft-lbs)" << delimeter
209  << " Total Gear Moment_N (ft-lbs)";
210 
211  return buf.str();
212 }
213 
214 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215 
216 string FGGroundReactions::GetGroundReactionValues(string delimeter) const
217 {
218  std::ostringstream buf;
219 
220  for (unsigned int i=0;i<lGear.size();i++) {
221  if (lGear[i]->IsBogey()) {
222  FGLGear *gear = lGear[i];
223  buf << (gear->GetWOW() ? "1" : "0") << delimeter
224  << setprecision(5) << gear->GetCompLen() << delimeter
225  << setprecision(6) << gear->GetCompVel() << delimeter
226  << setprecision(10) << gear->GetCompForce() << delimeter
227  << gear->GetWheelSideForce() << delimeter
228  << gear->GetWheelRollForce() << delimeter
229  << gear->GetBodyXForce() << delimeter
230  << gear->GetBodyYForce() << delimeter
231  << setprecision(6) << gear->GetWheelVel(eX) << delimeter
232  << gear->GetWheelVel(eY) << delimeter
233  << gear->GetWheelRollVel() << delimeter
234  << gear->GetWheelSideVel() << delimeter
235  << gear->GetWheelSlipAngle() << delimeter;
236  } else {
237  FGLGear *gear = lGear[i];
238  buf << (gear->GetWOW() ? "1" : "0") << delimeter
239  << setprecision(5) << gear->GetCompLen() << delimeter
240  << setprecision(6) << gear->GetCompVel() << delimeter
241  << setprecision(10) << gear->GetCompForce() << delimeter;
242  }
243  }
244 
245  FGAccelerations* Accelerations = FDMExec->GetAccelerations();
246 
247  buf << Accelerations->GetGroundForces(eX) << delimeter
248  << Accelerations->GetGroundForces(eY) << delimeter
249  << Accelerations->GetGroundForces(eZ) << delimeter
250  << Accelerations->GetGroundMoments(eX) << delimeter
251  << Accelerations->GetGroundMoments(eY) << delimeter
252  << Accelerations->GetGroundMoments(eZ);
253 
254  return buf.str();
255 }
256 
257 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258 
259 void FGGroundReactions::bind(void)
260 {
261  eSurfaceType = ctGROUND;
262  FGSurface::bind();
263 
264  PropertyManager->Tie("gear/num-units", this, &FGGroundReactions::GetNumGearUnits);
265  PropertyManager->Tie("gear/wow", this, &FGGroundReactions::GetWOW);
266  PropertyManager->Tie("fcs/steer-cmd-norm", this, &FGGroundReactions::GetDsCmd,
268 }
269 
270 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 // The bitmasked value choices are as follows:
272 // unset: In this case (the default) JSBSim would only print
273 // out the normally expected messages, essentially echoing
274 // the config files as they are read. If the environment
275 // variable is not set, debug_lvl is set to 1 internally
276 // 0: This requests JSBSim not to output any messages
277 // whatsoever.
278 // 1: This value explicity requests the normal JSBSim
279 // startup messages
280 // 2: This value asks for a message to be printed out when
281 // a class is instantiated
282 // 4: When this value is set, a message is displayed when a
283 // FGModel object executes its Run() method
284 // 8: When this value is set, various runtime state variables
285 // are printed out periodically
286 // 16: When set various parameters are sanity checked and
287 // a message is printed out when they go out of bounds
288 
289 void FGGroundReactions::Debug(int from)
290 {
291  if (debug_lvl <= 0) return;
292 
293  if (debug_lvl & 1) { // Standard console startup message output
294  if (from == 2) { // Loading
295  cout << endl << " Ground Reactions: " << endl;
296  }
297  }
298  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
299  if (from == 0) cout << "Instantiated: FGGroundReactions" << endl;
300  if (from == 1) cout << "Destroyed: FGGroundReactions" << endl;
301  }
302  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
303  }
304  if (debug_lvl & 8 ) { // Runtime state variables
305  }
306  if (debug_lvl & 16) { // Sanity checking
307  }
308  if (debug_lvl & 64) {
309  if (from == 0) { // Constructor
310  }
311  }
312 }
313 }
JSBSim::FGGroundReactions::Run
bool Run(bool Holding) override
Runs the Ground Reactions model; called by the Executive Can pass in a value indicating if the execut...
Definition: FGGroundReactions.cpp:94
JSBSim::FGModel::Upload
bool Upload(Element *el, bool preLoad)
Uploads this model in memory.
Definition: FGModel.cpp:110
JSBSim::Element::GetAttributeValue
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
Definition: FGXMLElement.cpp:260
JSBSim::FGGroundReactions::GetDsCmd
double GetDsCmd(void) const
Gets the steering command.
Definition: FGGroundReactions.h:114
JSBSim::Element::FindElement
Element * FindElement(const std::string &el="")
Searches for a specified element.
Definition: FGXMLElement.cpp:389
JSBSim::FGLGear
Landing gear model.
Definition: FGLGear.h:190
JSBSim::FGGroundReactions::SetDsCmd
void SetDsCmd(double cmd)
Sets the steering command.
Definition: FGGroundReactions.cpp:137
JSBSim::FGModel::Run
virtual bool Run(bool Holding)
Runs the model; called by the Executive.
Definition: FGModel.cpp:89
JSBSim::Element::GetNumElements
unsigned int GetNumElements(void)
Returns the number of child elements for this element.
Definition: FGXMLElement.h:192
JSBSim::FGGroundReactions::GetNumGearUnits
int GetNumGearUnits(void) const
Gets the number of gears.
Definition: FGGroundReactions.h:105
JSBSim::Element::FindNextElement
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
Definition: FGXMLElement.cpp:407
JSBSim::FGAccelerations::GetGroundForces
double GetGroundForces(int idx) const
Retrieves the ground forces applied on the body.
Definition: FGAccelerations.h:289
JSBSim::FGFDMExec::GetAccelerations
FGAccelerations * GetAccelerations(void)
Returns the FGAccelerations pointer.
Definition: FGFDMExec.h:355
JSBSim::Element
Definition: FGXMLElement.h:143
JSBSim::FGPropertyManager::Tie
void Tie(const std::string &name, T *pointer)
Tie a property to an external variable.
Definition: FGPropertyManager.h:449