FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
0002 — SeineConnector Pos and Vel select from opposite sources for the same Connected flag
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.

Evidence

src/seine/SeineConnector.cpp:42-58:

const double * SeineConnector::Vel( const double dT, const double *const adX )
{
bool connected = m_inIsConnected->GetPortValue(dT, adX)[0] > 0;
if (connected)
return m_inVel1->GetPortValue(dT,adX);
else
return m_inVel2->GetPortValue(dT,adX);
}
const double *const SeineConnector::GetPos( const double dT, const double *const adX )
{
bool connected = m_inIsConnected->GetPortValue(dT, adX)[0] > 0.5;
if (!connected)
return m_inPos1->GetPortValue(dT,adX);
else
return m_inPos2->GetPortValue(dT,adX);
}
ISignalPort * m_inIsConnected
A pointer to the input telling if the connector is connected to pos 1 or pos 2.
Definition SeineConnector.h:61
ISignalPort * m_inVel2
A pointer to the input velocity 2.
Definition SeineConnector.h:65
ISignalPort * m_inPos1
A pointer to the input position 1.
Definition SeineConnector.h:62
ISignalPort * m_inPos2
A pointer to the input position 2.
Definition SeineConnector.h:64
ISignalPort * m_inVel1
A pointer to the input velocity 1.
Definition SeineConnector.h:63

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).

Effect

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.

Possible fix

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.

Test that would prove it

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.

Risk

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.

Why not solved (fix pass 2026-09-15)

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.