Buoyancy: all up round mass and displacement
The all up round (AUR) properties of a vessel are those of the assembled vehicle as it goes in the water: hull, thrusters, accessories, batteries, ballast. Mass properties and displacement are treated differently, on purpose:
Property |
How it is obtained |
|---|---|
Mass, inertia, center of mass |
Derived. Composed from the parts; each part’s macro is the source for its own values. Mass is never declared at the assembly |
Displacement and center of buoyancy |
Declared at the assembly. A USV declares hull collision geometry; a UUV declares a net buoyant balance and a center of buoyancy offset |
Deriving mass keeps one source of truth per part: a config change (a battery, a sensor, an empty slot) propagates on its own and is visible in the generated model’s specs comment. Displacement cannot work that way: for a USV the displacing shape must be the hull and only the hull, so that fitting a bracket does not change the draft by whatever collision volume the bracket carries; for a UUV, flotation is a trim the operator sets with foam and lead, stated directly and held across configurations.
USV: hull displacement
hull_displacement in the config declares each pontoon as a row of box
segments (length, width, height, x, y, z, segments). The Gazebo
composition places them on a dedicated hull_displacement link, fixed to
base_link, and the worlds enable graded buoyancy on that link only
(<enable>blueboat::hull_displacement</enable>). Buoyancy is evaluated per
link, so the parts’ own collisions (the hull cylinders, hatch boxes, the
prop hubs) stay what they are, contact geometry, and never displace; the
chassis keeps them on. The pontoons in turn never collide
(collide_bitmask 0x00), so overlapping that geometry costs no
contacts. The URDF carries no displacement geometry at all: displacement
is a simulator concern. Segmenting matters:
each short box responds to its own local depth, so a pitched or rolled
waterplane restores correctly, where a single long box keys off its center
and barely restores. The boat self settles to a draft of roughly
mass / (water_density * 2 * length * width), which puts base_link at the
waterline for the BlueBoat.
A second link, windage, fixed to base_link the same way, carries one
box per hull spanning the whole pontoon and marked gz:wind="true". In a
world running gz-maritime’s wind system, the wind pushes on the part of each
box above the waterline, whatever the boat was spawned as. The boxes are not
the buoyancy segments, which would count each hull’s frontal area once per
segment in a head wind, and they are not on hull_displacement: the stock
buoyancy system floats every collision of the link it is enabled on, and a
box with the hull’s full volume there would double the displacement. They
neither collide nor carry gz:buoyancy, so they displace nothing in either
system.
UUV: declared trim (BlueROV2)
buoyancy: in the BlueROV2 config takes net_buoyancy (kg, positive floats
up; a displaced mass, not a fraction, so the trim does not scale silently
with heavier parts fitted), cob_offset and cob_frame (com: the offset is
the BG vector and sets righting stiffness directly; base_link: the center
of buoyancy is pinned in the hull like the real vehicle), and
fluid_density (must match the world’s buoyancy plugin; both default to
1025) and footprint (the box footprint; height is solved). The model
generation computes the assembled total mass and center of mass from the
URDF and solves an analytic box on a dedicated buoyancy_displacement
link, the only link the worlds enable buoyancy on, so both declarations
hold for the configured vehicle and the parts’ own collisions stay pure
contact geometry. The box itself never collides (collide_bitmask
0x00). The same pattern as the BlueBoat’s pontoons, with the box solved
instead of declared.
Marked for any world
The displacement collisions of both vehicles carry gz:buoyancy="true".
Gazebo’s buoyancy system gained a marked-collision mode
(gz-sim 229ec07e,
carried by gz-maritime’s
gz_buoyancy until a release ships it): a link with marked collisions
floats by those alone, under whatever name its model was spawned, in a
world that names no vehicle. The stock system ignores the attribute, so
the worlds here keep their <enable> lists and behave exactly as before;
on gz-maritime’s open water the same generated model floats with no world
edit.
Constraints
URDF cannot express
<fluid_added_mass>; added mass stays out of the description (the Gazebo hydrodynamics plugin is where it would go).Graded buoyancy accepts only box and sphere collisions; both vehicles therefore realize displacement as boxes on a dedicated enabled link, separate from the parts’ contact geometry. Displacement has to be expressed as collisions, so the boxes carry a zero
collide_bitmaskto keep them out of contact.Sensors need their own links for TF frames, which the parts’ frames provide.