You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
After #912, the simulator's architecture and internals have been changed to remove fatal bugs and add Polaris's mechanical constants.
After reviewing the (Boat Simulator Design Specification)[https://ubcsailbot.atlassian.net/wiki/spaces/prjt22/pages/1785790595/Boat+Simulator+Design+Specification] and the code base, we can safely say that the calculations need rework. Conventions are all over the place, and even with #912, there are no guarantees that the calculations use the correct units or angle conventions. There were assumptions made in fluid_forces.py and constants.py, such as the area, which are incorrect and would require some reworking with the interpolation functions provided.
Now, we need to move towards a stage-wise rewrite so that PR reviews are manageable 🤞.
The target model is 3-DOF (surge, sway, yaw), NED everywhere, following Fossen as adapted to sailboats (van Tonder 2024) with rigid-wingsail aerodynamics (Fang 2024 / Tinoco 2021). Each checkbox below is intended to be roughly one reviewable PR and maps to a design-spec sub-page.
Stages
Physics Engine Node
Conventions & frame foundation — single canonical internal frame (NED + FRD + radians); one frames.py transforms module (J(η), rotations, ENU↔NED); typed Vec3[Frame] wrappers; frame/unit variable suffixes; REP-103 ENU/FLU boundary isolated to one adapter; mypy + Hypothesis round-trip tests wired into CI. (Conventions & Reference Frames)
Rigid-body EOM core — η, ν, J(η), M_RB, C_RB, combined M_RB + M_A inverted once, RK4 integrator over [η; ν]. Runs under zero/placeholder forces (energy/momentum sanity). (Rigid-Body Equations of Motion)
Shared lift/drag module — ½·ρ·V²·A·C(α) with AoA lookup + post-stall handling, reused by wingsail/rudder/keel. Fixes the incorrect area + interpolation assumptions in fluid_forces.py / constants.py.
Hydrodynamics — added mass + Coriolis, linear damping, hull (quadratic drag, replacing the linear k=0.5 placeholder), rudder (NACA 0012), keel. (Hydrodynamic Forces & Moments)
Hydrostatics — g(η) roll restoring (−ρ_w·g·∇·GM_T·sin φ), tied to the roll-decay coefficient. (Hydrostatic Forces & Moments)(NON-CRITICAL | OPTIONAL)
Output interface — sensor sample→bias→noise→quantize→latency pipeline (apparent, not true, wind), actuator first-order lag + rate limits, and the single NED→ENU boundary conversion. (Output Interface — Sensors & Actuators)
Acceptance tests (validation gate) — reproduce van Tonder's three open-loop responses: surge-speed decay, yaw-rate step, roll decay. Run standalone, deterministic, in CI.
Retire TBD constants — swap placeholder constants for real values as Mechanical/Electrical deliver (areas, CoEs, inertias, GM_T, keel section, sensor/actuator specs, PID gains).
Low-Level Control Node
Actuator-execution model (permanent plant core) — apply commanded surface angle to the physics with slew rate + first-order lag + clamps (rudder ±30°, tab ±7°). Used for both surfaces regardless of who commands them.
Trim-tab control (sim-owned) — command δ_tab; PD-on-AoA after Tinoco (or pass-through if the incoming command is already a tab angle). This is the only controller the sim owns.
Rudder as external command input + placeholder — Create a rudder PID mock up. Documented interface: currentHeading + heelAngle → desiredRudderAngle [deg] at ~20 Hz (CAN encoding (angle + 90)·100).
Purpose
After #912, the simulator's architecture and internals have been changed to remove fatal bugs and add Polaris's mechanical constants.
After reviewing the (Boat Simulator Design Specification)[https://ubcsailbot.atlassian.net/wiki/spaces/prjt22/pages/1785790595/Boat+Simulator+Design+Specification] and the code base, we can safely say that the calculations need rework. Conventions are all over the place, and even with #912, there are no guarantees that the calculations use the correct units or angle conventions. There were assumptions made in
fluid_forces.pyandconstants.py, such as the area, which are incorrect and would require some reworking with the interpolation functions provided.Now, we need to move towards a stage-wise rewrite so that PR reviews are manageable 🤞.
The target model is 3-DOF (surge, sway, yaw), NED everywhere, following Fossen as adapted to sailboats (van Tonder 2024) with rigid-wingsail aerodynamics (Fang 2024 / Tinoco 2021). Each checkbox below is intended to be roughly one reviewable PR and maps to a design-spec sub-page.
Stages
Physics Engine Node
frames.pytransforms module (J(η), rotations, ENU↔NED); typedVec3[Frame]wrappers; frame/unit variable suffixes; REP-103 ENU/FLU boundary isolated to one adapter; mypy + Hypothesis round-trip tests wired into CI. (Conventions & Reference Frames)η,ν,J(η),M_RB,C_RB, combinedM_RB + M_Ainverted once, RK4 integrator over[η; ν]. Runs under zero/placeholder forces (energy/momentum sanity). (Rigid-Body Equations of Motion)½·ρ·V²·A·C(α)with AoA lookup + post-stall handling, reused by wingsail/rudder/keel. Fixes the incorrect area + interpolation assumptions influid_forces.py/constants.py.δ_tab → αroot-find), NACA 0018 polar, body-frameX_s/Y_sandK_s/N_s. (Aerodynamic Forces & Moments — Wingsail)k=0.5placeholder), rudder (NACA 0012), keel. (Hydrodynamic Forces & Moments)g(η)roll restoring (−ρ_w·g·∇·GM_T·sin φ), tied to the roll-decay coefficient. (Hydrostatic Forces & Moments) (NON-CRITICAL | OPTIONAL)Low-Level Control Node
δ_tab; PD-on-AoA after Tinoco (or pass-through if the incoming command is already a tab angle). This is the only controller the sim owns.currentHeading + heelAngle → desiredRudderAngle [deg]at ~20 Hz (CAN encoding(angle + 90)·100).sail_cmd); rudder node emitsdesiredRudderAnglelater.Visualizer Node
mode:="sim"runs.Resources
mainfirst (conflicts with Jb3982/805 PATH-SIM Integration #885)mode:="sim"); re-addsgeo_conversions.pythat Sim minimum integration work #912 refactored awaynaca0018_polar_Re500k.csv— attach to the issue/PR