Skip to content

Commit da44df5

Browse files
committed
Wave-Body: Linear potential wave-body model
This is squashed history of the linear potential wave-body model. 1. Linear potential wave-body model demo (#70) 1.1. Wave Body: Add linear potential wave-body model - Add model for an ellipsoid buoy - Add test model for hydrodynamics models. 1.2. Wave-Body: add plugin for testing linear wave-body interaction models - Initial version of plugin with hydrostatic restoring forces. 1.3. Wave-Body: update linear wave-body interaction model - Add contributions to moments from hydrostatic equilibrium term (centre of buoyancy). 1.4. Wave-Body: update linear wave-body interaction model - Update comments and disable debug output 1.5. Wave-Body: update models for testing linear wave-body interaction model - Set wave amplitudes to zero and compare the two hydrostatic models 1.6. Wave-Body: add hydro data file and load into plugin - Add BEM hydro data .hdf5 file for ellipsoid (generated by capytaine / bemio) - Add dependency on Eigen. HDF5 and HighFive to read data file (HighFive should be cloned into to workspace) 1.7. Wave-Body: use loaded hydro data in calculations - Store loaded hydro data in a struct and replace hardcoded data. 1.8. Wave-Body: use loaded hydro data in calculations - Clean up. 1.9. Wave-Body: load remaining hydro data - Complete loading of all hydro data (except for state space model data) - Load routines can be factored out and consolidated (2nd pass) 1.10. Wave-Body: split update into contributions by force type - Split out hydrostatic force calculation. 1.11. Wave-Body: add parameter for hydro data file - Add parameter <hydrodata> for specifying HDF5 file. - Move model specific config under model folder. 1.12. Wave-Body: document the hydrostatics calculation 1.13. Wave-Body: use waterplane origin as reference point for displacements 1.14. Wave-Body: add radiation damping test case - Update variable labelling for pose and vectors - Add radiation damping test case example (hardcoded) 1.15. Wave-Body: add parameters to control which forces are calculated - Add flags to control which force contributions are included - Format hdf5 file reader - Make hydrostatics forces switchable 1.16. Wave-Body: add force control parameters to ellipsoid example 1.17. Wave-Body: initial version of radiation added mass force - Reorganise code to enable switching forces on / off - Outline added mass calculation 1.18. Wave-Body: updated version of radiation added mass force - Investigate a couple of methods - both approaches to capture acceleration in the force contribution are unstable. - Alternative methods is to use the SetFluidAddedMass method of the inertial. - This can be set on the component attached to the link entity in the plugin config, and this appears to propagate to the physics engine. 1.19. Wave-Body: replace hardcoded added mass override with parameters - Allow the added mass and radiation damping to be set in parameters - Remove added mass calculation from update and set inertial in config - Add example parameters to demo world 1.20. Wave-Body: replace hardcoded radiation damping override with parameters - Allow the radiation damping to be set in parameters 1.21. Wave-Body: add gravity calculation - Add aliases for Vector6d and Matrix6d - Add gravity calculation to use instead of global physics engine gravity - Required when enabling added mass - Update added mass calculation to use gazebosim/gz-physics#384 1.22. Fluid added mass: update added mass example - Clean and symmetrise matrix 1.23. Fluid added mass: add code to symmetrise added mass (disabled) 1.24. Fluid added mass: add flags for additional debug info 1.25. Fluid added mass: cleanup 1.26. Wave Excitation: add parameters for constant coefficient overrides - Add parameters for storing wave excitation force coefficients - Add template specialisation to read Eigen::Vector6d - Add example data to sdf model - Remove stale code for added mass adjustments from class declaration 1.27. Wave Excitation: implement excitation force for regular waves - Add overrides for wave period, height and phase - Update documentation describing added mass calculation - Implement constant coefficient excitation calculation for regular waves - Update wave model to used trochoids with steepness = 0 (direction not implemented for sinusoids) - Rename elements for wave excitation force components 1.28. Wave Excitation: correct buoyancy moment calculation - Correct the buoyancy moment calculation for larger displacements. - Add missing parameter read for the flag to enable / disable the excitation force 1.29. Wave Excitation: implement excitation Froude-Krylov and scattering force components - Add example coefficients for excitation Froude-Krylove and scattering components. - Read parameters in Config. - Implement force calculations for new components. - Initialise vectors and matrices to zero. 1.30. Wave Excitation: rename variables using Kane/monogram notation - Rename pose, vectors using Kane/monogram notation described in the Drake docs. - Fix gravity calculation. - Factor out common link state updates. 1.31. Wave Body: update example model and add notes 1.32. Wave Body: add force publishers - Publish force and torque if enabled - Add parameters to enable force publishing - Update launch script to enable ROS bridge for forces 1.33. Wave Body: configure buoy example to use all forces - Set initial position to origin for linear potential model example - Update document with references 1.34. Wave Body: refactor flags and publishers - Group flags into structs to reduce clutter. - Move debug flags into their own SDF element. 1.35. Wave Body: refactor hydro coefficient overrides - Group coefficients into structs to reduce clutter. - Reorganise hydro coefficient elements in SDF. - Move waves and sim environment params into separate structs. - Add override for hydrostatic linear restoring. 1.36. Wave Body: add geometry overrides - Add section for geometry overrides. - Rename the initial pose the body waterplane. 1.37. Wave Body Tests: add wave models for test cases - Add regular wave models with different periods and amplitudes. 1.38. Wave Body: fix geometry overrides - Fix issue with parsing SDF and ensure SDF example valid. 1.39. Wave Body: use waves test model 1.40. Wave Body: revert waves.sdf to original - Move ellipsoid test to new world file. 1.41. Wave Body: add world for ellipsoid test case 1.42. Wave Body Tests: add spheroid test case - Add spheroid for added mass Test1a 1.42. Wave Body Tests: update spheroid test case - Add ROS launch file for tests. - Update BEM coeffs from WEC-Sim example 1.43. Wave Body: improve overrides - 1 - Rename hydro coefficient class. - Handle override for hydrostatic restoring. 1.44. Wave Body: improve overrides - 2 - Move HDF5 reader to separate function. 1.45. Wave Excitation: fix error in torque calculation - Fix indexing error in torque lookup. - Shorten spatial force names. 1.46. Wave Body Hydrostatics: update treatment of CoB offset from CoM - Use the initial offset of the CoB from CoM in updates - tricky as CoB is dynamic but linear model appears to rely on this being at initial position. 1.47 Wave Body: improve overrides - 3 - Refactor duplicated code in array read functions. 1.48. Wave Body: improve overrides - 4 - Refactor SDF element names. - Change <hydrodata> to <hdf5_file> as the element is a file name. - Move <waves> up a level. - Change <environment> to <simulation_parameters> - Shorten <force_publishers> to <publishers> 1.49. Wave Body: improve overrides - 5 - Add notes on model and WEC-Sim data structures and modelling. 1.50. Wave Body: improve overrides - 6 - Name refactoring - preparation for introducing new structs for data that will be used in updates. 1.51. Wave Body: improve overrides - 7 - Add improved handling of overrides. - Remove all override decision making from update loops. - Add separate data structure to contain the hydro force coefficients used in the update loop. - Document the load and override policy. 1.52. ROS: add a project to publish gazebo messages to ros2 1.53. ROS: add node to publish body response labelled using maritime conventions - Add body_response_publisher - Update launch file 1.54. ROS: update README 1.55. ROS: correct topic name for excitation force Signed-off-by: Rhys Mainwaring <rhys.mainwaring@me.com> 2. Wave Body: improve overrides - 8 (#71) - Remove hardcoded frequency index used to lookup hydro coeffs from hdf5 data. - Coefficients from hdf5 are linearly interpolated and scaled given the frequency in the simulation params. Signed-off-by: Rhys Mainwaring <rhys.mainwaring@me.com> 3. Wave Body: use model:// URI to specify BEM file location (#72) - Use model://<model_path_to_config> URI syntax to locate BEM data files. Signed-off-by: Rhys Mainwaring <rhys.mainwaring@me.com> 4. Wave Body: Update example regular wave models (#73) 4.1 Wave Body: rename regular wave example models to refer to wave height rather than amplitude - Use wave height in linear wave-body model SDF and in the names of the example regular wave models. 4.2 Wave Body: add extra regular wave models to cover spectrum - Add low and high frequency examples. 4.3. Wave Body: reset wave model used by examples - Set examples to use regular_waves_6s_2m model - this matches the override hydro coefficients. Signed-off-by: Rhys Mainwaring <rhys.mainwaring@me.com> 5. Wave Body: add checks when reading the hdf5 file (#74) 5.1. Wave Body: add checks when reading the hdf5 file - Check that datasets are present before loading. - Check that data is not empty before attempting to display. 5.2. Wave Body: update comments to clarify scaled means non-dimensioned Signed-off-by: Rhys Mainwaring <rhys.mainwaring@me.com> 6. Wave Body: add publisher for added mass force (#75) - Add publisher for estimated added mass force. Signed-off-by: Rhys Mainwaring <rhys.mainwaring@me.com> 7. Wave Body MBARI: add MBARI buoy example for testing (#76) - Add test model for the MBARI WEC buoy (float only) Signed-off-by: Rhys Mainwaring <rhys.mainwaring@me.com> 8. Wave Body MBARI: add collision mesh and change default BEM file (#77) 8.1. Wave Body MBARI: add collision mesh for buoy - Add simplified collision meshes for the buoy at different levels of refinement. - Use the mesh with 316 faces in the model. - Add BEM file generated using Capytaine and the 5548 face mesh. 8.2. Wave Body MBARI: change default the BEM data file - The excitation data in the hdf5 file generated from WAMIT data has the wrong sign, use Capytaine / bemio generated file in the meanwhile. - Simplify ramp function. Signed-off-by: Rhys Mainwaring <rhys.mainwaring@me.com> 9. Wave Body MBARI: fix ramp function missing bracket (#78) Signed-off-by: Rhys Mainwaring <rhys.mainwaring@me.com> 10. Wave Body: don't use auto with Eigen (#79) Signed-off-by: Rhys Mainwaring <rhys.mainwaring@me.com> 11. Wave Body: update cmake dependencies - Use FetchContent to retrieve dependency HighFive. - Fix typo in documentation. - Remove cpp style header for mlinterp 11.1 Wave Body: update ci workflow - Add build flag for HighFive dependency 11.2. Wave Body: update waves bridge tests - Remove breaking tests inherited from ROS project template. 11.3.Wave Body: post rebase fixes. 11.4. Wave-Body: fix config of regular_waves_3s_1m 11.5. Wave-Body: revert changes to regular_waves model Signed-off-by: Rhys Mainwaring <rhys.mainwaring@me.com>
1 parent 91fbece commit da44df5

File tree

71 files changed

+36388
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+36388
-2
lines changed

.github/scripts/macos_build.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ export CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}:/usr/local/opt/qt@5
1313
# Python scripts installed with: `pip3 install --user <package>`
1414
export PATH=$PATH:$HOME/Library/Python/3.11/bin
1515

