Underwater Vehicle-Manipulator System (UVMS) simulation: BlueROV2 Heavy + Reach Alpha 5 arm, using Stonefish simulator and ROS2 Humble. Features an LLM-driven MPC control pipeline that translates natural language commands into optimal vehicle trajectories.
src/
chatboat_description/ # URDF/xacro robot description (ROS2 ament_cmake)
chatboat_stonefish/ # Stonefish scenario, meshes, sim config (ROS2 ament_cmake)
chatboat_control/ # Teleop, MPC bridge, test commander, gripper (ROS2 ament_python)
chatboat_bringup/ # Top-level launch files (ROS2 ament_cmake)
llm2control/ # LLM→MPC pipeline (standalone Python, not a ROS2 package)
dashboard/ # Web dashboard for LLM→MPC control (index.html)
docker/ # Dockerfile for cloud GPU deployment
scripts/ # Build/push scripts, mesh converters
- Vehicle: BlueROV2 Heavy, ~11 kg, 8 thrusters (6-DOF: surge/sway/heave/roll/pitch/yaw)
- Arm: Reach Alpha 5, 4 revolute DOF, ~0.40 m reach
- Gripper: Magnetic sphere (PermanentMagnet)
- Namespace:
chatboat
Stonefish requires OpenGL 4.3+. macOS only supports 4.1, so a cloud GPU is needed. We use RunPod (~$0.32/hr for RTX A4000).
- Go to runpod.io/console/pods
- Click + GPU Pod → select RTX A4000 (or any GPU with OpenGL 4.3+)
- Choose template: Runpod Pytorch 2.1 (
runpod/pytorch:2.1.0-py3.10-cuda11.8.0-devel-ubuntu22.04)- This gives you Ubuntu 22.04 + Python 3.10 + CUDA — all required for ROS2 Humble
- Container Disk: 40 GB (ROS2 desktop-full is large)
- Deploy and SSH in
Run each command separately (long lines break when pasting into RunPod terminals):
apt-get update && apt-get install -y locales software-properties-common curllocale-gen en_US en_US.UTF-8export LANG=en_US.UTF-8add-apt-repository universecurl -sSL --output /usr/share/keyrings/ros-archive-keyring.gpg https://raw.githubusercontent.com/ros/rosdistro/master/ros.keyecho "deb [arch=amd64 signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu jammy main" > /etc/apt/sources.list.d/ros2.listapt-get update && apt-get install -y ros-humble-desktop-full python3-colcon-common-extensionsadd-apt-repository -y ppa:ubuntu-toolchain-r/testapt-get update && apt-get install -y gcc-13 g++-13apt-get install -y libglm-dev libsdl2-dev libfreetype6-dev libglew-dev libglu1-mesa-dev freeglut3-dev mesa-utils ros-humble-xacro ros-humble-robot-state-publisher ros-humble-joint-state-publisher xvfb x11vnc novnc websockifywget -q https://github.com/VirtualGL/virtualgl/releases/download/3.1.1/virtualgl_3.1.1_amd64.debdpkg -i virtualgl_3.1.1_amd64.deb || apt-get install -f -y/opt/VirtualGL/bin/vglserver_config -config +s +f -tcd /opt && git clone --depth 1 https://github.com/patrykcieslak/stonefish.gitcd /opt/stonefish && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc-13 -DCMAKE_CXX_COMPILER=g++-13 .. && make -j$(nproc) && make install && ldconfigImportant: After install, remove the stale config from the source tree (it shadows the real one):
rm -f /opt/stonefish/StonefishConfig.cmakemkdir -p ~/ChatBOAT/src && cd ~/ChatBOAT/srcgit clone --depth 1 --branch master https://github.com/patrykcieslak/stonefish_ros2.gitPatch required — ROS2 Humble type incompatibility on line 697 of ROS2Interface.cpp:
sed -i 's/msg.header.stamp + rclcpp::Duration/rclcpp::Time(msg.header.stamp) + rclcpp::Duration/' ~/ChatBOAT/src/stonefish_ros2/src/stonefish_ros2/ROS2Interface.cppBuild:
cd ~/ChatBOAT && source /opt/ros/humble/setup.bash && colcon build --packages-select stonefish_ros2 --cmake-args -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc-13 -DCMAKE_CXX_COMPILER=g++-13Version compatibility notes:
- Stonefish
main(latest) requires GCC 13+ for C++20<format>header- stonefish_ros2
masterbranch matches latest Stonefish API (Solver::SI,CollisionFilter::EXCLUSIVE)- stonefish_ros2
devbranch does NOT match — uses different enum names- stonefish_ros2
v1.3tag is too old for latest Stonefish- The
operator+patch is needed because ROS2 Humble'sbuiltin_interfaces::msg::Timedoesn't support+ rclcpp::Durationdirectly
cd ~/ChatBOAT/src && git clone https://github.com/filippogombac/ChatBOAT.git chatboat_srccp -r ~/ChatBOAT/src/chatboat_src/src/* ~/ChatBOAT/src/cd ~/ChatBOAT && source /opt/ros/humble/setup.bash && source install/setup.bashcolcon build --symlink-install --packages-select chatboat_description chatboat_stonefish chatboat_control chatboat_bringuppython3.10 -m pip install openai numpy casadi websocketsXvfb :99 -screen 0 1920x1080x24 &export DISPLAY=:99export VGL_DISPLAY=eglsource /opt/ros/humble/setup.bashsource ~/ChatBOAT/install/setup.bashvglrun -d egl ros2 launch chatboat_bringup bringup.launch.pyexport OPENROUTER_API_KEY=your-key-heresource /opt/ros/humble/setup.bashsource ~/ChatBOAT/install/setup.bashcd ~/ChatBOAT/srcpython3.10 -m llm2control.main --dashboard --port 8765On the pod:
x11vnc -display :99 -forever -nopw -bgwebsockify --web=/usr/share/novnc 6080 localhost:5900 &On your local machine, open a new terminal and create SSH tunnels:
ssh -L 6080:localhost:6080 -L 8765:localhost:8765 root@<POD_IP> -p <POD_PORT> -i ~/.ssh/id_ed25519Then open in your browser:
- Stonefish GUI: http://localhost:6080/vnc.html
- LLM Dashboard: http://localhost:8765
ros2 launch chatboat_bringup bringup.launch.py use_mpc:=true
# Send a goal:
ros2 topic pub --once /chatboat/mpc_bridge/goal geometry_msgs/PoseStamped \
'{header: {frame_id: "world"}, pose: {position: {x: 2.0, y: 0.0, z: 2.0}, orientation: {w: 1.0}}}'A dual-role Claude agent (via OpenRouter) translates natural language into MPC parameters:
- Task Planner — breaks a command into navigation subtasks
- Optimization Formulator — configures MPC weights, constraints, and targets for each subtask
- MPC Solver — CasADi/IPOPT solves a 10D damped double integrator with CBF obstacles
- ROS Bridge — publishes thruster commands at the control rate
- State (10D):
[x, y, z, φ, ψ, ẋ, ẏ, ż, φ̇, ψ̇]— position, roll, yaw, and their velocities - Control (5D):
[u_x, u_y, u_z, u_φ, u_ψ]— world-frame accelerations - Dynamics: damped double integrator with linear drag
- Horizon: N=15 steps, dt=0.1 s
- Roll stabilisation via cost function weight (
Q_roll)
| Topic | Type | Description |
|---|---|---|
/chatboat/odometry |
nav_msgs/Odometry |
Vehicle state (twist in body frame) |
/chatboat/thruster_commands |
std_msgs/Float64MultiArray |
8 thrusters, scaled setpoints |
/chatboat/joint_commands |
sensor_msgs/JointState |
4 arm joint positions |
/chatboat/joint_states |
sensor_msgs/JointState |
Arm encoder feedback |
/chatboat/mpc_bridge/goal |
geometry_msgs/PoseStamped |
Navigation target |
/chatboat/mpc_bridge/goal_reached |
std_msgs/Bool |
Goal completion status |
Latest Stonefish requires C++20. Install GCC 13: add-apt-repository -y ppa:ubuntu-toolchain-r/test && apt-get install -y gcc-13 g++-13, then pass -DCMAKE_C_COMPILER=gcc-13 -DCMAKE_CXX_COMPILER=g++-13 to cmake.
A stale StonefishConfig.cmake in /opt/stonefish/ shadows the real install at /usr/local/lib/cmake/Stonefish/. Fix: rm -f /opt/stonefish/StonefishConfig.cmake
You're using the wrong branch. Use master (not dev or v1.3).
ROS2 Humble incompatibility. Patch: sed -i 's/msg.header.stamp + rclcpp::Duration/rclcpp::Time(msg.header.stamp) + rclcpp::Duration/' src/stonefish_ros2/src/stonefish_ros2/ROS2Interface.cpp
Wrong Python version. Must use python3.10 explicitly — RunPod's default python is 3.11, which can't load ROS2 Humble's rclpy C extensions.
Check arm servo gains — values above 10 cause physics explosion on lightweight arm links. Use: position_gain=2.0, velocity_gain=3.0, max_torque=3.0.
RunPod's web terminal and SSH often break lines at whitespace. Always paste commands as short single lines. Export environment variables separately instead of inline.
- ROS2 Humble (Ubuntu 22.04)
- Stonefish (latest main) + stonefish_ros2 (
masterbranch) - GCC 13 (for C++20 support)
- VirtualGL 3.1.1
- llm2control: openai, numpy, casadi, websockets