|
FhSim
3.1.0
Marine systems simulation
|
SimObjects for autonomous underwater vehicles and their sensors. More...
Collaboration diagram for Auv:Modules | |
| Autonomous underwater vehicle | |
| Six degree-of-freedom rigid body for a torpedo-shaped survey AUV. | |
| AUV undulation dive control | |
| Outer depth loop that makes an AUV saw-tooth between a shallow and a deep limit. | |
| AUV undulation mission control | |
| Horizontal guidance for an undulating survey AUV: a waypoint track, an unwrapped heading reference, a cruise speed and a battery-aware return. | |
| CTD sensor | |
| Conductivity, temperature and depth instrument mounted on a moving body. | |
| Echosounder | |
| Downward and upward looking split-beam echosounder: an altimeter on its ports and a three-frequency echogram in a file. | |
| Silhouette camera | |
| In-situ silhouette camera counting and sizing plankton in a small imaged volume. | |
There is deliberately no autopilot SimObject. An AUV autopilot is three instances of Simple PID Controller, one each for heading, pitch and speed, wired in XML:
The loop is cyclic on paper and not algebraic in fact, because every PidController output port returns a member written only in AcceptedStep.
Two sign conventions decide whether that wiring flies or diverges, and both are easy to get backwards:
PidController composes an inverted error with a sign-inverting PID, and the two cancel, so a gain takes the sign of the plant it drives. See 0035 — PidController's error sign is inverted twice and the net convention is undocumented.Auv's fin ports are named for their effect: a positive RudderYaw raises the heading, but a positive RudderDive is nose down and lowers the pitch.So the heading and speed gains are positive and the pitch gains are negative. tests/in/Auv/Auv_ClosedLoop_in.xml is the worked example, with a tuned gain set for the default 2.0 m by 0.20 m vehicle and the reasoning for each number; Auv_ClosedLoopSlow and Auv_ClosedLoopFast show the same gains at half and at five thirds of the tuning speed.
The heading seam is handled upstream rather than in the loop. Auv.Heading wraps at plus or minus pi and PidController subtracts plainly, so a reference on the far side of the seam from the measurement would produce a full-scale error spike. AUV undulation mission control therefore takes a Heading inport and emits psiMeasured + wrap(psiDesired - psiMeasured), the representative of the bearing nearest the current measurement. The error the PID forms is then in minus pi to pi at every heading. The emitted reference is consequently not confined to that range, and it jumps by two pi whenever the measurement wraps; what is continuous is the error, which is what the loop is made of.
Two of the SimObjects in this group have a visualisation, and both draw themselves straight into the NED world the rest of FhSim works in — the Ogre world is the NED world, so there is no axis convention to get wrong and none is applied.
Autonomous underwater vehicle draws the vehicle as a torpedo: an elliptical nose, a parallel midbody of Diameter and a tail cone down to a thruster boss, Length long, with the two fin planes standing on the hull at RudderPos. The fins are not decoration. They are sized from RudderArea and RudderAspectRatio, the same two numbers the fin forces use, and they deflect with the commands, so a dive or a turn is visible as the fins moving before the vehicle answers. A vehicle configured with RudderArea = "0", which is how the hull-only regressions remove the fins, is drawn without them.
Echosounder draws the acoustic beam as two translucent cones from the transducer, out to MaxRangeDown along MountDirection and out to MaxRangeUp against it. The cones are a drawing: the acoustic model casts a single ray each way, and the opening angle BeamWidth exists so that the picture shows the beam a real transducer would have. Nothing the instrument reports depends on it.
Neither needs anything in the input file. The materials live in data/resources/ogre/assets/materials/AuvMaterials.material and are packed into the library's resource zip by the build.
examples/input/AuvSurvey.xml is the one input in this library set up to be watched as well as run:
cd build/Release/playpen/bin ./FhVis ../examples/input/fishery/AuvSurvey.xml
Two things make that work, and both are easy to leave out of a new input file.
The first is the observer. An <OBSERVERS> block is honoured exactly as it is written, so a file that has one for its <FileOutput> and nothing else runs headless even under FhVis. The scenario therefore lists <Visualization frameRate="25"/> beside its <FileOutput>. In a headless binary the element costs nothing and says nothing: no live view is attached, no observer is created, and AuvSurvey.xml remains byte for byte the regression input tests/in/AuvSurvey/AuvSurvey_in.xml.
The second is the environment. The vehicle and its beam draw themselves, but the water they are measuring does not, so the scenario adds three fhsim_environment visualisers: VisualScalarVolume on Calanus and on the seafloor-referenced Cod, and a VisualScalarPlane temperature section running 1900 m north through the water-mass front. They are standalone objects with no ports and no connections; they find the environment through the shared Environment resource and their field by the name it is listed under in ScalarField.Names. That lookup happens in FinalSetup, which runs headless too, so a mistyped FieldName fails the regression run and not only the live view.
Two things to know before composing a picture. ReferenceLength is the path length the volume's AlphaRange is quoted over, and its default of 1 m makes any box more than a few metres deep solid; the scenario sets it to the vertical scale of each structure. And the volume visualiser has two documented, accepted occlusion residuals, one of which bites here: while the camera is inside a box the volume is depth-tested at the far box face, so an opaque object in front of that face erases it. Back the camera out of the box and it returns.
The sensors are composed rather than inherited: each one is a direct SimObject with its own port list, and the three pieces they share are plain helper classes rather than a SensorBase. SensorFrame holds the Pos and Quater inports and the MountOffset/MountDirection parameters and turns them into a sensor position and a beam direction in NED; SampleClock decides when the next sample is due and warns once if the integrator step is too coarse for the rate; SensorNoise draws the random numbers from hand-rolled algorithms on std::mt19937, because the standard distributions are implementation defined and a recorded baseline would not survive a change of compiler.
Two conventions hold across every sensor:
NoiseSeed = 0 means a perfect instrument.** No bias, no noise, no quantisation and no random draw at all, so the run is an exact regression baseline and a model can be debugged without the measurement in the way.fhsim_base's Signal/Samplifier already does them well, and every sensor publishes a vector measurement port meant to be chained into one. See CTD sensor for a worked excerpt, and 0028 — Input files require the `base` SimObject library, which the package does not depend on for why that excerpt is documentation rather than a fixture in this repository.A sensor that lags is a dynamic SimObject and not a sampler: CTD sensor carries its three instrument time constants as integrator states, so the step controller resolves them with the same error control as the vehicle dynamics. Nothing random and nothing held is ever touched in OdeFcn, which is const and is re-entered at rejected trial states.