FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
Auv Class Reference
+ Inheritance diagram for Auv:
+ Collaboration diagram for Auv:

Classes

class  AuvCaster
 
struct  PortCommands
 
struct  RudderCommands
 The commanded deflections of the two fin planes, rad. More...
 

Public Member Functions

 Auv (std::string simObjectName, ISimObjectCreator *creator)
 
 ~Auv () override
 
void OdeFcn (const double dT, const double *const adX, double *const adXDot) const override
 Calculates the state derivatives.
 
void FinalSetup (const double dT, const double *const adX, ISimObjectCreator *const creator) override
 
void PreOdeFcn (double T, const double *X) override
 Rebuilds the hull wake and the propeller jet when due (CastWake) and takes the other objects' wakes at the vehicle.
 
Jacobian support for implicit integration
bool HasJacobians () const override
 
void OdeJacobian (double T, const double *X, double *J, int nStates) override
 
int GetJacobianSparsity (int nStates, int *rowPtr, int *colIdx) override
 
bool HasPortJacobians () const override
 
void InputPortJacobian (const std::string &portName, double T, const double *X, double *dF_dInput, int portSize, int nStates) override
 
void OutputPortJacobian (const std::string &portName, double T, const double *X, double *dPort_dX, int portSize, int nStates, int index) override
 

Protected Member Functions

hydro_body::Wrench SumLoads (double T, const double *X, const hydro_body::FlowFrame &frame, double &propulsionPower) const
 
void AddExternalForces (double T, const double *X, const hydro_body::FlowFrame &frame, hydro_body::Wrench &wrench) const
 Adds the ExternalForce input port, at the body origin.
 
void AddInternalForces (double T, const hydro_body::FlowFrame &frame, hydro_body::Wrench &wrench) const
 Adds the weight at COG and the buoyancy at the origin.
 
double AddThrustForces (double T, const double *X, const hydro_body::FlowFrame &frame, hydro_body::Wrench &wrench) const
 Adds the thruster wrench; returns the clamped propulsion power the battery pays for, W. Caches the command (PortCommands).
 
RudderCommands ReadRudderCommands (double T, const double *X) const
 Reads both fin ports and returns the deflections. Caches them (PortCommands).
 
void WarnIfTheFinsCannotDive (const std::string &simObjectName, double diveAngle) const
 
double AuthorityCheckCruiseSpeed () const
 The forward speed the dive-authority check assumes, from this vehicle's own parameters.
 
virtual double ComputeThrust (double propulsionPower, double surgeSpeed) const
 
double ClampedPropulsionPower (double commandedPower) const
 Clamps a commanded power to the range the thruster accepts, [0, MaxPropulsionPower].
 
virtual void CalcOutput (const double dT, const double *const adX)
 Recomputes every output port but Thrust from the given time and state; none reads an input port.
 
void CalcThrust (const double dT, const double *const adX)
 Recomputes the Thrust output, the only one that reads an input port (ThrustPower). Needs CalcOutput first.
 
void CalcOutputCommon (const double dT, const double *const adX) const
 Trampoline registered as the common computation of every output port.
 
int LocalIndex (unsigned long globalStateIndex) const
 
Output port functions
const double * OutPos (const double dT, const double *const adX)
 
const double * OutVel (const double dT, const double *const adX)
 
const double * OutQuater (const double dT, const double *const adX)
 
const double * OutEuler (const double dT, const double *const adX)
 
const double * OutHeading (const double dT, const double *const adX)
 
const double * OutPitch (const double dT, const double *const adX)
 
const double * OutDepth (const double dT, const double *const adX)
 
const double * OutSpeed (const double dT, const double *const adX)
 
const double * OutAltitude (const double dT, const double *const adX)
 
const double * OutSeaDepth (const double dT, const double *const adX)
 
const double * OutBattery (const double dT, const double *const adX)
 
const double * OutBatteryFraction (const double dT, const double *const adX)
 
const double * OutThrust (const double dT, const double *const adX)
 

Protected Attributes

double m_length = 0.0
 The hull length, m. Kept because the visualisation draws it.
 
auv_hull::Hull m_hull
 The derived radius, volume, mass and inertia.
 
double m_cOG [3]
 The centre of gravity in the body frame, m.
 
double m_rhoWater
 The density of the surrounding fluid, kg/m³.
 
double m_initialBattery
 The battery energy at the start of the mission, J.
 
double m_thrustPerPower
 Thrust per watt of propulsion power, N/W.
 
double m_maxPropulsionPower
 The largest propulsion power accepted, W.
 
double m_hotelPower
 The constant payload and computer load, W.
 
double m_thrusterPos [3]
 The thruster position in the body frame, m.
 
auv_hull::Sections m_sections
 The strip-theory sections of the hull.
 
auv_hull::Coefficients m_coefficients
 The drag and roll damping coefficients; rho copies m_rhoWater.
 
auv_hull::Rudder m_rudder
 The fin geometry and coefficients.
 
environment::EnvironmentProvider * m_environment = nullptr
 m_flow's Environment, from FinalSetup.
 
