JSBSim Flight Dynamics Model  1.1.11 (13 Feb 2022)
An Open Source Flight Dynamics and Control Software Library in C++
FGExternalForce.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Source: FGExternalForce.cpp
4  Author: Jon Berndt, Dave Culp
5  Date started: 9/21/07
6 
7  ------------- Copyright (C) 2007 Jon S. Berndt (jon@jsbsim.org) -------------
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  HISTORY
27 --------------------------------------------------------------------------------
28 9/21/07 JB Created
29 
30 <external_reactions>
31 
32  <!-- Interface properties, a.k.a. property declarations -->
33  <property> ... </property>
34 
35  <force name="name" frame="BODY|LOCAL|WIND">
36 
37  <function> ... </function>
38 
39  <location unit="units"> <!-- location -->
40  <x> value </x>
41  <y> value </y>
42  <z> value </z>
43  </location>
44  <direction> <!-- optional for initial direction vector -->
45  <x> value </x>
46  <y> value </y>
47  <z> value </z>
48  </direction>
49  </force>
50 
51  <moment name="name" frame="BODY|LOCAL|WIND">
52 
53  <function> ... </function>
54 
55  <direction> <!-- optional for initial direction vector -->
56  <x> value </x>
57  <y> value </y>
58  <z> value </z>
59  </direction>
60  </force>
61 
62 </external_reactions>
63 
64 */
65 
66 #include "FGFDMExec.h"
67 #include "FGExternalForce.h"
68 #include "input_output/FGXMLElement.h"
69 
70 using namespace std;
71 
72 namespace JSBSim {
73 
74 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75 
76 FGPropertyVector3::FGPropertyVector3(FGPropertyManager* pm,
77  const std::string& baseName,
78  const std::string& xcmp,
79  const std::string& ycmp,
80  const std::string& zcmp)
81 {
82  data[0] = pm->CreatePropertyObject<double>(baseName + "/" + xcmp);
83  data[1] = pm->CreatePropertyObject<double>(baseName + "/" + ycmp);
84  data[2] = pm->CreatePropertyObject<double>(baseName + "/" + zcmp);
85 }
86 
87 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
88 
89 FGParameter* FGExternalForce::bind(Element *el, const string& magName,
90  FGPropertyVector3& v)
91 {
92  // Set frame (from FGForce).
93  string sFrame = el->GetAttributeValue("frame");
94  if (sFrame.empty()) {
95  cerr << el->ReadFrom()
96  << "No frame specified for external " << el->GetName() << ", \""
97  << Name << "\"." << endl
98  << "Frame set to Body" << endl;
99  ttype = tNone;
100  } else if (sFrame == "BODY") {
101  ttype = tNone;
102  } else if (sFrame == "LOCAL") {
103  ttype = tLocalBody;
104  } else if (sFrame == "WIND") {
105  ttype = tWindBody;
106  } else {
107  cerr << el->ReadFrom()
108  << "Invalid frame specified for external " << el->GetName() << ", \""
109  << Name << "\"." << endl
110  << "Frame set to Body" << endl;
111  ttype = tNone;
112  }
113 
114  Element* direction_element = el->FindElement("direction");
115  if (!direction_element) {
116  cerr << el->ReadFrom()
117  << "No direction element specified in " << el->GetName()
118  << " object. Default is (0,0,0)." << endl;
119  } else {
120  FGColumnVector3 direction = direction_element->FindElementTripletConvertTo("IN");
121  direction.Normalize();
122  v = direction;
123  }
124 
125  // The value sent to the sim through the external_reactions/{force
126  // name}/magnitude property will be multiplied against the unit vector, which
127  // can come in initially in the direction vector. The frame in which the
128  // vector is defined is specified with the frame attribute. The vector is
129  // normalized to magnitude 1.
130 
131  Element* function_element = el->FindElement("function");
132  if (function_element) {
133  return new FGFunction(fdmex, function_element);
134  } else {
135  FGPropertyManager* pm = fdmex->GetPropertyManager();
136  FGPropertyNode* node = pm->GetNode(magName, true);
137  return new FGPropertyValue(node);
138  }
139 }
140 
141 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142 
143 void FGExternalForce::setForce(Element *el)
144 {
145  FGPropertyManager* PropertyManager = fdmex->GetPropertyManager();
146  Name = el->GetAttributeValue("name");
147  string BasePropertyName = "external_reactions/" + Name;
148 
149  forceDirection = FGPropertyVector3(PropertyManager, BasePropertyName,
150  "x", "y", "z");
151  forceMagnitude = bind(el, BasePropertyName + "/magnitude", forceDirection);
152 
153  Element* location_element = el->FindElement("location");
154  if (!location_element) {
155  cerr << el->ReadFrom()
156  << "No location element specified in force object." << endl;
157  } else {
158  FGColumnVector3 location = location_element->FindElementTripletConvertTo("IN");
159  SetLocation(location);
160  }
161  PropertyManager->Tie( BasePropertyName + "/location-x-in", (FGForce*)this,
162  &FGForce::GetLocationX, &FGForce::SetLocationX);
163  PropertyManager->Tie( BasePropertyName + "/location-y-in", (FGForce*)this,
164  &FGForce::GetLocationY, &FGForce::SetLocationY);
165  PropertyManager->Tie( BasePropertyName + "/location-z-in", (FGForce*)this,
166  &FGForce::GetLocationZ, &FGForce::SetLocationZ);
167 }
168 
169 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 
171 void FGExternalForce::setMoment(Element *el)
172 {
173  FGPropertyManager* PropertyManager = fdmex->GetPropertyManager();
174  Name = el->GetAttributeValue("name");
175  string BasePropertyName = "external_reactions/" + Name;
176 
177  momentDirection = FGPropertyVector3(PropertyManager, BasePropertyName,
178  "l", "m", "n");
179  momentMagnitude = bind(el, BasePropertyName + "/magnitude-lbsft",
180  momentDirection);
181 }
182 
183 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
184 
185 FGExternalForce::~FGExternalForce()
186 {
187  delete forceMagnitude;
188  delete momentMagnitude;
189  Debug(1);
190 }
191 
192 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193 
194 const FGColumnVector3& FGExternalForce::GetBodyForces(void)
195 {
196  if (forceMagnitude)
197  vFn = forceMagnitude->GetValue() * forceDirection;
198 
199  if (momentMagnitude)
200  vMn = Transform() * (momentMagnitude->GetValue() * momentDirection);
201 
202  return FGForce::GetBodyForces();
203 }
204 
205 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
206 // The bitmasked value choices are as follows:
207 // unset: In this case (the default) JSBSim would only print
208 // out the normally expected messages, essentially echoing
209 // the config files as they are read. If the environment
210 // variable is not set, debug_lvl is set to 1 internally
211 // 0: This requests JSBSim not to output any messages
212 // whatsoever.
213 // 1: This value explicity requests the normal JSBSim
214 // startup messages
215 // 2: This value asks for a message to be printed out when
216 // a class is instantiated
217 // 4: When this value is set, a message is displayed when a
218 // FGModel object executes its Run() method
219 // 8: When this value is set, various runtime state variables
220 // are printed out periodically
221 // 16: When set various parameters are sanity checked and
222 // a message is printed out when they go out of bounds
223 
224 void FGExternalForce::Debug(int from)
225 {
226  if (debug_lvl <= 0) return;
227 
228  if (debug_lvl & 1) { // Standard console startup message output
229  if (from == 0) { // Constructor
230  cout << " " << Name << endl;
231  cout << " Frame: ";
232  switch(ttype) {
233  case tNone:
234  cout << "BODY";
235  break;
236  case tLocalBody:
237  cout << "LOCAL";
238  break;
239  case tWindBody:
240  cout << "WIND";
241  break;
242  default:
243  cout << "ERROR/UNKNOWN";
244  }
245  cout << endl << " Location: (" << vXYZn(eX) << ", " << vXYZn(eY) << ", " << vXYZn(eZ) << ")" << endl;
246  }
247  }
248  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
249  if (from == 0) cout << "Instantiated: FGExternalForce" << endl;
250  if (from == 1) cout << "Destroyed: FGExternalForce" << endl;
251  }
252  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
253  }
254  if (debug_lvl & 8 ) { // Runtime state variables
255  }
256  if (debug_lvl & 16) { // Sanity checking
257  }
258  if (debug_lvl & 64) {
259  if (from == 0) { // Constructor
260  }
261  }
262 }
263 }
JSBSim::FGColumnVector3
This class implements a 3 element column vector.
Definition: FGColumnVector3.h:63