1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Module:       FGSurface.cpp
4  Author:       Erik Hofman
5  Date started: 01/15/14
6  Purpose:      Base class for all surface properties
7  Called by:    GroundReactions
8 
9  ------------- Copyright (C) 2014  Jon S. Berndt (jon@jsbsim.org) -------------
10 
11  This program is free software; you can redistribute it and/or modify it under
12  the terms of the GNU Lesser General Public License as published by the Free Software
13  Foundation; either version 2 of the License, or (at your option) any later
14  version.
15 
16  This program is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
19  details.
20 
21  You should have received a copy of the GNU Lesser General Public License along with
22  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23  Place - Suite 330, Boston, MA  02111-1307, USA.
24 
25  Further information about the GNU Lesser General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27 
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 This base class for the GroundReactions class defines methoed and holds data
31 for all surface types.
32 
33 HISTORY
34 --------------------------------------------------------------------------------
35 01/15/14   EMH   Created
36 
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 INCLUDES
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
40 
41 #include "input_output/FGPropertyManager.h"
42 #include "models/FGSurface.h"
43 
44 using namespace std;
45 
46 namespace JSBSim {
47 
48 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
49 CLASS IMPLEMENTATION
50 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
51 
FGSurface(FGFDMExec * fdmex,int number)52 FGSurface::FGSurface(FGFDMExec* fdmex, int number) :
53    contactNumber(number)
54 {
55   eSurfaceType = ctBOGEY;
56   _PropertyManager = fdmex->GetPropertyManager();
57   resetValues();
58 }
59 
60 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
61 
~FGSurface()62 FGSurface::~FGSurface()
63 {
64 }
65 
66 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67 
resetValues(void)68 void FGSurface::resetValues(void)
69 {
70   staticFFactor = 1.0;
71   rollingFFactor = 1.0;
72   maximumForce = DBL_MAX;
73   bumpiness = 0.0;
74   isSolid = true;
75   pos[0] = 0.0;
76   pos[1] = 0.0;
77   pos[2] = 0.0;
78 }
79 
80 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81 
bind(void)82 void FGSurface::bind(void)
83 {
84   if (!_PropertyManager) return;
85 
86   string base_property_name;
87   string property_name;
88 
89   switch(eSurfaceType) {
90   case ctBOGEY:
91     base_property_name = _CreateIndexedPropertyName("gear/unit", contactNumber);
92     break;
93   case ctSTRUCTURE:
94     base_property_name = _CreateIndexedPropertyName("contact/unit", contactNumber);
95     break;
96   case ctGROUND:
97     base_property_name = "ground";
98     break;
99   default:
100     return;
101   }
102 
103   property_name = base_property_name + "/solid";
104   _PropertyManager->Tie( property_name.c_str(), &isSolid);
105   property_name = base_property_name + "/bumpiness";
106   _PropertyManager->Tie( property_name.c_str(), &bumpiness);
107   property_name = base_property_name + "/maximum-force-lbs";
108   _PropertyManager->Tie( property_name.c_str(), &maximumForce);
109   property_name = base_property_name + "/rolling_friction-factor";
110   _PropertyManager->Tie( property_name.c_str(), &rollingFFactor);
111   property_name = base_property_name + "/static-friction-factor";
112   _PropertyManager->Tie( property_name.c_str(), &staticFFactor);
113 }
114 
115 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
116 
GetBumpHeight()117 float FGSurface::GetBumpHeight()
118 {
119   if (bumpiness < 0.001) return 0.0f;
120 
121   double x = pos[0]*0.1;
122   double y = pos[1]*0.1;
123   x -= floor(x);
124   y -= floor(y);
125   x *= 2*M_PI;
126   y *= 2*M_PI;
127   //now x and y are in the range of 0..2pi
128   //we need a function, that is periodically on 2pi and gives some
129   //height. This is not very fast, but for a beginning.
130   //maybe this should be done by interpolating between some precalculated
131   //values
132   static const float maxGroundBumpAmplitude=0.4;
133   float h = sin(x)+sin(7*x)+sin(8*x)+sin(13*x);
134   h += sin(2*y)+sin(5*y)+sin(9*y*x)+sin(17*y);
135 
136   return h*(1/8.)*bumpiness*maxGroundBumpAmplitude;
137 }
138 
139 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140 
_CreateIndexedPropertyName(const string & Property,int index)141 string FGSurface::_CreateIndexedPropertyName(const string& Property, int index)
142 {
143   std::ostringstream buf;
144   buf << Property << '[' << index << ']';
145   return buf.str();
146 }
147 
148 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149 
GetSurfaceStrings(string delimeter) const150 string FGSurface::GetSurfaceStrings(string delimeter) const
151 {
152   std::ostringstream buf;
153 
154   buf << "staticFFactor" << delimeter
155       << "rollingFFactor" << delimeter
156       << "maximumForce" << delimeter
157       << "bumpiness" << delimeter
158       << "isSolid";
159 
160   return buf.str();
161 }
162 
163 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164 
GetSurfaceValues(string delimeter) const165 string FGSurface::GetSurfaceValues(string delimeter) const
166 {
167   std::ostringstream buf;
168 
169   buf << staticFFactor << delimeter
170       << rollingFFactor << delimeter
171       << maximumForce << delimeter
172       << bumpiness << delimeter
173       << (isSolid ? "1" : "0");
174 
175   return buf.str();
176 }
177 
178 } // namespace JSBSim
179