AuvCaster m_caster
 The vehicle for its wake and jet; declared before m_flow, which keeps a pointer to it.
 
environment::wake::BodyFlowInteraction m_flow
 The wakes the vehicle casts and receives.
 
HydroBody m_body
 The states Pos, Quater, LocalVel and Omega, the mass matrix (rigid body and AddedMass) and the derivatives.
 
double m_propellerDiameter = 0.0
 PropellerDiameter [m], read with CastWake only.
 
PrintDuringExec * m_print = nullptr
 The simulation logger, null under a headless or mock host.
 
ISignalPort * m_inThrustPower = nullptr
 Commanded propulsion power, W.
 
ISignalPort * m_inRudderYaw = nullptr
 Commanded yaw-plane fin deflection, rad.
 
ISignalPort * m_inRudderDive = nullptr
 Commanded dive-plane fin deflection, rad.
 
ISignalPort * m_inExternalForce = nullptr
 An external force in NED, N.
 
ICommonComputation * m_commonCalc = nullptr
 Shared recomputation behind every output port.
 
PortCommands m_lastCommands
 See PortCommands.
 
double m_outPos [3] = {0, 0, 0}
 Position in NED, m.
 
double m_outVel [3] = {0, 0, 0}
 Velocity in NED, m/s.
 
double m_outQuater [4] = {1, 0, 0, 0}
 Attitude quaternion.
 
double m_outEuler [3] = {0, 0, 0}
 Roll, pitch and yaw, rad.
 
double m_outDepth = 0.0
 Depth below the mean free surface, m.
 
double m_outSpeed = 0.0
 Forward speed through the water, m/s.
 
double m_outAltitude = 0.0
 Height above the seafloor, m.
 
double m_outSeaDepth = 0.0
 Seafloor depth below the surface, m.
 
double m_outBatteryFraction = 0.0
 Remaining battery energy as a fraction of InitialBattery.
 
double m_outThrust = 0.0
 Thrust along body x, N.
 
State indices

These five are model-global**: ISimObjectCreator::AddState returns an offset into the whole model's state vector, accumulated over every SimObject before this one. So they are the right indices in OdeFcn() and the output port functions, all of which are handed the global state vector.

They are the wrong indices in OdeJacobian(), InputPortJacobian() and OutputPortJacobian(), which are handed a slice local to this SimObject and a local dimension. The two cases look identical at the call site — both are X + m_IStateSomething — which is exactly why this distinction is spelled out here. Subtract m_IStateBase, through LocalIndex(), in every Jacobian callback.

See issue FISH-0032 (resolved).

unsigned long m_IStatePos = 0
 Global index of the NED position state.
 
unsigned long m_IStateQuater = 0
 Global index of the attitude quaternion state.
 
unsigned long m_IStateLocalVel = 0
 Global index of the body-frame velocity state.
 
unsigned long m_IStateOmega = 0
 Global index of the body-frame angular velocity state.
 
unsigned long m_IStateBattery = 0
 Global index of the battery energy state.
 
unsigned long m_IStateBase = 0
 Global index of this object's first state, cached in the constructor.
 

Constructor & Destructor Documentation

◆ ~Auv()

Auv::~Auv ( )
override

Releases the visualisation geometry.

The SimObject interface has no render teardown hook, so the scene node and the ManualObjects RenderInit() created are destroyed here. Under a headless build, and under any host that never renders, there is nothing to release.

Member Function Documentation

◆ ComputeThrust()

virtual double Auv::ComputeThrust ( double  propulsionPower,
double  surgeSpeed 
) const
protectedvirtual

The thrust delivered by a given propulsion power.

The default implementation is the speed-independent \(T = k_T P\) of the specification. It is virtual, and takes the speed it does not use, so that a bollard-pull blend can be substituted later without touching any caller.

Parameters
propulsionPowerThe propulsion power actually drawn, W, already clamped.
surgeSpeedThe forward speed through the water, m/s. Unused here.
Returns
The thrust along body x, N.

◆ HasJacobians()

bool Auv::HasJacobians ( ) const
override

