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