Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00048 GazeboRosBumper::GazeboRosBumper()
00049 : ContactPlugin()
00050 {
00051 this->contact_connect_count_ = 0;
00052 }
00053
00055
00056 GazeboRosBumper::~GazeboRosBumper()
00057 {
00058 this->rosnode_->shutdown();
00059 this->callback_queue_thread_.join();
00060
00061 delete this->rosnode_;
00062 }
00063
00065
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
00075 this->bumper_topic_name_ = "bumper_states";
00076 if (_sdf->GetElement("bumperTopicName"))
00077 this->bumper_topic_name_ = _sdf->GetElement("bumperTopicName")->GetValueString();
00078
00079
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
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
00112
00113
00114
00115
00116 this->callback_queue_thread_ = boost::thread(
00117 boost::bind( &GazeboRosBumper::ContactQueueThread,this ) );
00118
00119
00120
00121 this->update_connection_ = event::Events::ConnectWorldUpdateStart(
00122 boost::bind(&GazeboRosBumper::UpdateChild, this));
00123 }
00124
00126
00127 void GazeboRosBumper::ContactConnect()
00128 {
00129 this->contact_connect_count_++;
00130 }
00132
00133 void GazeboRosBumper::ContactDisconnect()
00134 {
00135 this->contact_connect_count_--;
00136 }
00137
00139
00140 void GazeboRosBumper::UpdateChild()
00141 {
00142 if (this->contact_connect_count_ <= 0)
00143 return;
00144
00145
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
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
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
00181 this->contact_state_msg_.states.clear();
00182
00183
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
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 math::Pose pose, frame_pose;
00202 math::Quaternion rot, frame_rot;
00203 math::Vector3 pos, frame_pos;
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 {
00214
00215
00216 frame_pos = math::Vector3(0,0,0);
00217 frame_rot = math::Quaternion(1,0,0,0);
00218 frame_pose = math::Pose(frame_pos, frame_rot);
00219 }
00220
00221
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
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
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
00259
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
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
00286
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
00297
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
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
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
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
00334 GZ_REGISTER_SENSOR_PLUGIN(GazeboRosBumper)
00335
00336 }