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 <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
00067 std::string worldName = sensor_->GetWorldName();
00068 parent_ = gazebo::physics::get_world(worldName);
00069
00070
00071
00072 this->robot_namespace_ = "";
00073 if (_sdf->HasElement("robotNamespace"))
00074 this->robot_namespace_ = _sdf->GetElement("robotNamespace")->GetValueString() + "/";
00075
00076
00077 this->bumper_topic_name_ = "bumper_base";
00078 if (_sdf->GetElement("bumperTopicName"))
00079 this->bumper_topic_name_ = _sdf->GetElement("bumperTopicName")->GetValueString();
00080
00081
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
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
00108
00109
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
00117
00118
00119
00120
00121
00122 this->callback_queue_thread_ = boost::thread(boost::bind( &ReemGazeboBumper::ContactQueueThread,this ) );
00123
00124
00125
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
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
00158
00159
00160
00161
00162
00163 this->contact_state_msg_.states.clear();
00164
00165
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
00178
00179 frame_pos = math::Vector3(0,0,0);
00180 frame_rot = math::Quaternion(1,0,0,0);
00181 frame_pose = math::Pose(frame_pos, frame_rot);
00182 }
00183
00184
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
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
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
00222
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
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
00249
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
00260
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
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
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
00308 GZ_REGISTER_SENSOR_PLUGIN(ReemGazeboBumper)
00309
00310 }