Partial analytical Jacobian. Supplied:

  • the kinematics, complete (fhsim_base's BodyKinematics6Dof): d(PosDot)/d(Quater), d(PosDot)/d(LocalVel) = R(q), d(QuaterDot)/d(Quater) with the quaternion-normalisation term, and d(QuaterDot)/d(Omega) = T(q),
  • the whole six by six velocity block, that is the derivative of the six body-frame accelerations with respect to LocalVel and Omega.

The velocity block is complete rather than partial, and that is worth stating plainly because it was partial until the fins arrived. Every term in the force model that depends on a velocity at all is in it: the axial hull drag on surge, the cross-flow strip theory on sway, heave, pitch rate and yaw rate, the explicit roll damping on roll rate, both fin planes, the slender-body hull lift, and the rigid-body terms -omega x (M v), -omega x (I omega) and the Munk moment (R100, R106, R112). Gravity, buoyancy, the thrust and the external force do not depend on a velocity, so nothing is missing.

Until increment E the block was block-diagonal — surge alone, then a four by four in the transverse states, then roll — and the isolation of surge from the transverse states was an assertion the tests made. The fins break that isolation, and legitimately: a fin's dynamic pressure carries \(u^2\), so its side force depends on the forward speed and its drag depends on the sideslip. Writing only the old blocks would therefore now be writing wrong numbers, not merely incomplete ones.

Deliberately left to finite differences, in the style of TrawlDoorBase:

  • the dependence of the gravity and buoyancy wrench on Quater, which is smooth and whose dominant entry is the restoring moment,
  • the dependence of the buoyancy on Pos through the submerged fraction, which is zero while the vehicle is submerged and \(C^1\) when it is not.

A test that checks this class against finite differences must therefore check the supplied blocks, not the whole matrix. tests/Auv_Test.cpp does exactly that.

Every callback below is handed a state slice local to this SimObject**, so it indexes through LocalIndex(). See m_IStateBase.

◆ HasPortJacobians()

bool Auv::HasPortJacobians ( ) const
override

Analytic port Jacobians for the two input ports whose effect is exactly known.

  • ThrustPower: the thrust is \(k_T P\) inside the clamp, so the surge acceleration, the thruster moment and the battery discharge are all linear in the commanded power. Outside the clamp, and while the battery is flat, the derivative of the saturation is zero and so is the whole column.
  • ExternalForce: a NED force applied at the body origin, so it produces no moment and enters the body-frame acceleration through \(M^{-1} R(q)^{\mathsf{T}}\).
  • RudderYaw and RudderDive: the commanded deflection enters only through the angle of attack, so the derivative is the fin wrench's coefficient slope inside the mechanical stop and identically zero outside it. Only the commanded plane's column is written; the other plane does not see the command at all.

Both callbacks clear the whole destination matrix before writing their non-zero entries. JacobianAssembler gives every direct port link the same two workspaces and clears them only on the composed-link path, so a callback that writes only its non-zero entries — which is what every other model in FhSim does — reads back the previous link's numbers in the cells it skipped, and the assembler multiplies them into this link's block. That asymmetry is a defect of the FhSim core (fhsim/src/engine/model/JacobianAssembler.cpp:503-507 against :418-420), not of this class; clearing here is what makes this class immune to it.

Auditable assumption: whether the power command sits inside the clamp is read from m_lastCommands.power — and likewise which side of the mechanical stop each fin command sits on, from m_lastCommands.rudderDive and .rudderYaw — which the most recent OdeFcn() left behind, because an input port cannot be queried from a Jacobian callback — the callback is handed a local state slice and ISignalPort::GetPortValue needs the global one. Every path FhSim takes evaluates the derivatives at a state before asking for the Jacobian there, so the cached command belongs to the state being differentiated. Should that ever stop holding, the consequence is a derivative taken on the wrong side of the saturation, not an invalid read.

Auditable gap on the fin columns: no fixture in tests/in/Auv/ drives RudderYaw or RudderDive from another SimObject's output port, so the assembled-system Jacobian check never reaches those two columns. What is checked directly is the quantity they are built from — Auv_RudderWrenchJacobianMatchesFiniteDifferences finite-differences auv_hull::RudderWrench() with respect to the deflection and compares. The residual risk is therefore in the wiring of this function, not in the physics.

Auditable omissions on the output side: only Pos and Battery have an OutputPortJacobian, because those two are the only outputs that are an identity on a state. Every other output port — Vel, Euler, Speed, Depth, Thrust and the rest — is left unwritten, which the assembler reads as a zero block. A model that drives another stateful SimObject from one of those ports and has no other reason to run the numerical pass would therefore get a zero where a derivative belongs. This is the standing convention of the library (see CenterWeight), not a property of this class, and it is recorded here so that it is auditable rather than invisible.

◆ LocalIndex()

int Auv::LocalIndex ( unsigned long  globalStateIndex) const
inlineprotected

Turns one of the global state indices above into an index within this object's own slice, which is what every Jacobian callback is given.

Parameters
globalStateIndexOne of the m_IStateXxx members.
Returns
The same state, counted from this object's first state.

◆ SumLoads()

hydro_body::Wrench Auv::SumLoads ( double  T,
const double *  X,
const hydro_body::FlowFrame &  frame,
double &  propulsionPower 
) const
protected

The loads of one derivative evaluation at time T and global state X, with the flow frame frame of that state, summed in this order (the order fixes the rounding): AddExternalForces, AddInternalForces, AddThrustForces, then ReadRudderCommands and auv_hull::AddHullLoad.

Parameters
[out]propulsionPowerThe clamped propulsion power the battery pays for, W.

◆ WarnIfTheFinsCannotDive()

void Auv::WarnIfTheFinsCannotDive ( const std::string &  simObjectName,
double  diveAngle 
) const
protected

Warns when the fins cannot overcome the righting moment at the design dive angle.

Called from the constructor. See the "dive-authority check" part of the class documentation for the two assumptions the message names.

Parameters
simObjectNameThe instance name, so the message says which vehicle.
diveAngleThe dive angle to evaluate the check at, rad. Non-positive disables the check.

The documentation for this class was generated from the following file: