]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/models/FGExternalForce.cpp
Merge branch 'jsd/atmos' into topic/atmos-merge
[flightgear.git] / src / FDM / JSBSim / models / 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 Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  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 with
20  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21  Place - Suite 330, Boston, MA  02111-1307, USA.
22
23  Further information about the GNU Lesser General Public License can also be found on
24  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 </external_reactions>
52
53 */
54
55 #include "FGExternalForce.h"
56
57 namespace JSBSim {
58
59 static const char *IdSrc = "$Id$";
60 static const char *IdHdr = ID_EXTERNALFORCE;
61
62 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63
64 FGExternalForce::FGExternalForce(FGFDMExec *FDMExec, Element *el, int index): FGForce(FDMExec)
65 {
66   Element* location_element=0;
67   Element* direction_element=0;
68   Element* function_element=0;
69   string sFrame;
70   string BasePropertyName;
71   FGColumnVector3 location;
72   Magnitude_Function = 0;
73   magnitude = 0.0;
74   azimuth = 0.0;
75
76   PropertyManager = fdmex->GetPropertyManager();
77   Name = el->GetAttributeValue("name");
78   BasePropertyName = "external_reactions/" + Name;
79
80   // The value sent to the sim through the external_forces/{force name}/magnitude
81   // property will be multiplied against the unit vector, which can come in
82   // initially in the direction vector. The frame in which the vector is defined
83   // is specified with the frame attribute. The vector is normalized to magnitude 1.
84
85   function_element = el->FindElement("function");
86   if (function_element) {
87     Magnitude_Function = new FGFunction(PropertyManager, function_element);
88   } else {
89     PropertyManager->Tie( BasePropertyName + "/magnitude",(FGExternalForce*)this, &FGExternalForce::GetMagnitude, &FGExternalForce::SetMagnitude);
90     Magnitude_Node = PropertyManager->GetNode(BasePropertyName + "/magnitude");
91   }
92
93
94   // Set frame (from FGForce).
95   sFrame = el->GetAttributeValue("frame");
96   if (sFrame.empty()) {
97     cerr << "No frame specified for external force, \"" << Name << "\"." << endl;
98     cerr << "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     PropertyManager->Tie( BasePropertyName + "/azimuth", (FGExternalForce*)this, &FGExternalForce::GetAzimuth, &FGExternalForce::SetAzimuth);
105   } else if (sFrame == "WIND") {
106     ttype = tWindBody;
107   } else {
108     cerr << "Invalid frame specified for external force, \"" << Name << "\"." << endl;
109     cerr << "Frame set to Body" << endl;
110     ttype = tNone;
111   }
112   PropertyManager->Tie( BasePropertyName + "/x", (FGExternalForce*)this, &FGExternalForce::GetX, &FGExternalForce::SetX);
113   PropertyManager->Tie( BasePropertyName + "/y", (FGExternalForce*)this, &FGExternalForce::GetY, &FGExternalForce::SetY);
114   PropertyManager->Tie( BasePropertyName + "/z", (FGExternalForce*)this, &FGExternalForce::GetZ, &FGExternalForce::SetZ);
115
116   location_element = el->FindElement("location");
117   if (!location_element) {
118     cerr << "No location element specified in force object." << endl;
119   } else {
120     location = location_element->FindElementTripletConvertTo("IN");
121     SetLocation(location);
122   }
123
124   direction_element = el->FindElement("direction");
125   if (!direction_element) {
126     cerr << "No direction element specified in force object. Default is (0,0,0)." << endl;
127   } else {
128     vDirection = direction_element->FindElementTripletConvertTo("IN");
129     vDirection.Normalize();
130   }
131
132   Debug(0);
133 }
134
135 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 // Copy constructor
137
138 FGExternalForce::FGExternalForce(const FGExternalForce& extForce) : FGForce(extForce)
139 {
140   magnitude = extForce.magnitude;
141   Frame = extForce.Frame;
142   vDirection = extForce.vDirection;
143   Name = extForce.Name;
144   BasePropertyName = extForce.BasePropertyName;
145   PropertyManager = extForce.PropertyManager;
146 }
147   
148 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149
150 FGExternalForce::~FGExternalForce()
151 {
152   unbind( PropertyManager->GetNode("external_reactions"));
153   delete Magnitude_Function;
154   Debug(1);
155 }
156
157 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158
159 void FGExternalForce::SetMagnitude(double mag)
160 {
161   magnitude = mag;
162   vFn = vDirection*mag;
163 }
164
165 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166
167 FGColumnVector3& FGExternalForce::GetBodyForces(void)
168 {
169   if (Magnitude_Function) {
170     double mag = Magnitude_Function->GetValue();
171     SetMagnitude(mag);
172   }
173   
174   return FGForce::GetBodyForces();
175 }
176
177 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
178
179 void FGExternalForce::unbind(FGPropertyManager *node)
180 {
181   int N = node->nChildren();
182   for (int i=0; i<N; i++) {
183     if (node->getChild(i)->nChildren() ) {
184       unbind( (FGPropertyManager*)node->getChild(i) );
185     } else if ( node->getChild(i)->isTied() ) {
186       node->getChild(i)->untie();
187     }
188   }
189 }
190
191 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192 //    The bitmasked value choices are as follows:
193 //    unset: In this case (the default) JSBSim would only print
194 //       out the normally expected messages, essentially echoing
195 //       the config files as they are read. If the environment
196 //       variable is not set, debug_lvl is set to 1 internally
197 //    0: This requests JSBSim not to output any messages
198 //       whatsoever.
199 //    1: This value explicity requests the normal JSBSim
200 //       startup messages
201 //    2: This value asks for a message to be printed out when
202 //       a class is instantiated
203 //    4: When this value is set, a message is displayed when a
204 //       FGModel object executes its Run() method
205 //    8: When this value is set, various runtime state variables
206 //       are printed out periodically
207 //    16: When set various parameters are sanity checked and
208 //       a message is printed out when they go out of bounds
209
210 void FGExternalForce::Debug(int from)
211 {
212   if (debug_lvl <= 0) return;
213
214   if (debug_lvl & 1) { // Standard console startup message output
215     if (from == 0) { // Constructor
216       cout << "    " << Name << endl;
217       cout << "    Frame: " << Frame << endl;
218       cout << "    Location: (" << vXYZn(eX) << ", " << vXYZn(eY) << ", " << vXYZn(eZ) << ")" << endl;
219     }
220   }
221   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
222     if (from == 0) cout << "Instantiated: FGExternalForce" << endl;
223     if (from == 1) cout << "Destroyed:    FGExternalForce" << endl;
224   }
225   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
226   }
227   if (debug_lvl & 8 ) { // Runtime state variables
228   }
229   if (debug_lvl & 16) { // Sanity checking
230   }
231   if (debug_lvl & 64) {
232     if (from == 0) { // Constructor
233       cout << IdSrc << endl;
234       cout << IdHdr << endl;
235     }
236   }
237 }
238 }