Simulate surface waves and marine vehicle dynamics

This is a project to provide set of system plugins for simulating surface waves and the dynamics of marine surface craft. The original plugins were developed for legacy Gazebo and are being ported to Ignition. The target render system is Ogre2 and the plugins should work on both Ubuntu and macOS (using Metal).

The libraries are GPL because one of the core components used to implement the vehicle dynamics is CGAL and the ocean simulation uses FFTW to generate the surface waves. It would be possible to find alternatives for both components, but replacing CGAL would be a substantial undertaking.

The migration is being tracked here: Migrate to Ignition Gazebo · Issue #15 · srmainwaring/asv_wave_sim · GitHub and has progressed to the stage where there is an initial version that provides the main components that allow some of the example models that were used in Gazebo11 to be run on Ignition Garden.

There is a lot more to do, especially regarding optimisation, parameter setting and general usability. The details of the approach and references are described in the project README.


This is really great work! Excited to see it progress and eventually make use of the wave physics!!!

Hi Rhys,

Take a look at GitHub - osrf/mbzirc: Simulator for the MBZIRC Maritime Grand Challenge as well. We also implemented waves for this the MBZIRC project. We still haven’t upstreamed all the pieces. It’s a simplification over what you did for VRX.


Hi @caguero, thanks for the link. I’ll see if I can get the MBZIRC project up and running on macOS for comparison.

I have been looking at various approaches to improve the visuals:

  1. Use an HlmsLowLevel material and implement the ShaderParam plugin logic directly in the wave visual plugin (this appears to be the approach in MBZIRC)
  2. Use the ShaderParam visual plugin alongside another visual plugin attaching to a wave entity
  3. Define a PBS material within the existing system and attach to the visual (this is the method used in the example above)
  4. Create a new Hlms and datablock overloading HlmsPbs for a wave mesh
  5. Use a new Hlms and datablock overloading HlmsTerra using same vertex tricks in that implementation applied to waves (there is a example for ogre2.1 here: [2.1] Ocean - Ogre Forums with repo GitHub - yoyTeam/OgreOcean: Simple Ocean implementation using Ogre 2.1 and the Terra tutorial as base, with a nice baked animated texture, for more info see which uses a similar pixel shader to the one used in VRX with a pseudo wave generator in the vertex shader and additional bump map sampling with a fine grained mesh (4096x4096) to get detail.

Options 1 and 2 are quite similar and really only differ in that 2 factors out common code for defining custom shaders. At present multiple visual plugins are not supported which leaves option 1 as the approach using Ogre1 type materials and where the wave generation code is also in the shader.

In my case the vertex positions are calculated on the CPU, so I need a fast way to get these into the GPU. One way would be to use GPU code for the FFT wave generation as well as for sinusoidal and trochoidal waves. There is a OpenCL option for generating the waves, but it uses a read-back from the GPU into CPU vertices (for the physics and the visual), and then ships back to the GPU as an Ogre1 material for visuals. In principal that FFT shader code could be used in a render pass directly for the visuals, but I’m someway way away from understanding the Hlms and compositor systems well enough to implement that.

The other options 4, and 5 that use a custom Hlms could be seen as intermediate steps to using shader based wave generation. The Ogre2 examples for these are quite advanced and I’m slowly working through the methods to see how they can be adapted. Most of the wave generation code I use displaces the vertices in the xy-plane as well vertically, and I’m not yet sure whether the logic for cell tiling used in Terra can relax it’s assumptions about a fixed planar grid. With periodic boundary conditions it should tile correctly but that would all need to be worked through.

Hi Carlos,

I’ve managed to get the MBZIRC project built on macOS running Ignition Gazebo and ROS2 Galactic. With a little bit of tuning it’s working and it’s very useful to have a baseline.

As a side note: it would be nice to be able to control the thruster plugin for the USV using ArduPilot - this should be possible with some tweaks to the ardupilot_gazebo system plugin.


An example of the sea surface simulation applied to the GitHub - osrf/buoy_sim: Simulation of wave energy harvesting buoy project.

There is still optimisation required in the physics calculations in order to run complex models, such as the wave buoy, that have many links and collisions each contributing to buoyancy and hydrodynamics. For the visuals two approaches have been investigated. The first uses dynamic vertices - recalculating the vertices, normals and tangents then copying them to the GPU each frame. This is not fast and does not scale well for tiling as each geometry instance must update its vertex buffers. It does make it easy to use PBS materials however. This is the approach used in the clip. The second approach updates texture maps for the displacements and the surface derivatives. The textures are updated then staged for upload to the GPU each frame. This is done once per frame regardless of how many tiles are loaded (each share the same material). This is much better for large scenes but requires custom shaders that apply the displacements and compute the TBN matrix in the vertex shader. To use PBS materials with this approach requires a custom Hlms and adopting shader pieces to override the PBS vertex and fragment shaders where needed. This is work in progress. The second approach scales better, and is amenable to moving the wave model to the GPU as well.

To optimise the physics requires a fast-read back of the wave height given a surface state and collection of model mesh points. Also for future work.