UnderwaterCurrentPlugin.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 
17 
18 #include <boost/algorithm/string.hpp>
19 #include <boost/bind.hpp>
20 #include <boost/shared_ptr.hpp>
21 
22 #include <gazebo/gazebo.hh>
23 #include <gazebo/msgs/msgs.hh>
24 #include <gazebo/physics/Link.hh>
25 #include <gazebo/physics/Model.hh>
26 #include <gazebo/physics/PhysicsEngine.hh>
27 #include <gazebo/physics/World.hh>
28 #include <gazebo/transport/TransportTypes.hh>
29 #include <sdf/sdf.hh>
30 
31 #include <math.h>
32 
34 
35 using namespace gazebo;
36 
37 GZ_REGISTER_WORLD_PLUGIN(UnderwaterCurrentPlugin)
38 
41 {
42  // Doing nothing for now
43 }
44 
47 {
48 #if GAZEBO_MAJOR_VERSION >= 8
49  this->updateConnection.reset();
50 #else
51  event::Events::DisconnectWorldUpdateBegin(this->updateConnection);
52 #endif
53 }
54 
56 void UnderwaterCurrentPlugin::Load(physics::WorldPtr _world, sdf::ElementPtr _sdf)
57 {
58  GZ_ASSERT(_world != NULL, "World pointer is invalid");
59  GZ_ASSERT(_sdf != NULL, "SDF pointer is invalid");
60 
61  this->world = _world;
62  this->sdf = _sdf;
63 
64  // Read the namespace for topics and services
65  this->ns = _sdf->Get<std::string>("namespace");
66 
67  gzmsg << "Loading underwater world..." << std::endl;
68  // Initializing the transport node
69  this->node = transport::NodePtr(new transport::Node());
70 #if GAZEBO_MAJOR_VERSION >= 8
71  this->node->Init(this->world->Name());
72 #else
73  this->node->Init(this->world->GetName());
74 #endif
75  // Retrieve the current velocity configuration, if existent
76  GZ_ASSERT(this->sdf->HasElement("constant_current"),
77  "Constant current configuration not available");
78  sdf::ElementPtr currentVelocityParams = this->sdf->GetElement(
79  "constant_current");
80 
81  // Read the topic names from the SDF file
82  if (currentVelocityParams->HasElement("topic"))
83  this->currentVelocityTopic =
84  currentVelocityParams->Get<std::string>("topic");
85  else
86  this->currentVelocityTopic = "current_velocity";
87 
88  GZ_ASSERT(!this->currentVelocityTopic.empty(),
89  "Empty current velocity topic");
90 
91  if (currentVelocityParams->HasElement("velocity"))
92  {
93  sdf::ElementPtr elem = currentVelocityParams->GetElement("velocity");
94  if (elem->HasElement("mean"))
95  this->currentVelModel.mean = elem->Get<double>("mean");
96  if (elem->HasElement("min"))
97  this->currentVelModel.min = elem->Get<double>("min");
98  if (elem->HasElement("max"))
99  this->currentVelModel.max = elem->Get<double>("max");
100  if (elem->HasElement("mu"))
101  this->currentVelModel.mu = elem->Get<double>("mu");
102  if (elem->HasElement("noiseAmp"))
103  this->currentVelModel.noiseAmp = elem->Get<double>("noiseAmp");
104 
105  GZ_ASSERT(this->currentVelModel.min < this->currentVelModel.max,
106  "Invalid current velocity limits");
107  GZ_ASSERT(this->currentVelModel.mean >= this->currentVelModel.min,
108  "Mean velocity must be greater than minimum");
109  GZ_ASSERT(this->currentVelModel.mean <= this->currentVelModel.max,
110  "Mean velocity must be smaller than maximum");
111  GZ_ASSERT(this->currentVelModel.mu >= 0 && this->currentVelModel.mu < 1,
112  "Invalid process constant");
113  GZ_ASSERT(this->currentVelModel.noiseAmp < 1 &&
114  this->currentVelModel.noiseAmp >= 0,
115  "Noise amplitude has to be smaller than 1");
116  }
117 
118  this->currentVelModel.var = this->currentVelModel.mean;
119  gzmsg << "Current velocity [m/s] Gauss-Markov process model:" << std::endl;
120  this->currentVelModel.Print();
121 
122  if (currentVelocityParams->HasElement("horizontal_angle"))
123  {
124  sdf::ElementPtr elem =
125  currentVelocityParams->GetElement("horizontal_angle");
126 
127  if (elem->HasElement("mean"))
128  this->currentHorzAngleModel.mean = elem->Get<double>("mean");
129  if (elem->HasElement("min"))
130  this->currentHorzAngleModel.min = elem->Get<double>("min");
131  if (elem->HasElement("max"))
132  this->currentHorzAngleModel.max = elem->Get<double>("max");
133  if (elem->HasElement("mu"))
134  this->currentHorzAngleModel.mu = elem->Get<double>("mu");
135  if (elem->HasElement("noiseAmp"))
136  this->currentHorzAngleModel.noiseAmp = elem->Get<double>("noiseAmp");
137 
138  GZ_ASSERT(this->currentHorzAngleModel.min <
139  this->currentHorzAngleModel.max,
140  "Invalid current horizontal angle limits");
141  GZ_ASSERT(this->currentHorzAngleModel.mean >=
142  this->currentHorzAngleModel.min,
143  "Mean horizontal angle must be greater than minimum");
144  GZ_ASSERT(this->currentHorzAngleModel.mean <=
145  this->currentHorzAngleModel.max,
146  "Mean horizontal angle must be smaller than maximum");
147  GZ_ASSERT(this->currentHorzAngleModel.mu >= 0 &&
148  this->currentHorzAngleModel.mu < 1,
149  "Invalid process constant");
150  GZ_ASSERT(this->currentHorzAngleModel.noiseAmp < 1 &&
151  this->currentHorzAngleModel.noiseAmp >= 0,
152  "Noise amplitude for horizontal angle has to be between 0 and 1");
153  }
154 
156  gzmsg <<
157  "Current velocity horizontal angle [rad] Gauss-Markov process model:"
158  << std::endl;
160 
161  if (currentVelocityParams->HasElement("vertical_angle"))
162  {
163  sdf::ElementPtr elem = currentVelocityParams->GetElement("vertical_angle");
164 
165  if (elem->HasElement("mean"))
166  this->currentVertAngleModel.mean = elem->Get<double>("mean");
167  if (elem->HasElement("min"))
168  this->currentVertAngleModel.min = elem->Get<double>("min");
169  if (elem->HasElement("max"))
170  this->currentVertAngleModel.max = elem->Get<double>("max");
171  if (elem->HasElement("mu"))
172  this->currentVertAngleModel.mu = elem->Get<double>("mu");
173  if (elem->HasElement("noiseAmp"))
174  this->currentVertAngleModel.noiseAmp = elem->Get<double>("noiseAmp");
175 
176  GZ_ASSERT(this->currentVertAngleModel.min <
177  this->currentVertAngleModel.max, "Invalid current vertical angle limits");
178  GZ_ASSERT(this->currentVertAngleModel.mean >=
179  this->currentVertAngleModel.min,
180  "Mean vertical angle must be greater than minimum");
181  GZ_ASSERT(this->currentVertAngleModel.mean <=
182  this->currentVertAngleModel.max,
183  "Mean vertical angle must be smaller than maximum");
184  GZ_ASSERT(this->currentVertAngleModel.mu >= 0 &&
185  this->currentVertAngleModel.mu < 1,
186  "Invalid process constant");
187  GZ_ASSERT(this->currentVertAngleModel.noiseAmp < 1 &&
188  this->currentVertAngleModel.noiseAmp >= 0,
189  "Noise amplitude for vertical angle has to be between 0 and 1");
190  }
191 
193  gzmsg <<
194  "Current velocity horizontal angle [rad] Gauss-Markov process model:"
195  << std::endl;
197 
198  // Initialize the time update
199 #if GAZEBO_MAJOR_VERSION >= 8
200  this->lastUpdate = this->world->SimTime();
201 #else
202  this->lastUpdate = this->world->GetSimTime();
203 #endif
204  this->currentVelModel.lastUpdate = this->lastUpdate.Double();
205  this->currentHorzAngleModel.lastUpdate = this->lastUpdate.Double();
206  this->currentVertAngleModel.lastUpdate = this->lastUpdate.Double();
207 
208  // Advertise the current velocity topic
209  this->publishers[this->currentVelocityTopic] =
210  this->node->Advertise<msgs::Vector3d>(
211  this->ns + "/" + this->currentVelocityTopic);
212 
213  gzmsg << "Current velocity topic name: " <<
214  this->ns + "/" + this->currentVelocityTopic << std::endl;
215 
216  // Connect the update event
217  this->updateConnection = event::Events::ConnectWorldUpdateBegin(
218  boost::bind(&UnderwaterCurrentPlugin::Update,
219  this, _1));
220 
221  gzmsg << "Underwater current plugin loaded!" << std::endl
222  << "\tWARNING: Current velocity calculated in the ENU frame"
223  << std::endl;
224 }
225 
228 {
229  // Doing nothing for now
230 }
231 
233 void UnderwaterCurrentPlugin::Update(const common::UpdateInfo & )
234 {
235 #if GAZEBO_MAJOR_VERSION >= 8
236  common::Time time = this->world->SimTime();
237 #else
238  common::Time time = this->world->GetSimTime();
239 #endif
240  // Calculate the flow velocity and the direction using the Gauss-Markov
241  // model
242 
243  // Update current velocity
244  double currentVelMag = this->currentVelModel.Update(time.Double());
245 
246  // Update current horizontal direction around z axis of flow frame
247  double horzAngle = this->currentHorzAngleModel.Update(time.Double());
248 
249  // Update current horizontal direction around z axis of flow frame
250  double vertAngle = this->currentVertAngleModel.Update(time.Double());
251 
252  // Generating the current velocity vector as in the NED frame
253  this->currentVelocity = ignition::math::Vector3d(
254  currentVelMag * cos(horzAngle) * cos(vertAngle),
255  currentVelMag * sin(horzAngle) * cos(vertAngle),
256  currentVelMag * sin(vertAngle));
257 
258  // Update time stamp
259  this->lastUpdate = time;
260  this->PublishCurrentVelocity();
261 }
262 
265 {
266  msgs::Vector3d currentVel;
267  msgs::Set(&currentVel, ignition::math::Vector3d(this->currentVelocity.X(),
268  this->currentVelocity.Y(),
269  this->currentVelocity.Z()));
270  this->publishers[this->currentVelocityTopic]->Publish(currentVel);
271 }
GaussMarkovProcess currentVelModel
Gauss-Markov process instance for the current velocity.
double min
Minimum limit for the process variable.
std::string currentVelocityTopic
Current velocity topic.
double Update(double _time)
Update function for a new time stamp.
double noiseAmp
Gaussian white noise amplitude.
void PublishCurrentVelocity()
Publish current velocity and the pose of its frame.
sdf::ElementPtr sdf
Pointer to sdf.
void Print()
Print current model paramters.
virtual void Load(physics::WorldPtr _world, sdf::ElementPtr _sdf)
common::Time lastUpdate
Last update time stamp.
std::map< std::string, transport::PublisherPtr > publishers
Map of publishers.
GaussMarkovProcess currentHorzAngleModel
Gauss-Markov process instance for horizontal angle model.
virtual ~UnderwaterCurrentPlugin()
Class destructor.
double mean
Mean process value.
transport::NodePtr node
Pointer to a node for communication.
event::ConnectionPtr updateConnection
Update event.
double max
Maximum limit for the process variable.
GaussMarkovProcess currentVertAngleModel
Gauss-Markov process instance for vertical angle model.
double var
Process variable.
ignition::math::Vector3d currentVelocity
Current linear velocity vector.
physics::WorldPtr world
Pointer to world.
Class for the underwater current plugin TODO: Add option to make the underwater current also a functi...
double mu
Process constant, if zero, process becomes a random walk.
void Update(const common::UpdateInfo &_info)
Update the simulation state.
double lastUpdate
Timestamp for the last update.
Plugin that for the underwater world.
std::string ns
Namespace for topics and services.


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