reem_bumper_gazebo.cpp
Go to the documentation of this file.
00001 /*
00002  *  Gazebo - Outdoor Multi-Robot Simulator
00003  *  Copyright (C) 2003
00004  *     Nate Koenig & Andrew Howard
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 /*
00022  * Desc: Bumper controller
00023  * Author: Nate Koenig
00024  * Date: 09 Setp. 2008
00025  */
00026 
00027 #include <reem_bumper_gazebo/reem_bumper_gazebo.h>
00028 #include <gazebo/common/Event.hh>
00029 #include <gazebo/physics/physics.h>
00030 #include <gazebo/physics/Contact.hh>
00031 #include <gazebo/physics/Collision.hh>
00032 
00033 #include "math/Pose.hh"
00034 #include "math/Quaternion.hh"
00035 #include "math/Vector3.hh"
00036 
00037 #include "tf/tf.h"
00038 
00039 namespace gazebo
00040 {
00041 
00042 ReemGazeboBumper::ReemGazeboBumper()
00043 {
00044   this->contact_connect_count_ = 0;
00045 }
00046 
00047 ReemGazeboBumper::~ReemGazeboBumper()
00048 {
00049   this->rosnode_->shutdown();
00050   this->callback_queue_thread_.join();
00051 
00052   delete this->rosnode_;
00053 }
00054 
00055 void ReemGazeboBumper::Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf)
00056 {
00057     ROS_INFO_STREAM("Loading gazebo bumper");
00058 
00059     sensor_ = boost::shared_dynamic_cast<sensors::ContactSensor>(_parent);
00060     if (!sensor_)
00061     {
00062         gzthrow("GazeboRosSonar requires a Ray Sensor as its parent");
00063         return;
00064     }
00065 
00066     // Get the world name.
00067     std::string worldName = sensor_->GetWorldName();
00068     parent_ = gazebo::physics::get_world(worldName);
00069 
00070   //  ContactPlugin::Load(_parent, _sdf);
00071 
00072     this->robot_namespace_ = "";
00073     if (_sdf->HasElement("robotNamespace"))
00074         this->robot_namespace_ = _sdf->GetElement("robotNamespace")->GetValueString() + "/";
00075 
00076     // "publishing contact/collisions to this topic name: " << this->bumper_topic_name_ << std::endl;
00077     this->bumper_topic_name_ = "bumper_base";
00078     if (_sdf->GetElement("bumperTopicName"))
00079         this->bumper_topic_name_ = _sdf->GetElement("bumperTopicName")->GetValueString();
00080 
00081     // "transform contact/collisions pose, forces to this body (link) name: " << this->frame_name_ << std::endl;
00082     if (!_sdf->HasElement("frameName"))
00083     {
00084         ROS_INFO("bumper plugin missing <frameName>, defaults to world");
00085         this->frame_name_ = "world";
00086     }
00087     else
00088         this->frame_name_ = _sdf->GetElement("frameName")->GetValueString();
00089 
00090     ROS_INFO("Loaded with values:   robotNamespace = %s, bumperTopicName = %s, frameName = %s",
00091              this->robot_namespace_.c_str(), this->bumper_topic_name_.c_str(),this->frame_name_.c_str());
00092 
00093     if (!ros::isInitialized())
00094     {
00095         int argc = 0;
00096         char** argv = NULL;
00097         ros::init(argc,argv,"gazebo",ros::init_options::NoSigintHandler|ros::init_options::AnonymousName);
00098     }
00099 
00100     this->rosnode_ = new ros::NodeHandle(this->robot_namespace_);
00101 
00102     // resolve tf prefix
00103     std::string prefix;
00104     this->rosnode_->getParam(std::string("tf_prefix"), prefix);
00105     this->frame_name_ = tf::resolve(prefix, this->frame_name_);
00106 
00107     //contact_pub_ = rosnode_->advertise<reem_msgs::Bumper>(this->bumper_topic_name_.c_str(),1);
00108 
00109 //    gazebo_msgs::ContactsState
00110     ros::AdvertiseOptions ao = ros::AdvertiseOptions::create<reem_msgs::Bumper>(std::string(this->bumper_topic_name_),1,
00111                                                                                 boost::bind( &ReemGazeboBumper::ContactConnect,this),
00112                                                                                 boost::bind( &ReemGazeboBumper::ContactDisconnect,this),
00113                                                                                 ros::VoidPtr(), &this->contact_queue_);
00114     this->contact_pub_ = this->rosnode_->advertise(ao);
00115 
00116     // Initialize
00117     // preset myFrame to NULL, will search for the body with matching name in UpdateChild()
00118     // since most bodies are constructed on the fly
00119     //this->myFrame = NULL;
00120     // start custom queue for contact bumper
00121 
00122     this->callback_queue_thread_ = boost::thread(boost::bind( &ReemGazeboBumper::ContactQueueThread,this ) );
00123 
00124     // Listen to the update event. This event is broadcast every
00125     // simulation iteration.
00126     this->update_connection_ = event::Events::ConnectWorldUpdateStart(boost::bind(&ReemGazeboBumper::Update, this));
00127 
00128     ROS_INFO("loaded bumper");
00129 }
00130 
00131 void ReemGazeboBumper::ContactConnect()
00132 {
00133   this->contact_connect_count_++;
00134 }
00135 
00136 void ReemGazeboBumper::ContactDisconnect()
00137 {
00138   this->contact_connect_count_--;
00139 }
00140 
00141 void ReemGazeboBumper::Update()
00142 {
00143   if (this->contact_connect_count_ <= 0)
00144     return;
00145 
00146  // boost::mutex::scoped_lock sclock(*this->parentSensor->GetUpdateMutex());
00147 
00148   std::map<std::string, physics::Contact> contacts;
00149   math::Vector3 body1ContactForce, body2ContactForce;
00150   common::Time cur_time;
00151 
00152   cur_time = parent_->GetSimTime();
00153 
00154   reem_msgs::Bumper bumperMsg;
00155   bumperMsg.header.stamp = ros::Time::now();
00156 
00157   // information are in inertial coordinates
00158   //this->contact_state_msg_.header.frame_id = this->frame_name_;
00159   //this->contact_state_msg_.header.stamp.sec = cur_time.sec;
00160   //this->contact_state_msg_.header.stamp.nsec = cur_time.nsec;
00161 
00162   // set contact states size
00163   this->contact_state_msg_.states.clear();  // one contact_count per pair of geoms in contact (up to 64 contact points per pair of geoms)
00164 
00165   // For each collision that the sensor is monitoring
00166   for (unsigned int i=0; i < sensor_->GetCollisionCount();i++)
00167   {
00168     int l = 0;
00169     std::string collisionName = sensor_->GetCollisionName(i);
00170     contacts = sensor_->GetContacts(collisionName);
00171 
00172     math::Pose pose, frame_pose;
00173     math::Quaternion rot, frame_rot;
00174     math::Vector3 pos, frame_pos;
00175 
00176     {
00177       // no specific frames specified, use identity pose, keeping
00178       // relative frame at inertial origin
00179       frame_pos = math::Vector3(0,0,0);
00180       frame_rot = math::Quaternion(1,0,0,0); // gazebo u,x,y,z == identity
00181       frame_pose = math::Pose(frame_pos, frame_rot);
00182     }
00183 
00184     // For each collision contact
00185     for (std::map<std::string, gazebo::physics::Contact>::iterator citer =
00186          contacts.begin(); citer != contacts.end() ; citer++)
00187     {
00188       gazebo::physics::Contact contact = citer->second;
00189 
00190       // For each geom-geom contact
00191       unsigned int pts = contact.count;
00192 
00193       std::ostringstream stream;
00194       stream    << "touched!    i:" << l
00195         << "      my geom:" << contact.collision1->GetName()
00196         << "   other geom:" << contact.collision2->GetName()
00197         << "         time:" << contact.time
00198         << std::endl;
00199 
00200       gazebo_msgs::ContactState state;
00201       state.info = stream.str();
00202       state.collision1_name = contact.collision1->GetName();
00203       state.collision2_name = contact.collision2->GetName();
00204 
00205       state.wrenches.clear();
00206       state.contact_positions.clear();
00207       state.contact_normals.clear();
00208       state.depths.clear();
00209 
00210       // sum up all wrenches for each DOF
00211       geometry_msgs::Wrench total_wrench;
00212       total_wrench.force.x = 0;
00213       total_wrench.force.y = 0;
00214       total_wrench.force.z = 0;
00215       total_wrench.torque.x = 0;
00216       total_wrench.torque.y = 0;
00217       total_wrench.torque.z = 0;
00218 
00219       for (unsigned int k=0; k < pts; k++)
00220       {
00221         // rotate into user specified frame.
00222         // frame_rot is identity if world is used.
00223         math::Vector3 force = frame_rot.RotateVectorReverse(
00224             math::Vector3(contact.forces[k].body1Force.x,
00225               contact.forces[k].body1Force.y,
00226               contact.forces[k].body1Force.z));
00227         math::Vector3 torque = frame_rot.RotateVectorReverse(
00228             math::Vector3(contact.forces[k].body1Torque.x,
00229               contact.forces[k].body1Torque.y,
00230               contact.forces[k].body1Torque.z));
00231 
00232         // set wrenches
00233         geometry_msgs::Wrench wrench;
00234         wrench.force.x  = force.x;
00235         wrench.force.y  = force.y;
00236         wrench.force.z  = force.z;
00237         wrench.torque.x = torque.x;
00238         wrench.torque.y = torque.y;
00239         wrench.torque.z = torque.z;
00240         state.wrenches.push_back(wrench);
00241         total_wrench.force.x  += wrench.force.x ;
00242         total_wrench.force.y  += wrench.force.y ;
00243         total_wrench.force.z  += wrench.force.z ;
00244         total_wrench.torque.x += wrench.torque.x;
00245         total_wrench.torque.y += wrench.torque.y;
00246         total_wrench.torque.z += wrench.torque.z;
00247 
00248         // transform contact positions into relative frame
00249         // set contact positions
00250         gazebo::math::Vector3 contact_position;
00251         contact_position = contact.positions[k] - frame_pos;
00252         contact_position = frame_rot.RotateVectorReverse(contact_position);
00253         geometry_msgs::Vector3 tmp;
00254         tmp.x = contact_position.x;
00255         tmp.y = contact_position.y;
00256         tmp.z = contact_position.z;
00257         state.contact_positions.push_back(tmp);
00258 
00259         // rotate normal into user specified frame.
00260         // frame_rot is identity if world is used.
00261         math::Vector3 normal = frame_rot.RotateVectorReverse(
00262             math::Vector3(contact.normals[k].x,
00263               contact.normals[k].y,
00264               contact.normals[k].z));
00265         // set contact normals
00266         geometry_msgs::Vector3 contact_normal;
00267         contact_normal.x = normal.x;
00268         contact_normal.y = normal.y;
00269         contact_normal.z = normal.z;
00270         state.contact_normals.push_back(contact_normal);
00271 
00272         // set contact depth, interpenetration
00273         state.depths.push_back(contact.depths[k]);
00274       }
00275       state.total_wrench = total_wrench;
00276       this->contact_state_msg_.states.push_back(state);
00277 
00278       if (state.contact_positions.empty())
00279       {
00280           bumperMsg.is_pressed = false;
00281       }
00282       else
00283       {
00284           bumperMsg.is_pressed = true;
00285       }
00286 
00287     }
00288   }
00289 
00290   this->contact_pub_.publish(bumperMsg);
00291 
00292   bumperMsg.is_pressed = false;
00293 
00294 }
00295 
00296 
00297 void ReemGazeboBumper::ContactQueueThread()
00298 {
00299   static const double timeout = 0.01;
00300 
00301   while (this->rosnode_->ok())
00302   {
00303     this->contact_queue_.callAvailable(ros::WallDuration(timeout));
00304   }
00305 }
00306 
00307 // Register this plugin with the simulator
00308 GZ_REGISTER_SENSOR_PLUGIN(ReemGazeboBumper)
00309 
00310 }


bumper_gazebo_plugin
Author(s): Jose Rafael Capriles
autogenerated on Thu Jan 2 2014 11:37:02