gazebo_ros_bumper.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 <gazebo_plugins/gazebo_ros_bumper.h>
00028 
00029 #include "physics/World.hh"
00030 #include "physics/HingeJoint.hh"
00031 #include "physics/Contact.hh"
00032 #include "sensors/Sensor.hh"
00033 #include "sdf/interface/SDF.hh"
00034 #include "sdf/interface/Param.hh"
00035 #include "common/Exception.hh"
00036 #include "sensors/SensorTypes.hh"
00037 #include "math/Pose.hh"
00038 #include "math/Quaternion.hh"
00039 #include "math/Vector3.hh"
00040 
00041 #include "tf/tf.h"
00042 
00043 namespace gazebo
00044 {
00045 
00047 // Constructor
00048 GazeboRosBumper::GazeboRosBumper()
00049   : ContactPlugin()
00050 {
00051   this->contact_connect_count_ = 0;
00052 }
00053 
00055 // Destructor
00056 GazeboRosBumper::~GazeboRosBumper()
00057 {
00058   this->rosnode_->shutdown();
00059   this->callback_queue_thread_.join();
00060 
00061   delete this->rosnode_;
00062 }
00063 
00065 // Load the controller
00066 void GazeboRosBumper::Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf)
00067 {
00068   ContactPlugin::Load(_parent, _sdf);
00069 
00070   this->robot_namespace_ = "";
00071   if (_sdf->HasElement("robotNamespace"))
00072     this->robot_namespace_ = _sdf->GetElement("robotNamespace")->GetValueString() + "/";
00073 
00074   // "publishing contact/collisions to this topic name: " << this->bumper_topic_name_ << std::endl;
00075   this->bumper_topic_name_ = "bumper_states";
00076   if (_sdf->GetElement("bumperTopicName"))
00077     this->bumper_topic_name_ = _sdf->GetElement("bumperTopicName")->GetValueString();
00078 
00079   // "transform contact/collisions pose, forces to this body (link) name: " << this->frame_name_ << std::endl;
00080   if (!_sdf->HasElement("frameName"))
00081   {
00082     ROS_INFO("bumper plugin missing <frameName>, defaults to world");
00083     this->frame_name_ = "world";
00084   }
00085   else
00086     this->frame_name_ = _sdf->GetElement("frameName")->GetValueString();
00087 
00088   if (!ros::isInitialized())
00089   {
00090     int argc = 0;
00091     char** argv = NULL;
00092     ros::init(argc,argv,"gazebo",
00093         ros::init_options::NoSigintHandler|ros::init_options::AnonymousName);
00094   }
00095 
00096   this->rosnode_ = new ros::NodeHandle(this->robot_namespace_);
00097 
00098   // resolve tf prefix
00099   std::string prefix;
00100   this->rosnode_->getParam(std::string("tf_prefix"), prefix);
00101   this->frame_name_ = tf::resolve(prefix, this->frame_name_);
00102 
00103   ros::AdvertiseOptions ao = 
00104     ros::AdvertiseOptions::create<gazebo_msgs::ContactsState>(
00105         std::string(this->bumper_topic_name_),1,
00106         boost::bind( &GazeboRosBumper::ContactConnect,this),
00107         boost::bind( &GazeboRosBumper::ContactDisconnect,this), 
00108         ros::VoidPtr(), &this->contact_queue_);
00109   this->contact_pub_ = this->rosnode_->advertise(ao);
00110 
00111   // Initialize
00112   // preset myFrame to NULL, will search for the body with matching name in UpdateChild()
00113   // since most bodies are constructed on the fly
00114   //this->myFrame = NULL;
00115   // start custom queue for contact bumper
00116   this->callback_queue_thread_ = boost::thread( 
00117       boost::bind( &GazeboRosBumper::ContactQueueThread,this ) );
00118 
00119   // Listen to the update event. This event is broadcast every
00120   // simulation iteration.
00121   this->update_connection_ = event::Events::ConnectWorldUpdateStart(
00122       boost::bind(&GazeboRosBumper::UpdateChild, this));
00123 }
00124 
00126 // Increment count
00127 void GazeboRosBumper::ContactConnect()
00128 {
00129   this->contact_connect_count_++;
00130 }
00132 // Decrement count
00133 void GazeboRosBumper::ContactDisconnect()
00134 {
00135   this->contact_connect_count_--;
00136 }
00137 
00139 // Update the controller
00140 void GazeboRosBumper::UpdateChild()
00141 {
00142   if (this->contact_connect_count_ <= 0) 
00143     return;
00144 
00145 /*
00147   if (this->myFrame == NULL && this->frame_name_ != "world" && this->frame_name_ != "/map" && this->frame_name_ != "map")
00148   {
00149     // lock in case a model is being spawned
00150     boost::recursive_mutex::scoped_lock lock(*Simulator::Instance()->GetMRMutex());
00151     // look through all models in the world, search for body name that matches frameName
00152     std::vector<Model*> all_models = World::Instance()->GetModels();
00153     for (std::vector<Model*>::iterator iter = all_models.begin(); iter != all_models.end(); iter++)
00154     {
00155       if (*iter) this->myFrame = dynamic_cast<Body*>((*iter)->GetBody(this->frame_name_));
00156       if (this->myFrame) break;
00157     }
00158 
00159     // not found
00160     if (this->myFrame == NULL)
00161     {
00162       ROS_DEBUG("gazebo_ros_bumper plugin: frameName: %s does not exist yet, will not publish\n",this->frame_name_.c_str());
00163       return;
00164     }
00165   }
00166 */
00167   boost::mutex::scoped_lock sclock(*this->parentSensor->GetUpdateMutex());
00168 
00169   std::map<std::string, physics::Contact> contacts;
00170   math::Vector3 body1ContactForce, body2ContactForce;
00171   common::Time cur_time;
00172 
00173   cur_time = this->world->GetSimTime();
00174 
00175   // information are in inertial coordinates
00176   this->contact_state_msg_.header.frame_id = this->frame_name_;  
00177   this->contact_state_msg_.header.stamp.sec = cur_time.sec;
00178   this->contact_state_msg_.header.stamp.nsec = cur_time.nsec;;
00179 
00180   // set contact states size
00181   this->contact_state_msg_.states.clear();  // one contact_count per pair of geoms in contact (up to 64 contact points per pair of geoms)
00182 
00183   // For each collision that the sensor is monitoring
00184   for (unsigned int i=0; i < this->parentSensor->GetCollisionCount();i++)
00185   {
00186     int l = 0;
00187     std::string collisionName = this->parentSensor->GetCollisionName(i);
00188     contacts = this->parentSensor->GetContacts(collisionName);
00189 
00190     // populate header
00191     //if (cur_body)
00192     //  this->contactMsg.header.frame_id = cur_body->GetName();  // @todo: transform results to the link name
00193     
00194     // get contact array sizes for this contact param.  
00195     // each contact param has num_contact_count contact pairs,
00196     // each contact geom pair has up to 64 contact points
00197     //std::vector<physics::Collision*> contact_geoms;
00198 
00199     // get reference frame (body(link)) pose and subtract from it to get 
00200     // relative force, torque, position and normal vectors
00201     math::Pose pose, frame_pose;
00202     math::Quaternion rot, frame_rot;
00203     math::Vector3 pos, frame_pos;
00204     /*
00205     if (this->myFrame)
00206     {
00207       frame_pose = this->myFrame->GetWorldPose();//-this->myBody->GetCoMPose();
00208       frame_pos = frame_pose.pos;
00209       frame_rot = frame_pose.rot;
00210     }
00211     else
00212     */
00213     {
00214       // no specific frames specified, use identity pose, keeping 
00215       // relative frame at inertial origin
00216       frame_pos = math::Vector3(0,0,0);
00217       frame_rot = math::Quaternion(1,0,0,0); // gazebo u,x,y,z == identity
00218       frame_pose = math::Pose(frame_pos, frame_rot);
00219     }
00220 
00221     // For each collision contact 
00222     for (std::map<std::string, gazebo::physics::Contact>::iterator citer = 
00223          contacts.begin(); citer != contacts.end() ; citer++)
00224     {
00225       gazebo::physics::Contact contact = citer->second;
00226 
00227       // For each geom-geom contact
00228       unsigned int pts = contact.count;
00229 
00230       std::ostringstream stream;
00231       stream    << "touched!    i:" << l
00232         << "      my geom:" << contact.collision1->GetName()
00233         << "   other geom:" << contact.collision2->GetName()
00234         << "         time:" << contact.time
00235         << std::endl;
00236 
00237       gazebo_msgs::ContactState state;
00238       state.info = stream.str();
00239       state.collision1_name = contact.collision1->GetName();
00240       state.collision2_name = contact.collision2->GetName();
00241 
00242       state.wrenches.clear();
00243       state.contact_positions.clear();
00244       state.contact_normals.clear();
00245       state.depths.clear();
00246 
00247       // sum up all wrenches for each DOF
00248       geometry_msgs::Wrench total_wrench;
00249       total_wrench.force.x = 0;
00250       total_wrench.force.y = 0;
00251       total_wrench.force.z = 0;
00252       total_wrench.torque.x = 0;
00253       total_wrench.torque.y = 0;
00254       total_wrench.torque.z = 0;
00255 
00256       for (unsigned int k=0; k < pts; k++)
00257       {
00258         // rotate into user specified frame. 
00259         // frame_rot is identity if world is used.
00260         math::Vector3 force = frame_rot.RotateVectorReverse(
00261             math::Vector3(contact.forces[k].body1Force.x,
00262               contact.forces[k].body1Force.y,
00263               contact.forces[k].body1Force.z));
00264         math::Vector3 torque = frame_rot.RotateVectorReverse(
00265             math::Vector3(contact.forces[k].body1Torque.x,
00266               contact.forces[k].body1Torque.y,
00267               contact.forces[k].body1Torque.z));
00268 
00269         // set wrenches
00270         geometry_msgs::Wrench wrench;
00271         wrench.force.x  = force.x;
00272         wrench.force.y  = force.y;
00273         wrench.force.z  = force.z;
00274         wrench.torque.x = torque.x;
00275         wrench.torque.y = torque.y;
00276         wrench.torque.z = torque.z;
00277         state.wrenches.push_back(wrench);
00278         total_wrench.force.x  += wrench.force.x ;
00279         total_wrench.force.y  += wrench.force.y ;
00280         total_wrench.force.z  += wrench.force.z ;
00281         total_wrench.torque.x += wrench.torque.x;
00282         total_wrench.torque.y += wrench.torque.y;
00283         total_wrench.torque.z += wrench.torque.z;
00284 
00285         // transform contact positions into relative frame
00286         // set contact positions
00287         gazebo::math::Vector3 contact_position;
00288         contact_position = contact.positions[k] - frame_pos;
00289         contact_position = frame_rot.RotateVectorReverse(contact_position);
00290         geometry_msgs::Vector3 tmp;
00291         tmp.x = contact_position.x;
00292         tmp.y = contact_position.y;
00293         tmp.z = contact_position.z;
00294         state.contact_positions.push_back(tmp);
00295 
00296         // rotate normal into user specified frame. 
00297         // frame_rot is identity if world is used.
00298         math::Vector3 normal = frame_rot.RotateVectorReverse(
00299             math::Vector3(contact.normals[k].x,
00300               contact.normals[k].y,
00301               contact.normals[k].z));
00302         // set contact normals
00303         geometry_msgs::Vector3 contact_normal;
00304         contact_normal.x = normal.x;
00305         contact_normal.y = normal.y;
00306         contact_normal.z = normal.z;
00307         state.contact_normals.push_back(contact_normal);
00308 
00309         // set contact depth, interpenetration
00310         state.depths.push_back(contact.depths[k]);
00311       }
00312       state.total_wrench = total_wrench;
00313       this->contact_state_msg_.states.push_back(state);
00314     }
00315   }
00316 
00317   this->contact_pub_.publish(this->contact_state_msg_);
00318 }
00319 
00320 
00322 // Put laser data to the interface
00323 void GazeboRosBumper::ContactQueueThread()
00324 {
00325   static const double timeout = 0.01;
00326 
00327   while (this->rosnode_->ok())
00328   {
00329     this->contact_queue_.callAvailable(ros::WallDuration(timeout));
00330   }
00331 }
00332 
00333 // Register this plugin with the simulator
00334 GZ_REGISTER_SENSOR_PLUGIN(GazeboRosBumper)
00335 
00336 }


gazebo_plugins
Author(s): Sachin Chitta, Stu Glaser, John Hsu
autogenerated on Sun Jan 5 2014 11:34:58