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