Branch data Line data Source code
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 "FGFCS.h"
43 : : #include "input_output/FGPropertyManager.h"
44 : :
45 : : using namespace std;
46 : :
47 : : namespace JSBSim {
48 : :
49 : : static const char *IdSrc = "$Id: FGGroundReactions.cpp,v 1.29 2010/07/30 11:50:01 jberndt Exp $";
50 : : static const char *IdHdr = ID_GROUNDREACTIONS;
51 : :
52 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53 : : CLASS IMPLEMENTATION for MultiplierIterator (See below for FGGroundReactions)
54 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
55 : :
56 : 54006 : MultiplierIterator::MultiplierIterator(FGGroundReactions* GndReactions)
57 : : : GroundReactions(GndReactions),
58 : : multiplier(NULL),
59 : : gearNum(0),
60 : 54006 : entry(0)
61 : : {
62 [ - + ][ # # ]: 54006 : for (int i=0; i < GroundReactions->GetNumGearUnits(); i++) {
63 : 0 : FGLGear* gear = GroundReactions->GetGearUnit(i);
64 : :
65 [ # # ][ # # ]: 0 : if (!gear->GetWOW()) continue;
66 : :
67 : 0 : gearNum = i;
68 : 0 : multiplier = gear->GetMultiplierEntry(0);
69 : 0 : break;
70 : : }
71 : 54006 : }
72 : :
73 : 0 : MultiplierIterator& MultiplierIterator::operator++()
74 : : {
75 [ # # ]: 0 : for (int i=gearNum; i < GroundReactions->GetNumGearUnits(); i++) {
76 : 0 : FGLGear* gear = GroundReactions->GetGearUnit(i);
77 : :
78 [ # # ]: 0 : if (!gear->GetWOW()) continue;
79 : :
80 : 0 : multiplier = gear->GetMultiplierEntry(++entry);
81 [ # # ]: 0 : if (multiplier) {
82 : 0 : gearNum = i;
83 : 0 : break;
84 : : }
85 : : else
86 : 0 : entry = -1;
87 : : }
88 : :
89 : 0 : return *this;
90 : : }
91 : :
92 : : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93 : : CLASS IMPLEMENTATION
94 : : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
95 : :
96 : 1 : FGGroundReactions::FGGroundReactions(FGFDMExec* fgex) : FGModel(fgex)
97 : : {
98 : 1 : Name = "FGGroundReactions";
99 : :
100 : 1 : bind();
101 : :
102 : 1 : Debug(0);
103 : 1 : }
104 : :
105 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 : :
107 : 1 : FGGroundReactions::~FGGroundReactions(void)
108 : : {
109 [ # # ][ - + ]: 1 : for (unsigned int i=0; i<lGear.size();i++) delete lGear[i];
[ # # ][ # # ]
110 : 1 : lGear.clear();
111 : :
112 : 1 : Debug(1);
113 : 1 : }
114 : :
115 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
116 : :
117 : 1 : bool FGGroundReactions::InitModel(void)
118 : : {
119 [ - + ]: 1 : if (!FGModel::InitModel()) return false;
120 : :
121 : 1 : return true;
122 : : }
123 : :
124 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125 : :
126 : 54005 : bool FGGroundReactions::Run(void)
127 : : {
128 [ - + ]: 54005 : if (FGModel::Run()) return true;
129 [ - + ]: 54005 : if (FDMExec->Holding()) return false;
130 : :
131 : 54005 : RunPreFunctions();
132 : :
133 : 54005 : vForces.InitMatrix();
134 : 54005 : vMoments.InitMatrix();
135 : :
136 : : // Sum forces and moments for all gear, here.
137 : : // Some optimizations may be made here - or rather in the gear code itself.
138 : : // The gear ::Run() method is called several times - once for each gear.
139 : : // Perhaps there is some commonality for things which only need to be
140 : : // calculated once.
141 [ - + ]: 54005 : for (unsigned int i=0; i<lGear.size(); i++) {
142 : 0 : vForces += lGear[i]->GetBodyForces();
143 : 0 : vMoments += lGear[i]->GetMoments();
144 : : }
145 : :
146 : 54005 : RunPostFunctions();
147 : :
148 : 54005 : return false;
149 : : }
150 : :
151 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
152 : :
153 : 0 : bool FGGroundReactions::GetWOW(void)
154 : : {
155 : 0 : bool result = false;
156 [ # # ]: 0 : for (unsigned int i=0; i<lGear.size(); i++) {
157 [ # # ][ # # ]: 0 : if (lGear[i]->IsBogey() && lGear[i]->GetWOW()) {
[ # # ]
158 : 0 : result = true;
159 : 0 : break;
160 : : }
161 : : }
162 : 0 : return result;
163 : : }
164 : :
165 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166 : : // This function must be called after friction forces are resolved in order to
167 : : // include them in the ground reactions total force and moment.
168 : 0 : void FGGroundReactions::UpdateForcesAndMoments(void)
169 : : {
170 : 0 : vForces.InitMatrix();
171 : 0 : vMoments.InitMatrix();
172 : :
173 [ # # ]: 0 : for (unsigned int i=0; i<lGear.size(); i++) {
174 : 0 : vForces += lGear[i]->UpdateForces();
175 : 0 : vMoments += lGear[i]->GetMoments();
176 : : }
177 : 0 : }
178 : :
179 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180 : :
181 : 1 : bool FGGroundReactions::Load(Element* el)
182 : : {
183 : 1 : int num=0;
184 : :
185 : 1 : Debug(2);
186 : :
187 : 1 : Element* contact_element = el->FindElement("contact");
188 [ - + ]: 1 : while (contact_element) {
189 : 0 : lGear.push_back(new FGLGear(contact_element, FDMExec, num++));
190 : 0 : FCS->AddGear(); // make the FCS aware of the landing gear
191 : 0 : contact_element = el->FindNextElement("contact");
192 : : }
193 : :
194 : 1 : FGModel::Load(el); // Perform base class Load
195 : :
196 [ - + ]: 1 : for (unsigned int i=0; i<lGear.size();i++) lGear[i]->bind();
197 : :
198 : 1 : PostLoad(el, PropertyManager);
199 : :
200 : 1 : return true;
201 : : }
202 : :
203 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204 : :
205 : 0 : string FGGroundReactions::GetGroundReactionStrings(string delimeter)
206 : : {
207 : 0 : std::ostringstream buf;
208 : :
209 [ # # ]: 0 : for (unsigned int i=0;i<lGear.size();i++) {
210 [ # # ]: 0 : if (lGear[i]->IsBogey()) {
211 : 0 : string name = lGear[i]->GetName();
212 : : buf << name << " WOW" << delimeter
213 : : << name << " stroke (ft)" << delimeter
214 : : << name << " stroke velocity (ft/sec)" << delimeter
215 : : << name << " compress force (lbs)" << delimeter
216 : : << name << " wheel side force (lbs)" << delimeter
217 : : << name << " wheel roll force (lbs)" << delimeter
218 : : << name << " body X force (lbs)" << delimeter
219 : : << name << " body Y force (lbs)" << delimeter
220 : : << name << " wheel velocity vec X (ft/sec)" << delimeter
221 : : << name << " wheel velocity vec Y (ft/sec)" << delimeter
222 : : << name << " wheel rolling velocity (ft/sec)" << delimeter
223 : : << name << " wheel side velocity (ft/sec)" << delimeter
224 : 0 : << name << " wheel slip (deg)" << delimeter;
225 : : }
226 : : }
227 : :
228 : : buf << " Total Gear Force_X (lbs)" << delimeter
229 : : << " Total Gear Force_Y (lbs)" << delimeter
230 : : << " Total Gear Force_Z (lbs)" << delimeter
231 : : << " Total Gear Moment_L (ft-lbs)" << delimeter
232 : : << " Total Gear Moment_M (ft-lbs)" << delimeter
233 : 0 : << " Total Gear Moment_N (ft-lbs)";
234 : :
235 : 0 : return buf.str();
236 : : }
237 : :
238 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239 : :
240 : 0 : string FGGroundReactions::GetGroundReactionValues(string delimeter)
241 : : {
242 : 0 : std::ostringstream buf;
243 : :
244 [ # # ]: 0 : for (unsigned int i=0;i<lGear.size();i++) {
245 [ # # ]: 0 : if (lGear[i]->IsBogey()) {
246 : 0 : FGLGear *gear = lGear[i];
247 : : buf << (gear->GetWOW() ? "1" : "0") << delimeter
248 : : << setprecision(5) << gear->GetCompLen() << delimeter
249 : : << setprecision(6) << gear->GetCompVel() << delimeter
250 : : << setprecision(10) << gear->GetCompForce() << delimeter
251 : : << gear->GetWheelSideForce() << delimeter
252 : : << gear->GetWheelRollForce() << delimeter
253 : : << gear->GetBodyXForce() << delimeter
254 : : << gear->GetBodyYForce() << delimeter
255 : : << setprecision(6) << gear->GetWheelVel(eX) << delimeter
256 : : << gear->GetWheelVel(eY) << delimeter
257 : : << gear->GetWheelRollVel() << delimeter
258 : : << gear->GetWheelSideVel() << delimeter
259 [ # # ]: 0 : << gear->GetWheelSlipAngle() << delimeter;
260 : : }
261 : : }
262 : :
263 : : buf << vForces(eX) << delimeter
264 : : << vForces(eY) << delimeter
265 : : << vForces(eZ) << delimeter
266 : : << vMoments(eX) << delimeter
267 : : << vMoments(eY) << delimeter
268 : 0 : << vMoments(eZ);
269 : :
270 : 0 : return buf.str();
271 : : }
272 : :
273 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 : :
275 : 1 : void FGGroundReactions::bind(void)
276 : : {
277 : : typedef double (FGGroundReactions::*PMF)(int) const;
278 : 2 : PropertyManager->Tie("gear/num-units", this, &FGGroundReactions::GetNumGearUnits);
279 : 1 : PropertyManager->Tie("moments/l-gear-lbsft", this, eL, (PMF)&FGGroundReactions::GetMoments);
280 : 1 : PropertyManager->Tie("moments/m-gear-lbsft", this, eM, (PMF)&FGGroundReactions::GetMoments);
281 : 1 : PropertyManager->Tie("moments/n-gear-lbsft", this, eN, (PMF)&FGGroundReactions::GetMoments);
282 : 1 : PropertyManager->Tie("forces/fbx-gear-lbs", this, eX, (PMF)&FGGroundReactions::GetForces);
283 : 1 : PropertyManager->Tie("forces/fby-gear-lbs", this, eY, (PMF)&FGGroundReactions::GetForces);
284 : 1 : PropertyManager->Tie("forces/fbz-gear-lbs", this, eZ, (PMF)&FGGroundReactions::GetForces);
285 : 1 : }
286 : :
287 : : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288 : : // The bitmasked value choices are as follows:
289 : : // unset: In this case (the default) JSBSim would only print
290 : : // out the normally expected messages, essentially echoing
291 : : // the config files as they are read. If the environment
292 : : // variable is not set, debug_lvl is set to 1 internally
293 : : // 0: This requests JSBSim not to output any messages
294 : : // whatsoever.
295 : : // 1: This value explicity requests the normal JSBSim
296 : : // startup messages
297 : : // 2: This value asks for a message to be printed out when
298 : : // a class is instantiated
299 : : // 4: When this value is set, a message is displayed when a
300 : : // FGModel object executes its Run() method
301 : : // 8: When this value is set, various runtime state variables
302 : : // are printed out periodically
303 : : // 16: When set various parameters are sanity checked and
304 : : // a message is printed out when they go out of bounds
305 : :
306 : 3 : void FGGroundReactions::Debug(int from)
307 : : {
308 [ + - ]: 3 : if (debug_lvl <= 0) return;
309 : :
310 [ + - ]: 3 : if (debug_lvl & 1) { // Standard console startup message output
311 [ + + ]: 3 : if (from == 2) { // Loading
312 : 1 : cout << endl << " Ground Reactions: " << endl;
313 : : }
314 : : }
315 [ - + ]: 3 : if (debug_lvl & 2 ) { // Instantiation/Destruction notification
316 [ # # ]: 0 : if (from == 0) cout << "Instantiated: FGGroundReactions" << endl;
317 [ # # ]: 0 : if (from == 1) cout << "Destroyed: FGGroundReactions" << endl;
318 : : }
319 : 3 : if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
320 : : }
321 : 3 : if (debug_lvl & 8 ) { // Runtime state variables
322 : : }
323 : 3 : if (debug_lvl & 16) { // Sanity checking
324 : : }
325 [ - + ]: 3 : if (debug_lvl & 64) {
326 [ # # ]: 0 : if (from == 0) { // Constructor
327 : 0 : cout << IdSrc << endl;
328 : 0 : cout << IdHdr << endl;
329 : : }
330 : : }
331 : : }
332 [ + + ][ + - ]: 12 : }
|