FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
AuvSurvey.xml
1<!--
2 The complete AUV survey scenario: a virtual ocean, a vehicle, an autopilot, a
3 guidance stack and three scientific instruments, in one model.
4
5 A survey AUV undulates between waypoints over a rolling seabed at about 140 m,
6 sampling a stratified water column with a CTD, counting Calanus with a silhouette
7 camera and writing a three frequency echogram to file. Everything in it is already
8 covered by a focused regression case of its own under tests/in/Auv/; this file is
9 the one place where the whole stack runs together, and it is also the regression
10 input tests/in/AuvSurvey/AuvSurvey_in.xml, byte for byte, so the example and the
11 test cannot drift apart. AuvSurvey_Test asserts that.
12
13 ## The site
14
15 About 68 degrees north off Lofoten, in outer Vestfjorden, in June. Every number in
16 the environment below is only defensible relative to a stated site and season, so
17 here it is stated: bottom around 140 m, a Norwegian Coastal Current surface layer
18 over Norwegian Atlantic Water, a subsurface Calanus band in early summer, mackerel
19 on their epipelagic feeding migration above it, and a demersal cod aggregation near
20 the bottom.
21
22 ## The fields, and where they come from
23
24 Every scalar field here is ScalarField.<Name>.Model = "Parametric", read out of
25 auv_ocean_fields.json beside this file. A parametric field is a depth profile plus a
26 list of features - a Gaussian blob, a horizontal front, a depth band - so it is a
27 function of north, east and depth and not of depth alone. The five entries are:
28
29 SeaTemperature 9.5 degC June coastal water over a 20 m to 60 m thermocline down
30 to 7.4 degC and the 6.5 degC Atlantic core at 400 m, with a front
31 and a warm lens on top of it.
32 SeaSalinity 33.8 PSU coastal water over Atlantic water above 35.0 PSU below
33 80 m, with the same front. The salinity front shares the origin
34 and the heading of the temperature front and carries the opposite
35 sign, so the cooler side is the saltier, Atlantic side: it is one
36 water mass boundary and not two unrelated ones.
37 Calanus A band centred at 28 m with a 9 m standard deviation, peaking near
38 2.2e-3 kg/m3, over a weak background, with two patches on top.
39 Mackerel Held in the upper 20 m by its background profile, with two loose
40 schools centred at 12 m and 10 m, peaking near 6e-2 kg/m3.
41 Cod Demersal, and the one field whose meaning is different in kind.
42 It has its own section below.
43
44 The survey box is 300 m by 100 m at the origin, and the features are laid out over a
45 far wider region than that: the Calanus patches are centred 600 m and 1500 m north,
46 the mackerel schools 400 m and 1700 m north, the front 1000 m out. So for the most
47 part this mission flies through the flanks of the structure and not through its
48 cores. Inside the box the front is very nearly a constant offset, about -0.53 degC
49 and +0.34 PSU, and the nearer Calanus patch adds at most some 1.5e-5 kg/m3 on top of
50 the band, against a band peak of 2.2e-3. That is the intent and not an oversight:
51 the file describes a region, this mission samples one corner of it, and a mission
52 that ran north to 1500 m would fly through a patch.
53
54 The one feature the box does reach into is the first mackerel school, 400 m north
55 and 200 m east with sigmas of 150 m and 90 m: at the north-east corner of the track
56 it still holds about 2.2e-2 kg/m3, a third of its peak, at its own depth. The school
57 and the mackerel background stay above 20 m, clear of the Calanus band (FISH-0042).
58
59 ## Cod follows the seabed
60
61 The Cod entry sets "z_reference": "seafloor", so every vertical coordinate in it is
62 a HEIGHT ABOVE THE BOTTOM, positive up, and the layer rides the rolling bathymetry
63 instead of sitting at a fixed depth. It peaks near 1.2e-2 kg/m3 about 5 m above the
64 bottom, wherever the bottom happens to be. That is what a demersal aggregation is,
65 and it is precisely what a depth-only field cannot say: the previous version of this
66 file pinned the cod into a fixed 126 m to 145 m band and called it a bottom layer,
67 which it was only on average and never at a given point.
68
69 All three species fields also set "mask_below_seabed", so their concentration is
70 exactly zero under the bottom and the sounder does not integrate fish through rock.
71
72 ## ConfigFile, and the working directory it is resolved from
73
74 ScalarField.<Name>.ConfigFile is opened with the path exactly as written, relative to
75 the PROCESS working directory and not to the directory this file sits in. Both ways
76 the scenario is run start in playpen/bin - the example run below, and the ctest run
77 of tests/in/AuvSurvey/AuvSurvey_in.xml, which is this file byte for byte and which
78 CMake gives WORKING_DIRECTORY ${PLAYPEN_DIR}/bin - so one relative path serves both:
79
80 cd build/Release/playpen/bin
81 ./FhSim ../examples/input/fishery/AuvSurvey.xml
82
83 That is why the path below points into the installed playpen tree and not into the
84 source tree. Run it from anywhere else and the path has to move with you.
85
86 A Parametric field must use ConfigFile and not an inline Config: every XML attribute
87 in this tree is passed through the expression evaluator, which is not bracket aware
88 and mangles a JSON array of numbers. See fhsim_environment issue ENV-0019.
89
90 ## Watching it run
91
92 The same file, run with FhVis instead of FhSim, draws itself:
93
94 cd build/Release/playpen/bin
95 ./FhVis ../examples/input/fishery/AuvSurvey.xml
96
97 The vehicle is a yellow torpedo with fins that deflect to the commanded RudderDive
98 and RudderYaw, the echosounder draws its beam as a translucent cone out to
99 MaxRangeDown, the seabed is the SumOfSines surface the Cod field is
100 referenced to, and three visualisers in the OBJECTS block below draw the ocean the
101 instruments are measuring: the Calanus layer and the demersal cod as ray-marched
102 volumes, and a vertical temperature section running 1900 m north through the water
103 mass front. See the comment above those three objects for the sizing.
104
105 The live view exists only because of <Visualization frameRate="25"/> in the OBSERVERS
106 block. An OBSERVERS block is honoured exactly as written and there is one here for
107 the FileOutput, so without that line FhVis would run this model headless.
108
109 The camera starts at NED (-30, 0, 0) looking at the origin, which is beside the first
110 waypoint and above the vehicle's 20 m start depth. Steer it with the arrow keys and
111 the numeric keypad.
112
113 ## Why the species are what they are
114
115 The three species are chosen to separate by frequency, which is the whole reason a
116 three frequency sounder is worth simulating. Each field names its Species, a key of the
117 echosounder Parameter library (fhsim_fishery data/acoustics/parameter_library.json,
118 copied from the echosounder sensor repository), and its mean LengthM; the library gives
119 the target strength per frequency, the weight per length and the length spread.
120
121 The consequence worth knowing before reading the echogram: at the design Calanus peak
122 the layer alone is Sv = -101.0 dB at 38 kHz, -81.4 dB at 120 kHz and -73.2 dB at
123 200 kHz. The modelled noise floor of this sounder reaches -101 dB at about 16 m of
124 range at 38 kHz, so Calanus alone is invisible there beyond that, while at 200 kHz it
125 survives far beyond the vehicle's reach. That contrast between frequencies, not blanket
126 visibility, is what the echogram is for.
127
128 ## The Calanus band holds Calanus
129
130 The mackerel field stays above 20 m and the cod field below 80 m above the bottom, so
131 the 26 m to 31 m band is Calanus at 120 kHz and 200 kHz (FISH-0042). At 38 kHz Calanus
132 is below the noise floor and the tails of the mackerel schools, so the band's rise from
133 38 kHz to 200 kHz, about 24 dB, is a little short of the 27.8 dB of Calanus alone.
134
135 ## The seabed is pinned
136
137 Environment.RandomSeed defaults to a time based seed, and the default bathymetry is
138 a sum of randomly phased structures rather than a flat bottom. Both are pinned here,
139 so the seabed is the same rolling surface on every run. See FISH-0036.
140
141 ## Undulation envelope
142
143 The dive control flies the vehicle between 10 m and 45 m rather than down to the
144 80 m default, for two reasons. The band has to contain the Calanus layer at 28 m and
145 the mackerel above it, which is what the instruments are here to find; and a
146 commanded dive angle is not a flight path angle, so the vehicle makes only about
147 0.36 m/s of vertical speed at the default 0.349 rad command. A 35 m band is about
148 97 s per leg, so a 600 s mission is five legs. See FISH-0037.
149
150 DepthHysteresis is 4 m, not the 1 m default. One metre is the minimum for the
151 switching logic alone; it is not enough once the loop is closed, because the vehicle
152 makes 2 to 3 m of depth while the pitch loop swings over, and the depth then leaves
153 the commanded band at every turn.
154
155 ## The gain signs
156
157 Heading positive, pitch negative, speed positive: each gain takes the sign of the
158 plant it drives. PidController.cpp forms error = measurement - reference and
159 sfh::filters::PID then forms -kP*error, so the two inversions cancel and the
160 composition is the standard convention. See FISH-0035.
161
162 SpeedPid.InitOutput is a feed forward and not a tuning knob. 30 W is the cruise
163 power of this parameter set at the commanded 1.5 m/s; at a different commanded speed
164 it must be changed with it, or the loop spends tens of seconds unwinding an
165 integrator that started in the wrong place.
166
167 ## Neutral buoyancy on purpose
168
169 AverageDensity is 1025, the same as Rho. Depth hold in this stack is pitch hold, so
170 at the trimmed default of 1020 the vehicle rises at about 0.115 m/s regardless of
171 what the pitch loop does, and the undulation envelope would not hold.
172
173 ## A calm sea and no current
174
175 Waves.NumWaves is zero and the current is zero, which makes this the clean case. A
176 sea state is a one line change, and a shallow vehicle then sees the wave orbital
177 velocity through the hydrodynamics and the autopilots see it through Speed and
178 Pitch; that is intended behaviour and not a defect. StepMax of 0.0125 s resolves a
179 7 s peak period 560 times over.
180
181 ## StepMax divides every instrument period
182
183 0.0125 s is not the 0.05 s the plan suggested, and the difference is not about
184 accuracy. A sensor fires on the first accepted step at or after its due time, so an
185 integrator step that does not divide a sample period makes the samples late by up to
186 one step: at 0.05 s the CTD, which samples at 0.0625 s, is up to 37 ms late and
187 SampleClock says so once, in a warning naming the StepMax it wants. 0.0125 s divides
188 0.0625 s, the SilCam's 0.25 s frame period and the sounder's 1 s ping alike, so
189 every instrument fires on its own grid. It is also the number a co-simulation host
190 should pick for communicationStepSize.
191-->
192<Contents>
193 <OBJECTS>
194 <Lib
195 LibName = "environment"
196 SimObject = "Environment"
197 Name = "Env"
198 RandomSeed = "20240601"
199 Waves.Model = "Component"
200 Waves.NumWaves = "0"
201 Current.Model = "Constant"
202 Current.Vector = "0, 0, 0"
203
204 Bathymetry.Model = "SumOfSines"
205 Bathymetry.Depth = "140"
206 Bathymetry.NumStructures = "10"
207 Bathymetry.StructureLengthMin = "150"
208 Bathymetry.StructureLengthMax = "600"
209 Bathymetry.StructureMaxHeight = "6"
210
211 ScalarField.Names = "SeaTemperature, SeaSalinity, Calanus, Mackerel, Cod"
212
213 ScalarField.SeaTemperature.Quantity = "Temperature"
214 ScalarField.SeaTemperature.Unit = "degC"
215 ScalarField.SeaTemperature.Model = "Parametric"
216 ScalarField.SeaTemperature.ConfigFile = "../examples/input/fishery/auv_ocean_fields.json"
217 ScalarField.SeaTemperature.ConfigKey = "SeaTemperature"
218
219 ScalarField.SeaSalinity.Quantity = "Salinity"
220 ScalarField.SeaSalinity.Unit = "PSU"
221 ScalarField.SeaSalinity.Model = "Parametric"
222 ScalarField.SeaSalinity.ConfigFile = "../examples/input/fishery/auv_ocean_fields.json"
223 ScalarField.SeaSalinity.ConfigKey = "SeaSalinity"
224
225 ScalarField.Calanus.Quantity = "SpeciesConcentration"
226 ScalarField.Calanus.Unit = "kg/m^3"
227 ScalarField.Calanus.Model = "Parametric"
228 ScalarField.Calanus.ConfigFile = "../examples/input/fishery/auv_ocean_fields.json"
229 ScalarField.Calanus.ConfigKey = "Calanus"
230 ScalarField.Calanus.Species = "calanus_finmarchicus"
231 ScalarField.Calanus.PropertyNames = "LengthM"
232 ScalarField.Calanus.PropertyValues = "0.0028"
233
234 ScalarField.Mackerel.Quantity = "SpeciesConcentration"
235 ScalarField.Mackerel.Unit = "kg/m^3"
236 ScalarField.Mackerel.Model = "Parametric"
237 ScalarField.Mackerel.ConfigFile = "../examples/input/fishery/auv_ocean_fields.json"
238 ScalarField.Mackerel.ConfigKey = "Mackerel"
239 ScalarField.Mackerel.Species = "mackerel"
240 ScalarField.Mackerel.PropertyNames = "LengthM"
241 ScalarField.Mackerel.PropertyValues = "0.35"
242
243 ScalarField.Cod.Quantity = "SpeciesConcentration"
244 ScalarField.Cod.Unit = "kg/m^3"
245 ScalarField.Cod.Model = "Parametric"
246 ScalarField.Cod.ConfigFile = "../examples/input/fishery/auv_ocean_fields.json"
247 ScalarField.Cod.ConfigKey = "Cod"
248 ScalarField.Cod.Species = "cod"
249 ScalarField.Cod.PropertyNames = "LengthM"
250 ScalarField.Cod.PropertyValues = "0.60"
251 />
252
253 <!-- ConfigKey is given on every field even though it defaults to the field name,
254 because one JSON document holds all five entries and the mapping from an
255 XML field name to a key in that document is worth being able to read here.
256 The Cod entry is the seafloor referenced one; see the header. -->
257
258 <!-- ================================================================
259 The environment, drawn.
260
261 Three fhsim_environment visualisers, all of them standalone: they have no
262 ports and no connections, they find the Environment through the shared
263 "Environment" resource rather than by its name, and they find their field by
264 the name it is listed under in ScalarField.Names. That lookup and the
265 time-invariance check happen in VisualBakedScalarField::FinalSetup, which
266 runs in the HEADLESS binary too, so a typo in FieldName below fails the
267 regression run and not only the live view. That is deliberate.
268
269 Each one bakes its field once, at startup, into a texture and costs nothing
270 per frame afterwards, so the resolutions below are a startup cost and not a
271 frame cost. They are kept modest all the same - about 200 k cells per volume
272 against the 3.5 M of fhsim_environment's own ScalarVolumeBlobs demo - because
273 the bake is CPU work and this scenario is usually watched over software GL.
274
275 ReferenceLength is the path length AlphaRange is quoted over. The default of
276 1 m makes any ray crossing more than a few metres of visible field opaque, so
277 it is set here to the vertical scale of each structure: 20 m for the Calanus
278 band, 10 m for the thinner cod layer.
279
280 Mackerel is deliberately NOT drawn. Its field fills the upper 20 m, directly
281 above the Calanus box over its entire footprint, so seen from the side the two
282 ray-marched volumes would blend into one wash and neither would be readable.
283 Adding a third <Lib> for it is a copy of the Calanus block with FieldName,
284 ColorRange and VisibleRange changed, if that is the picture wanted.
285
286 Two occlusion artefacts of VisualScalarVolume are documented and accepted
287 upstream and are not defects: a ray that passes through the seabed still
288 blends its below-seabed samples over the seafloor unless the field masks them
289 (all three species fields here set mask_below_seabed, so they do not), and
290 while the camera is INSIDE a box the fragment is depth-tested at the far box
291 face, so the seafloor erases the volume across its whole footprint. Backing
292 the camera out of the box restores it.
293 ================================================================ -->
294
295 <!-- The Calanus layer over the survey box. The band is centred at 28 m with a 9 m
296 standard deviation, so a 0..60 m box holds all of it; 1.25 m of vertical
297 spacing resolves the band, 5 m horizontally is plenty for a field that has no
298 horizontal structure worth the name inside this box. VisibleRange starts at
299 3.0e-4, just above the 1e-4 to 3e-4 background, so the ambient water is clear
300 and only the layer is drawn. -->
301 <Lib
302 LibName = "environment"
303 SimObject = "VisualScalarVolume"
304 Name = "CalanusVolume"
305 FieldName = "Calanus"
306 BoxCentre = "150, 50, 30"
307 BoxSize = "420, 260, 60"
308 Resolution = "84, 52, 48"
309 ReferenceLength = "20"
310 ColorRange = "3.0e-4, 2.2e-3"
311 VisibleRange = "3.0e-4, 2.6e-3"
312 AlphaRange = "0.02, 0.30"
313 />
314
315 <!-- The demersal cod layer. This is the one that shows what a seafloor-referenced
316 field buys: the layer is 5 m above the BOTTOM, so it rides the rolling
317 bathymetry, and the box is a flat 110..154 m slab that the layer wanders
318 through rather than a band the layer fills. 1 m of vertical spacing, because
319 the band's sigma is 2.5 m. -->
320 <Lib
321 LibName = "environment"
322 SimObject = "VisualScalarVolume"
323 Name = "CodVolume"
324 FieldName = "Cod"
325 BoxCentre = "150, 50, 132"
326 BoxSize = "420, 260, 44"
327 Resolution = "84, 52, 44"
328 ReferenceLength = "10"
329 ColorRange = "1.0e-3, 1.2e-2"
330 VisibleRange = "1.0e-3, 1.6e-2"
331 AlphaRange = "0.03, 0.45"
332 />
333
334 <!-- A vertical temperature section along the track, from the surface to the
335 seabed. It is 1900 m long and the survey box is 300 m of that on purpose: the
336 water mass front sits 1000 m out and inside the box it is very nearly a
337 constant -0.53 degC offset, so a slice cropped to the box would show the
338 thermocline and nothing else. Run north far enough and the front, and the
339 warm lens on top of it, are both in the picture, and it is then visible that
340 this mission samples one corner of a much larger structure.
341
342 It sits at the EASTERN edge of the survey box, flush with the far face of
343 the two volumes, and not down the middle of it. That is not cosmetic: the
344 slice is nearly opaque where the field is strong, so anywhere it stands
345 between the camera and the vehicle it is a wall rather than a section. At the
346 far face it is a backdrop, and from the default camera - which is south of
347 the box at East 0, looking north - it is off to the right and seen at a
348 glancing angle. 4 m by 1 m sampling is 66.5 k cells, a tenth of either
349 volume. -->
350 <Lib
351 LibName = "environment"
352 SimObject = "VisualScalarPlane"
353 Name = "TemperatureSection"
354 FieldName = "SeaTemperature"
355 Position = "600, 180, 70"
356 LocalX = "1, 0, 0"
357 LocalY = "0, 0, 1"
358 Size = "1900, 140"
359 Resolution = "475, 140"
360 ColorRange = "6.5, 9.8"
361 VisibleRange = "6.2, 10.4"
362 AlphaRange = "0.45, 0.80"
363 />
364
365 <Lib
366 LibName = "fishery"
367 SimObject = "Auv/Vehicle"
368 Name = "Auv"
369 Length = "2.0"
370 Diameter = "0.20"
371 AverageDensity = "1025"
372 Rho = "1025"
373 COG = "0, 0, 0.020"
374 AddedMass = "3.2, 58, 58, 0.1, 19, 19"
375 ThrustPerPower = "0.30"
376 MaxPropulsionPower = "120"
377 HotelPower = "15"
378 ThrusterPos = "-1.0, 0, 0"
379 AxialDragCoeff = "0.25"
380 CrossFlowDragCoeff = "1.1"
381 RollDampingLinear = "4.6"
382 RollDampingQuadratic = "1.0"
383 RudderArea = "0.016"
384 RudderAspectRatio = "1.25"
385 RudderPos = "-0.85, 0, 0"
386 RudderClMax = "0.8"
387 RudderAoaMax = "0.436"
388 RudderCd0 = "0.02"
389 RudderOswald = "0.9"
390 MaxRudderAngle = "0.35"
391 InitialBattery = "1.8e6"
392 />
393
394 <!-- A short three leg survey box: 300 m north, 100 m east, 300 m south. About
395 700 m of track, that is about 470 s at cruise, so the mission finishes well
396 inside the 600 s run and EndMission has time to latch. RecoveryPosition is
397 the last waypoint, so no return leg is added. -->
398 <Lib
399 LibName = "fishery"
400 SimObject = "Auv/UndulateMissionControl"
401 Name = "Mission"
402 WaypointsX = "300, 300, 0"
403 WaypointsY = " 0, 100, 100"
404 RecoveryPosition = "0, 100"
405 WaypointRadius = "15"
406 CruiseSpeed = "1.5"
407 BatteryAtEndOfMission = "2.7e5"
408 LoopWaypoints = "0"
409 UpdatePeriod = "1.0"
410 />
411
412 <Lib
413 LibName = "fishery"
414 SimObject = "Auv/UndulateDiveControl"
415 Name = "Dive"
416 MaxDepth = "45"
417 MinDepth = "10"
418 MinSeafloorDistance = "15"
419 DiveAngle = "0.349"
420 DepthHysteresis = "4.0"
421 UpdatePeriod = "1.0"
422 />
423
424 <!-- Heading. POSITIVE gains; Ki deliberately zero, because a symmetric vehicle
425 needs no steady rudder and an integrator winds up through the saturated part
426 of a large step. -->
427 <Lib
428 LibName = "fishery"
429 SimObject = "Trawl/PIDController"
430 Name = "HeadingPid"
431 InitOutput = "0"
432 ProportionalGain = "0.4"
433 IntegratorGain = "0"
434 DerivativeGain = "0.6"
435 MinOut = "-0.35"
436 MaxOut = "0.35"
437 MaxDerivativePart = "0.2"
438 MaxIntegratorPart = "0.1"
439 />
440
441 <!-- Pitch. NEGATIVE gains, because a positive RudderDive lowers the pitch.
442 IntegratorGain -0.08 as in tests/in/Auv/Auv_Undulate_in.xml (R112, FISH-0095):
443 with the Munk moment and the hull lift the standing deflection at DiveAngle is
444 0.093 rad rather than 0.20, and -0.15 overshot each DiveAngle step by 27 %. -->
445 <Lib
446 LibName = "fishery"
447 SimObject = "Trawl/PIDController"
448 Name = "PitchPid"
449 InitOutput = "0"
450 ProportionalGain = "-0.6"
451 IntegratorGain = "-0.08"
452 DerivativeGain = "-0.8"
453 MinOut = "-0.35"
454 MaxOut = "0.35"
455 MaxDerivativePart = "0.2"
456 MaxIntegratorPart = "0.3"
457 />
458
459 <!-- Speed. POSITIVE gains. InitOutput 30 W is the cruise feed forward for the
460 commanded 1.5 m/s; change it with CruiseSpeed. -->
461 <Lib
462 LibName = "fishery"
463 SimObject = "Trawl/PIDController"
464 Name = "SpeedPid"
465 InitOutput = "30"
466 ProportionalGain = "200"
467 IntegratorGain = "10"
468 DerivativeGain = "0"
469 MinOut = "0"
470 MaxOut = "120"
471 MaxIntegratorPart = "120"
472 />
473
474 <!-- The CTD head is on the nose, ahead of the hull wake. The time constants and
475 the noise are an SBE49 FastCAT. NoiseSeed is non zero, so the instrument is
476 realistic rather than perfect, and the hand rolled generators make it
477 reproducible across compilers all the same. -->
478 <Lib
479 LibName = "fishery"
480 SimObject = "Auv/CTD"
481 Name = "Ctd"
482 TemperatureFieldName = "SeaTemperature"
483 SalinityFieldName = "SeaSalinity"
484 MountOffset = "0.8, 0, 0"
485 SamplePeriod = "0.0625"
486 TemperatureTimeConstant = "0.07"
487 ConductivityTimeConstant = "0.06"
488 DepthTimeConstant = "0.02"
489 NoiseSeed = "7"
490 />
491
492 <!-- The silhouette camera images 1.43e-4 cubic metres per frame, so a single
493 frame is almost pure noise: at the design Calanus peak the rate is 0.22
494 particles per frame after the capture and detection efficiencies. Forty
495 frames, that is 10 s and about 15 m of track, brings it to about 9 counts
496 and a 33 percent counting error. That is why the aggregation exists. -->
497 <Lib
498 LibName = "fishery"
499 SimObject = "Auv/SilCam"
500 Name = "SilCam"
501 SpeciesFieldName = "Calanus"
502 MountOffset = "0.6, 0, 0"
503 FrameRate = "4.0"
504 FramesPerOutput = "40"
505 SampleVolume = "0.040, 0.055, 0.065"
506 CaptureEfficiency = "0.85"
507 DetectionProbability = "0.92"
508 FalsePositiveRate = "0.05"
509 SizeErrorStdRelative = "0.08"
510 NumSizeBins = "8"
511 SizeBinMin = "0.0005"
512 SizeBinMax = "0.0060"
513 NoiseSeed = "11"
514 />
515
516 <!-- MountDirection must be given. SensorFrame defaults a beam axis to body x,
517 which is 90 degrees wrong for a nadir sounder.
518
519 NoiseSeed is non zero on purpose, and it is not only about realism: with the
520 seed at zero the instrument adds no range noise, no speckle AND no noise
521 floor, and the noise floor is precisely what makes the Calanus layer
522 invisible at 38 kHz and visible at 120 and 200 kHz.
523
524 PingPeriod is 1 s rather than the 0.5 s default. One hertz is a realistic
525 survey rate, it halves a file that would otherwise reach about 7.5 MB over
526 this mission, and StepMax of 0.0125 s still puts 80 integrator steps in a
527 ping interval. -->
528 <Lib
529 LibName = "fishery"
530 SimObject = "Auv/Echosounder"
531 Name = "Echo"
532 MountOffset = "0, 0, 0.10"
533 MountDirection = "0, 0, 1"
534 PingPeriod = "1.0"
535 MaxRangeDown = "150"
536 RayStepSize = "1.0"
537 RayTolerance = "0.01"
538 SpeciesFieldNames = "Calanus, Mackerel, Cod"
539 BinSize = "1.0"
540 SvPrecision = "2"
541 FlushEveryNPings = "20"
542 WriteFile = "1"
543 FileName = "AuvSurvey_echogram.csv"
544 NoiseSeed = "13"
545 />
546 </OBJECTS>
547
548 <INTERCONNECTIONS>
549 <Connection Mission.Pos = "Auv.Pos" Mission.Battery = "Auv.Battery" Mission.Heading = "Auv.Heading"/>
550 <Connection Dive.Depth = "Auv.Depth" Dive.Altitude = "Auv.Altitude"/>
551
552 <Connection HeadingPid.Reference = "Mission.Heading" HeadingPid.Measurement = "Auv.Heading"/>
553 <Connection PitchPid.Reference = "Dive.PitchRef" PitchPid.Measurement = "Auv.Pitch"/>
554 <Connection SpeedPid.Reference = "Mission.Speed" SpeedPid.Measurement = "Auv.Speed"/>
555
556 <!-- Two cycles, neither of them algebraic: Mission, Dive and PidController all
557 return output members written only in AcceptedStep, so nothing in either
558 cycle has direct feedthrough. -->
559 <Connection
560 Auv.RudderYaw = "HeadingPid.Out"
561 Auv.RudderDive = "PitchPid.Out"
562 Auv.ThrustPower = "SpeedPid.Out"
563 Auv.ExternalForce = "0,0,0"
564 />
565
566 <!-- The instruments ride the vehicle. Each one rotates its own mount offset and
567 beam axis out of the body frame, so the pose is all they need. -->
568 <Connection Ctd.Pos = "Auv.Pos" Ctd.Quater = "Auv.Quater"/>
569 <Connection SilCam.Pos = "Auv.Pos" SilCam.Quater = "Auv.Quater"/>
570 <Connection Echo.Pos = "Auv.Pos" Echo.Quater = "Auv.Quater"/>
571 </INTERCONNECTIONS>
572
573 <INITIALIZATION>
574 <InitialCondition
575 Auv.Pos = "0,0,20"
576 Auv.Quater = "1,0,0,0"
577 Auv.LocalVel = "1.5,0,0"
578 Auv.Omega = "0,0,0"
579 />
580 </INITIALIZATION>
581
582 <SIMULATION>
583 <Timing TStart="0" TEnd="600"/>
584 <Integrator Method="RK45_i" NumCores="1">
585 <StepControl StepMax="0.0125" StepMin="1e-8" AbsTol="1e-4" RelTol="1e-4"/>
586 </Integrator>
587 </SIMULATION>
588
589 <OBSERVERS>
590 <!-- A range, not a list: TOutput is start:delta:end. -->
591 <FileOutput TOutput="0:0.5:600" Select="objects:all"/>
592
593 <!-- Without this the scenario never draws. An OBSERVERS block is honoured
594 exactly as written, so once one is present the legacy default set - which is
595 where the live view used to come from - is gone, and FhVis runs the model
596 headless. In a headless binary the element is a silent no-op: FhSim never
597 attaches a live view, makeVisualizationObserverFromModel returns nothing and
598 nothing is registered, which is why this file can carry the observer and
599 still be the regression input byte for byte. -->
600 <Visualization frameRate="25"/>
601 </OBSERVERS>
602</Contents>