HydrodynamicModel.cc
Go to the documentation of this file.
1 // Copyright (c) 2016 The UUV Simulator Authors.
2 // All rights reserved.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include <gazebo/gazebo.hh>
18 
19 namespace gazebo
20 {
23  physics::LinkPtr _link) : BuoyantObject(_link)
24 {
25  GZ_ASSERT(_link != NULL, "Invalid link pointer");
26 
27  // Initialize filtered acceleration & last velocity
28  this->filteredAcc.setZero();
29  this->lastVelRel.setZero();
30 
31  // Set volume
32  if (_sdf->HasElement("volume"))
33  this->volume = _sdf->Get<double>("volume");
34 
35 
36  // Reading the information for the metacentric width and length in the case
37  // that the model is a surface vessel or floating object
38  if (_sdf->HasElement("metacentric_width") &&
39  _sdf->HasElement("metacentric_length") &&
40  _sdf->HasElement("submerged_height"))
41  {
42  this->metacentricWidth = _sdf->Get<double>("metacentric_width");
43  this->metacentricLength = _sdf->Get<double>("metacentric_length");
44  this->submergedHeight = _sdf->Get<double>("submerged_height");
45  this->isSurfaceVessel = true;
46 
47  gzmsg << "Surface vessel parameters" << std::endl;
48  gzmsg << "\tMetacentric width [m]=" << this->metacentricWidth << std::endl;
49  gzmsg << "\tMetacentric length [m]=" << this->metacentricLength << std::endl;
50  gzmsg << "\tSubmerged height [m]=" << this->submergedHeight << std::endl;
51  }
52  else
53  {
54  this->metacentricWidth = 0.0;
55  this->metacentricLength = 0.0;
56  this->waterLevelPlaneArea = 0.0;
57  this->isSurfaceVessel = false;
58  }
59 
60  // Get the center of buoyancy
61  std::vector<double> cob = {0, 0, 0};
62  if (_sdf->HasElement("center_of_buoyancy"))
63  {
64  cob = Str2Vector(_sdf->Get<std::string>("center_of_buoyancy"));
65  this->SetCoB(ignition::math::Vector3d(cob[0], cob[1], cob[2]));
66  }
67  // FIXME(mam0box) This is a work around the problem of the invalid bounding
68  // box returned by Gazebo
69  if (_sdf->HasElement("box"))
70  {
71  sdf::ElementPtr sdfModel = _sdf->GetElement("box");
72  if (sdfModel->HasElement("width") && sdfModel->HasElement("length") &&
73  sdfModel->HasElement("height"))
74  {
75  double width = sdfModel->Get<double>("width");
76  double length = sdfModel->Get<double>("length");
77  double height = sdfModel->Get<double>("height");
78  ignition::math::Box boundingBox = ignition::math::Box(
79  ignition::math::Vector3d(-width / 2, -length / 2, -height / 2),
80  ignition::math::Vector3d(width / 2, length / 2, height / 2));
81  // Setting the the bounding box from the given dimensions
82  this->SetBoundingBox(boundingBox);
83  }
84  }
85 
86  // If neutrally buoyant is given, then calculate restoring
87  // force to cancel out the gravitational force
88  if (_sdf->HasElement("neutrally_buoyant"))
89  {
90  if (_sdf->Get<bool>("neutrally_buoyant"))
91  this->SetNeutrallyBuoyant();
92  }
93 
94  // Initialize Reynolds number with zero (will not always be used)
95  this->Re = 0;
96 
97  // Initialize temperature (not used by all models)
98  this->temperature = 0;
99 }
100 
103  double _alpha)
104 {
105  // Compute Fossen's nu-dot numerically. We have to do this for now since
106  // Gazebo reports angular accelerations that are off by orders of magnitude.
107  double dt = _time - lastTime;
108 
109  if (dt <= 0.0) // Extra caution to prevent division by zero
110  return;
111 
112  Eigen::Vector6d acc = (_velRel - this->lastVelRel) / dt;
113 
114  // TODO We only have access to the acceleration of the previous simulation
115  // step. The added mass will induce a strong force/torque counteracting
116  // it in the current simulation step. This can lead to an oscillating
117  // system.
118  // The most accurate solution would probably be to first compute the
119  // latest acceleration without added mass and then use this to compute
120  // added mass effects. This is not how gazebo works, though.
121  this->filteredAcc = (1.0 - _alpha) * this->filteredAcc + _alpha * acc;
122 
123  lastTime = _time;
124  this->lastVelRel = _velRel;
125 }
126 
128 ignition::math::Vector3d HydrodynamicModel::ToNED(ignition::math::Vector3d _vec)
129 {
130  ignition::math::Vector3d output = _vec;
131  output.Y() = -1 * output.Y();
132  output.Z() = -1 * output.Z();
133  return output;
134 }
135 
137 ignition::math::Vector3d HydrodynamicModel::FromNED(ignition::math::Vector3d _vec)
138 {
139  return this->ToNED(_vec);
140 }
141 
143 bool HydrodynamicModel::CheckParams(sdf::ElementPtr _sdf)
144 {
145  if (this->params.empty()) return true;
146 
147  for (auto tag : this->params)
148  {
149  if (!_sdf->HasElement(tag))
150  {
151  gzerr << "Hydrodynamic model: Expected element " <<
152  tag << std::endl;
153  return false;
154  }
155  }
156 
157  return true;
158 }
159 
162  sdf::ElementPtr _sdf, physics::LinkPtr _link)
163 {
164  GZ_ASSERT(_sdf->HasElement("hydrodynamic_model"),
165  "Hydrodynamic model is missing");
166  sdf::ElementPtr sdfModel = _sdf->GetElement("hydrodynamic_model");
167  if (!sdfModel->HasElement("type"))
168  {
169  std::cerr << "Model has no type" << std::endl;
170  return NULL;
171  }
172 
173  std::string identifier = sdfModel->Get<std::string>("type");
174 
175  if (creators_.find(identifier) == creators_.end())
176  {
177  std::cerr << "Cannot create HydrodynamicModel with unknown identifier: "
178  << identifier << std::endl;
179  return NULL;
180  }
181 
182  return creators_[identifier](_sdf, _link);
183 }
184 
187 {
188  static HydrodynamicModelFactory instance;
189  return instance;
190 }
191 
193 bool HydrodynamicModelFactory::RegisterCreator(const std::string& _identifier,
194  HydrodynamicModelCreator _creator)
195 {
196  if (creators_.find(_identifier) != creators_.end())
197  {
198  std::cerr << "Warning: Registering HydrodynamicModel with identifier: "
199  << _identifier << " twice" << std::endl;
200  }
201  creators_[_identifier] = _creator;
202 
203  std::cout << "Registered HydrodynamicModel type " << _identifier << std::endl;
204  return true;
205 }
206 
208 // Fossen's robot-like equations of motion for underwater vehicles
210 
211 const std::string HMFossen::IDENTIFIER = "fossen";
214 
216 HydrodynamicModel* HMFossen::create(sdf::ElementPtr _sdf,
217  physics::LinkPtr _link)
218 {
219  return new HMFossen(_sdf, _link);
220 }
221 
223 HMFossen::HMFossen(sdf::ElementPtr _sdf,
224  physics::LinkPtr _link)
225  : HydrodynamicModel(_sdf, _link)
226 {
227  std::vector<double> addedMass(36, 0.0);
228  std::vector<double> linDampCoef(6, 0.0);
229  std::vector<double> linDampForward(6, 0.0);
230  std::vector<double> quadDampCoef(6, 0.0);
231 
232  GZ_ASSERT(_sdf->HasElement("hydrodynamic_model"),
233  "Hydrodynamic model is missing");
234 
235  sdf::ElementPtr modelParams = _sdf->GetElement("hydrodynamic_model");
236  // Load added-mass coefficients, if provided. Otherwise, the added-mass
237  // matrix is set to zero
238  if (modelParams->HasElement("added_mass"))
239  addedMass = Str2Vector(modelParams->Get<std::string>("added_mass"));
240  else
241  gzmsg << "HMFossen: Using added mass NULL" << std::endl;
242 
243  this->params.push_back("added_mass");
244 
245  // Load linear damping coefficients, if provided. Otherwise, the linear
246  // damping matrix is set to zero
247  if (modelParams->HasElement("linear_damping"))
248  linDampCoef = Str2Vector(modelParams->Get<std::string>("linear_damping"));
249  else
250  gzmsg << "HMFossen: Using linear damping NULL" << std::endl;
251 
252  // Add added mass' scaling factor to the parameter list
253  this->params.push_back("scaling_added_mass");
254  // Set default value for the added mass's scaling vector
255  this->scalingAddedMass = 1.0;
256  // Add added mass' scaling factor to the parameter list
257  this->params.push_back("offset_added_mass");
258  // Set default value for the added mass identity offset
259  this->offsetAddedMass = 0.0;
260 
261  // Add linear damping to the parameter list
262  this->params.push_back("linear_damping");
263 
264  // Load linear damping coefficients that described the damping forces
265  // proportional to the forward speed only, if provided. Otherwise, the linear
266  // damping matrix is set to zero
267  if (modelParams->HasElement("linear_damping_forward_speed"))
268  linDampForward = Str2Vector(
269  modelParams->Get<std::string>("linear_damping_forward_speed"));
270  else
271  gzmsg << "HMFossen: Using linear damping for forward speed NULL"
272  << std::endl;
273  // Add the matrix for linear damping proportional to forward speed to the
274  // parameter list
275  this->params.push_back("linear_damping_forward_speed");
276 
277  // Load nonlinear quadratic damping coefficients, if provided. Otherwise,
278  // the nonlinear quadratic damping matrix is set to zero
279  if (modelParams->HasElement("quadratic_damping"))
280  quadDampCoef = Str2Vector(
281  modelParams->Get<std::string>("quadratic_damping"));
282  else
283  gzmsg << "HMFossen: Using quad damping NULL" << std::endl;
284 
285  // Add quadratic damping coefficients to the parameter list
286  this->params.push_back("quadratic_damping");
287  // Add damping's scaling factor to the parameter list
288  this->params.push_back("scaling_damping");
289  // Setting the damping scaling default value
290  this->scalingDamping = 1.0;
291 
292  // Add the offset for the linear damping coefficients to the parameter list
293  this->params.push_back("offset_linear_damping");
294  // Set the offset of the linear damping coefficients to default value
295  this->offsetLinearDamping = 0.0;
296 
297  // Add the offset for the linear damping coefficients to the parameter list
298  this->params.push_back("offset_lin_forward_speed_damping");
299  // Set the offset of the linear damping coefficients to default value
300  this->offsetLinForwardSpeedDamping = 0.0;
301 
302  // Add the offset for the linear damping coefficients to the parameter list
303  this->params.push_back("offset_nonlin_damping");
304  // Set the offset of the linear damping coefficients to default value
305  this->offsetNonLinDamping = 0.0;
306 
307  // Adding the volume to the parameter list
308  this->params.push_back("volume");
309  // Add volume's scaling factor to the parameter list
310  this->params.push_back("scaling_volume");
311 
312  GZ_ASSERT(addedMass.size() == 36,
313  "Added-mass coefficients vector must have 36 elements");
314  GZ_ASSERT(linDampCoef.size() == 6 || linDampCoef.size() == 36,
315  "Linear damping coefficients vector must have 6 elements for a "
316  "diagonal matrix or 36 elements for a full matrix");
317  GZ_ASSERT(linDampForward.size() == 6 || linDampForward.size() == 36,
318  "Linear damping coefficients proportional to the forward speed "
319  "vector must have 6 elements for a diagonal matrix or 36 elements"
320  " for a full matrix");
321  GZ_ASSERT(quadDampCoef.size() == 6 || quadDampCoef.size() == 36,
322  "Quadratic damping coefficients vector must have 6 elements for a "
323  "diagonal matrix or 36 elements for a full matrix");
324 
325  this->DLin.setZero();
326  this->DNonLin.setZero();
327  this->DLinForwardSpeed.setZero();
328 
329  for (int row = 0; row < 6; row++)
330  for (int col = 0; col < 6; col++)
331  {
332  // Set added-mass coefficient
333  this->Ma(row, col) = addedMass[6*row+col];
334  // Set the linear damping matrix if a full matrix was provided
335  if (linDampCoef.size() == 36)
336  this->DLin(row, col) = linDampCoef[6*row+col];
337  if (quadDampCoef.size() == 36)
338  this->DNonLin(row, col) = quadDampCoef[6*row+col];
339  if (linDampForward.size() == 36)
340  this->DLinForwardSpeed(row, col) = linDampForward[6*row+col];
341  }
342 
343  // In the case the linear damping matrix was set as a diagonal matrix
344  for (int i = 0; i < 6; i++)
345  {
346  if (linDampCoef.size() == 6)
347  this->DLin(i, i) = linDampCoef[i];
348  if (quadDampCoef.size() == 6)
349  this->DNonLin(i, i) = quadDampCoef[i];
350  if (linDampForward.size() == 6)
351  this->DLinForwardSpeed(i, i) = linDampForward[i];
352  }
353 
354  // Store damping coefficients
355  this->linearDampCoef = linDampCoef;
356  this->quadDampCoef = quadDampCoef;
357 }
358 
361  double _time, const ignition::math::Vector3d &_flowVelWorld)
362 {
363  // Link's pose
364  ignition::math::Pose3d pose;
365  ignition::math::Vector3d linVel, angVel;
366 
367 #if GAZEBO_MAJOR_VERSION >= 8
368  pose = this->link->WorldPose();
369  linVel = this->link->RelativeLinearVel();
370  angVel = this->link->RelativeAngularVel();
371 #else
372  pose = this->link->GetWorldPose().Ign();
373 
374  gazebo::math::Vector3 linVelG, angVelG;
375  linVelG = this->link->GetRelativeLinearVel();
376  angVelG = this->link->GetRelativeAngularVel();
377  linVel = ignition::math::Vector3d(
378  linVelG.x, linVelG.y, linVelG.z);
379  angVel = ignition::math::Vector3d(
380  angVelG.x, angVelG.y, angVelG.z);
381 #endif
382 
383  // Transform the flow velocity to the BODY frame
384  ignition::math::Vector3d flowVel = pose.Rot().RotateVectorReverse(
385  _flowVelWorld);
386 
387  Eigen::Vector6d velRel, acc;
388  // Compute the relative velocity
389  velRel = EigenStack(
390  this->ToNED(linVel - flowVel),
391  this->ToNED(angVel));
392 
393  // Update added Coriolis matrix
394  this->ComputeAddedCoriolisMatrix(velRel, this->Ma, this->Ca);
395 
396  // Update damping matrix
397  this->ComputeDampingMatrix(velRel, this->D);
398 
399  // Filter acceleration (see issue explanation above)
400  this->ComputeAcc(velRel, _time, 0.3);
401 
402  // We can now compute the additional forces/torques due to thisdynamic
403  // effects based on Eq. 8.136 on p.222 of Fossen: Handbook of Marine Craft ...
404 
405  // Damping forces and torques
406  Eigen::Vector6d damping = -this->D * velRel;
407 
408  // Added-mass forces and torques
409  Eigen::Vector6d added = -this->GetAddedMass() * this->filteredAcc;
410 
411  // Added Coriolis term
412  Eigen::Vector6d cor = -this->Ca * velRel;
413 
414  // All additional (compared to standard rigid body) Fossen terms combined.
415  Eigen::Vector6d tau = damping + added + cor;
416 
417  GZ_ASSERT(!std::isnan(tau.norm()), "Hydrodynamic forces vector is nan");
418 
419  if (!std::isnan(tau.norm()))
420  {
421  // Convert the forces and moments back to Gazebo's reference frame
422  ignition::math::Vector3d hydForce =
423  this->FromNED(Vec3dToGazebo(tau.head<3>()));
424  ignition::math::Vector3d hydTorque =
425  this->FromNED(Vec3dToGazebo(tau.tail<3>()));
426 
427  // Forces and torques are also wrt link frame
428  this->link->AddRelativeForce(hydForce);
429  this->link->AddRelativeTorque(hydTorque);
430  }
431 
432  this->ApplyBuoyancyForce();
433 
434  if ( this->debugFlag )
435  {
436  // Store intermediate results for debugging purposes
437  this->StoreVector(UUV_DAMPING_FORCE, Vec3dToGazebo(damping.head<3>()));
438  this->StoreVector(UUV_DAMPING_TORQUE, Vec3dToGazebo(damping.tail<3>()));
439 
440  this->StoreVector(UUV_ADDED_MASS_FORCE, Vec3dToGazebo(added.head<3>()));
441  this->StoreVector(UUV_ADDED_MASS_TORQUE, Vec3dToGazebo(added.tail<3>()));
442 
443  this->StoreVector(UUV_ADDED_CORIOLIS_FORCE, Vec3dToGazebo(cor.head<3>()));
444  this->StoreVector(UUV_ADDED_CORIOLIS_TORQUE, Vec3dToGazebo(cor.tail<3>()));
445  }
446 }
447 
450  const Eigen::Matrix6d& _Ma,
451  Eigen::Matrix6d &_Ca) const
452 {
453  // This corresponds to eq. 6.43 on p. 120 in
454  // Fossen, Thor, "Handbook of Marine Craft and Hydrodynamics and Motion
455  // Control", 2011
456  Eigen::Vector6d ab = this->GetAddedMass() * _vel;
457  Eigen::Matrix3d Sa = -1 * CrossProductOperator(ab.head<3>());
458  _Ca << Eigen::Matrix3d::Zero(), Sa,
459  Sa, -1 * CrossProductOperator(ab.tail<3>());
460 }
461 
464  Eigen::Matrix6d &_D) const
465 {
466  // From Antonelli 2014: the viscosity of the fluid causes
467  // the presence of dissipative drag and lift forces on the
468  // body. A common simplification is to consider only linear
469  // and quadratic damping terms and group these terms in a
470  // matrix Drb
471 
472  _D.setZero();
473 
474  _D = -1 *
475  (this->DLin + this->offsetLinearDamping * Eigen::Matrix6d::Identity()) -
476  _vel[0] * (this->DLinForwardSpeed +
477  this->offsetLinForwardSpeedDamping * Eigen::Matrix6d::Identity());
478 
479  // Nonlinear damping matrix is considered as a diagonal matrix
480  for (int i = 0; i < 6; i++)
481  {
482  _D(i, i) += -1 *
483  (this->DNonLin(i, i) + this->offsetNonLinDamping) *
484  std::fabs(_vel[i]);
485  }
486  _D *= this->scalingDamping;
487 }
488 
491 {
492  return this->scalingAddedMass *
493  (this->Ma + this->offsetAddedMass * Eigen::Matrix6d::Identity());
494 }
495 
497 bool HMFossen::GetParam(std::string _tag, std::vector<double>& _output)
498 {
499  _output = std::vector<double>();
500  if (!_tag.compare("added_mass"))
501  {
502  for (int i = 0; i < 6; i++)
503  for (int j = 0; j < 6; j++)
504  _output.push_back(this->Ma(i, j));
505  }
506  else if (!_tag.compare("linear_damping"))
507  {
508  for (int i = 0; i < 6; i++)
509  for (int j = 0; j < 6; j++)
510  _output.push_back(this->DLin(i, j));
511  }
512  else if (!_tag.compare("linear_damping_forward_speed"))
513  {
514  for (int i = 0; i < 6; i++)
515  for (int j = 0; j < 6; j++)
516  _output.push_back(this->DLinForwardSpeed(i, j));
517  }
518  else if (!_tag.compare("quadratic_damping"))
519  {
520  for (int i = 0; i < 6; i++)
521  for (int j = 0; j < 6; j++)
522  _output.push_back(this->DNonLin(i, j));
523  }
524  else if (!_tag.compare("center_of_buoyancy"))
525  {
526  _output.push_back(this->centerOfBuoyancy.X());
527  _output.push_back(this->centerOfBuoyancy.Y());
528  _output.push_back(this->centerOfBuoyancy.Z());
529  }
530  else
531  return false;
532  gzmsg << "HydrodynamicModel::GetParam <" << _tag << ">=" << std::endl;
533  for (auto elem : _output)
534  std::cout << elem << " ";
535  std::cout << std::endl;
536  return true;
537 }
538 
540 bool HMFossen::GetParam(std::string _tag, double& _output)
541 {
542  _output = -1.0;
543  if (!_tag.compare("volume"))
544  _output = this->volume;
545  else if (!_tag.compare("scaling_volume"))
546  _output = this->scalingVolume;
547  else if (!_tag.compare("scaling_added_mass"))
548  _output = this->scalingAddedMass;
549  else if (!_tag.compare("scaling_damping"))
550  _output = this->scalingDamping;
551  else if (!_tag.compare("fluid_density"))
552  _output = this->fluidDensity;
553  else if (!_tag.compare("bbox_height"))
554  _output = this->boundingBox.ZLength();
555  else if (!_tag.compare("bbox_width"))
556  _output = this->boundingBox.YLength();
557  else if (!_tag.compare("bbox_length"))
558  _output = this->boundingBox.XLength();
559  else if (!_tag.compare("offset_volume"))
560  _output = this->offsetVolume;
561  else if (!_tag.compare("offset_added_mass"))
562  _output = this->offsetAddedMass;
563  else if (!_tag.compare("offset_linear_damping"))
564  _output = this->offsetLinearDamping;
565  else if (!_tag.compare("offset_lin_forward_speed_damping"))
566  _output = this->offsetLinForwardSpeedDamping;
567  else if (!_tag.compare("offset_nonlin_damping"))
568  _output = this->offsetNonLinDamping;
569  else
570  {
571  _output = -1.0;
572  return false;
573  }
574 
575  gzmsg << "HydrodynamicModel::GetParam <" << _tag << ">=" << _output <<
576  std::endl;
577  return true;
578 }
579 
581 bool HMFossen::SetParam(std::string _tag, double _input)
582 {
583  if (!_tag.compare("scaling_volume"))
584  {
585  if (_input < 0)
586  return false;
587  this->scalingVolume = _input;
588  }
589  else if (!_tag.compare("scaling_added_mass"))
590  {
591  if (_input < 0)
592  return false;
593  this->scalingAddedMass = _input;
594  }
595  else if (!_tag.compare("scaling_damping"))
596  {
597  if (_input < 0)
598  return false;
599  this->scalingDamping = _input;
600  }
601  else if (!_tag.compare("fluid_density"))
602  {
603  if (_input < 0)
604  return false;
605  this->fluidDensity = _input;
606  }
607  else if (!_tag.compare("offset_volume"))
608  this->offsetVolume = _input;
609  else if (!_tag.compare("offset_added_mass"))
610  this->offsetAddedMass = _input;
611  else if (!_tag.compare("offset_linear_damping"))
612  this->offsetLinearDamping = _input;
613  else if (!_tag.compare("offset_lin_forward_speed_damping"))
614  this->offsetLinForwardSpeedDamping = _input;
615  else if (!_tag.compare("offset_nonlin_damping"))
616  this->offsetNonLinDamping = _input;
617  else
618  return false;
619  gzmsg << "HydrodynamicModel::SetParam <" << _tag << ">=" << _input <<
620  std::endl;
621  return true;
622 }
623 
625 void HMFossen::Print(std::string _paramName, std::string _message)
626 {
627  if (!_paramName.compare("all"))
628  {
629  for (auto tag : this->params)
630  this->Print(tag);
631  return;
632  }
633  if (!_message.empty())
634  std::cout << _message << std::endl;
635  else
636  std::cout << this->link->GetModel()->GetName() << "::"
637  << this->link->GetName() << "::" << _paramName
638  << std::endl;
639  if (!_paramName.compare("added_mass"))
640  {
641  for (int i = 0; i < 6; i++)
642  {
643  for (int j = 0; j < 6; j++)
644  std::cout << std::setw(12) << this->Ma(i, j);
645  std::cout << std::endl;
646  }
647  }
648  else if (!_paramName.compare("linear_damping"))
649  {
650  for (int i = 0; i < 6; i++)
651  {
652  for (int j = 0; j < 6; j++)
653  std::cout << std::setw(12) << this->DLin(i, j);
654  std::cout << std::endl;
655  }
656  }
657  else if (!_paramName.compare("linear_damping_forward_speed"))
658  {
659  for (int i = 0; i < 6; i++)
660  {
661  for (int j = 0; j < 6; j++)
662  std::cout << std::setw(12) << this->DLinForwardSpeed(i, j);
663  std::cout << std::endl;
664  }
665  }
666  else if (!_paramName.compare("quadratic_damping"))
667  {
668  for (int i = 0; i < 6; i++)
669  {
670  for (int j = 0; j < 6; j++)
671  std::cout << std::setw(12) << this->DNonLin(i, j);
672  std::cout << std::endl;
673  }
674  }
675  else if (!_paramName.compare("volume"))
676  {
677  std::cout << std::setw(12) << this->volume << " m^3" << std::endl;
678  }
679 }
680 
682 // Hydrodynamic model for a sphere
684 
685 const std::string HMSphere::IDENTIFIER = "sphere";
688 
690 HydrodynamicModel* HMSphere::create(sdf::ElementPtr _sdf,
691  physics::LinkPtr _link)
692 {
693  return new HMSphere(_sdf, _link);
694 }
695 
697 HMSphere::HMSphere(sdf::ElementPtr _sdf,
698  physics::LinkPtr _link)
699  : HMFossen(_sdf, _link)
700 {
701  GZ_ASSERT(_sdf->HasElement("hydrodynamic_model"),
702  "Hydrodynamic model is missing");
703 
704  sdf::ElementPtr modelParams = _sdf->GetElement("hydrodynamic_model");
705 
706  if (modelParams->HasElement("radius"))
707  this->radius = modelParams->Get<double>("radius");
708  else
709  {
710  gzmsg << "HMSphere: Using the smallest length of bounding box as radius"
711  << std::endl;
712  this->radius = std::min(this->boundingBox.XLength(),
713  std::min(this->boundingBox.YLength(),
714  this->boundingBox.ZLength()));
715  }
716  gzmsg << "HMSphere::radius=" << this->radius << std::endl;
717  gzmsg << "HMSphere: Computing added mass" << std::endl;
718 
719  this->params.push_back("radius");
720  // Reynolds number for subcritical flow
721  // Reference:
722  // - MIT Marine Hydrodynamic (Lecture Notes)
723  // TODO Consider also critical flow
724  this->Re = 3e5;
725 
726  // Drag coefficient for a sphere in subcritical flow
727  // Reference:
728  // - MIT Marine Hydrodynamic (Lecture Notes)
729  this->Cd = 0.5;
730 
731  // Area of the cross section
732  this->areaSection = PI * std::pow(this->radius, 2.0);
733 
734  // See derivation in MIT's Marine Hydrodynamics lecture notes
735  // The sphere has the same projected area for X, Y and Z
736 
737  // TODO Interpolate temperatures in look-up table
738  double sphereMa = -2.0 / 3.0 * this->fluidDensity * PI * \
739  std::pow(this->radius, 3.0);
740  // At the moment, only pressure drag is calculated, no skin friction drag
741  double Dq = -0.5 * this->fluidDensity * this->Cd * this->areaSection;
742 
743  for (int i = 0; i < 3; i++)
744  {
745  // Setting the added mass
746  this->Ma(i, i) = -sphereMa;
747  // Setting the pressure drag
748  this->DNonLin(i, i) = Dq;
749  }
750 }
751 
753 void HMSphere::Print(std::string _paramName, std::string _message)
754 {
755  if (!_paramName.compare("all"))
756  {
757  for (auto tag : this->params)
758  this->Print(tag);
759  return;
760  }
761  if (!_message.empty())
762  std::cout << _message << std::endl;
763  else
764  std::cout << this->link->GetModel()->GetName() << "::"
765  << this->link->GetName() << "::" << _paramName
766  << std::endl;
767  if (!_paramName.compare("radius"))
768  std::cout << std::setw(12) << this->radius << std::endl;
769  else
770  HMFossen::Print(_paramName, _message);
771 }
772 
774 // Hydrodynamic model for a cylinder
776 
777 const std::string HMCylinder::IDENTIFIER = "cylinder";
780 
782 HydrodynamicModel* HMCylinder::create(sdf::ElementPtr _sdf,
783  physics::LinkPtr _link)
784 {
785  return new HMCylinder(_sdf, _link);
786 }
787 
789 HMCylinder::HMCylinder(sdf::ElementPtr _sdf,
790  physics::LinkPtr _link)
791  : HMFossen(_sdf, _link)
792 {
793  GZ_ASSERT(_sdf->HasElement("hydrodynamic_model"),
794  "Hydrodynamic model is missing");
795 
796  sdf::ElementPtr modelParams = _sdf->GetElement("hydrodynamic_model");
797 
798  if (modelParams->HasElement("radius"))
799  this->radius = modelParams->Get<double>("radius");
800  else
801  {
802  gzmsg << "HMCylinder: Using the smallest length of bounding box as radius"
803  << std::endl;
804  this->radius = std::min(this->boundingBox.XLength(),
805  std::min(this->boundingBox.YLength(),
806  this->boundingBox.ZLength()));
807  }
808  gzmsg << "HMCylinder::radius=" << this->radius << std::endl;
809 
810  if (modelParams->HasElement("length"))
811  this->length = modelParams->Get<double>("length");
812  else
813  {
814  gzmsg << "HMCylinder: Using the biggest length of bounding box as length"
815  << std::endl;
816  this->length = std::max(this->boundingBox.XLength(),
817  std::max(this->boundingBox.YLength(),
818  this->boundingBox.ZLength()));
819  }
820  gzmsg << "HMCylinder::length=" << this->length << std::endl;
821 
822  this->dimRatio = this->length / (2* this->radius);
823 
824  gzmsg << "HMCylinder::dimension_ratio=" << this->dimRatio << std::endl;
825 
826  // Approximation of drag coefficients
827  // Reference: http://www.mech.pk.edu.pl/~m52/pdf/fm/R_09.pdf
828  // For the circular profile
829  if (this->dimRatio <= 1) this->cdCirc = 0.91;
830  else if (this->dimRatio > 1 && this->dimRatio <= 2) this->cdCirc = 0.85;
831  else if (this->dimRatio > 2 && this->dimRatio <= 4) this->cdCirc = 0.87;
832  else if (this->dimRatio > 4 && this->dimRatio <= 7) this->cdCirc = 0.99;
833 
834  // For the rectagular profile
835  if (this->dimRatio <= 1) this->cdLength = 0.63;
836  else if (this->dimRatio > 1 && this->dimRatio <= 2) this->cdLength = 0.68;
837  else if (this->dimRatio > 2 && this->dimRatio <= 5) this->cdLength = 0.74;
838  else if (this->dimRatio > 5 && this->dimRatio <= 10) this->cdLength = 0.82;
839  else if (this->dimRatio > 10 && this->dimRatio <= 40) this->cdLength = 0.98;
840  else if (this->dimRatio > 40) this->cdLength = 0.98;
841 
842  if (modelParams->HasElement("axis"))
843  {
844  this->axis = modelParams->Get<std::string>("axis");
845  GZ_ASSERT(this->axis.compare("i") == 0 ||
846  this->axis.compare("j") == 0 ||
847  this->axis.compare("k") == 0, "Invalid axis of rotation");
848  }
849  else
850  {
851  gzmsg << "HMCylinder: Using the direction of biggest length as axis"
852  << std::endl;
853  double maxLength = std::max(this->boundingBox.XLength(),
854  std::max(this->boundingBox.YLength(),
855  this->boundingBox.ZLength()));
856  if (maxLength == this->boundingBox.XLength())
857  this->axis = "i";
858  else if (maxLength == this->boundingBox.YLength())
859  this->axis = "j";
860  else
861  this->axis = "k";
862  }
863  gzmsg << "HMCylinder::rotation_axis=" << this->axis << std::endl;
864 
865  // Calculating the added mass and damping for the cylinder
866  // Calculate added mass coefficients for the cylinder along its length
867  double MaLength = -this->fluidDensity * PI *
868  std::pow(this->radius, 2.0) * this->length;
869 
870  // Calculate the added mass coefficients for the circular area
871  double MaCirc = -this->fluidDensity * PI * std::pow(this->radius, 2.0);
872 
873  // Calculating added mass torque coefficients
874  // Reference: Schjolberg, 1994 (Modelling and Control of Underwater-Vehicle
875  // Manipulator System)
876  double MaLengthTorque = (-1.0/12.0) * this->fluidDensity * PI \
877  * std::pow(this->radius, 2.0) * std::pow(this->length, 3.0);
878 
879  // Calculate drag forces and moments
880  // At the moment, only pressure drag is calculated, no skin friction drag
881  double DCirc = -0.5 * this->cdCirc * PI * std::pow(this->radius, 2.0) \
882  * this->fluidDensity;
883  double DLength = -0.5 * this->cdLength * this->radius * this->length \
884  * this->fluidDensity;
885 
886  if (this->axis.compare("i") == 0)
887  {
888  this->Ma(0, 0) = -MaCirc;
889  this->Ma(1, 1) = -MaLength;
890  this->Ma(2, 2) = -MaLength;
891 
892  this->Ma(4, 4) = -MaLengthTorque;
893  this->Ma(5, 5) = -MaLengthTorque;
894 
895  this->DNonLin(0, 0) = DCirc;
896  this->DNonLin(1, 1) = DLength;
897  this->DNonLin(2, 2) = DLength;
898  }
899  else if (this->axis.compare("j") == 0)
900  {
901  this->Ma(0, 0) = -MaLength;
902  this->Ma(1, 1) = -MaCirc;
903  this->Ma(2, 2) = -MaLength;
904 
905  this->Ma(3, 3) = -MaLengthTorque;
906  this->Ma(5, 5) = -MaLengthTorque;
907 
908  this->DNonLin(0, 0) = DLength;
909  this->DNonLin(1, 1) = DCirc;
910  this->DNonLin(2, 2) = DLength;
911  }
912  else
913  {
914  this->Ma(0, 0) = -MaLength;
915  this->Ma(1, 1) = -MaLength;
916  this->Ma(2, 2) = -MaCirc;
917 
918  this->Ma(3, 3) = -MaLengthTorque;
919  this->Ma(4, 4) = -MaLengthTorque;
920 
921  this->DNonLin(0, 0) = DLength;
922  this->DNonLin(1, 1) = DLength;
923  this->DNonLin(2, 2) = DCirc;
924  }
925 }
926 
928 void HMCylinder::Print(std::string _paramName, std::string _message)
929 {
930  if (!_paramName.compare("radius"))
931  {
932  if (!_message.empty())
933  gzmsg << this->link->GetName() << std::endl;
934  std::cout << std::setw(12) << this->radius << std::endl;
935  }
936  else if (!_paramName.compare("length"))
937  {
938  if (!_message.empty())
939  gzmsg << _message << std::endl;
940  std::cout << std::setw(12) << this->length << std::endl;
941  }
942  else
943  HMFossen::Print(_paramName, _message);
944 }
945 
947 // Hydrodynamic model for a spheroid (STILL IN DEVELOPMENT, DON'T USE IT)
949 const std::string HMSpheroid::IDENTIFIER = "spheroid";
952 
954 HydrodynamicModel* HMSpheroid::create(sdf::ElementPtr _sdf,
955  physics::LinkPtr _link)
956 {
957  return new HMSpheroid(_sdf, _link);
958 }
959 
961 HMSpheroid::HMSpheroid(sdf::ElementPtr _sdf,
962  physics::LinkPtr _link)
963  : HMFossen(_sdf, _link)
964 {
965  gzerr << "Hydrodynamic model for a spheroid is still in development!"
966  << std::endl;
967  GZ_ASSERT(_sdf->HasElement("hydrodynamic_model"),
968  "Hydrodynamic model is missing");
969 
970  sdf::ElementPtr modelParams = _sdf->GetElement("hydrodynamic_model");
971 
972  if (modelParams->HasElement("radius"))
973  this->radius = modelParams->Get<double>("radius");
974  else
975  {
976  gzmsg << "HMSpheroid: Using the smallest length of bounding box as radius"
977  << std::endl;
978  this->radius = std::min(this->boundingBox.XLength(),
979  std::min(this->boundingBox.YLength(),
980  this->boundingBox.ZLength()));
981  }
982  GZ_ASSERT(this->radius > 0, "Radius cannot be negative");
983  gzmsg << "HMSpheroid::radius=" << this->radius << std::endl;
984 
985  if (modelParams->HasElement("length"))
986  this->length = modelParams->Get<double>("length");
987  else
988  {
989  gzmsg << "HMSpheroid: Using the biggest length of bounding box as length"
990  << std::endl;
991  this->length = std::max(this->boundingBox.XLength(),
992  std::max(this->boundingBox.YLength(),
993  this->boundingBox.ZLength()));
994  }
995  GZ_ASSERT(this->length > 0, "Length cannot be negative");
996  gzmsg << "HMSpheroid::length=" << this->length << std::endl;
997 
998  // Eccentricity
999  double ecc = std::sqrt(1 -
1000  std::pow(this->radius / this->length, 2.0));
1001 
1002  gzmsg << "ecc=" << ecc << std::endl;
1003 
1004  double ln = std::log((1 + ecc) / (1 - ecc));
1005  double alpha = 2 * (1 - std::pow(ecc, 2.0)) / std::pow(ecc, 3.0);
1006 
1007  alpha *= (0.5 * ln - ecc);
1008 
1009  double beta = 1 / std::pow(ecc, 2.0) - \
1010  (1 - std::pow(ecc, 2.0) / (2 * std::pow(ecc, 3.0))) * ln;
1011 
1012  gzmsg << "alpha=" << alpha << std::endl;
1013  gzmsg << "beta=" << beta << std::endl;
1014 
1015  double mass;
1016 #if GAZEBO_MAJOR_VERSION >= 8
1017  mass = this->link->GetInertial()->Mass();
1018 #else
1019  mass = this->link->GetInertial()->GetMass();
1020 #endif
1021 
1022  this->Ma(0, 0) = mass * alpha / (2 - alpha);
1023  this->Ma(1, 1) = mass * beta / (2 - beta);
1024  this->Ma(2, 2) = this->Ma(1, 1);
1025  this->Ma(3, 3) = 0;
1026 
1027  double ba_minus = std::pow(this->radius, 2.0) - std::pow(this->length, 2.0);
1028  double ba_plus = std::pow(this->radius, 2.0) + std::pow(this->length, 2.0);
1029  this->Ma(4, 4) = -0.2 * mass * std::pow(ba_minus, 2.0) * (alpha - beta);
1030  this->Ma(4, 4) /= (2 * ba_minus - ba_plus * (alpha - beta));
1031 
1032  this->Ma(5, 5) = this->Ma(4, 4);
1033 }
1034 
1036 void HMSpheroid::Print(std::string _paramName, std::string _message)
1037 {
1038  if (!_paramName.compare("radius"))
1039  {
1040  if (!_message.empty())
1041  gzmsg << this->link->GetName() << std::endl;
1042  std::cout << std::setw(12) << this->radius << std::endl;
1043  }
1044  else if (!_paramName.compare("length"))
1045  {
1046  if (!_message.empty())
1047  gzmsg << _message << std::endl;
1048  std::cout << std::setw(12) << this->length << std::endl;
1049  }
1050  else
1051  HMFossen::Print(_paramName, _message);
1052 }
1053 
1055 // Hydrodynamic model for a box (STILL IN DEVELOPMENT, DON'T USE IT)
1057 
1058 const std::string HMBox::IDENTIFIER = "box";
1060  &HMBox::create);
1061 
1063 HydrodynamicModel* HMBox::create(sdf::ElementPtr _sdf,
1064  physics::LinkPtr _link)
1065 {
1066  return new HMBox(_sdf, _link);
1067 }
1068 
1070 HMBox::HMBox(sdf::ElementPtr _sdf,
1071  physics::LinkPtr _link)
1072  : HMFossen(_sdf, _link)
1073 {
1074  gzerr << "Hydrodynamic model for box is still in development!" << std::endl;
1075 
1076  GZ_ASSERT(_sdf->HasElement("hydrodynamic_model"),
1077  "Hydrodynamic model is missing");
1078 
1079  sdf::ElementPtr modelParams = _sdf->GetElement("hydrodynamic_model");
1080 
1081  if (modelParams->HasElement("cd"))
1082  this->Cd = modelParams->Get<double>("cd");
1083  else
1084  {
1085  gzmsg << "HMBox: Using 1 as drag coefficient"
1086  << std::endl;
1087  this->Cd = 1;
1088  }
1089 
1090  GZ_ASSERT(modelParams->HasElement("length"), "Length of the box is missing");
1091  GZ_ASSERT(modelParams->HasElement("width"), "Width of the box is missing");
1092  GZ_ASSERT(modelParams->HasElement("height"), "Height of the box is missing");
1093 
1094  this->length = modelParams->Get<double>("length");
1095  this->width = modelParams->Get<double>("width");
1096  this->height = modelParams->Get<double>("height");
1097 
1098  // Calculate drag force coefficients
1099  this->quadDampCoef[0] = -0.5 * this->Cd * this->width * this->height \
1100  * this->fluidDensity;
1101  this->quadDampCoef[1] = -0.5 * this->Cd * this->length * this->height \
1102  * this->fluidDensity;
1103  this->quadDampCoef[2] = -0.5 * this->Cd * this->width * this->length \
1104  * this->fluidDensity;
1105 }
1106 
1108 void HMBox::Print(std::string _paramName, std::string _message)
1109 {
1110  if (!_paramName.compare("length"))
1111  {
1112  if (!_message.empty())
1113  gzmsg << _message << std::endl;
1114  std::cout << std::setw(12) << this->length << std::endl;
1115  }
1116  else if (!_paramName.compare("width"))
1117  {
1118  if (!_message.empty())
1119  gzmsg << _message << std::endl;
1120  std::cout << std::setw(12) << this->width << std::endl;
1121  }
1122  else if (!_paramName.compare("height"))
1123  {
1124  if (!_message.empty())
1125  gzmsg << _message << std::endl;
1126  std::cout << std::setw(12) << this->height << std::endl;
1127  }
1128  else
1129  HMFossen::Print(_paramName, _message);
1130 }
1131 }
double volume
Volume of fluid displaced by the submerged object.
double height
Height of the box.
double Cd
Drag coefficient.
virtual void Print(std::string _paramName, std::string _message=std::string())
Prints parameters.
double submergedHeight
Height of the robot that is submerged (only for surface vessels)
Eigen::Matrix6d DLin
Linear damping matrix.
void ComputeAddedCoriolisMatrix(const Eigen::Vector6d &_vel, const Eigen::Matrix6d &_Ma, Eigen::Matrix6d &_Ca) const
Computes the added-mass Coriolis matrix Ca.
void StoreVector(std::string _tag, ignition::math::Vector3d _vec)
Store vector in the hydroWrench map if the field has been created.
Eigen::Matrix6d DLinForwardSpeed
Linear damping matrix proportional only to the forward speed (useful for modeling AUVs)...
double radius
Prolate spheroid&#39;s smaller radius.
double cdCirc
Approximated drag coefficient for the circular area.
void ComputeAcc(Eigen::Vector6d _velRel, double _time, double _alpha=0.3)
Filter acceleration (fix due to the update structure of Gazebo)
#define UUV_ADDED_CORIOLIS_FORCE
Definition: Def.hh:35
ignition::math::Vector3d FromNED(ignition::math::Vector3d _vec)
Convert vector to comply with the NED reference frame.
double width
Width of the box.
static const std::string IDENTIFIER
Unique identifier for this geometry.
virtual void Print(std::string _paramName, std::string _message=std::string())
Prints parameters.
Class containing the methods and attributes for a hydrodynamic model for a spheroid in the fluid Refe...
virtual void Print(std::string _paramName, std::string _message=std::string())
Prints parameters.
static HydrodynamicModel * create(sdf::ElementPtr _sdf, physics::LinkPtr _link)
Create model of this type with parameter values from sdf.
HMBox(sdf::ElementPtr _sdf, physics::LinkPtr _link)
Constructor.
double radius
Sphere radius.
double areaSection
Area of the cross section.
double offsetLinearDamping
Offset for the linear damping matrix.
#define PI
Definition: Def.hh:52
double length
Length of the cylinder.
double offsetAddedMass
Offset for the added-mass matrix.
static const std::string IDENTIFIER
Unique identifier for this geometry.
bool debugFlag
Debug flag, storing all intermediate forces and torques.
ignition::math::Vector3d Vec3dToGazebo(const Eigen::Vector3d &_x)
Definition: Def.hh:107
double length
Length of the sphroid.
static HydrodynamicModel * create(sdf::ElementPtr _sdf, physics::LinkPtr _link)
Create model of this type with parameter values from sdf.
double offsetNonLinDamping
Offset for the linear damping matrix.
double Re
Reynolds number (not used by all models)
Class containing the methods and attributes for a hydrodynamic model for a box in the fluid...
ignition::math::Box boundingBox
TEMP for calculation of the buoyancy force close to the surface.
double lastTime
Last timestamp (in seconds) at which ApplyHydrodynamicForces was called.
Eigen::Matrix< double, 6, 1 > Vector6d
Definition of a 6 element Eigen vector.
Definition: Def.hh:46
virtual bool SetParam(std::string _tag, double _input)
Set scalar parameter.
Factory singleton class that creates a HydrodynamicModel from sdf.
virtual void Print(std::string _paramName, std::string _message=std::string())
Prints parameters.
HMFossen(sdf::ElementPtr _sdf, physics::LinkPtr _link)
void SetNeutrallyBuoyant()
Sets this link as neutrally buoyant.
HydrodynamicModel(sdf::ElementPtr _sdf, physics::LinkPtr _link)
Protected constructor: Use the factory for object creation.
#define UUV_DAMPING_TORQUE
Definition: Def.hh:34
Eigen::Matrix6d GetAddedMass() const
Returns the added-mass matrix with the scaling and offset.
static HydrodynamicModelFactory & GetInstance()
Returns the singleton instance of this factory.
Class containing the methods and attributes for a hydrodynamic model for a sphere in the fluid...
bool RegisterCreator(const std::string &_identifier, HydrodynamicModelCreator _creator)
Register a class with its creator.
Eigen::Vector6d filteredAcc
Filtered linear & angular acceleration vector in link frame. This is used to prevent the model to bec...
void SetCoB(const ignition::math::Vector3d &_centerOfBuoyancy)
Sets the position of the center of buoyancy on the body frame.
static const std::string IDENTIFIER
Unique identifier for this geometry.
ignition::math::Vector3d ToNED(ignition::math::Vector3d _vec)
Convert vector to comply with the NED reference frame.
Eigen::Vector6d lastVelRel
Last body-fixed relative velocity (nu_R in Fossen&#39;s equations)
double offsetVolume
Offset for the volume.
HMCylinder(sdf::ElementPtr _sdf, physics::LinkPtr _link)
double waterLevelPlaneArea
If the cross section area around water level of the surface vessel is not given, it will be computed ...
static const std::string IDENTIFIER
Unique identifier for this geometry.
void SetBoundingBox(const ignition::math::Box &_bBox)
Sets bounding box.
double temperature
Temperature (not used by all models)
Eigen::Matrix6d Ca
Added-mass associated Coriolis matrix.
#define UUV_ADDED_CORIOLIS_TORQUE
Definition: Def.hh:36
Class containting the methods and attributes for a Fossen robot-like hydrodynamic model...
Eigen::Matrix6d Ma
Added-mass matrix.
HydrodynamicModel *(* HydrodynamicModelCreator)(sdf::ElementPtr, physics::LinkPtr)
Function pointer to create a certain a model.
HydrodynamicModel * CreateHydrodynamicModel(sdf::ElementPtr _sdf, physics::LinkPtr _link)
Create HydrodynamicModel object according to its sdf Description.
Eigen::Vector6d EigenStack(const ignition::math::Vector3d &_x, const ignition::math::Vector3d &_y)
Definition: Def.hh:97
void ApplyBuoyancyForce()
Applies buoyancy force on link.
#define UUV_ADDED_MASS_FORCE
Definition: Def.hh:37
std::vector< double > quadDampCoef
Quadratic damping coefficients.
static HydrodynamicModel * create(sdf::ElementPtr _sdf, physics::LinkPtr _link)
Create model of this type with parameter values from sdf.
HMSpheroid(sdf::ElementPtr _sdf, physics::LinkPtr _link)
bool isSurfaceVessel
Flag set to true if the information about the metacentric width and height is available.
static HydrodynamicModel * create(sdf::ElementPtr _sdf, physics::LinkPtr _link)
Create model of this type with parameter values from sdf.
Eigen::Matrix6d D
Damping matrix.
Eigen::Matrix< double, 6, 6 > Matrix6d
Definition of a 6x6 Eigen matrix.
Definition: Def.hh:43
Eigen::Matrix3d CrossProductOperator(Eigen::Vector3d _x)
Returns the cross product operator matrix for Eigen vectors.
Definition: Def.hh:67
virtual bool GetParam(std::string _tag, std::vector< double > &_output)
Return paramater in vector form for the given tag.
std::vector< double > Str2Vector(std::string _input)
Conversion of a string to a double vector.
Definition: Def.hh:55
virtual void Print(std::string _paramName, std::string _message=std::string())
Prints parameters.
double fluidDensity
Fluid density.
std::string axis
Name of the unit rotation axis (just a tag for x, y or z)
This file contains the definition for different classes of hydrodynamic models for submerged objects...
bool CheckParams(sdf::ElementPtr _sdf)
Returns true if all parameters are available from the SDF element.
ignition::math::Vector3d centerOfBuoyancy
Center of buoyancy in the body frame.
REGISTER_HYDRODYNAMICMODEL_CREATOR(HMFossen,&HMFossen::create)
double scalingDamping
Scaling of the damping matrix.
double metacentricLength
Metacentric length of the robot, used only for surface vessels and floating objects.
Class describing the dynamics of a buoyant object, useful for simple representations of underwater st...
double Cd
Drag coefficient.
#define UUV_ADDED_MASS_TORQUE
Definition: Def.hh:38
double cdLength
Approximated drag coefficient for the rectangular section.
physics::LinkPtr link
Pointer to the correspondent robot link.
void ComputeDampingMatrix(const Eigen::Vector6d &_vel, Eigen::Matrix6d &_D) const
Updates the damping matrix for the current velocity.
virtual void ApplyHydrodynamicForces(double time, const ignition::math::Vector3d &_flowVelWorld)
Computation of the hydrodynamic forces.
Class containing the methods and attributes for a hydrodynamic model for a cylinder in the fluid...
Eigen::Matrix6d DNonLin
Nonlinear damping coefficients.
#define UUV_DAMPING_FORCE
Definition: Def.hh:33
double scalingVolume
Scaling factor for the volume.
double dimRatio
Ratio between length and diameter.
double offsetLinForwardSpeedDamping
Offset for the linear damping matrix.
static const std::string IDENTIFIER
Unique identifier for this geometry.
static HydrodynamicModel * create(sdf::ElementPtr _sdf, physics::LinkPtr _link)
Create model of this type with parameter values from sdf.
std::vector< std::string > params
List of parameters needed from the SDF element.
std::vector< double > linearDampCoef
Linear damping coefficients.
double radius
Sphere radius.
HMSphere(sdf::ElementPtr _sdf, physics::LinkPtr _link)
double scalingAddedMass
Scaling of the added-mass matrix.
double length
Length of the box.


uuv_gazebo_plugins
Author(s): Musa Morena Marcusso Manhaes , Sebastian Scherer , Luiz Ricardo Douat
autogenerated on Thu Jun 18 2020 03:28:24