20 #include <gazebo/common/Assert.hh> 21 #include <gazebo/common/Events.hh> 30 BuoyancyObject::BuoyancyObject()
33 pose(0, 0, 0, 0, 0, 0),
45 shape(std::move(obj.shape))
51 const sdf::ElementPtr elem)
54 if (elem->HasElement(
"link_name"))
56 this->
linkName = elem->GetElement(
"link_name")->Get<std::string>();
57 physics::LinkPtr link = model->GetLink(
linkName);
60 throw ParseException(
"link_name",
"invalid link name");
62 this->
linkId = link->GetId();
66 throw ParseException(
"link_name",
"missing element");
70 if (elem->HasElement(
"pose"))
72 this->
pose = elem->GetElement(
"pose")->Get<ignition::math::Pose3d>();
76 if (elem->HasElement(
"geometry"))
78 sdf::ElementPtr geometry = elem->GetElement(
"geometry");
81 this->
shape = std::move(ShapeVolume::makeShape(geometry));
90 throw ParseException(
"geometry",
"missing element");
97 ss <<
"Buoyancy object\n" 99 <<
"\tpose: " <<
pose <<
'\n' 100 <<
"\tgeometry " <<
shape->Display() <<
'\n' 101 <<
"\tmass " <<
mass;
119 GZ_ASSERT(_model !=
nullptr,
"Received NULL model pointer");
120 GZ_ASSERT(_sdf !=
nullptr,
"Received NULL SDF pointer");
123 this->
model = _model;
127 if (_sdf->HasElement(
"wave_model"))
133 if (_sdf->HasElement(
"fluid_density"))
135 this->
fluidDensity = _sdf->Get<
double>(
"fluid_density");
137 if (_sdf->HasElement(
"fluid_level"))
139 this->
fluidLevel = _sdf->Get<
double>(
"fluid_level");
141 if (_sdf->HasElement(
"linear_drag"))
143 this->
linearDrag = _sdf->Get<
double>(
"linear_drag");
145 if (_sdf->HasElement(
"angular_drag"))
147 this->
angularDrag = _sdf->Get<
double>(
"angular_drag");
150 if (_sdf->HasElement(
"buoyancy"))
152 gzmsg <<
"Found buoyancy element(s), looking at each element..." 154 for (sdf::ElementPtr buoyancyElem = _sdf->GetElement(
"buoyancy");
156 buoyancyElem = buoyancyElem->GetNextElement(
"buoyancy")) {
160 buoyObj.
Load(_model, buoyancyElem);
180 #if GAZEBO_MAJOR_VERSION >= 8 188 gzmsg << buoyObj.
Disp() << std::endl;
191 catch (
const std::exception& e)
193 gzwarn << e.what() << std::endl;
199 #if GAZEBO_MAJOR_VERSION >= 8 222 gzmsg <<
"usv_gazebo_dynamics_plugin: waveParams is null. " 223 <<
"Trying to get wave parameters from ocean model" << std::endl;
224 this->
waveParams = WavefieldModelPlugin::GetWaveParams(
228 #if GAZEBO_MAJOR_VERSION >= 8 229 double simTime = this->
world->SimTime().Double();
231 double simTime = this->
world->GetSimTime().Double();
235 this->lastSimTime = simTime;
238 for (
auto& link : this->
linkMap) {
239 auto linkPtr = link.second;
240 #if GAZEBO_MAJOR_VERSION >= 8 241 ignition::math::Pose3d linkFrame = linkPtr->WorldPose();
243 ignition::math::Pose3d linkFrame = linkPtr->GetWorldPose().Ign();
248 double waveHeight = WavefieldSampler::ComputeDepthSimply(
259 auto link = this->
linkMap[buoyancyObj.linkId];
260 #if GAZEBO_MAJOR_VERSION >= 8 261 ignition::math::Pose3d linkFrame = link->WorldPose();
263 ignition::math::Pose3d linkFrame = link->GetWorldPose().Ign();
265 linkFrame = linkFrame * buoyancyObj.pose;
267 auto submergedVolume = buoyancyObj.shape->CalculateVolume(linkFrame,
270 GZ_ASSERT(submergedVolume.volume >= 0,
271 "Non-positive volume found in volume properties!");
274 if (submergedVolume.volume > 1e-6)
280 * submergedVolume.volume *
model->GetWorld()->Gravity();
282 #if GAZEBO_MAJOR_VERSION >= 8 283 ignition::math::Vector3d linVel = link->WorldLinearVel();
284 ignition::math::Vector3d angVel = link->RelativeAngularVel();
286 ignition::math::Vector3d linVel= link->GetWorldLinearVel().Ign();
287 ignition::math::Vector3d angVel = link->GetRelativeAngularVel().Ign();
291 float partialMass = buoyancyObj.mass * submergedVolume.volume
292 / buoyancyObj.shape->volume;
296 ignition::math::Vector3d relVel =
297 ignition::math::Vector3d(0, 0, this->
linkHeightDots[link]) - linVel;
298 ignition::math::Vector3d dragForce =
linearDrag * partialMass * relVel;
299 buoyancy += dragForce;
300 if (buoyancy.Z() < 0.0)
305 link->AddForceAtWorldPosition(buoyancy, submergedVolume.centroid);
308 double averageLength2 = ::pow(buoyancyObj.shape->averageLength, 2);
309 ignition::math::Vector3d dragTorque = (-partialMass *
angularDrag 310 * averageLength2) * angVel;
311 link->AddRelativeTorque(dragTorque);
ignition::math::Pose3d pose
Pose of buoyancy relative to link.
double fluidLevel
The height of the fluid/air interface [m]. Defaults to 0.
int linkId
Associated link ID.
This plugin simulates buoyancy of an object in fluid. <wave_model>: Name of the wave model object (op...
void Load(const physics::ModelPtr model, const sdf::ElementPtr elem)
Load buoyancy object from SDF.
std::vector< buoyancy::BuoyancyObject > buoyancyObjects
List of buoyancy objects for model.
::buoyancy::ShapeVolumePtr shape
Buoyancy object's shape properties.
BuoyancyPlugin()
Constructor.
GZ_REGISTER_MODEL_PLUGIN(AcousticPinger)
std::map< gazebo::physics::LinkPtr, double > linkHeightDots
Map of water velocity at each link.
std::map< gazebo::physics::LinkPtr, double > linkHeights
Map of water height at each link from previous timestep.
std::string Disp()
Display string for buoyancy object.
virtual void OnUpdate()
Callback for World Update events.
std::shared_ptr< const asv::WaveParameters > waveParams
The wave parameters.
std::map< int, gazebo::physics::LinkPtr > linkMap
Map of <link ID, link pointer>
double lastSimTime
Previous update time.
double angularDrag
Angular drag coefficient. Defaults to 0.
BuoyancyObject()
Default constructor.
double mass
Object mass (from inertial elem)
virtual void Load(physics::ModelPtr _model, sdf::ElementPtr _sdf)
std::string linkName
Associated link name.
std::string waveModelName
The name of the wave model.
event::ConnectionPtr updateConnection
Connection to World Update events.
double fluidDensity
The density of the fluid in which the object is submerged in kg/m^3. Defaults to 1000, the fluid density of water at 15 Celsius.
double linearDrag
Linear drag coefficient. Defaults to 0.
physics::ModelPtr model
Pointer to base model.
A class for storing buoyancy object properties.
physics::WorldPtr world
Pointer to the Gazebo world Retrieved when the model is loaded.