Skip to content

Bridge active PTO to Marine_Robotics_HIL_SEA-Stack over ROS 2 via RosPTOModel #4

Description

@salhus

Goal

Implement the RosPTOModel : public seastack::pto::IPTOModel sketched in docs/HIL_MIGRATION.md so the HIL dynamometer in salhus/Marine_Robotics_HIL_SEA-Stack can drive this simulation through the ChLinkRSDA + RsdaPtoFunctor seam that was finalized in #3.

Because all four controllers already implement IPTOModel::ComputeForce(displacement, velocity, time) and actuation now flows through RsdaPtoFunctor, a ROS 2 controller is a drop-in: it publishes flap state to the hardware and returns the torque command received back from it. No changes to the multibody wiring are required — only which IPTOModel is handed to the functor.

Blocked by: none — the prerequisite (#3, RSDA + RsdaPtoFunctor actuation) is merged. Ready to start.

Important: the HIL repo already has the ROS 2 topology — do NOT build from scratch

salhus/Marine_Robotics_HIL_SEA-Stack is already a working ROS 2 Jazzy workspace. Relevant packages found under src/:

  • chrono_flap_sim/chrono_flap_node with SIL / HIL / parallel modes, and an existing optional SeaStackHydroAdapter gated by CHRONO_FLAP_USE_SEASTACK (find_package(SEAStack QUIET CONFIG)). Publishes sensor_msgs/JointState, hydro torque, wave elevation; has HIL load + hydro engage services.
  • odrive_velocity_pid/ — cascade position→velocity→torque PID; publishes std_msgs/Float64MultiArray torque commands.
  • hil_torque_mixer/ — sums τ_pid + τ_hydro with independent watchdogs and a hard safety clamp, publishes to /motor_effort_controller/commands.
  • odrive_ros2_control/ + odrive_base/ — ODrive CAN ros2_control hardware interface.

(Package list gathered via code search, which is capped at 10 results — browse the full src/ tree and re-scan when this session starts.)

Integration approach — OPEN QUESTIONS (decide at session start)

  1. Client vs. adapter reuse. Two viable paths:
    • (a) Add a RosPTOModel inside cpp-vgoswec that publishes flap angle and subscribes to a torque command, making demo_vgoswec a HIL client that talks to the mixer.
    • (b) Route cpp-vgoswec's excitation/hydro torque into the HIL repo's existing SeaStackHydroAdapter instead of duplicating it. Likely the cleaner architecture, since that adapter already exists. Decide which — or whether both are needed.
  2. Message types. docs/HIL_MIGRATION.md sketches std_msgs/Float64 pub/sub, but the live HIL repo uses std_msgs/Float64MultiArray (torque commands) and sensor_msgs/JointState (flap state). Which contract does RosPTOModel adopt? Reconcile before coding.
  3. Topic names. The doc uses /vgoswec/pto_torque_cmd and /vgoswec/flap_angle; the mixer uses /velocity_pid_node/torque_command, /chrono_flap_node/load_torque, /motor_effort_controller/commands. Which topic graph is authoritative?
  4. Who owns the loop / time base? Does demo_vgoswec remain the integrator (HIL client) or does chrono_flap_node stay the sim owner with cpp-vgoswec contributing only the hydro/PTO model? This determines where SetPerComponentCaptureEnabled + GetLastComponentForces live.
  5. Build coupling. cpp-vgoswec is CMake + find_package(SEAStack); the HIL repo is ament_cmake + colcon. If RosPTOModel lives in cpp-vgoswec, does it become an optional find_package(rclcpp) target, or a separate ROS package?

Contract to preserve

  • Interface: seastack::pto::IPTOModel::ComputeForce(double displacement /*θ [rad]*/, double velocity /*θ̇ [rad/s]*/, double time).
  • Sign convention (from src/active_pto.h and docs/CONTROLLERS.md): positive PTO torque opposes positive θ; absorbed power P_abs = −τ_pto · ω.
  • Latency caveat (from docs/HIL_MIGRATION.md): ComputeForce is called every Chrono sub-step (dt ≈ 0.005 s). Network latency > dt causes stale torque, which is benign for slow systems but can destabilize the resonant WEC near ω₀. Run the ROS node same-machine (intra-process) or on a dedicated real-time executor.
  • Optionally publish ExcitationForceProvider::GetLatestExcitationTorque() over ROS so hardware feedforward has the same F_exc signal.

Acceptance criteria (draft — refine once options above are settled)

  • RosPTOModel implements IPTOModel and is selectable (e.g. --controller ros).
  • Flap state is published and torque command is consumed each step with thread-safe latest-value handling.
  • Message types and topic names reconciled with the existing HIL mixer/chrono_flap_node graph.
  • End-to-end loop demonstrated: cpp-vgoswechil_torque_mixer / chrono_flap_node over ROS 2.
  • No changes to controller/provider/PID/impedance math.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions