|
FhSim
3.1.0
Marine systems simulation
|
Six degree-of-freedom rigid body for a torpedo-shaped survey AUV.
Collaboration diagram for Autonomous underwater vehicle:0033 — Auv thrust does not fall off with speed
0034 — Auv yaw and pitch rate damping are independent of the forward speed
0038 — Auv output ports dereference a null environment during InitialConditionSetup
0041 — SimObject render teardown runs after the Ogre root is destroyed
A survey AUV modelled as a rigid cylinder in six degrees of freedom, carrying a battery state. The state layout, the constant inverse mass matrix, the AddXxxForces → ma_adSumForces → CalcDerivatives pipeline and the FinalSetup environment lookup all follow TrawlDoorBase, so a reader who knows the trawl door knows this file.
The hull is idealised as a solid cylinder of uniform density. Length, Diameter and AverageDensity are the only geometric parameters; the volume, the mass and the inertia are derived from them, so displacement, mass and inertia cannot be configured into an inconsistent combination and the buoyancy trim is the single number AverageDensity:
\begin{eqnarray*} r &=& \frac{D}{2} \\ \nabla &=& \pi r^2 L \\ m &=& \rho_{avg} \nabla \\ I_{xx} &=& \frac{1}{2} m r^2 \\ I_{yy} = I_{zz} &=& \frac{m (3 r^2 + L^2)}{12} \end{eqnarray*}
With the defaults (2.0 m by 0.20 m at 1020 kg/m³ in 1025 kg/m³ water) the vehicle has about 0.31 kg of net buoyancy, so a dead vehicle surfaces.
The mass matrix \(M = \mathrm{diag}(m + A_{11}, \ldots, I_{zz} + A_{66})\) is assembled and inverted once, in the constructor. It stays diagonal because the body origin is placed at the centre of buoyancy and the centre of gravity is carried as the offset COG, whose only effect is a moment.
The weight acts at COG and is the entire pitch and roll restoring model. The buoyancy is \(\rho g \nabla f\) applied at the body origin, where \(f\) is the submerged fraction. Because the hull is a cylinder, \(f\) is the exact circular-segment area of a horizontal cylinder rather than the ad-hoc linear ramp used by TrawlDoorBase, so surfacing is \(C^1\) — see SubmergedFraction().
The thruster delivers \(T = k_T\,\mathrm{clamp}(P_{cmd}, 0, P_{max})\) along body x at ThrusterPos, so a thruster placed off the x axis produces a moment as well. The model is deliberately speed independent: real thrust at fixed shaft power falls with speed, and ThrustPerPower is calibrated at the cruise point rather than being a propeller curve. ComputeThrust() is virtual so that a bollard-pull blend can replace it later without touching any caller.
The hull resists surge with \(F_x = -\tfrac12 \rho A_f C_d |u_{rel}| u_{rel}\) on the frontal area \(A_f = \pi D^2/4\). That is the only component it touches. The transverse resistance is the business of the cross-flow strip theory below, and adding a transverse term here as well would double-count it; AxialDragWrench() is a pure function so that a unit test can pin the other five components to exactly zero.
The transverse hydrodynamics are a three-section strip model. Each section \(k\) sits at \(\mathbf{r}_k = (\mathrm{SectionX}_k, 0, 0)\) and sees the local relative velocity \(\mathbf{v}_k = \mathbf{v}_{rel} + \boldsymbol{\omega} \times \mathbf{r}_k\). Only the cross-flow components enter — a cross-flow drag is by definition independent of the axial flow — so with \(w_k = \sqrt{v_{ky}^2 + v_{kz}^2 + \varepsilon}\) and \(c_k = \tfrac12 \rho C_{d,cf} D_k L_k\) the section wrench is
\[ \mathbf{F}_k = (0,\; -c_k w_k v_{ky},\; -c_k w_k v_{kz}), \qquad \mathbf{M}_k = \mathbf{r}_k \times \mathbf{F}_k . \]
The tiny \(\varepsilon\) keeps \(w_k\) differentiable at zero cross-flow so the adaptive integrator is not driven to its minimum step there; see kCrossFlowSpeedEpsilon.
One loop delivers three things**: the transverse force, the pitch and yaw moment that its distribution along the hull produces, and — through the \(\boldsymbol{\omega} \times \mathbf{r}_k\) term — pitch and yaw rate damping. No separate \(C_{mq}\) coefficient exists or is needed.
Two consequences of "cross-flow only" are worth stating plainly, because both are easy to expect the other way round:
SectionDiameter or SectionLength to taper the hull is what breaks the symmetry, and a stern-heavy taper is weathercock stable — it turns the bow into the flow.Strip theory contributes nothing about the x axis, because \(\mathbf{r}_k \times \mathbf{F}_k\) has no x component for an \(\mathbf{r}_k\) on the x axis. Roll is therefore damped by the explicit \(K_p = -(\mathrm{RollDampingLinear} + \mathrm{RollDampingQuadratic}\,|p|)\,p\), and that term is the only thing in the whole class that damps roll.
Two fin planes, each one routine call: the dive plane (the stern planes, commanded by RudderDive, working in the body x-z plane) and the yaw plane (commanded by RudderYaw, working in the body x-y plane). Both act at RudderPos, and both the force and the moment are applied there, so moving the fins aft increases their moment in proportion.
The inflow at the fin is the body's relative velocity plus the rotation about the fin arm, \(\mathbf{v}_f = \mathbf{v}_{rel} + \boldsymbol{\omega} \times \mathbf{r}_{fin}\); that term is where the fins' rate damping comes from. Writing \(u_f\) for the axial and \(s_f\) for the in-plane transverse component,
\begin{eqnarray*} \alpha_{flow} &=& \mathrm{atan2}(s_f, u_f) \\ \alpha &=& \mathrm{clamp}(\delta, \pm\,\mathrm{MaxRudderAngle}) + \alpha_{flow} \\ q_{dyn} &=& \tfrac12 \rho\, A_{fin} \left(u_f^2 + s_f^2\right) \\ F_x &=& q_{dyn}\left(-C_d \cos\alpha_{flow} + C_l \sin\alpha_{flow}\right) \\ F_s &=& q_{dyn}\left(-C_l \cos\alpha_{flow} - C_d \sin\alpha_{flow}\right) \end{eqnarray*}
that is, the drag acts along the inflow and the lift across it, both resolved back into the body frame. \(C_l\) and \(C_d\) come from AuvFoil, whose lift curve is \(C^1\) through the stall so that a fin passing through 25 degrees does not pin the adaptive integrator at StepMin.
Two behaviours fall out of that rather than being added on top:
Both established by experiment, not by inspection, and pinned by Auv_PositiveRudderYawGivesAPositiveYawRate and Auv_PositiveRudderDiveGivesANoseDownMoment:
RudderYaw gives a positive yaw moment and so a positive yaw rate — the vehicle turns to starboard. The fin force is to port and the fin is aft of the origin, so \(M_z = x_{fin} F_y > 0\).RudderDive gives a negative, that is nose-down, pitch moment, and the vehicle dives. The fin force is upward (negative body z) and the fin is aft, so \(M_y = -x_{fin} F_z < 0\). Note that this means a positive command on the port named for diving produces a negative Pitch output; the port is named for its effect, as the AUV's ports all are.A vehicle whose COG is too far below the centre of buoyancy simply cannot dive: the righting moment beats the fin moment at every reachable angle, and the symptom is a vehicle that flies level and a dive autopilot stuck at its integrator limit. The constructor therefore warns when
\[ A_{fin}\, q_{dyn}\, C_{l,max}\, |x_{fin}| \le m g |COG_z| \sin(\mathrm{DiveAngle}), \]
naming both assumptions it had to make in the message, because neither belongs to this class:
DiveAngleForAuthorityCheck, defaulting to the 0.349 rad that AuvUndulateDiveControl defaults to;MaxPropulsionPower, which is the design cruise point of the suggested parameter set (30 W of 120 W, giving 1.5 m/s).The check uses RudderClMax, which is the peak of the lift curve and is reached at RudderAoaMax, not at MaxRudderAngle. Since MaxRudderAngle is deliberately inside the stall, the attainable coefficient is about 0.9 of RudderClMax, and the check is correspondingly optimistic by that much. It is written that way on purpose: it is a necessary condition, so it never warns about a vehicle that can in fact dive.
The battery discharges at the clamped propulsion power plus the constant HotelPower while it holds any energy, and stops — rather than going negative — when it is flat. A flat battery also stops the thrust. The discharge is driven by an input port and by the sign of the battery state alone, so the whole battery row of the Jacobian is identically zero, exactly as in Actuator.
fhsim_gauss six degree-of-freedom body. The vehicle is slow and the rates are small, so the omission is acceptable, but a hard turn is modelled optimistically.RudderYaw and RudderDive take effect within the step they are commanded.All four input ports must be connected; a constant is the usual choice while the control stack is not yet wired:
| Name | Width | Description |
|---|---|---|
| ThrustPower | 1 | Commanded propulsion power [W], clamped to [0, MaxPropulsionPower] before it is used. |
| RudderYaw | 1 | Commanded deflection of the fin pair that turns the vehicle in the horizontal plane [rad], that is the pair whose chord lies in the body x-y plane. Named by effect, not by fin plane. A positive command gives a positive yaw rate, that is a turn to starboard. Clamped to plus or minus MaxRudderAngle. |
| RudderDive | 1 | Commanded deflection of the fin pair that pitches the vehicle in the vertical plane [rad], that is the stern planes, whose chord lies in the body x-z plane. Named by effect, not by fin plane. A positive command gives a nose-down, that is negative, pitch moment and therefore a dive. Clamped to plus or minus MaxRudderAngle. |
| ExternalForce | 3 | An external force in the NED frame [N], applied at the body origin and therefore contributing no moment. |
| Name | Width | Description |
|---|---|---|
| Pos | 3 | Position of the body origin in NED [m]. |
| Vel | 3 | Velocity of the body origin in NED [m/s]. |
| Quater | 4 | Attitude quaternion, scalar first [q0, q1, q2, q3]. |
| Euler | 3 | Roll, pitch and yaw [rad], from the ZYX convention. |
| Heading | 1 | Yaw angle [rad], the third element of Euler. |
| Pitch | 1 | Pitch angle [rad], the second element of Euler. Positive is nose up. |
| Depth | 1 | Depth below the mean free surface [m], positive down. |
| Speed | 1 | Forward speed through the water [m/s], the body-x component of the velocity relative to the fluid. This, not the speed over ground and not the magnitude of the velocity, is what a speed autopilot regulates. |
| Altitude | 1 | Height of the body origin above the seafloor [m]. |
| SeaDepth | 1 | Depth of the seafloor below the surface at the vehicle position [m]. |
| Battery | 1 | Remaining battery energy [J]. |
| BatteryFraction | 1 | Remaining battery energy as a fraction of InitialBattery. |
| Thrust | 1 | The thrust actually delivered along body x [N], which is zero while the battery is flat. |
| Name | Width | Description |
|---|---|---|
| Length | 1 | Hull length [m] (Default: 2.0). |
| Diameter | 1 | Hull diameter [m] (Default: 0.20). |
| AverageDensity | 1 | Mean density of the whole vehicle [kg/m³] (Default: 1020). Below Rho the vehicle is positively buoyant. This one number is the buoyancy trim. |
| Rho | 1 | Density of the sea water [kg/m³] (Default: 1025). |
| COG | 3 | Centre of gravity in the body frame [m], relative to the centre of buoyancy at the origin (Default: "0,0,0.020"). The vertical component is the entire pitch and roll restoring model. |
| AddedMass | 6 | Added mass and added inertia on the diagonal, [A11, A22, A33, A44, A55, A66] in kg and kg·m² (Default: "3.2, 58, 58, 0.1, 19, 19"). A44 is floored well above zero so that the mass matrix stays invertible for a body of revolution. |
| ThrustPerPower | 1 | Thrust delivered per watt of propulsion power [N/W] (Default: 0.30). Calibrated at the cruise point, 9.0 N from 30 W. |
| MaxPropulsionPower | 1 | The largest propulsion power the thruster accepts [W] (Default: 120, four times cruise). Commands are clamped to [0, this]. |
| HotelPower | 1 | The constant payload, computer and navigation load [W] (Default: 15). It is drawn whenever the battery holds any energy. |
| ThrusterPos | 3 | Position of the thruster in the body frame [m] (Default: "-1.0, 0, 0"). An axial thruster on the x axis contributes no moment, but the moment is computed anyway so that an offset thruster stays correct. |
| AxialDragCoeff | 1 | Hull drag coefficient on the frontal area pi D²/4 [-] (Default: 0.25). Gives 9.0 N at 1.5 m/s, which matches published REMUS-class drag. |
| CrossFlowDragCoeff | 1 | Two-dimensional cross-flow drag coefficient of a hull section [-] (Default: 1.1, a circular cylinder at Re of order 1e5). Set it to zero to remove the transverse hydrodynamics entirely. |
| SectionX | 3 | Body-frame x of the centroid of each strip-theory section [m] (Default: Length/3, 0, -Length/3, that is the centroids of three equal thirds). |
| SectionDiameter | 3 | Cross-flow diameter of each section [m] (Default: Diameter for all three). Override it together with SectionLength to taper a non-cylindrical hull; the defaults are the cylinder the rest of the class assumes. |
| SectionLength | 3 | Length of each section [m] (Default: Length/3 for all three). The sum is not forced to equal Length, so a tapered hull can leave gaps or overlap. |
| RollDampingLinear | 1 | Linear roll damping [N·m·s] (Default: 4.6, chosen to critically damp the 12.6 N·m/rad roll mode of the default trim). Strip theory contributes nothing about the x axis, so this term and RollDampingQuadratic are the whole roll damping. |
| RollDampingQuadratic | 1 | Quadratic roll damping [N·m·s²] (Default: 1.0). |
| RudderArea | 1 | Planform area of one fin plane [m²] (Default: 0.016, that is two 0.10 by 0.08 m fins). Set it to zero to remove the fins entirely, which is what the hull-only regression inputs do. |
| RudderAspectRatio | 1 | Aspect ratio of a fin [-] (Default: 1.25). It enters the induced drag alone, not the lift curve. |
| RudderPos | 3 | Position of both fin planes in the body frame [m] (Default: "-0.85, 0, 0"). Both the force and the moment act here, so moving the fins aft increases the control moment in proportion. |
| RudderClMax | 1 | Peak lift coefficient of a fin [-] (Default: 0.8). |
| RudderAoaMax | 1 | Angle of attack at which the peak lift is reached [rad] (Default: 0.436, that is 25 degrees). The lift curve is C1 through this angle, by construction; see AuvFoil. |
| RudderCd0 | 1 | Profile drag coefficient of a fin at zero lift [-] (Default: 0.02). |
| RudderOswald | 1 | Oswald span efficiency of the fin induced drag [-] (Default: 0.9). |
| MaxRudderAngle | 1 | Mechanical stop on the commanded deflection [rad] (Default: 0.35, that is 20 degrees, inside the 25 degree stall). Commands are clamped to plus or minus this before the flow angle is added. |
| DiveAngleForAuthorityCheck | 1 | The dive angle the startup dive-authority warning is evaluated at [rad] (Default: 0.349, that is 20 degrees, the default DiveAngle of AuvUndulateDiveControl). It is a parameter because the dive angle belongs to the dive controller, not to the vehicle, so hard-coding it would make the warning unfalsifiable for a differently configured controller. Set it to zero to silence the check. |
| InitialBattery | 1 | Battery energy at the start of the mission [J] (Default: 1.8e6, that is 0.5 kWh). |
| Name | Width | Description |
|---|---|---|
| Pos | 3 | Position in NED [m] (Default: "0,0,0"). |
| Quater | 4 | Attitude quaternion, scalar first (Default: "1,0,0,0"). |
| LocalVel | 3 | Velocity in the body frame [m/s] (Default: "0,0,0"). |
| Omega | 3 | Angular velocity in the body frame [rad/s] (Default: "0,0,0"). |
| Battery | 1 | Battery energy [J] (Default: InitialBattery). |
AuvSurvey.xml is the whole stack in one model: the environment, this vehicle, the three PID loops that fly it, the dive and mission guidance and all three instruments. It is also the regression input tests/in/AuvSurvey/AuvSurvey_in.xml, byte for byte, so the example and the test cannot drift apart; AuvSurvey_Test asserts that they are identical. A co-simulation variant of the same scenario, with the FMU boundary added, is examples/input/FMU/AuvSurvey.xml.
This SimObject is referred to as Auv/Vehicle