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
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.
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)
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 existingSeaStackHydroAdapter instead of duplicating it. Likely the cleaner architecture, since that adapter already exists. Decide which — or whether both are needed.
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.
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?
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.
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?
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.
Goal
Implement the
RosPTOModel : public seastack::pto::IPTOModelsketched indocs/HIL_MIGRATION.mdso the HIL dynamometer insalhus/Marine_Robotics_HIL_SEA-Stackcan drive this simulation through theChLinkRSDA+RsdaPtoFunctorseam that was finalized in #3.Because all four controllers already implement
IPTOModel::ComputeForce(displacement, velocity, time)and actuation now flows throughRsdaPtoFunctor, 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 whichIPTOModelis handed to the functor.Important: the HIL repo already has the ROS 2 topology — do NOT build from scratch
salhus/Marine_Robotics_HIL_SEA-Stackis already a working ROS 2 Jazzy workspace. Relevant packages found undersrc/:chrono_flap_sim/—chrono_flap_nodewith SIL / HIL / parallel modes, and an existing optionalSeaStackHydroAdaptergated byCHRONO_FLAP_USE_SEASTACK(find_package(SEAStack QUIET CONFIG)). Publishessensor_msgs/JointState, hydro torque, wave elevation; has HIL load + hydro engage services.odrive_velocity_pid/— cascade position→velocity→torque PID; publishesstd_msgs/Float64MultiArraytorque 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 CANros2_controlhardware 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)
RosPTOModelinsidecpp-vgoswecthat publishes flap angle and subscribes to a torque command, makingdemo_vgosweca HIL client that talks to the mixer.cpp-vgoswec's excitation/hydro torque into the HIL repo's existingSeaStackHydroAdapterinstead of duplicating it. Likely the cleaner architecture, since that adapter already exists. Decide which — or whether both are needed.docs/HIL_MIGRATION.mdsketchesstd_msgs/Float64pub/sub, but the live HIL repo usesstd_msgs/Float64MultiArray(torque commands) andsensor_msgs/JointState(flap state). Which contract doesRosPTOModeladopt? Reconcile before coding./vgoswec/pto_torque_cmdand/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?demo_vgoswecremain the integrator (HIL client) or doeschrono_flap_nodestay the sim owner withcpp-vgosweccontributing only the hydro/PTO model? This determines whereSetPerComponentCaptureEnabled+GetLastComponentForceslive.cpp-vgoswecis CMake +find_package(SEAStack); the HIL repo isament_cmake+colcon. IfRosPTOModellives incpp-vgoswec, does it become an optionalfind_package(rclcpp)target, or a separate ROS package?Contract to preserve
seastack::pto::IPTOModel::ComputeForce(double displacement /*θ [rad]*/, double velocity /*θ̇ [rad/s]*/, double time).src/active_pto.handdocs/CONTROLLERS.md): positive PTO torque opposes positive θ; absorbed powerP_abs = −τ_pto · ω.docs/HIL_MIGRATION.md):ComputeForceis 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.ExcitationForceProvider::GetLatestExcitationTorque()over ROS so hardware feedforward has the same F_exc signal.Acceptance criteria (draft — refine once options above are settled)
RosPTOModelimplementsIPTOModeland is selectable (e.g.--controller ros).chrono_flap_nodegraph.cpp-vgoswec↔hil_torque_mixer/chrono_flap_nodeover ROS 2.References
docs/HIL_MIGRATION.md,docs/CONTROLLERS.md,src/rsda_pto_functor.{h,cpp},src/active_pto.h,src/excitation_force_provider.{h,cpp}.src/chrono_flap_sim/,src/odrive_velocity_pid/,src/hil_torque_mixer/,src/odrive_ros2_control/.