gazebo_pressure_plugin.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016 Pavel Vechersky, ASL, ETH Zurich, Switzerland
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 
17 // MODULE HEADER
19 
20 // USER HEADERS
21 #include "ConnectGazeboToRosTopic.pb.h"
22 
23 namespace gazebo {
24 
26  : ModelPlugin(),
27  node_handle_(0),
28  pubs_and_subs_created_(false) {
29 }
30 
32 }
33 
34 void GazeboPressurePlugin::Load(physics::ModelPtr _model, sdf::ElementPtr _sdf) {
35  if (kPrintOnPluginLoad) {
36  gzdbg << __FUNCTION__ << "() called." << std::endl;
37  }
38 
39  gzdbg << "_model = " << _model->GetName() << std::endl;
40 
41  // Store the pointer to the model and the world.
42  model_ = _model;
43  world_ = model_->GetWorld();
44 
45  //==============================================//
46  //========== READ IN PARAMS FROM SDF ===========//
47  //==============================================//
48 
49  // Use the robot namespace to create the node handle.
50  if (_sdf->HasElement("robotNamespace"))
51  namespace_ = _sdf->GetElement("robotNamespace")->Get<std::string>();
52  else
53  gzerr << "[gazebo_pressure_plugin] Please specify a robotNamespace.\n";
54 
55  // Get node handle.
56  node_handle_ = transport::NodePtr(new transport::Node());
57 
58  // Initialise with default namespace (typically /gazebo/default/).
59  node_handle_->Init();
60 
61  std::string link_name;
62  if (_sdf->HasElement("linkName"))
63  link_name = _sdf->GetElement("linkName")->Get<std::string>();
64  else
65  gzerr << "[gazebo_pressure_plugin] Please specify a linkName.\n";
66  // Get the pointer to the link.
67  link_ = model_->GetLink(link_name);
68  if (link_ == NULL)
69  gzthrow("[gazebo_pressure_plugin] Couldn't find specified link \"" << link_name << "\".");
70 
71  frame_id_ = link_name;
72 
73  // Retrieve the rest of the SDF parameters.
74  getSdfParam<std::string>(_sdf, "pressureTopic", pressure_topic_, kDefaultPressurePubTopic);
75  getSdfParam<double>(_sdf, "referenceAltitude", ref_alt_, kDefaultRefAlt);
76  getSdfParam<double>(_sdf, "pressureVariance", pressure_var_, kDefaultPressureVar);
77  CHECK(pressure_var_ >= 0.0);
78 
79  // Initialize the normal distribution for pressure.
80  double mean = 0.0;
81  pressure_n_[0] = NormalDistribution(mean, sqrt(pressure_var_));
82 
83  // Listen to the update event. This event is broadcast every simulation
84  // iteration.
85  this->updateConnection_ = event::Events::ConnectWorldUpdateBegin(
86  boost::bind(&GazeboPressurePlugin::OnUpdate, this, _1));
87 
88  //==============================================//
89  //=== POPULATE STATIC PARTS OF PRESSURE MSG ====//
90  //==============================================//
91 
92  pressure_message_.mutable_header()->set_frame_id(frame_id_);
93  pressure_message_.set_variance(pressure_var_);
94 }
95 
96 void GazeboPressurePlugin::OnUpdate(const common::UpdateInfo& _info) {
97  if (kPrintOnUpdates) {
98  gzdbg << __FUNCTION__ << "() called." << std::endl;
99  }
100 
101  if (!pubs_and_subs_created_) {
103  pubs_and_subs_created_ = true;
104  }
105 
106  common::Time current_time = world_->SimTime();
107 
108  // Get the current geometric height.
109  double height_geometric_m = ref_alt_ + model_->WorldPose().Pos().Z();
110 
111  // Compute the geopotential height.
112  double height_geopotential_m = kEarthRadiusMeters * height_geometric_m /
113  (kEarthRadiusMeters + height_geometric_m);
114 
115  // Compute the temperature at the current altitude.
116  double temperature_at_altitude_kelvin =
117  kSeaLevelTempKelvin - kTempLapseKelvinPerMeter * height_geopotential_m;
118 
119  // Compute the current air pressure.
120  double pressure_at_altitude_pascal =
122  log(kSeaLevelTempKelvin / temperature_at_altitude_kelvin));
123 
124  // Add noise to pressure measurement.
125  if(pressure_var_ > 0.0) {
126  pressure_at_altitude_pascal += pressure_n_[0](random_generator_);
127  }
128 
129  // Fill the pressure message.
130  pressure_message_.mutable_header()->mutable_stamp()->set_sec(
131  current_time.sec);
132  pressure_message_.mutable_header()->mutable_stamp()->set_nsec(
133  current_time.nsec);
134  pressure_message_.set_fluid_pressure(pressure_at_altitude_pascal);
135 
136  // Publish the pressure message.
138 }
139 
141  // Create temporary "ConnectGazeboToRosTopic" publisher and message.
142  gazebo::transport::PublisherPtr connect_gazebo_to_ros_topic_pub =
143  node_handle_->Advertise<gz_std_msgs::ConnectGazeboToRosTopic>(
144  "~/" + kConnectGazeboToRosSubtopic, 1);
145 
146  // ============================================ //
147  // ========= FLUID PRESSURE MSG SETUP ========= //
148  // ============================================ //
149 
150  pressure_pub_ = node_handle_->Advertise<gz_sensor_msgs::FluidPressure>(
151  "~/" + namespace_ + "/" + pressure_topic_, 1);
152 
153  gz_std_msgs::ConnectGazeboToRosTopic connect_gazebo_to_ros_topic_msg;
154  connect_gazebo_to_ros_topic_msg.set_gazebo_topic("~/" + namespace_ + "/" +
155  pressure_topic_);
156  connect_gazebo_to_ros_topic_msg.set_ros_topic(namespace_ + "/" +
157  pressure_topic_);
158  connect_gazebo_to_ros_topic_msg.set_msgtype(
159  gz_std_msgs::ConnectGazeboToRosTopic::FLUID_PRESSURE);
160  connect_gazebo_to_ros_topic_pub->Publish(connect_gazebo_to_ros_topic_msg,
161  true);
162 }
163 
165 
166 } // namespace gazebo
static constexpr double kEarthRadiusMeters
std::normal_distribution NormalDistribution
event::ConnectionPtr updateConnection_
Pointer to the update event connection.
physics::LinkPtr link_
Pointer to the link.
NormalDistribution pressure_n_[1]
Normal distribution for pressure noise.
double pressure_var_
Pressure measurement variance (Pa^2).
physics::ModelPtr model_
Pointer to the model.
physics::WorldPtr world_
Pointer to the world.
std::string frame_id_
Frame ID for pressure messages.
void OnUpdate(const common::UpdateInfo &)
This gets called by the world update start event.
gz_sensor_msgs::FluidPressure pressure_message_
Fluid pressure message.
gazebo::transport::PublisherPtr pressure_pub_
Pressure message publisher.
gazebo::transport::NodePtr node_handle_
Handle for the Gazebo node.
bool pubs_and_subs_created_
Flag that is set to true once CreatePubsAndSubs() is called, used to prevent CreatePubsAndSubs() from...
static constexpr double kPressureOneAtmospherePascals
static const std::string kDefaultPressurePubTopic
static constexpr double kDefaultPressureVar
double ref_alt_
Reference altitude (meters).
static const bool kPrintOnPluginLoad
Definition: common.h:41
static constexpr double kSeaLevelTempKelvin
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
static constexpr double kTempLapseKelvinPerMeter
void Load(physics::ModelPtr _model, sdf::ElementPtr _sdf)
Called when the plugin is first created, and after the world has been loaded. This function should no...
static constexpr double kDefaultRefAlt
virtual ~GazeboPressurePlugin()
Destructor.
INLINE Rall1d< T, V, S > exp(const Rall1d< T, V, S > &arg)
static constexpr double kAirConstantDimensionless
void CreatePubsAndSubs()
Creates all required publishers and subscribers, incl. routing of messages to/from ROS if required...
static const bool kPrintOnUpdates
Definition: common.h:42
GZ_REGISTER_MODEL_PLUGIN(GazeboRosP3D)
static const std::string kConnectGazeboToRosSubtopic
Definition: common.h:56
std::string namespace_
Transport namespace.
std::string pressure_topic_
Topic name for pressure messages.


rotors_gazebo_plugins
Author(s): Fadri Furrer, Michael Burri, Mina Kamel, Janosch Nikolic, Markus Achtelik
autogenerated on Mon Feb 28 2022 23:39:04