gazebo_magnetometer_plugin.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2016 Pavel Vechersky, ASL, ETH Zurich, Switzerland
00003  * Copyright 2016 Geoffrey Hunter <gbmhunter@gmail.com>
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 // MODULE HEADER INCLUDE
00018 #include "rotors_gazebo_plugins/gazebo_magnetometer_plugin.h"
00019 
00020 #include <mav_msgs/default_topics.h>  // This comes from the mav_comm repo
00021 
00022 #include "ConnectGazeboToRosTopic.pb.h"
00023 
00024 namespace gazebo {
00025 
00026 GazeboMagnetometerPlugin::GazeboMagnetometerPlugin()
00027     : ModelPlugin(),
00028       random_generator_(random_device_()),
00029       pubs_and_subs_created_(false) {
00030   // Nothing
00031 }
00032 
00033 GazeboMagnetometerPlugin::~GazeboMagnetometerPlugin() {
00034 }
00035 
00036 void GazeboMagnetometerPlugin::Load(physics::ModelPtr _model,
00037                                     sdf::ElementPtr _sdf) {
00038   if (kPrintOnPluginLoad) {
00039     gzdbg << __FUNCTION__ << "() called." << std::endl;
00040   }
00041 
00042   // Store the pointer to the model and the world
00043   model_ = _model;
00044   world_ = model_->GetWorld();
00045 
00046   // Use the robot namespace to create the node handle
00047   if (_sdf->HasElement("robotNamespace"))
00048     namespace_ = _sdf->GetElement("robotNamespace")->Get<std::string>();
00049   else
00050     gzerr << "[gazebo_magnetometer_plugin] Please specify a robotNamespace.\n";
00051 
00052   node_handle_ = gazebo::transport::NodePtr(new transport::Node());
00053 
00054   // Initialise with default namespace (typically /gazebo/default/)
00055   node_handle_->Init();
00056 
00057   // Use the link name as the frame id
00058   std::string link_name;
00059   if (_sdf->HasElement("linkName"))
00060     link_name = _sdf->GetElement("linkName")->Get<std::string>();
00061   else
00062     gzerr << "[gazebo_magnetometer_plugin] Please specify a linkName.\n";
00063   // Get the pointer to the link
00064   link_ = model_->GetLink(link_name);
00065   if (link_ == NULL)
00066     gzthrow("[gazebo_magnetometer_plugin] Couldn't find specified link \""
00067             << link_name << "\".");
00068 
00069   frame_id_ = link_name;
00070 
00071   double ref_mag_north;
00072   double ref_mag_east;
00073   double ref_mag_down;
00074   SdfVector3 noise_normal;
00075   SdfVector3 noise_uniform_initial_bias;
00076   const SdfVector3 zeros3(0.0, 0.0, 0.0);
00077 
00078   // Retrieve the rest of the SDF parameters
00079   getSdfParam<std::string>(_sdf, "magnetometerTopic", magnetometer_topic_,
00080                            mav_msgs::default_topics::MAGNETIC_FIELD);
00081 
00082   getSdfParam<double>(_sdf, "refMagNorth", ref_mag_north, kDefaultRefMagNorth);
00083   getSdfParam<double>(_sdf, "refMagEast", ref_mag_east, kDefaultRefMagEast);
00084   getSdfParam<double>(_sdf, "refMagDown", ref_mag_down, kDefaultRefMagDown);
00085   getSdfParam<SdfVector3>(_sdf, "noiseNormal", noise_normal, zeros3);
00086   getSdfParam<SdfVector3>(_sdf, "noiseUniformInitialBias",
00087                           noise_uniform_initial_bias, zeros3);
00088 
00089   // Listen to the update event. This event is broadcast every simulation
00090   // iteration.
00091   this->updateConnection_ = event::Events::ConnectWorldUpdateBegin(
00092       boost::bind(&GazeboMagnetometerPlugin::OnUpdate, this, _1));
00093 
00094   // Create the normal noise distributions
00095   noise_n_[0] = NormalDistribution(0, noise_normal.X());
00096   noise_n_[1] = NormalDistribution(0, noise_normal.Y());
00097   noise_n_[2] = NormalDistribution(0, noise_normal.Z());
00098 
00099   // Create the uniform noise distribution for initial bias
00100   UniformDistribution initial_bias[3];
00101   initial_bias[0] = UniformDistribution(-noise_uniform_initial_bias.X(),
00102                                         noise_uniform_initial_bias.X());
00103   initial_bias[1] = UniformDistribution(-noise_uniform_initial_bias.Y(),
00104                                         noise_uniform_initial_bias.Y());
00105   initial_bias[2] = UniformDistribution(-noise_uniform_initial_bias.Z(),
00106                                         noise_uniform_initial_bias.Z());
00107 
00108   // Initialize the reference magnetic field vector in world frame, taking into
00109   // account the initial bias
00110   mag_W_ = ignition::math::Vector3d (ref_mag_north + initial_bias[0](random_generator_),
00111                          ref_mag_east + initial_bias[1](random_generator_),
00112                          ref_mag_down + initial_bias[2](random_generator_));
00113 
00114   // Fill the static parts of the magnetometer message.
00115   mag_message_.mutable_header()->set_frame_id(frame_id_);
00116 
00117   for (int i = 0; i < 9; i++) {
00118     switch (i) {
00119       case 0:
00120         mag_message_.add_magnetic_field_covariance(noise_normal.X() *
00121                                                    noise_normal.X());
00122         break;
00123       case 1:
00124       case 2:
00125       case 3:
00126         mag_message_.add_magnetic_field_covariance(0);
00127         break;
00128       case 4:
00129         mag_message_.add_magnetic_field_covariance(noise_normal.Y() *
00130                                                    noise_normal.Y());
00131         break;
00132       case 5:
00133       case 6:
00134       case 7:
00135         mag_message_.add_magnetic_field_covariance(0);
00136         break;
00137       case 8:
00138         mag_message_.add_magnetic_field_covariance(noise_normal.Z() *
00139                                                    noise_normal.Z());
00140         break;
00141     }
00142   }
00143 }
00144 
00145 void GazeboMagnetometerPlugin::OnUpdate(const common::UpdateInfo& _info) {
00146   if (kPrintOnUpdates) {
00147     gzdbg << __FUNCTION__ << "() called." << std::endl;
00148   }
00149 
00150   if (!pubs_and_subs_created_) {
00151     CreatePubsAndSubs();
00152     pubs_and_subs_created_ = true;
00153   }
00154 
00155   // Get the current pose and time from Gazebo
00156   ignition::math::Pose3d T_W_B = link_->WorldPose();
00157   common::Time current_time = world_->SimTime();
00158 
00159   // Calculate the magnetic field noise.
00160   ignition::math::Vector3d mag_noise(noise_n_[0](random_generator_),
00161                           noise_n_[1](random_generator_),
00162                           noise_n_[2](random_generator_));
00163 
00164   // Rotate the earth magnetic field into the inertial frame
00165   ignition::math::Vector3d field_B = T_W_B.Rot().RotateVectorReverse(mag_W_ + mag_noise);
00166 
00167   // Fill the magnetic field message
00168   mag_message_.mutable_header()->mutable_stamp()->set_sec(current_time.sec);
00169   mag_message_.mutable_header()->mutable_stamp()->set_nsec(current_time.nsec);
00170   mag_message_.mutable_magnetic_field()->set_x(field_B.X());
00171   mag_message_.mutable_magnetic_field()->set_y(field_B.Y());
00172   mag_message_.mutable_magnetic_field()->set_z(field_B.Z());
00173 
00174   // Publish the message
00175   magnetometer_pub_->Publish(mag_message_);
00176 }
00177 
00178 void GazeboMagnetometerPlugin::CreatePubsAndSubs() {
00179   // Create temporary "ConnectGazeboToRosTopic" publisher and message
00180   gazebo::transport::PublisherPtr connect_gazebo_to_ros_topic_pub =
00181       node_handle_->Advertise<gz_std_msgs::ConnectGazeboToRosTopic>(
00182           "~/" + kConnectGazeboToRosSubtopic, 1);
00183 
00184   // ============================================ //
00185   // ========= MAGNETIC FIELD MSG SETUP ========= //
00186   // ============================================ //
00187 
00188   magnetometer_pub_ = node_handle_->Advertise<gz_sensor_msgs::MagneticField>(
00189       "~/" + namespace_ + "/" + magnetometer_topic_, 1);
00190 
00191   gz_std_msgs::ConnectGazeboToRosTopic connect_gazebo_to_ros_topic_msg;
00192   // connect_gazebo_to_ros_topic_msg.set_gazebo_namespace(namespace_);
00193   connect_gazebo_to_ros_topic_msg.set_gazebo_topic("~/" + namespace_ + "/" +
00194                                                    magnetometer_topic_);
00195   connect_gazebo_to_ros_topic_msg.set_ros_topic(namespace_ + "/" +
00196                                                 magnetometer_topic_);
00197   connect_gazebo_to_ros_topic_msg.set_msgtype(
00198       gz_std_msgs::ConnectGazeboToRosTopic::MAGNETIC_FIELD);
00199   connect_gazebo_to_ros_topic_pub->Publish(connect_gazebo_to_ros_topic_msg,
00200                                            true);
00201 }
00202 
00203 GZ_REGISTER_MODEL_PLUGIN(GazeboMagnetometerPlugin);
00204 
00205 }  // namespace gazebo


rotors_gazebo_plugins
Author(s): Fadri Furrer, Michael Burri, Mina Kamel, Janosch Nikolic, Markus Achtelik
autogenerated on Thu Apr 18 2019 02:43:43