gazebo_magnetometer_plugin.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016 Pavel Vechersky, ASL, ETH Zurich, Switzerland
3  * Copyright 2016 Geoffrey Hunter <gbmhunter@gmail.com>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
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 INCLUDE
19 
20 #include <mav_msgs/default_topics.h> // This comes from the mav_comm repo
21 
22 #include "ConnectGazeboToRosTopic.pb.h"
23 
24 namespace gazebo {
25 
27  : ModelPlugin(),
28  random_generator_(random_device_()),
29  pubs_and_subs_created_(false) {
30  // Nothing
31 }
32 
34 }
35 
36 void GazeboMagnetometerPlugin::Load(physics::ModelPtr _model,
37  sdf::ElementPtr _sdf) {
38  if (kPrintOnPluginLoad) {
39  gzdbg << __FUNCTION__ << "() called." << std::endl;
40  }
41 
42  // Store the pointer to the model and the world
43  model_ = _model;
44  world_ = model_->GetWorld();
45 
46  // Use the robot namespace to create the node handle
47  if (_sdf->HasElement("robotNamespace"))
48  namespace_ = _sdf->GetElement("robotNamespace")->Get<std::string>();
49  else
50  gzerr << "[gazebo_magnetometer_plugin] Please specify a robotNamespace.\n";
51 
52  node_handle_ = gazebo::transport::NodePtr(new transport::Node());
53 
54  // Initialise with default namespace (typically /gazebo/default/)
55  node_handle_->Init();
56 
57  // Use the link name as the frame id
58  std::string link_name;
59  if (_sdf->HasElement("linkName"))
60  link_name = _sdf->GetElement("linkName")->Get<std::string>();
61  else
62  gzerr << "[gazebo_magnetometer_plugin] Please specify a linkName.\n";
63  // Get the pointer to the link
64  link_ = model_->GetLink(link_name);
65  if (link_ == NULL)
66  gzthrow("[gazebo_magnetometer_plugin] Couldn't find specified link \""
67  << link_name << "\".");
68 
69  frame_id_ = link_name;
70 
71  double ref_mag_north;
72  double ref_mag_east;
73  double ref_mag_down;
74  SdfVector3 noise_normal;
75  SdfVector3 noise_uniform_initial_bias;
76  const SdfVector3 zeros3(0.0, 0.0, 0.0);
77 
78  // Retrieve the rest of the SDF parameters
79  getSdfParam<std::string>(_sdf, "magnetometerTopic", magnetometer_topic_,
81 
82  getSdfParam<double>(_sdf, "refMagNorth", ref_mag_north, kDefaultRefMagNorth);
83  getSdfParam<double>(_sdf, "refMagEast", ref_mag_east, kDefaultRefMagEast);
84  getSdfParam<double>(_sdf, "refMagDown", ref_mag_down, kDefaultRefMagDown);
85  getSdfParam<SdfVector3>(_sdf, "noiseNormal", noise_normal, zeros3);
86  getSdfParam<SdfVector3>(_sdf, "noiseUniformInitialBias",
87  noise_uniform_initial_bias, zeros3);
88 
89  // Listen to the update event. This event is broadcast every simulation
90  // iteration.
91  this->updateConnection_ = event::Events::ConnectWorldUpdateBegin(
92  boost::bind(&GazeboMagnetometerPlugin::OnUpdate, this, _1));
93 
94  // Create the normal noise distributions
95  noise_n_[0] = NormalDistribution(0, noise_normal.X());
96  noise_n_[1] = NormalDistribution(0, noise_normal.Y());
97  noise_n_[2] = NormalDistribution(0, noise_normal.Z());
98 
99  // Create the uniform noise distribution for initial bias
100  UniformDistribution initial_bias[3];
101  initial_bias[0] = UniformDistribution(-noise_uniform_initial_bias.X(),
102  noise_uniform_initial_bias.X());
103  initial_bias[1] = UniformDistribution(-noise_uniform_initial_bias.Y(),
104  noise_uniform_initial_bias.Y());
105  initial_bias[2] = UniformDistribution(-noise_uniform_initial_bias.Z(),
106  noise_uniform_initial_bias.Z());
107 
108  // Initialize the reference magnetic field vector in world frame, taking into
109  // account the initial bias
110  mag_W_ = ignition::math::Vector3d (ref_mag_north + initial_bias[0](random_generator_),
111  ref_mag_east + initial_bias[1](random_generator_),
112  ref_mag_down + initial_bias[2](random_generator_));
113 
114  // Fill the static parts of the magnetometer message.
115  mag_message_.mutable_header()->set_frame_id(frame_id_);
116 
117  for (int i = 0; i < 9; i++) {
118  switch (i) {
119  case 0:
120  mag_message_.add_magnetic_field_covariance(noise_normal.X() *
121  noise_normal.X());
122  break;
123  case 1:
124  case 2:
125  case 3:
126  mag_message_.add_magnetic_field_covariance(0);
127  break;
128  case 4:
129  mag_message_.add_magnetic_field_covariance(noise_normal.Y() *
130  noise_normal.Y());
131  break;
132  case 5:
133  case 6:
134  case 7:
135  mag_message_.add_magnetic_field_covariance(0);
136  break;
137  case 8:
138  mag_message_.add_magnetic_field_covariance(noise_normal.Z() *
139  noise_normal.Z());
140  break;
141  }
142  }
143 }
144 
145 void GazeboMagnetometerPlugin::OnUpdate(const common::UpdateInfo& _info) {
146  if (kPrintOnUpdates) {
147  gzdbg << __FUNCTION__ << "() called." << std::endl;
148  }
149 
150  if (!pubs_and_subs_created_) {
152  pubs_and_subs_created_ = true;
153  }
154 
155  // Get the current pose and time from Gazebo
156  ignition::math::Pose3d T_W_B = link_->WorldPose();
157  common::Time current_time = world_->SimTime();
158 
159  // Calculate the magnetic field noise.
160  ignition::math::Vector3d mag_noise(noise_n_[0](random_generator_),
163 
164  // Rotate the earth magnetic field into the inertial frame
165  ignition::math::Vector3d field_B = T_W_B.Rot().RotateVectorReverse(mag_W_ + mag_noise);
166 
167  // Fill the magnetic field message
168  mag_message_.mutable_header()->mutable_stamp()->set_sec(current_time.sec);
169  mag_message_.mutable_header()->mutable_stamp()->set_nsec(current_time.nsec);
170  mag_message_.mutable_magnetic_field()->set_x(field_B.X());
171  mag_message_.mutable_magnetic_field()->set_y(field_B.Y());
172  mag_message_.mutable_magnetic_field()->set_z(field_B.Z());
173 
174  // Publish the message
176 }
177 
179  // Create temporary "ConnectGazeboToRosTopic" publisher and message
180  gazebo::transport::PublisherPtr connect_gazebo_to_ros_topic_pub =
181  node_handle_->Advertise<gz_std_msgs::ConnectGazeboToRosTopic>(
182  "~/" + kConnectGazeboToRosSubtopic, 1);
183 
184  // ============================================ //
185  // ========= MAGNETIC FIELD MSG SETUP ========= //
186  // ============================================ //
187 
188  magnetometer_pub_ = node_handle_->Advertise<gz_sensor_msgs::MagneticField>(
189  "~/" + namespace_ + "/" + magnetometer_topic_, 1);
190 
191  gz_std_msgs::ConnectGazeboToRosTopic connect_gazebo_to_ros_topic_msg;
192  // connect_gazebo_to_ros_topic_msg.set_gazebo_namespace(namespace_);
193  connect_gazebo_to_ros_topic_msg.set_gazebo_topic("~/" + namespace_ + "/" +
194  magnetometer_topic_);
195  connect_gazebo_to_ros_topic_msg.set_ros_topic(namespace_ + "/" +
196  magnetometer_topic_);
197  connect_gazebo_to_ros_topic_msg.set_msgtype(
198  gz_std_msgs::ConnectGazeboToRosTopic::MAGNETIC_FIELD);
199  connect_gazebo_to_ros_topic_pub->Publish(connect_gazebo_to_ros_topic_msg,
200  true);
201 }
202 
204 
205 } // namespace gazebo
void CreatePubsAndSubs()
Creates all required publishers and subscribers, incl. routing of messages to/from ROS if required...
gz_sensor_msgs::MagneticField mag_message_
Magnetic field message.
bool pubs_and_subs_created_
Flag that is set to true once CreatePubsAndSubs() is called, used to prevent CreatePubsAndSubs() from...
void OnUpdate(const common::UpdateInfo &)
static constexpr double kDefaultRefMagEast
static const bool kPrintOnPluginLoad
Definition: common.h:41
std::uniform_real_distribution UniformDistribution
static constexpr char MAGNETIC_FIELD[]
static constexpr double kDefaultRefMagDown
gazebo::transport::PublisherPtr magnetometer_pub_
static const bool kPrintOnUpdates
Definition: common.h:42
physics::LinkPtr link_
Pointer to the link.
GZ_REGISTER_MODEL_PLUGIN(GazeboRosP3D)
static const std::string kConnectGazeboToRosSubtopic
Definition: common.h:56
physics::ModelPtr model_
Pointer to the model.
void Load(physics::ModelPtr _model, sdf::ElementPtr _sdf)
static constexpr double kDefaultRefMagNorth
physics::WorldPtr world_
Pointer to the world.


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