extern std::string& to_lower(std::string& str);
extern bool is_number(const std::string& str);
std::vector <std::string> split(std::string str, char d);
-
-// libc++ has these as built-ins for all C++ language versions
-#if !defined(_LIBCPP_VERSION)
+/* Comment out to_string functions when they are defined already - C++ 11 defines these */
extern std::string to_string(int);
extern std::string to_string(double);
extern std::string to_string(float);
-#endif
-
extern std::string replace(std::string str, const std::string& old, const std::string& newstr);
#else
#include <cctype>
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGGroundReactions.cpp,v 1.47 2014/01/13 10:46:07 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGGroundReactions.cpp,v 1.49 2014/01/28 09:42:21 ehofman Exp $");
IDENT(IdHdr,ID_GROUNDREACTIONS);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-FGGroundReactions::FGGroundReactions(FGFDMExec* fgex) : FGModel(fgex)
+FGGroundReactions::FGGroundReactions(FGFDMExec* fgex) :
+ FGModel(fgex),
+ FGSurface(fgex)
{
Name = "FGGroundReactions";
void FGGroundReactions::bind(void)
{
+ eSurfaceType = ctGROUND;
+ FGSurface::bind();
+
PropertyManager->Tie("gear/num-units", this, &FGGroundReactions::GetNumGearUnits);
PropertyManager->Tie("gear/wow", this, &FGGroundReactions::GetWOW);
}
GLOBAL DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-IDENT(IdSrc,"$Id: FGLGear.cpp,v 1.111 2014/01/16 14:00:30 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGLGear.cpp,v 1.114 2014/01/28 09:42:21 ehofman Exp $");
IDENT(IdHdr,ID_LGEAR);
// Body To Structural (body frame is rotated 180 deg about Y and lengths are given in
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number, const struct Inputs& inputs) :
+ FGSurface(fdmex, number),
FGForce(fdmex),
in(inputs),
GearNumber(number),
// not compressed) with respect to the ground level
double height = gearLoc.GetContactPoint(t, contact, normal, terrainVel, dummy);
- double maxForce = DBL_MAX;
- bool isSolid = true;
+ // Does this surface contact point interact with another surface?
if (surface) {
height -= (*surface).GetBumpHeight();
- frictionFactor = (*surface).GetFrictionFactor();
- maxForce = (*surface).GetMaximumForce();
+ staticFFactor = (*surface).GetStaticFFactor();
+ rollingFFactor = (*surface).GetRollingFFactor();
+ maximumForce = (*surface).GetMaximumForce();
isSolid = (*surface).GetSolid();
}
compressLength = LGearProj > 0.0 ? height * normalZ / LGearProj : 0.0;
vWhlDisplVec = mTGear * FGColumnVector3(0., 0., -compressLength);
} else {
- // Gears don't (or hardly) compress is liquids
+ // Gears don't (or hardly) compress in liquids
compressLength = 0.0;
vWhlDisplVec = 0.0 * vGroundNormal;
}
compressSpeed /= LGearProj;
}
- ComputeVerticalStrutForce(maxForce);
+ ComputeVerticalStrutForce();
// Compute the friction coefficients in the wheel ground plane.
if (eContactType == ctBOGEY) {
void FGLGear::ComputeBrakeForceCoefficient(void)
{
- BrakeFCoeff = frictionFactor * rollingFCoeff;
+ BrakeFCoeff = rollingFFactor * rollingFCoeff;
if (eBrakeGrp != bgNone)
- BrakeFCoeff += in.BrakePos[eBrakeGrp] * frictionFactor * (staticFCoeff - rollingFCoeff);
+ BrakeFCoeff += in.BrakePos[eBrakeGrp] * staticFFactor * (staticFCoeff - rollingFCoeff);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
double StiffSlip = Stiffness*WheelSlip;
FCoeff = Peak * sin(Shape*atan(StiffSlip - Curvature*(StiffSlip - atan(StiffSlip))));
}
- FCoeff *= frictionFactor;
+ FCoeff *= staticFFactor;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// possibly give a "rebound damping factor" that differs from the compression
// case.
-void FGLGear::ComputeVerticalStrutForce(double maxForce)
+void FGLGear::ComputeVerticalStrutForce()
{
double springForce = 0;
double dampForce = 0;
}
StrutForce = min(springForce + dampForce, (double)0.0);
- if (StrutForce > maxForce) {
- StrutForce = maxForce;
+ if (StrutForce > maximumForce) {
+ StrutForce = maximumForce;
compressLength = -StrutForce / kSpring;
}
}
LMultiplier[ftDynamic].ForceJacobian = mT * velocityDirection;
LMultiplier[ftDynamic].MomentJacobian = vWhlContactVec * LMultiplier[ftDynamic].ForceJacobian;
LMultiplier[ftDynamic].Max = 0.;
- LMultiplier[ftDynamic].Min = -fabs(frictionFactor * dynamicFCoeff * vFn(eZ));
+ LMultiplier[ftDynamic].Min = -fabs(staticFFactor * dynamicFCoeff * vFn(eZ));
// The Lagrange multiplier value obtained from the previous iteration is kept
// This is supposed to accelerate the convergence of the projected Gauss-Seidel
LMultiplier[ftSide].Max = fabs(FCoeff * vFn(eZ));
break;
case ctSTRUCTURE:
- LMultiplier[ftRoll].Max = fabs(staticFCoeff * vFn(eZ));
+ LMultiplier[ftRoll].Max = fabs(staticFFactor * staticFCoeff * vFn(eZ));
LMultiplier[ftSide].Max = LMultiplier[ftRoll].Max;
break;
}
switch(eContactType) {
case ctBOGEY:
+ eSurfaceType = FGSurface::ctBOGEY;
base_property_name = CreateIndexedPropertyName("gear/unit", GearNumber);
break;
case ctSTRUCTURE:
+ eSurfaceType = FGSurface::ctSTRUCTURE;
base_property_name = CreateIndexedPropertyName("contact/unit", GearNumber);
break;
default:
return;
}
+ FGSurface::bind();
property_name = base_property_name + "/WOW";
PropertyManager->Tie( property_name.c_str(), &WOW );
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_LGEAR "$Id: FGLGear.h,v 1.61 2014/01/16 14:00:42 ehofman Exp $"
+#define ID_LGEAR "$Id: FGLGear.h,v 1.64 2014/01/28 09:42:21 ehofman Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
</contact>
@endcode
@author Jon S. Berndt
- @version $Id: FGLGear.h,v 1.61 2014/01/16 14:00:42 ehofman Exp $
+ @version $Id: FGLGear.h,v 1.64 2014/01/28 09:42:21 ehofman Exp $
@see Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
NASA-Ames", NASA CR-2497, January 1975
@see Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
CLASS DECLARATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-class FGLGear : public FGForce, protected FGSurface
+class FGLGear : protected FGSurface, public FGForce
{
public:
struct Inputs {
/// Destructor
~FGLGear();
- /// The Force vector for this gear
+ /** The Force vector for this gear
+ @param surface another surface to interact with, set to NULL for none.
+ */
const FGColumnVector3& GetBodyForces(FGSurface *surface = NULL);
/// Gets the location of the gear in Body axes
double bDampRebound;
double compressLength;
double compressSpeed;
+ double rollingFCoeff;
double Stiffness, Shape, Peak, Curvature; // Pacejka factors
double BrakeFCoeff;
double maxCompLen;
void ComputeSteeringAngle(void);
void ComputeSlipAngle(void);
void ComputeSideForceCoefficient(void);
- void ComputeVerticalStrutForce(double maxForce = DBL_MAX);
+ void ComputeVerticalStrutForce(void);
void ComputeGroundFrame(void);
void ComputeJacobian(const FGColumnVector3& vWhlContactVec);
void UpdateForces(void);
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#include "FGSurface.h"
+#include "input_output/FGPropertyManager.h"
+#include "models/FGSurface.h"
using namespace std;
namespace JSBSim {
-IDENT(IdSrc,"$Id: FGSurface.cpp,v 1.2 2014/01/16 12:31:50 ehofman Exp $");
+IDENT(IdSrc,"$Id: FGSurface.cpp,v 1.5 2014/01/28 09:42:21 ehofman Exp $");
IDENT(IdHdr,ID_SURFACE);
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-FGSurface::FGSurface()
+FGSurface::FGSurface(FGFDMExec* fdmex, int number) :
+ contactNumber(number)
{
- frictionFactor = 1.0;
- rollingFCoeff = 0.02;
- MaximumForce = DBL_MAX;
- bumpiness = 0.0;
- isSolid = true;
+ eSurfaceType = ctBOGEY;
+ _PropertyManager = fdmex->GetPropertyManager();
+ resetValues();
}
-FGSurface::FGSurface(FGFDMExec* fdmex)
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGSurface::~FGSurface()
{
- frictionFactor = 1.0;
- rollingFCoeff = 0.02;
- MaximumForce = DBL_MAX;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGSurface::resetValues(void)
+{
+ staticFFactor = 1.0;
+ rollingFFactor = 1.0;
+ maximumForce = DBL_MAX;
bumpiness = 0.0;
isSolid = true;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FGSurface::~FGSurface()
+void FGSurface::bind(void)
{
+ if (!_PropertyManager) return;
+
+ string base_property_name;
+ string property_name;
+
+ switch(eSurfaceType) {
+ case ctBOGEY:
+ base_property_name = _CreateIndexedPropertyName("gear/unit", contactNumber);
+ break;
+ case ctSTRUCTURE:
+ base_property_name = _CreateIndexedPropertyName("contact/unit", contactNumber);
+ break;
+ case ctGROUND:
+ base_property_name = "ground";
+ break;
+ default:
+ return;
+ }
+
+ property_name = base_property_name + "/solid";
+ _PropertyManager->Tie( property_name.c_str(), &isSolid);
+ property_name = base_property_name + "/bumpiness";
+ _PropertyManager->Tie( property_name.c_str(), &bumpiness);
+ property_name = base_property_name + "/maximum-force-lbs";
+ _PropertyManager->Tie( property_name.c_str(), &maximumForce);
+ property_name = base_property_name + "/rolling_friction-factor";
+ _PropertyManager->Tie( property_name.c_str(), &rollingFFactor);
+ property_name = base_property_name + "/static-friction-factor";
+ _PropertyManager->Tie( property_name.c_str(), &staticFFactor);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+string FGSurface::_CreateIndexedPropertyName(const string& Property, int index)
+{
+ std::ostringstream buf;
+ buf << Property << '[' << index << ']';
+ return buf.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
string FGSurface::GetSurfaceStrings(string delimeter) const
{
std::ostringstream buf;
- buf << "FrictionFactor" << delimeter
- << "RollingFriction" << delimeter
- << "MaximumForce" << delimeter
- << "Bumpiness" << delimeter
- << "IsSolid";
+ buf << "staticFFactor" << delimeter
+ << "rollingFFactor" << delimeter
+ << "maximumForce" << delimeter
+ << "bumpiness" << delimeter
+ << "isSolid";
return buf.str();
}
{
std::ostringstream buf;
- buf << GetFrictionFactor() << delimeter
- << GetRollingFriction() << delimeter
- << GetMaximumForce() << delimeter
- << GetBumpiness() << delimeter
- << (GetSolid() ? "1" : "0");
+ buf << staticFFactor << delimeter
+ << rollingFFactor << delimeter
+ << maximumForce << delimeter
+ << bumpiness << delimeter
+ << (isSolid ? "1" : "0");
return buf.str();
}
-}
+} // namespace JSBSim
+
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-#define ID_SURFACE "$Id: FGSurface.h,v 1.2 2014/01/16 12:31:50 ehofman Exp $"
+#define ID_SURFACE "$Id: FGSurface.h,v 1.5 2014/01/28 09:42:21 ehofman Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
{
public:
- /// Constructor
- FGSurface();
+ enum ContactType {ctBOGEY, ctSTRUCTURE, ctGROUND};
/// Constructor
- FGSurface(FGFDMExec* fdmex);
+ FGSurface(FGFDMExec* fdmex, int number = -1);
+
/// Destructor
~FGSurface();
- /// Sets the friction factor of the surface area
- void SetFrictionFactor(double friction) { frictionFactor = friction; }
+ void bind(void);
+
+ /// Reset all surface values to a default
+ void resetValues(void);
+
+ /// Sets the static friction factor of the surface area
+ void SetStaticFFactor(double friction) { staticFFactor = friction; }
+
+ /// Sets the rolling friction factor of the surface area
+ void SetRollingFFactor(double friction) { rollingFFactor = friction; }
- /// Sets the load capacity of the surface area
- void SetMaximumForce(double force ) { MaximumForce = force; }
+ /// Sets the maximum force for the surface area
+ void SetMaximumForce(double force) { maximumForce = force; }
- /// Sets the bumpiness factor associated with the surface
+ /// Sets the normalized bumpiness factor associated with the surface
void SetBumpiness(double bump) { bumpiness = bump; }
/// Sets the surface is a solid flag value
}
- /// Gets the friction factor of the surface area
- double GetFrictionFactor(void) const { return frictionFactor; }
+ /// Gets the static friction factor of the surface area
+ double GetStaticFFactor(void) { return staticFFactor; }
- /// Gets the rolling friction of the surface area
- double GetRollingFriction(void) const { return rollingFCoeff; }
+ /// Gets the rolling friction factor of the surface area
+ double GetRollingFFactor(void) { return rollingFFactor; }
- /// Gets the static friction of the surface area
- double GetStaticFriction(void) const { return staticFCoeff; }
+ /// Gets the maximum force of the surface area
+ double GetMaximumForce(void) { return maximumForce; }
- /// Gets the dynamic friction of the surface area
- double GetDynamicFriction(void) const { return dynamicFCoeff; }
-
- /// Gets the maximum force for this surface point
- double GetMaximumForce(void) const { return MaximumForce; }
-
- /// Gets the bumpiness factor associated with the surface
- double GetBumpiness(void) const { return bumpiness; }
+ /// Gets the normalized bumpiness factor associated with the surface
+ double GetBumpiness(void) { return bumpiness; }
/// Gets the surface is a solid flag value
- bool GetSolid(void) const { return isSolid; }
+ bool GetSolid(void) { return isSolid; }
/// Returns the height of the bump at the provided offset
float GetBumpHeight();
std::string GetSurfaceValues(std::string delimeter) const;
protected:
- double staticFCoeff, dynamicFCoeff, rollingFCoeff;
- double frictionFactor;
- double MaximumForce;
+ ContactType eSurfaceType;
+ double staticFFactor, rollingFFactor;
+ double maximumForce;
double bumpiness;
bool isSolid;
+ double staticFCoeff, dynamicFCoeff;
+
private:
+ int contactNumber;
double pos[3];
+
+ FGPropertyManager* _PropertyManager;
+
+ static std::string _CreateIndexedPropertyName(const std::string& Property, int index);
};
}