16-
colcon build --symlink-install --merge-install --cmake-args -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=ON -DCMAKE_CXX_STANDARD=17 -DCMAKE_MACOSX_RPATH=FALSE -DCMAKE_INSTALL_NAME_DIR=$(pwd)/install/lib
16+
colcon build --symlink-install --merge-install --cmake-args -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=ON -DCMAKE_CXX_STANDARD=17 -DCMAKE_MACOSX_RPATH=FALSE -DCMAKE_INSTALL_NAME_DIR=$(pwd)/install/lib -DHIGHFIVE_USE_EIGEN=ON

.github/workflows/ubuntu-jammy-ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
3939
- name: Build Wave Sim
4040
run: |
41-
colcon build --symlink-install --merge-install --cmake-args -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_CXX_STANDARD=17 -DBUILD_TESTING=ON
41+
colcon build --symlink-install --merge-install --cmake-args -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_CXX_STANDARD=17 -DBUILD_TESTING=ON -DHIGHFIVE_USE_EIGEN=ON
4242
4343
- name: Test Wave Sim
4444
run: |

AddedMass.md

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# Gazebo / DART inertia conversion
2+
3+
An explanation of the Gazebo to DART inertial conversion and the different
4+
conventions used by each system. The conclusion is that there is a missing
5+
term when populating the DART spatial tensor with added mass because the
6+
moments of inertia are taken about different axis.
7+
8+
## Drake labelling conventions
9+
10+
- https://drake.mit.edu/doxygen_cxx/group__multibody__spatial__pose.html
11+
- https://drake.mit.edu/doxygen_cxx/group__multibody__spatial__inertia.html
12+
13+
### Frame labels
14+
15+
- `W` - world frame.
16+
- `B` - body frame.
17+
- `Bcm` - body CoM frame.
18+
19+
### Point labels
20+
21+
- `Bo` - body origin.
22+
- `Bcm` - body center of mass.
23+
24+
### Pose
25+
26+
- `X_WB` - the pose of the body frame `B` in the world frame `W`.
27+
- `X_BBcm` - the pose of the body CoM frame `Bcm` in the body frame `B`.
28+
29+
30+
### Inertia matrix
31+
32+
The inertia matrix, taken about a point `P`, expressed in frame `F`.
33+
34+
- `I_BBcm_Bcm` - inertia matrix of body `B` about the body center of mass `Bcm` in frame `Bcm`
35+
- `I_BBcm_B` - inertia matrix of body `B` about the body center of mass `Bcm` in frame `B`
36+
- `I_BBo_B` - inertia matrix of body `B` about the body origin `Bo` in frame `B`
37+
38+
### Position vectors
39+
40+
- `c_BoBcm_B` position vector from the body origin `Bo` to the body center of mass `Bcm` in the body frame `B`.
41+
42+
43+
## Gazebo inertial object
44+
45+
The SDF documentation http://sdformat.org/spec?ver=1.9&elem=link#inertial_inertia for the `<inertia>` element states:
46+
47+
48+
> Description: This link's moments of inertia ixx, iyy, izz and products of inertia ixy, ixz, iyz about Co
49+
> (the link's center of mass) for the unit vectors Ĉx, Ĉy, Ĉᴢ fixed in the center-of-mass-frame C.
50+
51+
This means that the object `gz::math::MassMatrix3` contains:
52+
53+
- `m` - the scalar mass.
54+
- `I_BBcm_Bcm` - inertia matrix of body `B` about the body center of mass `Bcm` in frame `Bcm`.
55+
56+
This is used to construct the object `gz::math::Inertial` which is the inertial taken about point `Bcm`
57+
for body `B` in frame `F`. Since the pose from SDFFormat is `X_BBcm`, the object stores internally:
58+
59+
- `m`
60+
- `I_BBcm_Bcm`
61+
- `X_BBcm`
62+
63+
The functions return the following:
64+
65+
- `MassMatrix -> (m, I_BBcm_Bcm)`
66+
- `Pose -> (X_BBcm)`
67+
- `Moi -> (I_BBcm_B = X_BBcm.R * I_BBcm_Bcm * X_BBcm.R^T)`
68+
69+
The key point to note is that when accessing the the moment of inertia it is transformed
70+
to the body frame `B` but is taken about a point located at the CoM `P = Bcm`.
71+
72+
## DART spatial tensor
73+
74+
The Gazebo function we are interested in is: `gz::physics::dartsim::SDFFeatures::ConstructSdfLink`
75+
where `gz::math::Inertial` is translated into `dart::dynamics::Inertia`.
76+
77+
### 1. First examine the case when there is no fluid added mass:
78+
79+
```c++
80+
const gz::math::Inertiald &sdfInertia = _sdfLink.Inertial();
81+
bodyProperties.mInertia.setMass(sdfInertia.MassMatrix().Mass());
82+
83+
const Eigen::Matrix3d I_link = math::eigen3::convert(sdfInertia.Moi());
84+
85+
bodyProperties.mInertia.setMoment(I_link);
86+
87+
const Eigen::Vector3d localCom =
88+
math::eigen3::convert(sdfInertia.Pose().Pos());
89+
90+
bodyProperties.mInertia.setLocalCOM(localCom);
91+
```
92+
93+
Break down what is going on:
94+
95+
- Set `m` - the scalar mass `m`.
96+
- Set `I_BBcm_B` - the moment of inertia of the body `B`, taken about the body CoM `Bcm` in frame `B`.
97+
- Set `c_BoBcm_B` - position vector from the body origin `Bo` to the body center of mass `Bcm` in the body frame `B`.
98+
99+
From these inputs DART, calculates the spatial tensor for rigid body rotations about the **body origin** `Bo`.
100+
101+
This is the spatial inertial tensor from Roy Featherstone, Rigid Body Dynamics Algorithms, §2.13, p33, Eq(2.63) Springer, 2008. Internally DART computes the spatial tensor to have the following elements:
102+
103+
- `TL = I_BBo_B = I_BBcm_B + m * cx * cx^T`
104+
- `TR = m * cx`
105+
- `BL = m * cx^T`
106+
- `BR = m * Identity(3)`
107+
108+
where `cx` is the skew-symmetric operator created from `c_BoBcm_B`.
109+
110+
Compare this to the definition for the Gazebo body matrix returned by: `gz::math::Inertial::BodyMatrix`:
111+
112+
- `BR = I_BBcm_B
113+
- `BL = m * cx`
114+
- `TR = m * cx^T`
115+
- `TL = m * Identity(3)`
116+
117+
which is for rigid body rotations about the **body center of mass** `Bm`.
118+
119+
Now in this case, the different convention for the axis of rotation does not matter because Gazebo does not use
120+
the `BodyMatrix` function to set the DART spatial inertial tensor, and the change of axis is calculated internally
121+
by DART. However this is not the case when added mass is considered.
122+
123+
### 2. With fluid added mass
124+
125+
In this case the DART spatial inertial tensor is first calculated as in case 1., then a spatial inertial tensor
126+
for the fluid added mass is calculated and the sum of the two is set using
127+
`dart::dynamics::Inertia::setSpatialTensor`:
128+
129+
```c++
130+
bodyProperties.mInertia.setSpatialTensor(
131+
bodyProperties.mInertia.getSpatialTensor() +
132+
math::eigen3::convert(featherstoneMatrix)
133+
```
134+
135+
So the important note here is that the featherstoneMatrix must be for rotations
136+
about the body orgin `Bo` and with respect to the body frame `B`.
137+
138+
139+
While not clearly documented in the Gazebo class, it is suggested by the function:
140+
141+
```c++
142+
/// \brief Spatial mass matrix, which includes the body's inertia, as well
143+
/// as the inertia of the fluid that is dislocated when the body moves.
144+
/// The matrix is expressed in the object's frame F, not to be confused
145+
/// with the center of mass frame Bi.
146+
/// \return The spatial mass matrix.
147+
/// \sa BodyMatrix
148+
/// \sa FluidAddedMass
149+
public: Matrix6<T> SpatialMatrix() const
150+
{
151+
return this->addedMass.has_value() ?
152+
this->BodyMatrix() + this->addedMass.value() : this->BodyMatrix();
153+
}
154+
```
155+
156+
that the Gazebo fluid added mass is expected to be computed in the body frame `B` for rotations about
157+
the body center of mass `Bcm` (because the quantities are being summed, and this is consistent with
158+
the other interfaces to this class that return moment of intertia etc.)
159+
160+
## Conclusion
161+
162+
The above suggests that there is a term missing in the current calculation of the featherstone matrix
163+
in `gz::physics::dartsim::SDFFeatures::ConstructSdfLink` to account for the change of axis
164+
from `Bcm` to `Bo`.
165+
166+
For fluid added mass the mass matrix is not diagonal with equal entries, so we can't calculate
167+
`m * cx * cx^T` as for the inertial term. My suggestion is to use:
168+
169+
```
170+
I_BBo_B = I_BBcm_B + cx * M * cx^T
171+
```
172+
173+
and deduce `CMCT = cx * M * cx^T` using:
174+
175+
```c++
176+
auto M = sdfInertia.FluidAddedMass().value().Submatrix(
177+
math::Matrix6d::TOP_LEFT);
178+
179+
auto CM = sdfInertia.FluidAddedMass().value().Submatrix(
180+
math::Matrix6d::BOTTOM_LEFT);
181+
182+
auto invM = M.Inverse();
183+
auto C = CM * invM;
184+
auto CMCT = CM * C.Transposed();
185+
```

0 commit comments

Comments
 (0)