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 <gazebo/Global.hh>
00030 #include <gazebo/XMLConfig.hh>
00031 #include <gazebo/ContactSensor.hh>
00032 #include <gazebo/World.hh>
00033 #include <gazebo/gazebo.h>
00034 #include <gazebo/GazeboError.hh>
00035 #include <gazebo/ControllerFactory.hh>
00036 #include <gazebo/Simulator.hh>
00037 #include <gazebo/Body.hh>
00038 #include <gazebo/Model.hh>
00039 #include <gazebo/Geom.hh>
00040
00041 namespace gazebo
00042 {
00043
00044 GZ_REGISTER_DYNAMIC_CONTROLLER("gazebo_ros_bumper", GazeboRosBumper);
00045
00047
00048 GazeboRosBumper::GazeboRosBumper(Entity *parent )
00049 : Controller(parent)
00050 {
00051 this->myParent = dynamic_cast<ContactSensor*>(this->parent);
00052
00053 if (!this->myParent)
00054 gzthrow("Bumper controller requires a Contact Sensor as its parent");
00055
00056 Param::Begin(&this->parameters);
00057 this->bumperTopicNameP = new ParamT<std::string>("bumperTopicName", "", 1);
00058 this->frameNameP = new ParamT<std::string>("frameName", "world", 0);
00059 this->robotNamespaceP = new ParamT<std::string>("robotNamespace", "/", 0);
00060 Param::End();
00061
00062 this->contactConnectCount = 0;
00063 }
00064
00066
00067 GazeboRosBumper::~GazeboRosBumper()
00068 {
00069 delete this->robotNamespaceP;
00070 delete this->frameNameP;
00071 delete this->bumperTopicNameP;
00072 delete this->rosnode_;
00073 }
00074
00076
00077 void GazeboRosBumper::LoadChild(XMLConfigNode *node)
00078 {
00079 this->robotNamespaceP->Load(node);
00080 this->robotNamespace = this->robotNamespaceP->GetValue();
00081
00082 if (!ros::isInitialized())
00083 {
00084 int argc = 0;
00085 char** argv = NULL;
00086 ros::init(argc,argv,"gazebo",ros::init_options::NoSigintHandler|ros::init_options::AnonymousName);
00087 }
00088
00089 this->rosnode_ = new ros::NodeHandle(this->robotNamespace);
00090
00091
00092 this->bumperTopicNameP->Load(node);
00093 this->bumperTopicName = this->bumperTopicNameP->GetValue();
00094 ROS_DEBUG("publishing contact/collisions to topic name: %s",
00095 this->bumperTopicName.c_str());
00096
00097
00098 this->frameNameP->Load(node);
00099 this->frameName = this->frameNameP->GetValue();
00100
00101 #ifdef USE_CBQ
00102 ros::AdvertiseOptions ao = ros::AdvertiseOptions::create<gazebo_plugins::ContactsState>(
00103 this->bumperTopicName+std::string("/state"),1,
00104 boost::bind( &GazeboRosBumper::ContactConnect,this),
00105 boost::bind( &GazeboRosBumper::ContactDisconnect,this), ros::VoidPtr(), &this->contact_queue_);
00106 this->contact_pub_ = this->rosnode_->advertise(ao);
00107 #else
00108 this->contact_pub_ = this->rosnode_->advertise<gazebo_plugins::ContactsState>(this->bumperTopicName+std::string("/state"),1);
00109 #endif
00110 }
00111
00113
00114 void GazeboRosBumper::ContactConnect()
00115 {
00116 this->contactConnectCount++;
00117 }
00119
00120 void GazeboRosBumper::ContactDisconnect()
00121 {
00122 this->contactConnectCount--;
00123 }
00124
00126
00127 void GazeboRosBumper::InitChild()
00128 {
00129
00130
00131 this->myFrame = NULL;
00132 #ifdef USE_CBQ
00133
00134 this->callback_queue_thread_ = boost::thread( boost::bind( &GazeboRosBumper::ContactQueueThread,this ) );
00135 #endif
00136 }
00137
00139
00140 void GazeboRosBumper::UpdateChild()
00141 {
00142 if (this->contactConnectCount > 0)
00143 {
00145 if (this->myFrame == NULL && this->frameName != "world" && this->frameName != "/map" && this->frameName != "map")
00146 {
00147
00148 boost::recursive_mutex::scoped_lock lock(*Simulator::Instance()->GetMRMutex());
00149
00150 std::vector<Model*> all_models = World::Instance()->GetModels();
00151 for (std::vector<Model*>::iterator iter = all_models.begin(); iter != all_models.end(); iter++)
00152 {
00153 if (*iter) this->myFrame = dynamic_cast<Body*>((*iter)->GetBody(this->frameName));
00154 if (this->myFrame) break;
00155 }
00156
00157
00158 if (this->myFrame == NULL)
00159 {
00160 ROS_DEBUG("gazebo_ros_bumper plugin: frameName: %s does not exist yet, will not publish\n",this->frameName.c_str());
00161 return;
00162 }
00163 }
00164
00165 boost::mutex::scoped_lock sclock(this->lock);
00166
00167 bool in_contact;
00168 unsigned int num_contact_count = 0;
00169 int l = 0;
00170 std::string geom2_name;
00171 Vector3 body1ContactForce, body2ContactForce;
00172 Geom *geom1;
00173
00174
00175 for (unsigned int i=0; i < this->myParent->GetGeomCount(); i++)
00176 num_contact_count += this->myParent->GetGeomContactCount(i) > 0;
00177
00178
00179
00180
00181
00182 Time cur_time = Simulator::Instance()->GetSimTime();
00183 this->contactsStateMsg.header.frame_id = frameName;
00184 this->contactsStateMsg.header.stamp.sec = cur_time.sec;
00185 this->contactsStateMsg.header.stamp.nsec = cur_time.nsec;;
00186
00187
00188 this->contactsStateMsg.states.clear();
00189
00190
00191
00192
00193
00194 int total_contact_points = 0;
00195
00196
00197
00198 Pose3d pose, frame_pose;
00199 Quatern rot, frame_rot;
00200 Vector3 pos, frame_pos;
00201 if (this->myFrame)
00202 {
00203 frame_pose = this->myFrame->GetWorldPose();
00204 frame_pos = frame_pose.pos;
00205 frame_rot = frame_pose.rot;
00206 }
00207 else
00208 {
00209
00210 frame_pos = Vector3(0,0,0);
00211 frame_rot = Quatern(1,0,0,0);
00212 frame_pose = Pose3d(frame_pos,frame_rot);
00213 }
00214
00215
00216 for (unsigned int i=0; i < this->myParent->GetGeomCount(); i++)
00217 {
00218 in_contact = this->myParent->GetGeomContactCount(i) > 0;
00219
00220 if (!in_contact)
00221 continue;
00222
00223
00224 geom1 = this->myParent->GetGeom(i);
00225
00226
00227
00228 unsigned int contactCount = geom1->GetContactCount();
00229
00230 total_contact_points += contactCount;
00231
00232
00233 for (unsigned int j=0; j < contactCount; j++)
00234 {
00235 Contact contact = geom1->GetContact(j);
00236 unsigned int pts = contact.positions.size();
00237
00238 std::ostringstream stream;
00239 stream << "touched! i:" << l
00240 << " my geom:" << contact.geom1->GetName()
00241 << " other geom:" << contact.geom2->GetName()
00242 << " time:" << contact.time
00243 << std::endl;
00244
00245 gazebo_plugins::ContactState state;
00246 state.info = stream.str();
00247 state.geom1_name = contact.geom1->GetName();
00248 state.geom2_name = contact.geom2->GetName();
00249
00250 state.wrenches.clear();
00251 state.contact_positions.clear();
00252 state.contact_normals.clear();
00253 state.depths.clear();
00254
00255 for (unsigned int k=0; k < pts; k++)
00256 {
00257
00258 Vector3 force = frame_rot.RotateVector(Vector3(contact.forces[k].body1Force.x,
00259 contact.forces[k].body1Force.y,
00260 contact.forces[k].body1Force.z));
00261 Vector3 torque = frame_rot.RotateVector(Vector3(contact.forces[k].body1Torque.x,
00262 contact.forces[k].body1Torque.y,
00263 contact.forces[k].body1Torque.z));
00264
00265
00266 geometry_msgs::Wrench wrench;
00267 wrench.force.x = force.x;
00268 wrench.force.y = force.y;
00269 wrench.force.z = force.z;
00270 wrench.torque.x = torque.x;
00271 wrench.torque.y = torque.y;
00272 wrench.torque.z = torque.z;
00273 state.wrenches.push_back(wrench);
00274
00275
00276
00277 gazebo::Vector3 contact_position;
00278 contact_position = contact.positions[k] - frame_pos;
00279 contact_position = frame_rot.RotateVectorReverse(contact_position);
00280 geometry_msgs::Vector3 tmp;
00281 tmp.x = contact_position.x;
00282 tmp.y = contact_position.y;
00283 tmp.z = contact_position.z;
00284 state.contact_positions.push_back(tmp);
00285
00286
00287 Vector3 normal = frame_rot.RotateVectorReverse(Vector3(contact.normals[k].x,
00288 contact.normals[k].y,
00289 contact.normals[k].z));
00290
00291 geometry_msgs::Vector3 contact_normal;
00292 contact_normal.x = normal.x;
00293 contact_normal.y = normal.y;
00294 contact_normal.z = normal.z;
00295 state.contact_normals.push_back(contact_normal);
00296
00297
00298 state.depths.push_back(contact.depths[k]);
00299 }
00300 this->contactsStateMsg.states.push_back(state);
00301 }
00302 }
00303
00304 if (total_contact_points == 0)
00305 {
00306 this->contactsStateMsg.states.clear();
00307 }
00308 else
00309 this->contact_pub_.publish(this->contactsStateMsg);
00310
00311
00312 }
00313
00314 }
00315
00317
00318 void GazeboRosBumper::FiniChild()
00319 {
00320 this->rosnode_->shutdown();
00321 this->callback_queue_thread_.join();
00322 }
00323
00324 #ifdef USE_CBQ
00325
00326
00327 void GazeboRosBumper::ContactQueueThread()
00328 {
00329 static const double timeout = 0.01;
00330
00331 while (this->rosnode_->ok())
00332 {
00333 this->contact_queue_.callAvailable(ros::WallDuration(timeout));
00334 }
00335 }
00336 #endif
00337
00338 }