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 <string>
00025 #include <stdlib.h>
00026 #include <tf/tf.h>
00027
00028 #include <gazebo_plugins/gazebo_ros_joint_pose_trajectory.h>
00029
00030 namespace gazebo
00031 {
00032 GZ_REGISTER_MODEL_PLUGIN(GazeboRosJointPoseTrajectory);
00033
00035
00036 ROS_DEPRECATED GazeboRosJointPoseTrajectory::GazeboRosJointPoseTrajectory()
00037 {
00038
00039 this->has_trajectory_ = false;
00040 this->trajectory_index = 0;
00041 this->joint_trajectory_.points.clear();
00042 this->physics_engine_enabled_ = true;
00043 this->disable_physics_updates_ = true;
00044 }
00045
00047
00048 GazeboRosJointPoseTrajectory::~GazeboRosJointPoseTrajectory()
00049 {
00050 event::Events::DisconnectWorldUpdateBegin(this->update_connection_);
00051
00052 this->rosnode_->shutdown();
00053 this->queue_.clear();
00054 this->queue_.disable();
00055 this->callback_queue_thread_.join();
00056 delete this->rosnode_;
00057 }
00058
00060
00061 void GazeboRosJointPoseTrajectory::Load(physics::ModelPtr _model,
00062 sdf::ElementPtr _sdf)
00063 {
00064
00065 this->model_ = _model;
00066 this->sdf = _sdf;
00067 this->world_ = this->model_->GetWorld();
00068
00069
00070
00071
00072 this->robot_namespace_ = "";
00073 if (this->sdf->HasElement("robotNamespace"))
00074 this->robot_namespace_ = this->sdf->Get<std::string>("robotNamespace") + "/";
00075
00076 if (!this->sdf->HasElement("serviceName"))
00077 {
00078
00079 this->service_name_ = "set_joint_trajectory";
00080 }
00081 else
00082 this->service_name_ = this->sdf->Get<std::string>("serviceName");
00083
00084 if (!this->sdf->HasElement("topicName"))
00085 {
00086
00087 this->topic_name_ = "set_joint_trajectory";
00088 }
00089 else
00090 this->topic_name_ = this->sdf->Get<std::string>("topicName");
00091
00092 if (!this->sdf->HasElement("updateRate"))
00093 {
00094 ROS_INFO("joint trajectory plugin missing <updateRate>, defaults"
00095 " to 0.0 (as fast as possible)");
00096 this->update_rate_ = 0;
00097 }
00098 else
00099 this->update_rate_ = this->sdf->Get<double>("updateRate");
00100
00101
00102 if (!ros::isInitialized())
00103 {
00104 ROS_FATAL_STREAM("A ROS node for Gazebo has not been initialized, unable to load plugin. "
00105 << "Load the Gazebo system plugin 'libgazebo_ros_api_plugin.so' in the gazebo_ros package)");
00106 return;
00107 }
00108
00109 this->deferred_load_thread_ = boost::thread(
00110 boost::bind(&GazeboRosJointPoseTrajectory::LoadThread, this));
00111
00112 }
00113
00115
00116 void GazeboRosJointPoseTrajectory::LoadThread()
00117 {
00118 this->rosnode_ = new ros::NodeHandle(this->robot_namespace_);
00119
00120
00121 std::string prefix;
00122 this->rosnode_->getParam(std::string("tf_prefix"), prefix);
00123
00124 if (this->topic_name_ != "")
00125 {
00126 ros::SubscribeOptions trajectory_so =
00127 ros::SubscribeOptions::create<trajectory_msgs::JointTrajectory>(
00128 this->topic_name_, 100, boost::bind(
00129 &GazeboRosJointPoseTrajectory::SetTrajectory, this, _1),
00130 ros::VoidPtr(), &this->queue_);
00131 this->sub_ = this->rosnode_->subscribe(trajectory_so);
00132 }
00133
00134 #ifdef ENABLE_SERVICE
00135 if (this->service_name_ != "")
00136 {
00137 ros::AdvertiseServiceOptions srv_aso =
00138 ros::AdvertiseServiceOptions::create<gazebo_msgs::SetJointTrajectory>(
00139 this->service_name_,
00140 boost::bind(&GazeboRosJointPoseTrajectory::SetTrajectory, this, _1, _2),
00141 ros::VoidPtr(), &this->queue_);
00142 this->srv_ = this->rosnode_->advertiseService(srv_aso);
00143 }
00144 #endif
00145
00146 this->last_time_ = this->world_->GetSimTime();
00147
00148
00149 this->callback_queue_thread_ =
00150 boost::thread(boost::bind(&GazeboRosJointPoseTrajectory::QueueThread, this));
00151
00152
00153
00154
00155 this->update_connection_ = event::Events::ConnectWorldUpdateBegin(
00156 boost::bind(&GazeboRosJointPoseTrajectory::UpdateStates, this));
00157 }
00158
00160
00161 void GazeboRosJointPoseTrajectory::SetTrajectory(
00162 const trajectory_msgs::JointTrajectory::ConstPtr& trajectory)
00163 {
00164 boost::mutex::scoped_lock lock(this->update_mutex);
00165
00166 this->reference_link_name_ = trajectory->header.frame_id;
00167
00168
00169 if (this->reference_link_name_ != "world" &&
00170 this->reference_link_name_ != "/map" &&
00171 this->reference_link_name_ != "map")
00172 {
00173 physics::EntityPtr ent =
00174 this->world_->GetEntity(this->reference_link_name_);
00175 if (ent)
00176 this->reference_link_ = boost::dynamic_pointer_cast<physics::Link>(ent);
00177 if (!this->reference_link_)
00178 {
00179 ROS_ERROR("ros_joint_trajectory plugin needs a reference link [%s] as"
00180 " frame_id, aborting.\n", this->reference_link_name_.c_str());
00181 return;
00182 }
00183 else
00184 {
00185 this->model_ = this->reference_link_->GetParentModel();
00186 ROS_DEBUG("test: update model pose by keeping link [%s] stationary"
00187 " inertially", this->reference_link_->GetName().c_str());
00188 }
00189 }
00190
00191
00192 unsigned int chain_size = trajectory->joint_names.size();
00193 this->joints_.resize(chain_size);
00194 for (unsigned int i = 0; i < chain_size; ++i)
00195 {
00196 this->joints_[i] = this->model_->GetJoint(trajectory->joint_names[i]);
00197 }
00198
00199 unsigned int points_size = trajectory->points.size();
00200 this->points_.resize(points_size);
00201 for (unsigned int i = 0; i < points_size; ++i)
00202 {
00203 this->points_[i].positions.resize(chain_size);
00204 this->points_[i].time_from_start = trajectory->points[i].time_from_start;
00205 for (unsigned int j = 0; j < chain_size; ++j)
00206 {
00207 this->points_[i].positions[j] = trajectory->points[i].positions[j];
00208 }
00209 }
00210
00211
00212 this->trajectory_start = gazebo::common::Time(trajectory->header.stamp.sec,
00213 trajectory->header.stamp.nsec);
00214 common::Time cur_time = this->world_->GetSimTime();
00215 if (this->trajectory_start < cur_time)
00216 this->trajectory_start = cur_time;
00217
00218
00219 this->has_trajectory_ = true;
00220
00221 this->trajectory_index = 0;
00222
00223 if (this->disable_physics_updates_)
00224 {
00225 this->physics_engine_enabled_ = this->world_->GetEnablePhysicsEngine();
00226 this->world_->EnablePhysicsEngine(false);
00227 }
00228 }
00229
00230 #ifdef ENABLE_SERVICE
00231 bool GazeboRosJointPoseTrajectory::SetTrajectory(
00232 const gazebo_msgs::SetJointTrajectory::Request& req,
00233 const gazebo_msgs::SetJointTrajectory::Response& res)
00234 {
00235 boost::mutex::scoped_lock lock(this->update_mutex);
00236
00237 this->model_pose_ = req.model_pose;
00238 this->set_model_pose_ = req.set_model_pose;
00239
00240 this->reference_link_name_ = req.joint_trajectory.header.frame_id;
00241
00242
00243 if (this->reference_link_name_ != "world" &&
00244 this->reference_link_name_ != "/map" &&
00245 this->reference_link_name_ != "map")
00246 {
00247 physics::EntityPtr ent =
00248 this->world_->GetEntity(this->reference_link_name_);
00249 if (ent)
00250 this->reference_link_ = boost::dynamic_pointer_cast<physics::Link>(ent);
00251 if (!this->reference_link_)
00252 {
00253 ROS_ERROR("ros_joint_trajectory plugin specified a reference link [%s]"
00254 " that does not exist, aborting.\n",
00255 this->reference_link_name_.c_str());
00256 ROS_DEBUG("will set model [%s] configuration, keeping model root link"
00257 " stationary.", this->model_->GetName().c_str());
00258 return false;
00259 }
00260 else
00261 ROS_DEBUG("test: update model pose by keeping link [%s] stationary"
00262 " inertially", this->reference_link_->GetName().c_str());
00263 }
00264
00265 this->model_ = this->world_->GetModel(req.model_name);
00266 if (!this->model_)
00267 {
00268 this->model_ = this->reference_link_->GetParentModel();
00269 if (this->model_)
00270 {
00271 ROS_INFO("found model[%s] by link name specified in frame_id[%s]",
00272 this->model_->GetName().c_str(),
00273 req.joint_trajectory.header.frame_id.c_str());
00274 }
00275 else
00276 {
00277 ROS_WARN("no model found by link name specified in frame_id[%s],"
00278 " aborting.", req.joint_trajectory.header.frame_id.c_str());
00279 return false;
00280 }
00281 }
00282
00283
00284 this->joint_trajectory_ = req.joint_trajectory;
00285
00286
00287 this->trajectory_start = gazebo::common::Time(
00288 req.joint_trajectory.header.stamp.sec,
00289 req.joint_trajectory.header.stamp.nsec);
00290
00291
00292 this->has_trajectory_ = true;
00293
00294 this->trajectory_index = 0;
00295 this->disable_physics_updates_ = req.disable_physics_updates;
00296 if (this->disable_physics_updates_)
00297 {
00298 this->physics_engine_enabled_ = this->world_->GetEnablePhysicsEngine();
00299 this->world_->EnablePhysicsEngine(false);
00300 }
00301
00302 return true;
00303 }
00304 #endif
00305
00307
00308 void GazeboRosJointPoseTrajectory::UpdateStates()
00309 {
00310 boost::mutex::scoped_lock lock(this->update_mutex);
00311 if (this->has_trajectory_)
00312 {
00313 common::Time cur_time = this->world_->GetSimTime();
00314
00315
00316
00317 if (cur_time >= this->trajectory_start)
00318 {
00319
00320
00321
00322 if (this->trajectory_index < this->points_.size())
00323 {
00324 ROS_INFO("time [%f] updating configuration [%d/%lu]",
00325 cur_time.Double(), this->trajectory_index, this->points_.size());
00326
00327
00328 math::Pose reference_pose = this->model_->GetWorldPose();
00329 if (this->reference_link_)
00330 {
00331 reference_pose = this->reference_link_->GetWorldPose();
00332 }
00333
00334
00335
00336 unsigned int chain_size = this->joints_.size();
00337 if (chain_size ==
00338 this->points_[this->trajectory_index].positions.size())
00339 {
00340 for (unsigned int i = 0; i < chain_size; ++i)
00341 {
00342
00343 if (this->joints_[i])
00344 {
00345 #if GAZEBO_MAJOR_VERSION >= 4
00346 this->joints_[i]->SetPosition(0,
00347 #else
00348 this->joints_[i]->SetAngle(0,
00349 #endif
00350 this->points_[this->trajectory_index].positions[i]);
00351 }
00352 }
00353
00354
00355 if (this->reference_link_)
00356 this->model_->SetLinkWorldPose(reference_pose,
00357 this->reference_link_);
00358 else
00359 this->model_->SetWorldPose(reference_pose);
00360 }
00361 else
00362 {
00363 ROS_ERROR("point[%u] in JointTrajectory has different number of"
00364 " joint names[%u] and positions[%lu].",
00365 this->trajectory_index, chain_size,
00366 this->points_[this->trajectory_index].positions.size());
00367 }
00368
00369
00370 gazebo::common::Time duration(
00371 this->points_[this->trajectory_index].time_from_start.sec,
00372 this->points_[this->trajectory_index].time_from_start.nsec);
00373
00374
00375 this->trajectory_start += duration;
00376 this->trajectory_index++;
00377
00378
00379 this->last_time_ = cur_time;
00380 }
00381 else
00382 {
00383
00384 this->reference_link_.reset();
00385 this->has_trajectory_ = false;
00386 if (this->disable_physics_updates_)
00387 this->world_->EnablePhysicsEngine(this->physics_engine_enabled_);
00388 }
00389 }
00390 }
00391 }
00392
00394
00395 void GazeboRosJointPoseTrajectory::QueueThread()
00396 {
00397 static const double timeout = 0.01;
00398 while (this->rosnode_->ok())
00399 {
00400 this->queue_.callAvailable(ros::WallDuration(timeout));
00401 }
00402 }
00403 }