|
FhSim
3.1.0
Marine systems simulation
|
Outer depth loop that makes an AUV saw-tooth between a shallow and a deep limit.
Collaboration diagram for AUV undulation dive control:The vertical guidance of an undulating survey AUV. It watches the vehicle's Depth and Altitude and commands a constant nose-up or nose-down PitchRef to the pitch autopilot, reversing at a shallow and a deep turning depth. A survey flown this way profiles the whole water column instead of one horizontal slice, which is the point of putting a CTD, a SilCam and an echosounder on a vehicle rather than on a mooring.
There is no depth hold anywhere in this stack: the inner loop is PidController on Auv.Pitch, and this class is the outer loop that decides which way to point. A constant pitch at a constant speed is a constant vertical speed, so the depth trace is a triangle wave.
Evaluated once per UpdatePeriod, in AcceptedStep only:
In NED the vertical component of body-forward motion is \(-u \sin\theta\), so a positive pitch is nose up and ascending** and descending therefore commands \(-\)DiveAngle. This composes with the rest of the stack as follows, and every link of the chain inverts something, which is why it is written out here:
PitchRef into a PidController whose gains are negative (see 0035 — PidController's error sign is inverted twice and the net convention is undocumented) gives a positive Out;Auv.RudderDive is a nose-**down** fin moment, because that port is named for its effect;So Dir_Down really does dive. AuvUndulateDiveControl_Test asserts both the unit-level sign and the composed sign in simulation.
MinSeafloorDistance beats MaxDepth by the min, and it beats MinDepth by the thin-water clamp: the safety floor always wins, and the user is told about it once.
In water so thin that the two turning depths would overlap, there is nothing sensible to undulate between, so the class commands PitchRef = 0 and the vehicle flies level at whatever depth it has. The direction is left as it was rather than being switched, because the switching tests in that geometry would flip on the noise in the depth measurement, which is the chatter the hysteresis exists to prevent.
The thin-water threshold is twice the hysteresis, not once: the down-to-up test fires at zLower - DepthHysteresis and the up-to-down test at zUpper + DepthHysteresis, so the two bands only stay disjoint while zLower - DepthHysteresis > zUpper + DepthHysteresis. At a threshold of one hysteresis there is a band of geometries in which both tests fire in the same evaluation, leaving the direction permanently Down and the vehicle descending into the floor.
At the suggested parameter set and cruise the vehicle climbs and dives at about 0.36 m/s where \(1.5 \sin(0.349) = 0.51\) m/s would be expected, and the difference is physical rather than a control error: the dive plane carries a standing deflection of about 0.2 rad to hold the nose down against the COG righting moment, and the upward fin force that comes with it is balanced by the hull flying at roughly 0.1 rad of angle of attack. The flight path angle is therefore about 0.24 rad where the pitch angle is 0.34. A survey's vertical coverage rate and its energy budget must be taken from the flight path angle, not from DiveAngle. See 0037 — The undulation climbs and dives at 0.7 of u sin(DiveAngle), and the pitch loop needs 40 s to get there, which also records that the pitch loop needs about 40 s to reach a DiveAngle step, so an undulation amplitude below roughly 15 m never reaches the commanded angle at all.
DepthHysteresis is the distance before the turning depth at which the reversal is commanded, so it has to cover the depth the vehicle still makes while the pitch loop swings from \(-\)DiveAngle to \(+\)DiveAngle. That is roughly \(u \sin(\mathrm{DiveAngle}) \cdot T_{pitch}\): at the suggested 1.5 m/s and 0.349 rad with a pitch loop that turns over in about 5 s, about 2.5 m. The 1.0 m default is the smallest band that keeps the switching logic well behaved and is not enough to keep the depth trace strictly inside the limits at cruise; a fixture that needs that asserts it with DepthHysteresis near 3 m. See tests/in/Auv/Auv_Undulate_in.xml.
The class holds no integrator states. The direction is a member flipped only in AcceptedStep, exactly as SeineOperation holds its operational phase. This is not a convenience: hysteresis switching evaluated inside OdeFcn or inside an output function would also be evaluated at rejected trial times, and the direction would then depend on steps the integrator threw away.
The same property is what keeps the control stack free of algebraic loops. The wiring Auv -> Dive -> PitchPid -> Auv is cyclic on paper, but every output port of this class and of PidController returns a member written only in AcceptedStep, so there is no direct feedthrough anywhere in the cycle and the whole control stack is a sampled-data layer on a continuous plant.
Because the switching depends on where the accepted steps fall, a regression input must fix StepMax.
| Name | Width | Description @addoption{Depth, 1, The vehicle depth below the surface, positive down, m. } @addoption{Altitude, 1, The vehicle height above the seabed, m. } |
|---|
| Name | Width | Description @addoption{PitchRef, 1, The commanded pitch angle, rad. Negative is nose down and descending. Zero when the water is too thin to undulate in. } @addoption{DepthRef, 1, Diagnostic. The turning depth currently being flown towards, m, or the depth being held while the water is too thin. } |
|---|---|---|
| Direction | 1 | Diagnostic. Plus one while descending and minus one while ascending. |
| Name | Width | Description @addoption{MaxDepth, 1, The deepest turning depth the vehicle is allowed, m. Default 80. } @addoption{MinDepth, 1, The shallowest turning depth the vehicle is allowed, m. Default 5. } @addoption{MinSeafloorDistance, 1, The smallest height above the seabed the vehicle is allowed, m. It overrides both depth limits. Default 10. } @addoption{DiveAngle, 1, The magnitude of the commanded pitch angle, rad. Default 0.349, that is 20 degrees, which is inside the fins' 25 degree stall. } @addoption{DepthHysteresis, 1, The distance before a turning depth at which the reversal is commanded, m. Default 1. } @addoption{UpdatePeriod, 1, The time between evaluations of the law, s. Default 1. } |
|---|
This SimObject has no states and therefore no initial conditions. It starts out descending.
This SimObject is referred to as Auv/UndulateDiveControl