UnderwaterObjectPlugin.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>
17 #include <gazebo/physics/Collision.hh>
18 #include <gazebo/physics/Link.hh>
19 #include <gazebo/physics/Model.hh>
20 #include <gazebo/physics/PhysicsEngine.hh>
21 #include <gazebo/physics/Shape.hh>
22 #include <gazebo/physics/World.hh>
23 #include <gazebo/transport/TransportTypes.hh>
24 #include <gazebo/transport/transport.hh>
25 
28 
29 namespace gazebo {
30 
31 GZ_REGISTER_MODEL_PLUGIN(UnderwaterObjectPlugin)
32 
33 UnderwaterObjectPlugin::UnderwaterObjectPlugin() : useGlobalCurrent(true)
35 {
36 }
37 
40 {
41 #if GAZEBO_MAJOR_VERSION >= 8
42  this->updateConnection.reset();
43 #else
44  event::Events::DisconnectWorldUpdateBegin(this->updateConnection);
45 #endif
46 }
47 
49 void UnderwaterObjectPlugin::Load(physics::ModelPtr _model,
50  sdf::ElementPtr _sdf)
51 {
52  GZ_ASSERT(_model != NULL, "Invalid model pointer");
53  GZ_ASSERT(_sdf != NULL, "Invalid SDF element pointer");
54 
55  this->model = _model;
56  this->world = _model->GetWorld();
57 
58  // Initialize the transport node
59  this->node = transport::NodePtr(new transport::Node());
60  std::string worldName;
61 #if GAZEBO_MAJOR_VERSION >= 8
62  worldName = this->world->Name();
63 #else
64  worldName = this->world->GetName();
65 #endif
66  this->node->Init(worldName);
67 
68  // If fluid topic is available, subscribe to it
69  if (_sdf->HasElement("flow_velocity_topic"))
70  {
71  std::string flowTopic = _sdf->Get<std::string>("flow_velocity_topic");
72  GZ_ASSERT(!flowTopic.empty(),
73  "Fluid velocity topic tag cannot be empty");
74 
75  gzmsg << "Subscribing to current velocity topic: " << flowTopic
76  << std::endl;
77  this->flowSubscriber = this->node->Subscribe(flowTopic,
79  }
80 
81  double fluidDensity = 1028.0;
82  // Get the fluid density, if present
83  if (_sdf->HasElement("fluid_density"))
84  fluidDensity = _sdf->Get<double>("fluid_density");
85 
86  if (_sdf->HasElement("use_global_current"))
87  this->useGlobalCurrent = _sdf->Get<bool>("use_global_current");
88 
89  // Get the debug flag, if available
90  bool debugFlag = false;
91  if (_sdf->HasElement("debug"))
92  debugFlag = static_cast<bool>(_sdf->Get<int>("debug"));
93 
94  // Center of buoyancy
95  ignition::math::Vector3d cob;
96  // g
97  double gAcc;
98 #if GAZEBO_MAJOR_VERSION >= 8
99  gAcc = std::abs(this->world->Gravity().Z());
100 #else
101  gAcc = std::abs(this->world->GetPhysicsEngine()->GetGravity().z);
102 #endif
103  this->baseLinkName = std::string();
104  if (_sdf->HasElement("link"))
105  {
106  for (sdf::ElementPtr linkElem = _sdf->GetElement("link"); linkElem;
107  linkElem = linkElem->GetNextElement("link"))
108  {
109  physics::LinkPtr link;
110  std::string linkName = "";
111 
112  if (linkElem->HasAttribute("name"))
113  {
114  linkName = linkElem->Get<std::string>("name");
115  std::size_t found = linkName.find("base_link");
116  if (found != std::string::npos)
117  {
118  this->baseLinkName = linkName;
119  gzmsg << "Name of the BASE_LINK: " << this->baseLinkName << std::endl;
120  }
121 
122  link = this->model->GetLink(linkName);
123  if (!link)
124  {
125  gzwarn << "Specified link [" << linkName << "] not found."
126  << std::endl;
127  continue;
128  }
129  }
130  else
131  {
132  gzwarn << "Attribute name missing from link [" << linkName
133  << "]" << std::endl;
134  continue;
135  }
136 
137  // Creating a new hydrodynamic model for this link
138  HydrodynamicModelPtr hydro;
139  hydro.reset(
140  HydrodynamicModelFactory::GetInstance().CreateHydrodynamicModel(
141  linkElem, link));
142  hydro->SetFluidDensity(fluidDensity);
143  hydro->SetGravity(gAcc);
144 
145  if (debugFlag)
146  this->InitDebug(link, hydro);
147 
148  this->models[link] = hydro;
149  this->models[link]->Print("all");
150  } // for each link mentioned in plugin sdf
151  }
152 
153  // Connect the update event callback
154  this->Connect();
155 }
156 
158 void UnderwaterObjectPlugin::InitDebug(physics::LinkPtr _link,
159  HydrodynamicModelPtr _hydro)
160 {
161  // Create topics for the individual hydrodynamic and hydrostatic forces
162  std::string rootTopic = "/debug/forces/" + _link->GetName() + "/";
163  std::vector<std::string> topics {"restoring", "damping", "added_mass",
164  "added_coriolis"};
165  for (auto topic : topics)
166  {
167  this->hydroPub[_link->GetName() + "/" + topic] =
168  this->node->Advertise<msgs::WrenchStamped>(rootTopic + topic);
169  }
170 
171  // Setup the vectors to be stored
172  _hydro->SetDebugFlag(true);
173  _hydro->SetStoreVector(RESTORING_FORCE);
174  _hydro->SetStoreVector(UUV_DAMPING_FORCE);
175  _hydro->SetStoreVector(UUV_DAMPING_TORQUE);
176  _hydro->SetStoreVector(UUV_ADDED_CORIOLIS_FORCE);
177  _hydro->SetStoreVector(UUV_ADDED_CORIOLIS_TORQUE);
178  _hydro->SetStoreVector(UUV_ADDED_MASS_FORCE);
179  _hydro->SetStoreVector(UUV_ADDED_MASS_TORQUE);
180 }
181 
184 {
185  // Doing nothing for now
186 }
187 
189 void UnderwaterObjectPlugin::Update(const common::UpdateInfo &_info)
190 {
191  double time = _info.simTime.Double();
192 
193  for (std::map<gazebo::physics::LinkPtr,
194  HydrodynamicModelPtr>::iterator it = models.begin();
195  it != models.end(); ++it)
196  {
197  physics::LinkPtr link = it->first;
198  HydrodynamicModelPtr hydro = it->second;
199  // Apply hydrodynamic and hydrostatic forces and torques
200  double linearAccel, angularAccel;
201 #if GAZEBO_MAJOR_VERSION >= 8
202  linearAccel = link->RelativeLinearAccel().Length();
203  angularAccel = link->RelativeAngularAccel().Length();
204 #else
205  linearAccel = link->GetRelativeLinearAccel().GetLength();
206  angularAccel = link->GetRelativeAngularAccel().GetLength();
207 #endif
208 
209  GZ_ASSERT(!std::isnan(linearAccel) && !std::isnan(angularAccel),
210  "Linear or angular accelerations are invalid.");
211 
212  hydro->ApplyHydrodynamicForces(time, this->flowVelocity);
213  this->PublishRestoringForce(link);
214  this->PublishHydrodynamicWrenches(link);
216  this->PublishIsSubmerged();
217  }
218 }
219 
222 {
223  // Connect the update event
224  this->updateConnection = event::Events::ConnectWorldUpdateBegin(
225  boost::bind(&UnderwaterObjectPlugin::Update,
226  this, _1));
227 }
228 
231 {
232  // Does nothing for now
233  return;
234 }
235 
238 {
239  // Does nothing for now
240  return;
241 }
242 
244 void UnderwaterObjectPlugin::UpdateFlowVelocity(ConstVector3dPtr &_msg)
245 {
246  if (this->useGlobalCurrent)
247  {
248  this->flowVelocity.X() = _msg->x();
249  this->flowVelocity.Y() = _msg->y();
250  this->flowVelocity.Z() = _msg->z();
251  }
252 }
253 
256  physics::LinkPtr _link)
257 {
258  if (this->models.count(_link))
259  {
260  if (!this->models[_link]->GetDebugFlag())
261  return;
262 
263  ignition::math::Vector3d restoring = this->models[_link]->GetStoredVector(
265 
266  msgs::WrenchStamped msg;
267  this->GenWrenchMsg(restoring, ignition::math::Vector3d(0, 0, 0), msg);
268  this->hydroPub[_link->GetName() + "/restoring"]->Publish(msg);
269  }
270 }
271 
274  physics::LinkPtr _link)
275 {
276  if (this->models.count(_link))
277  {
278  if (!this->models[_link]->GetDebugFlag())
279  return;
280  msgs::WrenchStamped msg;
281  ignition::math::Vector3d force, torque;
282 
283  // Publish wrench generated by the acceleraton of fluid aroung the object
284  force = this->models[_link]->GetStoredVector(UUV_ADDED_MASS_FORCE);
285  torque = this->models[_link]->GetStoredVector(UUV_ADDED_MASS_TORQUE);
286 
287  this->GenWrenchMsg(force, torque, msg);
288  this->hydroPub[_link->GetName() + "/added_mass"]->Publish(msg);
289 
290  // Publish wrench generated by the acceleraton of fluid aroung the object
291  force = this->models[_link]->GetStoredVector(UUV_DAMPING_FORCE);
292  torque = this->models[_link]->GetStoredVector(UUV_DAMPING_TORQUE);
293 
294  this->GenWrenchMsg(force, torque, msg);
295  this->hydroPub[_link->GetName() + "/damping"]->Publish(msg);
296 
297  // Publish wrench generated by the acceleraton of fluid aroung the object
298  force = this->models[_link]->GetStoredVector(UUV_ADDED_CORIOLIS_FORCE);
299  torque = this->models[_link]->GetStoredVector(UUV_ADDED_CORIOLIS_TORQUE);
300 
301  this->GenWrenchMsg(force, torque, msg);
302  this->hydroPub[_link->GetName() + "/added_coriolis"]->Publish(msg);
303  }
304 }
305 
307 void UnderwaterObjectPlugin::GenWrenchMsg(ignition::math::Vector3d _force,
308  ignition::math::Vector3d _torque, gazebo::msgs::WrenchStamped &_output)
309 {
310  common::Time curTime;
311 #if GAZEBO_MAJOR_VERSION >= 8
312  curTime = this->world->SimTime();
313 #else
314  curTime = this->world->GetSimTime();
315 #endif
316 
317  msgs::Wrench * wrench = _output.mutable_wrench();
318  msgs::Time * t = _output.mutable_time();
319  msgs::Vector3d * msgForce = wrench->mutable_force();
320  msgs::Vector3d * msgTorque = wrench->mutable_torque();
321 
322  msgs::Set(msgTorque,
323  ignition::math::Vector3d(_torque.X(), _torque.Y(), _torque.Z()));
324  msgs::Set(msgForce,
325  ignition::math::Vector3d(_force.X(), _force.Y(), _force.Z()));
326 
327  t->set_sec(curTime.sec);
328  t->set_nsec(curTime.nsec);
329 }
330 }
std::map< gazebo::physics::LinkPtr, HydrodynamicModelPtr > models
Pairs of links & corresponding hydrodynamic models.
gazebo::event::ConnectionPtr updateConnection
Update event.
std::map< std::string, gazebo::transport::PublisherPtr > hydroPub
Publishers of hydrodynamic and hydrostatic forces and torques in the case the debug flag is on...
virtual void PublishHydrodynamicWrenches(gazebo::physics::LinkPtr _link)
Publish hydrodynamic wrenches.
#define UUV_ADDED_CORIOLIS_FORCE
Definition: Def.hh:35
virtual void PublishIsSubmerged()
Publishes the state of the vehicle (is submerged)
virtual void PublishRestoringForce(gazebo::physics::LinkPtr _link)
Publish restoring force.
void UpdateFlowVelocity(ConstVector3dPtr &_msg)
Reads flow velocity topic.
Class declaration for the underwater objects subject to buoyancy, lift and drag forces.
gazebo::physics::WorldPtr world
Pointer to the world plugin.
GZ_REGISTER_MODEL_PLUGIN(UmbilicalPlugin)
virtual void Connect()
Connects the update event callback.
gazebo::transport::NodePtr node
Gazebo node.
ignition::math::Vector3d flowVelocity
Flow velocity vector read from topic.
virtual ~UnderwaterObjectPlugin()
Destructor.
#define UUV_DAMPING_TORQUE
Definition: Def.hh:34
static HydrodynamicModelFactory & GetInstance()
Returns the singleton instance of this factory.
#define RESTORING_FORCE
bool useGlobalCurrent
Flag to use the global current velocity or the individually assigned current velocity.
#define UUV_ADDED_CORIOLIS_TORQUE
Definition: Def.hh:36
virtual void InitDebug(gazebo::physics::LinkPtr _link, gazebo::HydrodynamicModelPtr _hydro)
Sets the topics used for publishing the intermediate data during the simulation.
#define UUV_ADDED_MASS_FORCE
Definition: Def.hh:37
std::string baseLinkName
Name of vehicle&#39;s base_link.
virtual void Update(const gazebo::common::UpdateInfo &_info)
Update the simulation state.
#define UUV_ADDED_MASS_TORQUE
Definition: Def.hh:38
virtual void PublishCurrentVelocityMarker()
Publish current velocity marker.
virtual void GenWrenchMsg(ignition::math::Vector3d _force, ignition::math::Vector3d _torque, gazebo::msgs::WrenchStamped &_output)
Returns the wrench message for debugging topics.
gazebo::physics::ModelPtr model
Pointer to the model structure.
#define UUV_DAMPING_FORCE
Definition: Def.hh:33
General definitions.
boost::shared_ptr< HydrodynamicModel > HydrodynamicModelPtr
Pointer to model.
gazebo::transport::SubscriberPtr flowSubscriber
Subcriber to flow message.
virtual void Load(gazebo::physics::ModelPtr _model, sdf::ElementPtr _sdf)


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