|
FhSim
3.1.0
Marine systems simulation
|
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**: 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 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. | |
|
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.
|
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.
| propulsionPower | The propulsion power actually drawn, W, already clamped. |
| surgeSpeed | The forward speed through the water, m/s. Unused here. |
|
override |
Partial analytical Jacobian. Supplied:
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),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:
Quater, which is smooth and whose dominant entry is the restoring moment,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.
|
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.
|
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.
| globalStateIndex | One of the m_IStateXxx members. |
|
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.
| [out] | propulsionPower | The clamped propulsion power the battery pays for, W. |
|
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.
| simObjectName | The instance name, so the message says which vehicle. |
| diveAngle | The dive angle to evaluate the check at, rad. Non-positive disables the check. |