1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 3 Header: FGMassBalance.h 4 Author: Jon S. Berndt 5 Date started: 09/12/2000 6 7 ------------- Copyright (C) 2000 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 09/12/2000 JSB Created 29 30 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 31 SENTRY 32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 33 34 #ifndef FGMASSBALANCE_H 35 #define FGMASSBALANCE_H 36 37 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 38 INCLUDES 39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 40 41 #include "FGModel.h" 42 #include "math/FGMatrix33.h" 43 44 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 45 FORWARD DECLARATIONSS 46 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 47 48 namespace JSBSim { 49 50 class FGPropagate; 51 class FGGroundReactions; 52 53 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 54 CLASS DOCUMENTATION 55 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 56 57 /** Models weight, balance and moment of inertia information. 58 59 Maintains a vector of point masses. Sums the contribution of all, and 60 provides this to FGPropagate. Loads the <mass_balance> section of the 61 aircraft configuration file. There can be any number of <pointmasses>. Each 62 can also have a shape which - if present - causes an associated moment of 63 inertia to be calculated based on the shape. Note that a cylinder is solid, 64 a tube is hollow, a ball is solid and a sphere is hollow. 65 66 The inertia tensor must be specified in the structural frame (x axis 67 positive aft, y axis positive out of the right wing and z axis upward). The 68 sign of the inertia cross products are not modified by JSBSim so in most 69 cases, negative values should be provided for <ixy>, <ixz> and <iyz>. 70 71 <h3>Configuration File Format for \<mass_balance> Section:</h3> 72 @code{.xml} 73 <mass_balance> 74 <ixx unit="{SLUG*FT2 | KG*M2}"> {number} </ixx> 75 <iyy unit="{SLUG*FT2 | KG*M2}"> {number} </iyy> 76 <izz unit="{SLUG*FT2 | KG*M2}"> {number} </izz> 77 <ixy unit="{SLUG*FT2 | KG*M2}"> {number} </ixy> 78 <ixz unit="{SLUG*FT2 | KG*M2}"> {number} </ixz> 79 <iyz unit="{SLUG*FT2 | KG*M2}"> {number} </iyz> 80 <emptywt unit="{LBS | KG"> {number} </emptywt> 81 <location name="CG" unit="{IN | FT | M}"> 82 <x> {number} </x> 83 <y> {number} </y> 84 <z> {number} </z> 85 </location> 86 [<pointmass name="{string}"> 87 <form shape="{tube | cylinder | sphere | ball}"> 88 <radius unit="{IN | FT | M}"> {number} </radius> 89 <length unit="{IN | FT | M}"> {number} </length> 90 </form> 91 <weight unit="{LBS | KG}"> {number} </weight> 92 <location name="{string}" unit="{IN | FT | M}"> 93 <x> {number} </x> 94 <y> {number} </y> 95 <z> {number} </z> 96 </location> 97 </pointmass> 98 ... other point masses ...] 99 </mass_balance> 100 @endcode 101 */ 102 103 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 104 CLASS DECLARATION 105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 106 107 class FGMassBalance : public FGModel 108 { 109 110 public: 111 explicit FGMassBalance(FGFDMExec*); 112 ~FGMassBalance(); 113 114 bool Load(Element* el); 115 bool InitModel(void) override; 116 /** Runs the Mass Balance model; called by the Executive 117 Can pass in a value indicating if the executive is directing the 118 simulation to Hold. 119 @param Holding if true, the executive has been directed to hold the sim 120 from advancing time. Some models may ignore this flag, such 121 as the Input model, which may need to be active to listen 122 on a socket for the "Resume" command to be given. @return 123 false if no error */ 124 bool Run(bool Holding) override; 125 GetMass(void)126 double GetMass(void) const {return Mass;} GetWeight(void)127 double GetWeight(void) const {return Weight;} GetEmptyWeight(void)128 double GetEmptyWeight(void) const {return EmptyWeight;} 129 /** Returns the coordinates of the center of gravity expressed in the 130 structural frame. */ GetXYZcg(void)131 const FGColumnVector3& GetXYZcg(void) const {return vXYZcg;} GetXYZcg(int axis)132 double GetXYZcg(int axis) const {return vXYZcg(axis);} GetDeltaXYZcg(void)133 const FGColumnVector3& GetDeltaXYZcg(void) const {return vDeltaXYZcg;} GetDeltaXYZcg(int axis)134 double GetDeltaXYZcg(int axis) const {return vDeltaXYZcg(axis);} 135 136 /** Computes the inertia contribution of a pointmass. 137 Computes and returns the inertia matrix of a pointmass of mass 138 slugs at the given vector r in the structural frame. The units 139 should be for the mass in slug and the vector in the structural 140 frame as usual in inches. 141 @param mass_sl the mass of this single pointmass given in slugs 142 @param r the location of this single pointmass in the structural frame 143 */ GetPointmassInertia(double mass_sl,const FGColumnVector3 & r)144 FGMatrix33 GetPointmassInertia(double mass_sl, const FGColumnVector3& r) const 145 { 146 FGColumnVector3 v = StructuralToBody( r ); 147 FGColumnVector3 sv = mass_sl*v; 148 double xx = sv(1)*v(1); 149 double yy = sv(2)*v(2); 150 double zz = sv(3)*v(3); 151 double xy = -sv(1)*v(2); 152 double xz = -sv(1)*v(3); 153 double yz = -sv(2)*v(3); 154 return FGMatrix33( yy+zz, xy, xz, 155 xy, xx+zz, yz, 156 xz, yz, xx+yy ); 157 } 158 159 /** Conversion from the structural frame to the body frame. 160 Converts the location given in the structural frame 161 coordinate system to the body frame. The units of the structural 162 frame are assumed to be in inches. The unit of the result is in 163 ft. 164 @param r vector coordinate in the structural reference frame (X positive 165 aft, measurements in inches). 166 @return vector coordinate in the body frame, in feet. 167 */ 168 FGColumnVector3 StructuralToBody(const FGColumnVector3& r) const; 169 SetEmptyWeight(double EW)170 void SetEmptyWeight(double EW) { EmptyWeight = EW;} SetBaseCG(const FGColumnVector3 & CG)171 void SetBaseCG(const FGColumnVector3& CG) {vbaseXYZcg = vXYZcg = CG;} 172 173 void AddPointMass(Element* el); 174 double GetTotalPointMassWeight(void) const; 175 176 const FGColumnVector3& GetPointMassMoment(void); 177 /// Returns the inertia matrix expressed in the body frame. GetJ(void)178 const FGMatrix33& GetJ(void) const {return mJ;} 179 /// Returns the inverse of the inertia matrix expressed in the body frame. GetJinv(void)180 const FGMatrix33& GetJinv(void) const {return mJinv;} SetAircraftBaseInertias(const FGMatrix33 & BaseJ)181 void SetAircraftBaseInertias(const FGMatrix33& BaseJ) {baseJ = BaseJ;} 182 void GetMassPropertiesReport(int i); 183 184 struct Inputs { 185 double GasMass; 186 double TanksWeight; 187 FGColumnVector3 GasMoment; 188 FGMatrix33 GasInertia; 189 FGColumnVector3 TanksMoment; 190 FGMatrix33 TankInertia; 191 } in; 192 193 private: 194 FGPropagate* Propagate; 195 FGGroundReactions* GroundReactions; 196 double Weight; 197 double EmptyWeight; 198 double Mass; 199 FGMatrix33 mJ; 200 FGMatrix33 mJinv; 201 FGMatrix33 pmJ; 202 FGMatrix33 baseJ; 203 FGColumnVector3 vXYZcg; 204 FGColumnVector3 vLastXYZcg; 205 FGColumnVector3 vDeltaXYZcg; 206 FGColumnVector3 vDeltaXYZcgBody; 207 FGColumnVector3 vXYZtank; 208 FGColumnVector3 vbaseXYZcg; 209 FGColumnVector3 vPMxyz; 210 FGColumnVector3 PointMassCG; 211 const FGMatrix33& CalculatePMInertias(void); GetIxx(void)212 double GetIxx(void) const { return mJ(1,1); } GetIyy(void)213 double GetIyy(void) const { return mJ(2,2); } GetIzz(void)214 double GetIzz(void) const { return mJ(3,3); } GetIxy(void)215 double GetIxy(void) const { return -mJ(1,2); } GetIxz(void)216 double GetIxz(void) const { return mJ(1,3); } GetIyz(void)217 double GetIyz(void) const { return -mJ(2,3); } 218 219 /** The PointMass structure encapsulates a point mass object, moments of inertia 220 mass, location, etc. */ 221 struct PointMass { PointMassPointMass222 PointMass(double w, FGColumnVector3& vXYZ) : 223 eShapeType(esUnspecified), Location(vXYZ), Weight(w), Radius(0.0), 224 Length(0.0) {} 225 CalculateShapeInertiaPointMass226 void CalculateShapeInertia(void) { 227 switch(eShapeType) { 228 case esTube: 229 mPMInertia(1,1) = (Weight/(slugtolb))*Radius*Radius; // mr^2 230 mPMInertia(2,2) = (Weight/(slugtolb*12))*(6*Radius*Radius + Length*Length); 231 mPMInertia(3,3) = mPMInertia(2,2); 232 break; 233 case esCylinder: 234 mPMInertia(1,1) = (Weight/(slugtolb*2))*Radius*Radius; // 0.5*mr^2 235 mPMInertia(2,2) = (Weight/(slugtolb*12))*(3*Radius*Radius + Length*Length); 236 mPMInertia(3,3) = mPMInertia(2,2); 237 break; 238 case esSphere: 239 mPMInertia(1,1) = (Weight/(slugtolb*3))*Radius*Radius*2; // (2mr^2)/3 240 mPMInertia(2,2) = mPMInertia(1,1); 241 mPMInertia(3,3) = mPMInertia(1,1); 242 break; 243 case esBall: 244 mPMInertia(1,1) = (Weight/(slugtolb*5))*Radius*Radius*2; // (2mr^2)/5 245 mPMInertia(2,2) = mPMInertia(1,1); 246 mPMInertia(3,3) = mPMInertia(1,1); 247 break; 248 default: 249 break; 250 } 251 } 252 253 enum esShape {esUnspecified, esTube, esCylinder, esSphere, esBall} eShapeType; 254 FGColumnVector3 Location; 255 double Weight; /// Weight in pounds. 256 double Radius; /// Radius in feet. 257 double Length; /// Length in feet. 258 std::string Name; 259 FGMatrix33 mPMInertia; 260 GetPointMassLocationPointMass261 double GetPointMassLocation(int axis) const {return Location(axis);} GetPointMassWeightPointMass262 double GetPointMassWeight(void) const {return Weight;} GetShapeTypePointMass263 esShape GetShapeType(void) {return eShapeType;} GetLocationPointMass264 const FGColumnVector3& GetLocation(void) {return Location;} GetPointMassInertiaPointMass265 const FGMatrix33& GetPointMassInertia(void) {return mPMInertia;} GetNamePointMass266 const std::string& GetName(void) {return Name;} 267 SetPointMassLocationPointMass268 void SetPointMassLocation(int axis, double value) {Location(axis) = value;} SetPointMassWeightPointMass269 void SetPointMassWeight(double wt) { 270 Weight = wt; 271 CalculateShapeInertia(); 272 } SetPointMassShapeTypePointMass273 void SetPointMassShapeType(esShape st) {eShapeType = st;} SetRadiusPointMass274 void SetRadius(double r) {Radius = r;} SetLengthPointMass275 void SetLength(double l) {Length = l;} SetNamePointMass276 void SetName(const std::string& name) {Name = name;} SetPointMassMoIPointMass277 void SetPointMassMoI(const FGMatrix33& MoI) { mPMInertia = MoI; } GetPointMassMoIPointMass278 double GetPointMassMoI(int r, int c) {return mPMInertia(r,c);} 279 280 void bind(FGPropertyManager* PropertyManager, unsigned int num); 281 }; 282 283 std::vector <struct PointMass*> PointMasses; 284 285 void bind(void); 286 void Debug(int from) override; 287 }; 288 } 289 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 290 #endif 291