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 #include <gazebo_plugins/gazebo_ros_f3d.h>
00025 #include <tf/tf.h>
00026
00027 namespace gazebo
00028 {
00029 GZ_REGISTER_MODEL_PLUGIN(GazeboRosF3D);
00030
00032
00033 GazeboRosF3D::GazeboRosF3D()
00034 {
00035 this->f3d_connect_count_ = 0;
00036 }
00037
00039
00040 GazeboRosF3D::~GazeboRosF3D()
00041 {
00042 event::Events::DisconnectWorldUpdateBegin(this->update_connection_);
00043
00044 this->queue_.clear();
00045 this->queue_.disable();
00046 this->rosnode_->shutdown();
00047 this->callback_queue_thread_.join();
00048 delete this->rosnode_;
00049 }
00050
00052
00053 void GazeboRosF3D::Load( physics::ModelPtr _parent, sdf::ElementPtr _sdf )
00054 {
00055
00056 this->world_ = _parent->GetWorld();
00057
00058
00059 this->robot_namespace_ = "";
00060 if (_sdf->HasElement("robotNamespace"))
00061 this->robot_namespace_ = _sdf->GetElement("robotNamespace")->Get<std::string>() + "/";
00062
00063 if (!_sdf->HasElement("bodyName"))
00064 {
00065 ROS_FATAL("f3d plugin missing <bodyName>, cannot proceed");
00066 return;
00067 }
00068 else
00069 this->link_name_ = _sdf->GetElement("bodyName")->Get<std::string>();
00070
00071 this->link_ = _parent->GetLink(this->link_name_);
00072 if (!this->link_)
00073 {
00074 ROS_FATAL("gazebo_ros_f3d plugin error: bodyName: %s does not exist\n",this->link_name_.c_str());
00075 return;
00076 }
00077
00078 if (!_sdf->HasElement("topicName"))
00079 {
00080 ROS_FATAL("f3d plugin missing <topicName>, cannot proceed");
00081 return;
00082 }
00083 else
00084 this->topic_name_ = _sdf->GetElement("topicName")->Get<std::string>();
00085
00086 if (!_sdf->HasElement("frameName"))
00087 {
00088 ROS_INFO("f3d plugin missing <frameName>, defaults to world");
00089 this->frame_name_ = "world";
00090 }
00091 else
00092 {
00093 this->frame_name_ = _sdf->GetElement("frameName")->Get<std::string>();
00094
00095 ROS_INFO("f3d plugin specifies <frameName> [%s], not used, default to world",this->frame_name_.c_str());
00096 }
00097
00098
00099
00100 if (!ros::isInitialized())
00101 {
00102 ROS_FATAL_STREAM("A ROS node for Gazebo has not been initialized, unable to load plugin. "
00103 << "Load the Gazebo system plugin 'libgazebo_ros_api_plugin.so' in the gazebo_ros package)");
00104 return;
00105 }
00106
00107 this->rosnode_ = new ros::NodeHandle(this->robot_namespace_);
00108
00109
00110 std::string prefix;
00111 this->rosnode_->getParam(std::string("tf_prefix"), prefix);
00112 this->frame_name_ = tf::resolve(prefix, this->frame_name_);
00113
00114
00115 ros::AdvertiseOptions ao = ros::AdvertiseOptions::create<geometry_msgs::WrenchStamped>(
00116 this->topic_name_,1,
00117 boost::bind( &GazeboRosF3D::F3DConnect,this),
00118 boost::bind( &GazeboRosF3D::F3DDisconnect,this), ros::VoidPtr(), &this->queue_);
00119 this->pub_ = this->rosnode_->advertise(ao);
00120
00121
00122 this->callback_queue_thread_ = boost::thread( boost::bind( &GazeboRosF3D::QueueThread,this ) );
00123
00124
00125
00126
00127 this->update_connection_ = event::Events::ConnectWorldUpdateBegin(
00128 boost::bind(&GazeboRosF3D::UpdateChild, this));
00129 }
00130
00132
00133 void GazeboRosF3D::F3DConnect()
00134 {
00135 this->f3d_connect_count_++;
00136 }
00137
00139
00140 void GazeboRosF3D::F3DDisconnect()
00141 {
00142 this->f3d_connect_count_--;
00143 }
00144
00146
00147 void GazeboRosF3D::UpdateChild()
00148 {
00149 if (this->f3d_connect_count_ == 0)
00150 return;
00151
00152 math::Vector3 torque;
00153 math::Vector3 force;
00154
00155
00156 force = this->link_->GetWorldForce();
00157
00158
00159 torque = this->link_->GetWorldTorque();
00160
00161 this->lock_.lock();
00162
00163 this->wrench_msg_.header.frame_id = this->frame_name_;
00164 this->wrench_msg_.header.stamp.sec = (this->world_->GetSimTime()).sec;
00165 this->wrench_msg_.header.stamp.nsec = (this->world_->GetSimTime()).nsec;
00166
00167 this->wrench_msg_.wrench.force.x = force.x;
00168 this->wrench_msg_.wrench.force.y = force.y;
00169 this->wrench_msg_.wrench.force.z = force.z;
00170 this->wrench_msg_.wrench.torque.x = torque.x;
00171 this->wrench_msg_.wrench.torque.y = torque.y;
00172 this->wrench_msg_.wrench.torque.z = torque.z;
00173
00174 this->pub_.publish(this->wrench_msg_);
00175 this->lock_.unlock();
00176
00177 }
00178
00179
00181
00182 void GazeboRosF3D::QueueThread()
00183 {
00184 static const double timeout = 0.01;
00185
00186 while (this->rosnode_->ok())
00187 {
00188 this->queue_.callAvailable(ros::WallDuration(timeout));
00189 }
00190 }
00191
00192 }