WIP. Added Stage objects, and made Stage and Rocket a Propagatable. Changed Propagator to propagate a Propagatable instead of a Rocket. This is to allow for propagating dropped stages
This commit is contained in:
parent
9b807d53a4
commit
41183b8397
@ -81,7 +81,7 @@ QtRocket::QtRocket()
|
|||||||
setEnvironment(std::make_shared<sim::Environment>());
|
setEnvironment(std::make_shared<sim::Environment>());
|
||||||
|
|
||||||
rocket.first =
|
rocket.first =
|
||||||
std::make_shared<Rocket>();
|
std::make_shared<model::Rocket>();
|
||||||
|
|
||||||
rocket.second =
|
rocket.second =
|
||||||
std::make_shared<sim::Propagator>(rocket.first);
|
std::make_shared<sim::Propagator>(rocket.first);
|
||||||
|
@ -44,13 +44,13 @@ public:
|
|||||||
|
|
||||||
std::shared_ptr<sim::Environment> getEnvironment() { return environment; }
|
std::shared_ptr<sim::Environment> getEnvironment() { return environment; }
|
||||||
void setTimeStep(double t) { rocket.second->setTimeStep(t); }
|
void setTimeStep(double t) { rocket.second->setTimeStep(t); }
|
||||||
std::shared_ptr<Rocket> getRocket() { return rocket.first; }
|
std::shared_ptr<model::Rocket> getRocket() { return rocket.first; }
|
||||||
|
|
||||||
std::shared_ptr<utils::MotorModelDatabase> getMotorDatabase() { return motorDatabase; }
|
std::shared_ptr<utils::MotorModelDatabase> getMotorDatabase() { return motorDatabase; }
|
||||||
|
|
||||||
void addMotorModels(std::vector<model::MotorModel>& m);
|
void addMotorModels(std::vector<model::MotorModel>& m);
|
||||||
|
|
||||||
void addRocket(std::shared_ptr<Rocket> r) { rocket.first = r; }
|
void addRocket(std::shared_ptr<model::Rocket> r) { rocket.first = r; }
|
||||||
|
|
||||||
void setEnvironment(std::shared_ptr<sim::Environment> e) { environment = e; }
|
void setEnvironment(std::shared_ptr<sim::Environment> e) { environment = e; }
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ private:
|
|||||||
|
|
||||||
utils::Logger* logger;
|
utils::Logger* logger;
|
||||||
|
|
||||||
std::pair<std::shared_ptr<Rocket>, std::shared_ptr<sim::Propagator>> rocket;
|
std::pair<std::shared_ptr<model::Rocket>, std::shared_ptr<sim::Propagator>> rocket;
|
||||||
|
|
||||||
std::shared_ptr<sim::Environment> environment;
|
std::shared_ptr<sim::Environment> environment;
|
||||||
std::shared_ptr<utils::MotorModelDatabase> motorDatabase;
|
std::shared_ptr<utils::MotorModelDatabase> motorDatabase;
|
||||||
|
@ -91,8 +91,8 @@ void AnalysisWindow::onButton_plotVelocity_clicked()
|
|||||||
|
|
||||||
void AnalysisWindow::onButton_plotMotorCurve_clicked()
|
void AnalysisWindow::onButton_plotMotorCurve_clicked()
|
||||||
{
|
{
|
||||||
std::shared_ptr<Rocket> rocket = QtRocket::getInstance()->getRocket();
|
std::shared_ptr<model::Rocket> rocket = QtRocket::getInstance()->getRocket();
|
||||||
model::MotorModel motor = rocket->getCurrentMotorModel();
|
model::MotorModel& motor = rocket->getCurrentStage()->getMotorModel();
|
||||||
ThrustCurve tc = motor.getThrustCurve();
|
ThrustCurve tc = motor.getThrustCurve();
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,8 +5,12 @@ add_library(model
|
|||||||
MotorModelDatabase.h
|
MotorModelDatabase.h
|
||||||
Part.cpp
|
Part.cpp
|
||||||
Part.h
|
Part.h
|
||||||
|
Propagatable.cpp
|
||||||
|
Propagatable.h
|
||||||
Rocket.cpp
|
Rocket.cpp
|
||||||
Rocket.h
|
Rocket.h
|
||||||
|
Stage.cpp
|
||||||
|
Stage.h
|
||||||
ThrustCurve.cpp
|
ThrustCurve.cpp
|
||||||
ThrustCurve.h)
|
ThrustCurve.h)
|
||||||
|
|
||||||
|
@ -1,6 +1,103 @@
|
|||||||
#include "Part.h"
|
#include "Part.h"
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
|
||||||
namespace model
|
namespace model
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Part::Part()
|
||||||
|
{}
|
||||||
|
|
||||||
|
Part::~Part()
|
||||||
|
{}
|
||||||
|
|
||||||
|
Part::Part(const Part& orig)
|
||||||
|
: parent(orig.parent),
|
||||||
|
name(orig.name),
|
||||||
|
inertiaTensor(orig.inertiaTensor),
|
||||||
|
compositeInertiaTensor(orig.compositeInertiaTensor),
|
||||||
|
mass(orig.mass),
|
||||||
|
compositeMass(orig.compositeMass),
|
||||||
|
cm(orig.cm),
|
||||||
|
length(orig.length),
|
||||||
|
innerRadiusTop(orig.innerRadiusTop),
|
||||||
|
outerRadiusTop(orig.outerRadiusTop),
|
||||||
|
innerRadiusBottom(orig.innerRadiusBottom),
|
||||||
|
outerRadiusBottom(orig.outerRadiusBottom),
|
||||||
|
needsRecomputing(orig.needsRecomputing),
|
||||||
|
childParts()
|
||||||
|
{
|
||||||
|
|
||||||
|
// We are copying the whole tree. If the part we're copying itself has child
|
||||||
|
// parts, we are also copying all of them! This may be inefficient and not what
|
||||||
|
// is desired, but it is less likely to lead to weird bugs with the same part
|
||||||
|
// appearing in multiple locations of the rocket
|
||||||
|
utils::Logger::getInstance()->debug("Calling model::Part copy constructor. Recursively copying all child parts. Check Part names for uniqueness");
|
||||||
|
|
||||||
|
|
||||||
|
for(const auto& i : orig.childParts)
|
||||||
|
{
|
||||||
|
Part& x = *std::get<0>(i);
|
||||||
|
std::shared_ptr<Part> tempPart = std::make_shared<Part>(x);
|
||||||
|
childParts.emplace_back(tempPart, std::get<1>(i));;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double Part::getChildMasses(double t)
|
||||||
|
{
|
||||||
|
double childMasses{0.0};
|
||||||
|
for(const auto& i : childParts)
|
||||||
|
{
|
||||||
|
childMasses += std::get<0>(i)->getMass(t);
|
||||||
|
}
|
||||||
|
return childMasses;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Part::addChildPart(const Part& childPart, Vector3 position)
|
||||||
|
{
|
||||||
|
|
||||||
|
double childMass = childPart.compositeMass;
|
||||||
|
Matrix3 childInertiaTensor = childPart.compositeInertiaTensor;
|
||||||
|
std::shared_ptr<Part> newChild = std::make_shared<Part>(childPart);
|
||||||
|
// Set the parent pointer
|
||||||
|
newChild->parent = this;
|
||||||
|
|
||||||
|
// Recompute inertia tensor
|
||||||
|
|
||||||
|
childInertiaTensor += childMass * ( position.dot(position) * Matrix3::Identity() - position*position.transpose());
|
||||||
|
|
||||||
|
compositeInertiaTensor += childInertiaTensor;
|
||||||
|
compositeMass += childMass;
|
||||||
|
|
||||||
|
childParts.emplace_back(std::move(newChild), std::move(position));
|
||||||
|
|
||||||
|
if(parent)
|
||||||
|
{
|
||||||
|
parent->markAsNeedsRecomputing();
|
||||||
|
parent->recomputeInertiaTensor();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Part::recomputeInertiaTensor()
|
||||||
|
{
|
||||||
|
if(!needsRecomputing)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// recompute the whole composite inertia tensor
|
||||||
|
// Reset the composite inertia tensor
|
||||||
|
compositeInertiaTensor = inertiaTensor;
|
||||||
|
compositeMass = mass;
|
||||||
|
for(auto& [child, pos] : childParts)
|
||||||
|
{
|
||||||
|
child->recomputeInertiaTensor();
|
||||||
|
compositeInertiaTensor += child->compositeInertiaTensor + child->compositeMass * ( pos.dot(pos) * Matrix3::Identity() - pos*pos.transpose());
|
||||||
|
compositeMass += child->compositeMass;
|
||||||
|
}
|
||||||
|
needsRecomputing = false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace model
|
} // namespace model
|
61
model/Part.h
61
model/Part.h
@ -4,16 +4,16 @@
|
|||||||
/// \cond
|
/// \cond
|
||||||
// C headers
|
// C headers
|
||||||
// C++ headers
|
// C++ headers
|
||||||
#include <atomic>
|
#include <vector>
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
// 3rd party headers
|
// 3rd party headers
|
||||||
/// \endcond
|
/// \endcond
|
||||||
|
|
||||||
// qtrocket headers
|
// qtrocket headers
|
||||||
#include "utils/math/MathTypes.h"
|
#include "utils/math/MathTypes.h"
|
||||||
|
#include "model/Part.h"
|
||||||
|
|
||||||
namespace model
|
namespace model
|
||||||
{
|
{
|
||||||
@ -24,6 +24,8 @@ public:
|
|||||||
Part();
|
Part();
|
||||||
virtual ~Part();
|
virtual ~Part();
|
||||||
|
|
||||||
|
Part(const Part&);
|
||||||
|
|
||||||
void setMass(double m) { mass = m; }
|
void setMass(double m) { mass = m; }
|
||||||
|
|
||||||
// Set the inertia tensor
|
// Set the inertia tensor
|
||||||
@ -37,11 +39,58 @@ public:
|
|||||||
|
|
||||||
void setInnerRadius(double r) { innerRadiusTop = r; innerRadiusBottom = r; }
|
void setInnerRadius(double r) { innerRadiusTop = r; innerRadiusBottom = r; }
|
||||||
void setOuterRadius(double r) { outerRadiusTop = r; outerRadiusBottom = r; }
|
void setOuterRadius(double r) { outerRadiusTop = r; outerRadiusBottom = r; }
|
||||||
|
|
||||||
|
double getMass(double t)
|
||||||
|
{
|
||||||
|
return mass;
|
||||||
|
}
|
||||||
|
|
||||||
|
double getCompositeMass(double t)
|
||||||
|
{
|
||||||
|
return compositeMass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add a child part to this part.
|
||||||
|
*
|
||||||
|
* @param childPart Child part to add
|
||||||
|
* @param position Relative position of the child part's center-of-mass w.r.t the
|
||||||
|
* parent's center of mass
|
||||||
|
*/
|
||||||
|
void addChildPart(const Part& childPart, Vector3 position);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Recomputes the inertia tensor. If the change is due to the change in inertia
|
||||||
|
* of a child part, an optional name of the child part can be given to
|
||||||
|
* only recompute that change rather than recompute all child inertia
|
||||||
|
* tensors
|
||||||
|
*
|
||||||
|
* @param name Optional name of the child part to recompute. If empty, it will
|
||||||
|
* recompute all child inertia tensors
|
||||||
|
*/
|
||||||
|
//void recomputeInertiaTensor(std::string name = "");
|
||||||
|
void recomputeInertiaTensor();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
// This is a pointer to the parent Part, if it has one. Purpose is to be able to
|
||||||
|
// tell the parent if it needs to recompute anything if this part changes. e.g.
|
||||||
|
// if a change to this part's inertia tensor occurs, the parent needs to recompute
|
||||||
|
// it's total inertia tensor.
|
||||||
|
Part* parent{nullptr};
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
double getChildMasses(double t);
|
||||||
|
void markAsNeedsRecomputing()
|
||||||
|
{ needsRecomputing = true; if(parent) { parent->markAsNeedsRecomputing(); }}
|
||||||
|
|
||||||
|
// Because a part is both a simple part and the composite of itself with all of it's children,
|
||||||
|
// we will keep track of this object's inertia tensor (without children), and the composite
|
||||||
|
// one with all of it's children attached
|
||||||
Matrix3 inertiaTensor; // moment of inertia tensor with respect to the part's center of mass and
|
Matrix3 inertiaTensor; // moment of inertia tensor with respect to the part's center of mass and
|
||||||
//
|
Matrix3 compositeInertiaTensor;
|
||||||
double mass; // The moment of inertia tensor also has this, so don't double compute
|
double mass; // The moment of inertia tensor also has this, so don't double compute
|
||||||
|
double compositeMass; // The mass of this part along with all attached parts
|
||||||
|
|
||||||
Vector3 cm; // center of mass wrt middle of component
|
Vector3 cm; // center of mass wrt middle of component
|
||||||
|
|
||||||
@ -53,7 +102,11 @@ private:
|
|||||||
double innerRadiusBottom;
|
double innerRadiusBottom;
|
||||||
double outerRadiusBottom;
|
double outerRadiusBottom;
|
||||||
|
|
||||||
|
bool needsRecomputing{false};
|
||||||
|
|
||||||
|
/// @brief child parts and the relative positions of their center of mass w.r.t.
|
||||||
|
/// the center of mass of this part
|
||||||
|
std::vector<std::tuple<std::shared_ptr<Part>, Vector3>> childParts;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
0
model/Propagatable.cpp
Normal file
0
model/Propagatable.cpp
Normal file
40
model/Propagatable.h
Normal file
40
model/Propagatable.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef MODEL_PROPAGATABLE_H
|
||||||
|
#define MODEL_PROPAGATABLE_H
|
||||||
|
|
||||||
|
/// \cond
|
||||||
|
// C headers
|
||||||
|
// C++ headers
|
||||||
|
#include <utility>
|
||||||
|
// 3rd party headers
|
||||||
|
/// \endcond
|
||||||
|
|
||||||
|
// qtrocket headers
|
||||||
|
#include "sim/Aero.h"
|
||||||
|
#include "sim/StateData.h"
|
||||||
|
|
||||||
|
namespace model
|
||||||
|
{
|
||||||
|
|
||||||
|
class Propagatable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Propagatable() {}
|
||||||
|
virtual ~Propagatable() {}
|
||||||
|
|
||||||
|
virtual double getDragCoefficient() = 0;
|
||||||
|
virtual void setDragCoefficient(double d) = 0;
|
||||||
|
|
||||||
|
virtual bool terminateCondition(const std::pair<double, StateData>&) = 0;
|
||||||
|
|
||||||
|
virtual double getMass(double t) = 0;
|
||||||
|
virtual double getThrust(double t) = 0;
|
||||||
|
private:
|
||||||
|
|
||||||
|
sim::Aero aeroData;
|
||||||
|
|
||||||
|
StateData state;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MODEL_PROPAGATABLE_H
|
@ -3,6 +3,9 @@
|
|||||||
#include "Rocket.h"
|
#include "Rocket.h"
|
||||||
#include "QtRocket.h"
|
#include "QtRocket.h"
|
||||||
|
|
||||||
|
namespace model
|
||||||
|
{
|
||||||
|
|
||||||
Rocket::Rocket()
|
Rocket::Rocket()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -10,12 +13,12 @@ Rocket::Rocket()
|
|||||||
|
|
||||||
void Rocket::launch()
|
void Rocket::launch()
|
||||||
{
|
{
|
||||||
mm.startMotor(0.0);
|
currentStage->getMotorModel().startMotor(0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rocket::setMotorModel(const model::MotorModel& motor)
|
void Rocket::setMotorModel(const model::MotorModel& motor)
|
||||||
{
|
{
|
||||||
mm = motor;
|
currentStage->setMotorModel(motor);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Rocket::terminateCondition(const std::pair<double, StateData>& cond)
|
bool Rocket::terminateCondition(const std::pair<double, StateData>& cond)
|
||||||
@ -29,5 +32,17 @@ bool Rocket::terminateCondition(const std::pair<double, StateData>& cond)
|
|||||||
|
|
||||||
double Rocket::getThrust(double t)
|
double Rocket::getThrust(double t)
|
||||||
{
|
{
|
||||||
return mm.getThrust(t);
|
return currentStage->getMotorModel().getThrust(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double Rocket::getMass(double t)
|
||||||
|
{
|
||||||
|
double totalMass = 0.0;
|
||||||
|
for(const auto& stage : stages)
|
||||||
|
{
|
||||||
|
totalMass += stage.second->getMass(t);
|
||||||
|
}
|
||||||
|
return totalMass;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace model
|
@ -4,6 +4,7 @@
|
|||||||
/// \cond
|
/// \cond
|
||||||
// C headers
|
// C headers
|
||||||
// C++ headers
|
// C++ headers
|
||||||
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility> // std::move
|
#include <utility> // std::move
|
||||||
@ -13,15 +14,20 @@
|
|||||||
|
|
||||||
// qtrocket headers
|
// qtrocket headers
|
||||||
#include "model/ThrustCurve.h"
|
#include "model/ThrustCurve.h"
|
||||||
#include "model/MotorModel.h"
|
|
||||||
#include "sim/Propagator.h"
|
#include "sim/Propagator.h"
|
||||||
#include "utils/math/MathTypes.h"
|
#include "utils/math/MathTypes.h"
|
||||||
|
|
||||||
|
#include "model/Stage.h"
|
||||||
|
#include "model/Propagatable.h"
|
||||||
|
|
||||||
|
namespace model
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The Rocket class holds all rocket components
|
* @brief The Rocket class holds all rocket components
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class Rocket
|
class Rocket : public Propagatable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -29,40 +35,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
Rocket();
|
Rocket();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Rocket class destructor
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
virtual ~Rocket() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief launch Propagates the Rocket object until termination,
|
* @brief launch Propagates the Rocket object until termination,
|
||||||
* normally when altitude crosses from positive to negative
|
* normally when altitude crosses from positive to negative
|
||||||
*/
|
*/
|
||||||
void launch();
|
void launch();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief getMass returns the current mass of the rocket. This is the sum of all components' masses
|
|
||||||
* @return total current mass of the Rocket
|
|
||||||
*/
|
|
||||||
double getMass(double simTime) const { return mass + mm.getMass(simTime); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief setMass sets the current total mass of the Rocket
|
|
||||||
* @param m total Rocket mass
|
|
||||||
* @todo This should be dynamically computed, not set. Fix this
|
|
||||||
*/
|
|
||||||
void setMass(double m) { mass = m;}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief setDragCoefficient sets the current total drag coefficient of the Rocket
|
|
||||||
* @param d drag coefficient
|
|
||||||
* @todo This should be dynamically computed, not set. Fix this
|
|
||||||
*/
|
|
||||||
void setDragCoefficient(double d) { dragCoeff = d; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief getDragCoefficient returns the current drag coefficient
|
|
||||||
*
|
|
||||||
* This is intended to be called by the propagator during propagation.
|
|
||||||
* @return the coefficient of drag
|
|
||||||
*/
|
|
||||||
double getDragCoefficient() const { return dragCoeff; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief getThrust returns current motor thrust
|
* @brief getThrust returns current motor thrust
|
||||||
* @param t current simulation time
|
* @param t current simulation time
|
||||||
@ -70,6 +54,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
double getThrust(double t);
|
double getThrust(double t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getMass returns current rocket
|
||||||
|
* @param t current simulation time
|
||||||
|
* @return mass in kg
|
||||||
|
*/
|
||||||
|
virtual double getMass(double t) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief setMotorModel
|
* @brief setMotorModel
|
||||||
* @param motor
|
* @param motor
|
||||||
@ -80,14 +71,14 @@ public:
|
|||||||
* @brief Returns the current motor model.
|
* @brief Returns the current motor model.
|
||||||
* @return The current motor model
|
* @return The current motor model
|
||||||
*/
|
*/
|
||||||
const model::MotorModel& getCurrentMotorModel() const { return mm; }
|
//const model::MotorModel& getCurrentMotorModel() const { return mm; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief terminateCondition returns true or false, whether the passed-in time/state matches the terminate condition
|
* @brief terminateCondition returns true or false, whether the passed-in time/state matches the terminate condition
|
||||||
* @param cond time/state pair
|
* @param cond time/state pair
|
||||||
* @return true if the passed-in time/state satisfies the terminate condition
|
* @return true if the passed-in time/state satisfies the terminate condition
|
||||||
*/
|
*/
|
||||||
bool terminateCondition(const std::pair<double, StateData>& cond);
|
virtual bool terminateCondition(const std::pair<double, StateData>& cond) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief setName sets the rocket name
|
* @brief setName sets the rocket name
|
||||||
@ -95,16 +86,22 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setName(const std::string& n) { name = n; }
|
void setName(const std::string& n) { name = n; }
|
||||||
|
|
||||||
|
virtual double getDragCoefficient() override { return 1.0; }
|
||||||
|
virtual void setDragCoefficient(double d) override { }
|
||||||
|
void setMass(double m) { }
|
||||||
|
|
||||||
|
std::shared_ptr<Stage> getCurrentStage() { return currentStage; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::string name; /// Rocket name
|
std::string name; /// Rocket name
|
||||||
double dragCoeff; /// @todo get rid of this, should be dynamically calculated
|
|
||||||
double mass; /// @todo get rid of this, should be dynamically computed, but is the current rocket mass
|
|
||||||
|
|
||||||
model::MotorModel mm; /// Current Motor Model
|
std::map<unsigned int, std::shared_ptr<Stage>> stages;
|
||||||
|
std::shared_ptr<Stage> currentStage;
|
||||||
|
//model::MotorModel mm; /// Current Motor Model
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace model
|
||||||
#endif // ROCKET_H
|
#endif // ROCKET_H
|
||||||
|
27
model/Stage.cpp
Normal file
27
model/Stage.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/// \cond
|
||||||
|
// C headers
|
||||||
|
// C++ headers
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// 3rd party headers
|
||||||
|
/// \endcond
|
||||||
|
|
||||||
|
// qtrocket headers
|
||||||
|
#include "Stage.h"
|
||||||
|
|
||||||
|
namespace model
|
||||||
|
{
|
||||||
|
|
||||||
|
Stage::Stage()
|
||||||
|
{}
|
||||||
|
|
||||||
|
Stage::~Stage()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Stage::setMotorModel(const model::MotorModel& motor)
|
||||||
|
{
|
||||||
|
mm = motor;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace model
|
69
model/Stage.h
Normal file
69
model/Stage.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#ifndef SIM_STAGE_H
|
||||||
|
#define SIM_STAGE_H
|
||||||
|
|
||||||
|
/// \cond
|
||||||
|
// C headers
|
||||||
|
// C++ headers
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// 3rd party headers
|
||||||
|
/// \endcond
|
||||||
|
|
||||||
|
// qtrocket headers
|
||||||
|
#include "model/MotorModel.h"
|
||||||
|
#include "model/Part.h"
|
||||||
|
#include "model/Propagatable.h"
|
||||||
|
|
||||||
|
namespace model
|
||||||
|
{
|
||||||
|
|
||||||
|
class Stage : public Propagatable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Stage();
|
||||||
|
virtual ~Stage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief setMotorModel
|
||||||
|
* @param motor
|
||||||
|
*/
|
||||||
|
void setMotorModel(const model::MotorModel& motor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the current motor model.
|
||||||
|
* @return The current motor model
|
||||||
|
*/
|
||||||
|
model::MotorModel& getMotorModel() { return mm; }
|
||||||
|
|
||||||
|
virtual double getMass(double t) override
|
||||||
|
{
|
||||||
|
return topPart.getCompositeMass(t) + mm.getMass(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual double getDragCoefficient() override { return 1.0 ;}
|
||||||
|
virtual void setDragCoefficient(double d) override {}
|
||||||
|
|
||||||
|
virtual bool terminateCondition(const std::pair<double, StateData>& cond) override
|
||||||
|
{
|
||||||
|
// Terminate propagation when the z coordinate drops below zero
|
||||||
|
if(cond.second.position[2] < 0)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual double getThrust(double t) override { return mm.getThrust(t); }
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
Part topPart;
|
||||||
|
|
||||||
|
model::MotorModel mm;
|
||||||
|
Vector3 motorModelPosition; // position of motor cg w.r.t. the stage c.g.
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace model
|
||||||
|
|
||||||
|
#endif // SIM_STAGE_H
|
0
sim/Aero.cpp
Normal file
0
sim/Aero.cpp
Normal file
41
sim/Aero.h
Normal file
41
sim/Aero.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef SIM_AERO_H
|
||||||
|
#define SIM_AERO_H
|
||||||
|
|
||||||
|
/// \cond
|
||||||
|
// C headers
|
||||||
|
// C++ headers
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// 3rd party headers
|
||||||
|
/// \endcond
|
||||||
|
|
||||||
|
// qtrocket headers
|
||||||
|
#include "utils/math/MathTypes.h"
|
||||||
|
|
||||||
|
namespace sim
|
||||||
|
{
|
||||||
|
|
||||||
|
class Aero
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Vector3 cp; /// center of pressure
|
||||||
|
|
||||||
|
double Cx; /// longitudinal coefficient
|
||||||
|
double Cy; /// These are probably the same for axial symmetric
|
||||||
|
double Cz; /// rockets. The coeffients in the y and z body directions
|
||||||
|
|
||||||
|
double Cl; // roll moment coefficient
|
||||||
|
double Cm; // pitch moment coefficient
|
||||||
|
double Cn; // yaw moment coefficient
|
||||||
|
|
||||||
|
double baseCd; // coefficient of drag due to base drag
|
||||||
|
double Cd; // total coeffient of drag
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SIM_AERO_H
|
@ -13,6 +13,10 @@ public:
|
|||||||
virtual double getDensity(double altitude) = 0;
|
virtual double getDensity(double altitude) = 0;
|
||||||
virtual double getPressure(double altitude) = 0;
|
virtual double getPressure(double altitude) = 0;
|
||||||
virtual double getTemperature(double altitude) = 0;
|
virtual double getTemperature(double altitude) = 0;
|
||||||
|
|
||||||
|
virtual double getSpeedOfSound(double altitude) = 0;
|
||||||
|
virtual double getDynamicViscosity(double altitude) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sim
|
} // namespace sim
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
add_library(sim
|
add_library(sim
|
||||||
|
Aero.cpp
|
||||||
|
Aero.h
|
||||||
AtmosphericModel.h
|
AtmosphericModel.h
|
||||||
ConstantAtmosphere.h
|
ConstantAtmosphere.h
|
||||||
ConstantGravityModel.h
|
ConstantGravityModel.h
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
// qtrocket headers
|
// qtrocket headers
|
||||||
#include "AtmosphericModel.h"
|
#include "AtmosphericModel.h"
|
||||||
|
#include "utils/math/Constants.h"
|
||||||
|
|
||||||
namespace sim {
|
namespace sim {
|
||||||
|
|
||||||
@ -15,6 +16,10 @@ public:
|
|||||||
double getDensity(double) override { return 1.225; }
|
double getDensity(double) override { return 1.225; }
|
||||||
double getPressure(double) override { return 101325.0; }
|
double getPressure(double) override { return 101325.0; }
|
||||||
double getTemperature(double) override { return 288.15; }
|
double getTemperature(double) override { return 288.15; }
|
||||||
|
|
||||||
|
double getSpeedOfSound(double) override { return 340.294; }
|
||||||
|
|
||||||
|
double getDynamicViscosity(double) override { return 1.78938e-5; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sim
|
} // namespace sim
|
||||||
|
@ -22,10 +22,10 @@
|
|||||||
|
|
||||||
namespace sim {
|
namespace sim {
|
||||||
|
|
||||||
Propagator::Propagator(std::shared_ptr<Rocket> r)
|
Propagator::Propagator(std::shared_ptr<model::Rocket> r)
|
||||||
: linearIntegrator(),
|
: linearIntegrator(),
|
||||||
//orientationIntegrator(),
|
//orientationIntegrator(),
|
||||||
rocket(r),
|
object(r),
|
||||||
currentState(),
|
currentState(),
|
||||||
nextState(),
|
nextState(),
|
||||||
currentGravity(),
|
currentGravity(),
|
||||||
@ -154,7 +154,7 @@ void Propagator::runUntilTerminate()
|
|||||||
{
|
{
|
||||||
states.push_back(std::make_pair(currentTime, nextState));
|
states.push_back(std::make_pair(currentTime, nextState));
|
||||||
}
|
}
|
||||||
if(rocket->terminateCondition(std::make_pair(currentTime, currentState)))
|
if(object->terminateCondition(std::make_pair(currentTime, currentState)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
currentTime += timeStep;
|
currentTime += timeStep;
|
||||||
@ -171,27 +171,27 @@ void Propagator::runUntilTerminate()
|
|||||||
|
|
||||||
double Propagator::getMass()
|
double Propagator::getMass()
|
||||||
{
|
{
|
||||||
return rocket->getMass(currentTime);
|
return object->getMass(currentTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Propagator::getForceX()
|
double Propagator::getForceX()
|
||||||
{
|
{
|
||||||
QtRocket* qtrocket = QtRocket::getInstance();
|
QtRocket* qtrocket = QtRocket::getInstance();
|
||||||
return (currentState.velocity[0] >= 0 ? -1.0 : 1.0) * qtrocket->getEnvironment()->getAtmosphericModel()->getDensity(currentState.position[2])/ 2.0 * 0.008107 * rocket->getDragCoefficient() * currentState.velocity[0]* currentState.velocity[0];
|
return (currentState.velocity[0] >= 0 ? -1.0 : 1.0) * qtrocket->getEnvironment()->getAtmosphericModel()->getDensity(currentState.position[2])/ 2.0 * 0.008107 * object->getDragCoefficient() * currentState.velocity[0]* currentState.velocity[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
double Propagator::getForceY()
|
double Propagator::getForceY()
|
||||||
{
|
{
|
||||||
QtRocket* qtrocket = QtRocket::getInstance();
|
QtRocket* qtrocket = QtRocket::getInstance();
|
||||||
return (currentState.velocity[1] >= 0 ? -1.0 : 1.0) * qtrocket->getEnvironment()->getAtmosphericModel()->getDensity(currentState.position[2]) / 2.0 * 0.008107 * rocket->getDragCoefficient() * currentState.velocity[1]* currentState.velocity[1];
|
return (currentState.velocity[1] >= 0 ? -1.0 : 1.0) * qtrocket->getEnvironment()->getAtmosphericModel()->getDensity(currentState.position[2]) / 2.0 * 0.008107 * object->getDragCoefficient() * currentState.velocity[1]* currentState.velocity[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
double Propagator::getForceZ()
|
double Propagator::getForceZ()
|
||||||
{
|
{
|
||||||
QtRocket* qtrocket = QtRocket::getInstance();
|
QtRocket* qtrocket = QtRocket::getInstance();
|
||||||
double gravity = (qtrocket->getEnvironment()->getGravityModel()->getAccel(currentState.position[0], currentState.position[1], currentState.position[2]))[2];
|
double gravity = (qtrocket->getEnvironment()->getGravityModel()->getAccel(currentState.position[0], currentState.position[1], currentState.position[2]))[2];
|
||||||
double airDrag = (currentState.velocity[2] >= 0 ? -1.0 : 1.0) * qtrocket->getEnvironment()->getAtmosphericModel()->getDensity(currentState.position[2]) / 2.0 * 0.008107 * rocket->getDragCoefficient() * currentState.velocity[2]* currentState.velocity[2];
|
double airDrag = (currentState.velocity[2] >= 0 ? -1.0 : 1.0) * qtrocket->getEnvironment()->getAtmosphericModel()->getDensity(currentState.position[2]) / 2.0 * 0.008107 * object->getDragCoefficient() * currentState.velocity[2]* currentState.velocity[2];
|
||||||
double thrust = rocket->getThrust(currentTime);
|
double thrust = object->getThrust(currentTime);
|
||||||
return gravity + airDrag + thrust;
|
return gravity + airDrag + thrust;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,10 +14,14 @@
|
|||||||
#include "sim/RK4Solver.h"
|
#include "sim/RK4Solver.h"
|
||||||
#include "utils/math/MathTypes.h"
|
#include "utils/math/MathTypes.h"
|
||||||
#include "sim/StateData.h"
|
#include "sim/StateData.h"
|
||||||
|
#include "model/Propagatable.h"
|
||||||
|
|
||||||
|
|
||||||
// Forward declare
|
// Forward declare
|
||||||
|
namespace model
|
||||||
|
{
|
||||||
class Rocket;
|
class Rocket;
|
||||||
|
}
|
||||||
class QtRocket;
|
class QtRocket;
|
||||||
|
|
||||||
namespace sim
|
namespace sim
|
||||||
@ -26,7 +30,7 @@ namespace sim
|
|||||||
class Propagator
|
class Propagator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Propagator(std::shared_ptr<Rocket> r);
|
Propagator(std::shared_ptr<model::Rocket> r);
|
||||||
~Propagator();
|
~Propagator();
|
||||||
|
|
||||||
void setInitialState(const StateData& initialState)
|
void setInitialState(const StateData& initialState)
|
||||||
@ -70,7 +74,7 @@ private:
|
|||||||
std::unique_ptr<sim::RK4Solver<Vector3>> linearIntegrator;
|
std::unique_ptr<sim::RK4Solver<Vector3>> linearIntegrator;
|
||||||
// std::unique_ptr<sim::RK4Solver<Quaternion>> orientationIntegrator;
|
// std::unique_ptr<sim::RK4Solver<Quaternion>> orientationIntegrator;
|
||||||
|
|
||||||
std::shared_ptr<Rocket> rocket;
|
std::shared_ptr<model::Propagatable> object;
|
||||||
|
|
||||||
StateData currentState;
|
StateData currentState;
|
||||||
StateData nextState;
|
StateData nextState;
|
||||||
|
@ -74,12 +74,11 @@ public:
|
|||||||
//}
|
//}
|
||||||
// private:
|
// private:
|
||||||
|
|
||||||
// These are 4-vectors so quaternion multiplication works out. The last term (scalar) is always
|
// Intended to be used as world state data
|
||||||
// zero. I could just use quaternions here, but I want to make it clear that these aren't
|
|
||||||
// rotations, they're vectors
|
|
||||||
Vector3 position{0.0, 0.0, 0.0};
|
Vector3 position{0.0, 0.0, 0.0};
|
||||||
Vector3 velocity{0.0, 0.0, 0.0};
|
Vector3 velocity{0.0, 0.0, 0.0};
|
||||||
|
|
||||||
|
// Orientation of body coordinates w.r.t. world coordinates
|
||||||
Quaternion orientation{0.0, 0.0, 0.0, 0.0}; /// (vector, scalar)
|
Quaternion orientation{0.0, 0.0, 0.0, 0.0}; /// (vector, scalar)
|
||||||
Quaternion orientationRate{0.0, 0.0, 0.0, 0.0}; /// (vector, scalar)
|
Quaternion orientationRate{0.0, 0.0, 0.0, 0.0}; /// (vector, scalar)
|
||||||
|
|
||||||
|
@ -80,8 +80,6 @@ utils::BinMap USStandardAtmosphere::standardTemperature(initTemps());
|
|||||||
utils::BinMap USStandardAtmosphere::standardDensity(initDensities());
|
utils::BinMap USStandardAtmosphere::standardDensity(initDensities());
|
||||||
utils::BinMap USStandardAtmosphere::standardPressure(initPressures());
|
utils::BinMap USStandardAtmosphere::standardPressure(initPressures());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
USStandardAtmosphere::USStandardAtmosphere()
|
USStandardAtmosphere::USStandardAtmosphere()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -119,7 +117,6 @@ double USStandardAtmosphere::getTemperature(double altitude)
|
|||||||
double baseAltitude = standardTemperature.getBinBase(altitude);
|
double baseAltitude = standardTemperature.getBinBase(altitude);
|
||||||
return baseTemp - (altitude - baseAltitude) * temperatureLapseRate[altitude];
|
return baseTemp - (altitude - baseAltitude) * temperatureLapseRate[altitude];
|
||||||
|
|
||||||
return 0.0;
|
|
||||||
}
|
}
|
||||||
double USStandardAtmosphere::getPressure(double altitude)
|
double USStandardAtmosphere::getPressure(double altitude)
|
||||||
{
|
{
|
||||||
@ -142,4 +139,17 @@ double USStandardAtmosphere::getPressure(double altitude)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double USStandardAtmosphere::getSpeedOfSound(double altitude)
|
||||||
|
{
|
||||||
|
return std::sqrt( (Constants::gamma * Constants::Rstar * getTemperature(altitude))
|
||||||
|
/
|
||||||
|
Constants::airMolarMass);
|
||||||
|
}
|
||||||
|
|
||||||
|
double USStandardAtmosphere::getDynamicViscosity(double altitude)
|
||||||
|
{
|
||||||
|
double temperature = getTemperature(altitude);
|
||||||
|
return (Constants::beta * std::pow(temperature, 1.5)) / ( temperature + Constants::S);
|
||||||
|
}
|
||||||
} // namespace sim
|
} // namespace sim
|
||||||
|
@ -28,6 +28,10 @@ public:
|
|||||||
double getPressure(double altitude) override;
|
double getPressure(double altitude) override;
|
||||||
double getTemperature(double altitude) override;
|
double getTemperature(double altitude) override;
|
||||||
|
|
||||||
|
double getSpeedOfSound(double altitude) override;
|
||||||
|
|
||||||
|
double getDynamicViscosity(double altitude) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static utils::BinMap temperatureLapseRate;
|
static utils::BinMap temperatureLapseRate;
|
||||||
static utils::BinMap standardTemperature;
|
static utils::BinMap standardTemperature;
|
||||||
|
@ -6,26 +6,85 @@ TEST(USStandardAtmosphereTests, DensityTests)
|
|||||||
{
|
{
|
||||||
sim::USStandardAtmosphere atmosphere;
|
sim::USStandardAtmosphere atmosphere;
|
||||||
|
|
||||||
// Test that the calucated values are with 1% of the published values in the NOAA report
|
// Test that the calucated values are with 0.1% of the published values in the NOAA report
|
||||||
EXPECT_NEAR(atmosphere.getDensity(0.0) / 1.225, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(0.0) / 1.225, 1.0, 0.001);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(1000.0) / 1.112, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(1000.0) / 1.112, 1.0, 0.001);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(2000.0) / 1.007, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(2000.0) / 1.007, 1.0, 0.001);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(3000.0) / 0.9093, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(3000.0) / 0.9093, 1.0, 0.001);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(4000.0) / 0.8194, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(4000.0) / 0.8194, 1.0, 0.001);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(5000.0) / 0.7364, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(5000.0) / 0.7364, 1.0, 0.001);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(6000.0) / 0.6601, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(6000.0) / 0.6601, 1.0, 0.001);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(7000.0) / 0.5900, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(7000.0) / 0.5900, 1.0, 0.001);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(8000.0) / 0.5258, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(15000.0) / 0.19367, 1.0, 0.001);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(9000.0) / 0.4647, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(20000.0) / 0.088035, 1.0, 0.001);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(10000.0) / 0.4135, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(25000.0) / 0.039466, 1.0, 0.001);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(15000.0) / 0.1948, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(30000.0) / 0.018012, 1.0, 0.001);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(20000.0) / 0.08891, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(40000.0) / 0.0038510, 1.0, 0.001);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(25000.0) / 0.039466, 1.0, 0.01);
|
|
||||||
EXPECT_NEAR(atmosphere.getDensity(30000.0) / 0.018012, 1.0, 0.01);
|
// These are generally accurate to ~0.5%. Slight deviation of calculated
|
||||||
EXPECT_NEAR(atmosphere.getDensity(40000.0) / 0.0038510, 1.0, 0.01);
|
// density from the given density in the report table
|
||||||
EXPECT_NEAR(atmosphere.getDensity(50000.0) / 0.00097752, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(8000.0) / 0.52579, 1.0, 0.005);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(60000.0) / 0.00028832, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(9000.0) / 0.46706, 1.0, 0.005);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(70000.0) / 0.000074243, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(10000.0) / 0.41351, 1.0, 0.005);
|
||||||
EXPECT_NEAR(atmosphere.getDensity(80000.0) / 0.000015701, 1.0, 0.01);
|
EXPECT_NEAR(atmosphere.getDensity(50000.0) / 0.00097752, 1.0, 0.005);
|
||||||
|
EXPECT_NEAR(atmosphere.getDensity(60000.0) / 0.00028832, 1.0, 0.005);
|
||||||
|
EXPECT_NEAR(atmosphere.getDensity(70000.0) / 0.000074243, 1.0, 0.005);
|
||||||
|
EXPECT_NEAR(atmosphere.getDensity(80000.0) / 0.000015701, 1.0, 0.005);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(USStandardAtmosphereTests, PressureTests)
|
||||||
|
{
|
||||||
|
sim::USStandardAtmosphere atmosphere;
|
||||||
|
|
||||||
|
// Test that the calucated values are with 0.1% of the published values in the NOAA report
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(0.0) / 101325.0, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(1000.0) / 89876.0, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(2000.0) / 79501.0, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(3000.0) / 70108.0, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(4000.0) / 61640.0, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(5000.0) / 54019.0, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(6000.0) / 47181.0, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(7000.0) / 41060.0, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(8000.0) / 35599.0, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(9000.0) / 30742.0, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(10000.0) / 26436.0, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(15000.0) / 12044.0, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(20000.0) / 5474.8, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(25000.0) / 2511.0, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(30000.0) / 1171.8, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(40000.0) / 277.52, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(50000.0) / 75.944, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(60000.0) / 20.314, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(70000.0) / 4.6342, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getPressure(80000.0) / 0.88627, 1.0, 0.001);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(USStandardAtmosphereTests, TemperatureTests)
|
||||||
|
{
|
||||||
|
sim::USStandardAtmosphere atmosphere;
|
||||||
|
|
||||||
|
// Test that the calucated values are with 0.1% of the published values in the NOAA report
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(0.0) / 288.15, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(1000.0) / 281.651, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(2000.0) / 275.154, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(3000.0) / 268.659, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(4000.0) / 262.166, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(5000.0) / 255.676, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(6000.0) / 249.187, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(7000.0) / 242.7, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(8000.0) / 236.215, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(9000.0) / 229.733, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(10000.0) / 223.252, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(15000.0) / 216.65, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(20000.0) / 216.65, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(25000.0) / 221.552, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(30000.0) / 226.509, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(40000.0) / 251.05, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(50000.0) / 270.65, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(60000.0) / 245.45, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(70000.0) / 217.450, 1.0, 0.001);
|
||||||
|
EXPECT_NEAR(atmosphere.getTemperature(80000.0) / 196.650, 1.0, 0.001);
|
||||||
|
|
||||||
}
|
}
|
@ -6,9 +6,19 @@ namespace utils::math
|
|||||||
|
|
||||||
namespace Constants
|
namespace Constants
|
||||||
{
|
{
|
||||||
constexpr double Rstar = 8.3144598;
|
constexpr double Rstar = 8.31432;
|
||||||
constexpr const double g0 = 9.80665;
|
constexpr const double g0 = 9.80665;
|
||||||
constexpr const double airMolarMass = 0.0289644;
|
constexpr const double airMolarMass = 0.0289644;
|
||||||
|
|
||||||
|
// gamma is the ratio of the specific heat of air at constant pressure to that at
|
||||||
|
// constant volume. Used in computing the speed of sound
|
||||||
|
constexpr const double gamma = 1.4;
|
||||||
|
|
||||||
|
// beta is used in calculating the dynamic viscosity of air. Based on the 1976 US Standard
|
||||||
|
// Atmosphere report, it is empirically measured to be:
|
||||||
|
constexpr const double beta = 1.458e-6;
|
||||||
|
// Sutherland's constant
|
||||||
|
constexpr const double S = 110.4;
|
||||||
constexpr const double standardTemperature = 288.15;
|
constexpr const double standardTemperature = 288.15;
|
||||||
constexpr const double standardDensity = 1.2250;
|
constexpr const double standardDensity = 1.2250;
|
||||||
constexpr const double meanEarthRadiusWGS84 = 6371008.8;
|
constexpr const double meanEarthRadiusWGS84 = 6371008.8;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user