|
FhSim
3.1.0
Marine systems simulation
|
| ID | 0002 |
| Class | BUG |
| Severity | 3 |
| Status | blocked |
| Models | Seine/Buoy |
| Found | 2026-09-15 audit (a7d080d) |
| Decision needed | Does Connected != 0 mean the vessel holds the warp end? If yes, invert the branch in Vel; if no, invert the branch in GetPos and the matching render visibility. |
src/seine/SeineConnector.cpp:42-58:
Pos (:38-41) forwards to GetPos. Two differences: the threshold (> 0 in Vel, > 0.5 in GetPos) and the polarity (Vel returns source 1 when connected, GetPos returns source 1 when not connected). For any flag value the two output ports report kinematics of different physical points. The visualization at src/seine/SeineConnector.cpp:102 uses a third form, setVisible(flag < 0.5) — the buoy mesh is shown when not connected, agreeing with GetPos's branch. The flag is driven by SeineOperation's WarpConnectedVessel output, which is 1 during Phase_NotSet and Phase_Towing and 0 otherwise (src/seine/SeineOperation.cpp:135-150).
In a Danish-seining model the warp end's position and velocity come from different bodies at every instant. Downstream the warp cable sees a position/velocity pair that is not a consistent rigid-body state, so its damping term is computed against a velocity that does not differentiate its own position. Expect spurious warp tension and, with the cable's numerical damping, either a stiff, slow integration or a blow-up at the phase transitions where the flag flips.
Pick one convention and make both selectors use it, with one shared threshold (> 0.5, matching RenderUpdate and tolerating a filtered flag). The reading the rest of the code supports: Connected != 0 means the vessel holds the warp end and source 2 is the vessel — RenderUpdate hides the buoy mesh when the flag is high, and WarpConnected raises it during Phase_NotSet (before the buoy is dropped; BuoyPos is still being latched to the vessel position) and during Phase_Towing (after the vessel has picked the end back up). Under that reading GetPos is correct and Vel is inverted. Either way the change is confined to the two branch conditions. While there, the header prose at src/seine/SeineConnector.h:9-10 describes the class as "Simulation of a minimum
trawl vessel. Used as a base class for other trawl vessels", with its own @todo This is wrongly documented?; it is a two-source position/velocity switch.
Owner question: is Connected != 0 "the vessel holds the warp end" (so Vel is inverted), or the opposite (so GetPos and the render visibility are both wrong)? The code does not exclude either; the port names Pos1/Vel1 vs Pos2/Vel2 carry no hint.
Depends on FISH-0001. A headless signal-level case tests/in/SimObj-SeineConnector/ with a Src/SmoothTrajectory or Src/Step driving Connected across the 0→1 edge, two distinct constant Pos/Vel pairs, and Select="objects:all". Assert Pos and Vel come from the same index on both sides of the edge. Red before the fix.
Behaviour-changing for any input file using Seine/Buoy, which is every seine model. No seine input file ships in this repository (see FISH-0017), so there is no in-repo baseline to update, but downstream seine models will move.
Re-confirmed at HEAD (SeineConnector.cpp:42-58): Vel tests > 0 and returns source 1 when connected, while GetPos tests > 0.5 and returns source 1 when not connected. The fix is a one-line branch inversion in one of the two functions, but which one is right depends on the physical meaning of the flag, and the code alone does not settle it. Guessing wrong would silently swap the warp end between buoy and vessel in every seine model, with no test to catch it (FISH-0001) and no shipped seine scenario to observe it in (FISH-0017). Owner question: does Connected != 0 mean the vessel holds the warp end? If yes, invert the branch in Vel; if no, invert the branch in GetPos and the matching render visibility.