JSBSim Flight Dynamics Model  1.1.11 (13 Feb 2022)
An Open Source Flight Dynamics and Control Software Library in C++
FGMagnetometer.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Module: FGMagnetometer.cpp
4  Author: Matthew Chave
5  Date started: August 2009
6 
7  ------------- Copyright (C) 2009 -------------
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 FUNCTIONAL DESCRIPTION
27 --------------------------------------------------------------------------------
28 
29 HISTORY
30 --------------------------------------------------------------------------------
31 
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33 COMMENTS, REFERENCES, and NOTES
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 INCLUDES
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39 
40 #include "FGMagnetometer.h"
41 #include "simgear/magvar/coremag.hxx"
42 #include "models/FGFCS.h"
43 #include "models/FGMassBalance.h"
44 
45 using namespace std;
46 
47 namespace JSBSim {
48 
49 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
50 CLASS IMPLEMENTATION
51 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
52 
53 
54 FGMagnetometer::FGMagnetometer(FGFCS* fcs, Element* element)
55  : FGSensor(fcs, element), FGSensorOrientation(element), counter(0),
56  INERTIAL_UPDATE_RATE(1000)
57 {
58  Propagate = fcs->GetExec()->GetPropagate();
59  MassBalance = fcs->GetExec()->GetMassBalance();
60  Inertial = fcs->GetExec()->GetInertial();
61 
62  Element* location_element = element->FindElement("location");
63  if (location_element)
64  vLocation = location_element->FindElementTripletConvertTo("IN");
65  else {
66  cerr << element->ReadFrom()
67  << "No location given for magnetometer. " << endl;
68  throw("Malformed magnetometer specification.");
69  }
70 
71  vRadius = MassBalance->StructuralToBody(vLocation);
72 
73  //assuming date wont significantly change over a flight to affect mag field
74  //would be better to get the date from the sim if its simulated...
75  time_t rawtime;
76  time( &rawtime );
77  struct tm ptm;
78  #if defined(_MSC_VER) || defined(__MINGW32__)
79  gmtime_s(&ptm, &rawtime);
80  #else
81  gmtime_r(&rawtime, &ptm);
82  #endif
83 
84  int year = ptm.tm_year;
85  if(year>100)
86  {
87  year-= 100;
88  }
89  //the months here are zero based TODO find out if the function expects 1s based
90  date = (yymmdd_to_julian_days(ptm.tm_year, ptm.tm_mon, ptm.tm_mday)); //Julian 1950-2049 yy,mm,dd
91  updateInertialMag();
92 
93  Debug(0);
94 }
95 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
96 
97 FGMagnetometer::~FGMagnetometer()
98 {
99  Debug(1);
100 }
101 
102 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
103 
104 void FGMagnetometer::ResetPastStates(void)
105 {
106  FGSensor::ResetPastStates();
107  counter = 0;
108 }
109 
110 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
111 
112 void FGMagnetometer::updateInertialMag(void)
113 {
114  if (counter++ % INERTIAL_UPDATE_RATE == 0)//dont need to update every iteration
115  {
116  usedLat = (Propagate->GetGeodLatitudeRad());//radians, N and E lat and long are positive, S and W negative
117  usedLon = (Propagate->GetLongitude());//radians
118  usedAlt = (Propagate->GetGeodeticAltitude()*fttom*0.001);//km
119 
120  //this should be done whenever the position changes significantly (in nTesla)
121  calc_magvar( usedLat, usedLon, usedAlt, date, field );
122  }
123 }
124 
125 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
126 
127 bool FGMagnetometer::Run(void )
128 {
129  // There is no input assumed. This is a dedicated magnetic field sensor.
130 
131  vRadius = MassBalance->StructuralToBody(vLocation);
132 
133  updateInertialMag();
134 
135  // Inertial magnetic field rotated to the body frame
136  vMag = Propagate->GetTl2b() * FGColumnVector3(field[3], field[4], field[5]);
137 
138  // Allow for sensor orientation
139  vMag = mT * vMag;
140 
141  Input = vMag(axis);
142 
143  ProcessSensorSignal();
144 
145  SetOutput();
146 
147  return true;
148 }
149 
150 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
151 // The bitmasked value choices are as follows:
152 // unset: In this case (the default) JSBSim would only print
153 // out the normally expected messages, essentially echoing
154 // the config files as they are read. If the environment
155 // variable is not set, debug_lvl is set to 1 internally
156 // 0: This requests JSBSim not to output any messages
157 // whatsoever.
158 // 1: This value explicity requests the normal JSBSim
159 // startup messages
160 // 2: This value asks for a message to be printed out when
161 // a class is instantiated
162 // 4: When this value is set, a message is displayed when a
163 // FGModel object executes its Run() method
164 // 8: When this value is set, various runtime state variables
165 // are printed out periodically
166 // 16: When set various parameters are sanity checked and
167 // a message is printed out when they go out of bounds
168 
169 void FGMagnetometer::Debug(int from)
170 {
171  string ax[4] = {"none", "X", "Y", "Z"};
172 
173  if (debug_lvl <= 0) return;
174 
175  if (debug_lvl & 1) { // Standard console startup message output
176  if (from == 0) { // Constructor
177  cout << " Axis: " << ax[axis] << endl;
178  }
179  }
180  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
181  if (from == 0) cout << "Instantiated: FGMagnetometer" << endl;
182  if (from == 1) cout << "Destroyed: FGMagnetometer" << endl;
183  }
184  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
185  }
186  if (debug_lvl & 8 ) { // Runtime state variables
187  }
188  if (debug_lvl & 16) { // Sanity checking
189  }
190  if (debug_lvl & 64) {
191  if (from == 0) { // Constructor
192  }
193  }
194 }
195 }
JSBSim::FGMassBalance::StructuralToBody
FGColumnVector3 StructuralToBody(const FGColumnVector3 &r) const
Conversion from the structural frame to the body frame.
Definition: FGMassBalance.cpp:364
JSBSim::FGPropagate::GetTl2b
const FGMatrix33 & GetTl2b(void) const
Retrieves the local-to-body transformation matrix.
Definition: FGPropagate.h:465