gazebo_ros_joint_trajectory.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2013 Open Source Robotics Foundation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  *
00016 */
00017 
00018 
00019 // *************************************************************
00020 // DEPRECATED
00021 // This class has been renamed to gazebo_ros_joint_pose_trajectory
00022 // *************************************************************
00023 
00024 #include <string>
00025 #include <stdlib.h>
00026 #include <tf/tf.h>
00027 
00028 #include "gazebo_plugins/gazebo_ros_joint_trajectory.h"
00029 
00030 namespace gazebo
00031 {
00032 GZ_REGISTER_MODEL_PLUGIN(GazeboRosJointTrajectory);
00033 
00035 // Constructor
00036 ROS_DEPRECATED GazeboRosJointTrajectory::GazeboRosJointTrajectory()  // replaced with GazeboROSJointPoseTrajectory
00037 {
00038   ROS_WARN_NAMED("gazebo_ros_joint_trajectory","DEPRECATED: gazebo_ros_joint_trajectory has been renamed to gazebo_ros_joint_pose_trajectory");
00039 
00040   this->has_trajectory_ = false;
00041   this->trajectory_index = 0;
00042   this->joint_trajectory_.points.clear();
00043   this->physics_engine_enabled_ = true;
00044   this->disable_physics_updates_ = true;
00045 }
00046 
00048 // Destructor
00049 GazeboRosJointTrajectory::~GazeboRosJointTrajectory()
00050 {
00051   event::Events::DisconnectWorldUpdateBegin(this->update_connection_);
00052   // Finalize the controller
00053   this->rosnode_->shutdown();
00054   this->queue_.clear();
00055   this->queue_.disable();
00056   this->callback_queue_thread_.join();
00057   delete this->rosnode_;
00058 }
00059 
00061 // Load the controller
00062 void GazeboRosJointTrajectory::Load(physics::ModelPtr _model,
00063   sdf::ElementPtr _sdf)
00064 {
00065   // save pointers
00066   this->model_ = _model;
00067   this->sdf = _sdf;
00068   this->world_ = this->model_->GetWorld();
00069 
00070   // this->world_->GetPhysicsEngine()->SetGravity(math::Vector3(0, 0, 0));
00071 
00072   // load parameters
00073   this->robot_namespace_ = "";
00074   if (this->sdf->HasElement("robotNamespace"))
00075     this->robot_namespace_ = this->sdf->Get<std::string>("robotNamespace") + "/";
00076 
00077   if (!this->sdf->HasElement("serviceName"))
00078   {
00079     // default
00080     this->service_name_ = "set_joint_trajectory";
00081   }
00082   else
00083     this->service_name_ = this->sdf->Get<std::string>("serviceName");
00084 
00085   if (!this->sdf->HasElement("topicName"))
00086   {
00087     // default
00088     this->topic_name_ = "set_joint_trajectory";
00089   }
00090   else
00091     this->topic_name_ = this->sdf->Get<std::string>("topicName");
00092 
00093   if (!this->sdf->HasElement("updateRate"))
00094   {
00095     ROS_INFO("joint trajectory plugin missing <updateRate>, defaults"
00096              " to 0.0 (as fast as possible)");
00097     this->update_rate_ = 0;
00098   }
00099   else
00100     this->update_rate_ = this->sdf->Get<double>("updateRate");
00101 
00102   // ros callback queue for processing subscription
00103   if (ros::isInitialized())
00104   {
00105     this->deferred_load_thread_ = boost::thread(
00106       boost::bind(&GazeboRosJointTrajectory::LoadThread, this));
00107   }
00108   else
00109   {
00110     gzerr << "Not loading plugin since ROS hasn't been "
00111           << "properly initialized.  Try starting gazebo with ros plugin:\n"
00112           << "  gazebo -s libgazebo_ros_api_plugin.so\n";
00113   }
00114 }
00115 
00117 // Load the controller
00118 void GazeboRosJointTrajectory::LoadThread()
00119 {
00120   this->rosnode_ = new ros::NodeHandle(this->robot_namespace_);
00121 
00122   // resolve tf prefix
00123   std::string prefix;
00124   this->rosnode_->getParam(std::string("tf_prefix"), prefix);
00125 
00126   if (this->topic_name_ != "")
00127   {
00128     ros::SubscribeOptions trajectory_so =
00129       ros::SubscribeOptions::create<trajectory_msgs::JointTrajectory>(
00130       this->topic_name_, 100, boost::bind(
00131       &GazeboRosJointTrajectory::SetTrajectory, this, _1),
00132       ros::VoidPtr(), &this->queue_);
00133     this->sub_ = this->rosnode_->subscribe(trajectory_so);
00134   }
00135 
00136 #ifdef ENABLE_SERVICE
00137   if (this->service_name_ != "")
00138   {
00139     ros::AdvertiseServiceOptions srv_aso =
00140       ros::AdvertiseServiceOptions::create<gazebo_msgs::SetJointTrajectory>(
00141       this->service_name_,
00142       boost::bind(&GazeboRosJointTrajectory::SetTrajectory, this, _1, _2),
00143       ros::VoidPtr(), &this->queue_);
00144     this->srv_ = this->rosnode_->advertiseService(srv_aso);
00145   }
00146 #endif
00147 
00148   this->last_time_ = this->world_->GetSimTime();
00149 
00150   // start custom queue for joint trajectory plugin ros topics
00151   this->callback_queue_thread_ =
00152     boost::thread(boost::bind(&GazeboRosJointTrajectory::QueueThread, this));
00153 
00154   // New Mechanism for Updating every World Cycle
00155   // Listen to the update event. This event is broadcast every
00156   // simulation iteration.
00157   this->update_connection_ = event::Events::ConnectWorldUpdateBegin(
00158       boost::bind(&GazeboRosJointTrajectory::UpdateStates, this));
00159 }
00160 
00162 // set joint trajectory
00163 void GazeboRosJointTrajectory::SetTrajectory(
00164   const trajectory_msgs::JointTrajectory::ConstPtr& trajectory)
00165 {
00166   boost::mutex::scoped_lock lock(this->update_mutex);
00167 
00168   this->reference_link_name_ = trajectory->header.frame_id;
00169   // do this every time a new joint trajectory is supplied,
00170   // use header.frame_id as the reference_link_name_
00171   if (this->reference_link_name_ != "world" &&
00172       this->reference_link_name_ != "/map" &&
00173       this->reference_link_name_ != "map")
00174   {
00175     physics::EntityPtr ent =
00176       this->world_->GetEntity(this->reference_link_name_);
00177     if (ent)
00178       this->reference_link_ = boost::dynamic_pointer_cast<physics::Link>(ent);
00179     if (!this->reference_link_)
00180     {
00181       ROS_ERROR("ros_joint_trajectory plugin needs a reference link [%s] as"
00182                 " frame_id, aborting.\n", this->reference_link_name_.c_str());
00183       return;
00184     }
00185     else
00186     {
00187       this->model_ = this->reference_link_->GetParentModel();
00188       ROS_DEBUG("test: update model pose by keeping link [%s] stationary"
00189                 " inertially", this->reference_link_->GetName().c_str());
00190     }
00191   }
00192 
00193   // copy joint configuration into a map
00194   unsigned int chain_size = trajectory->joint_names.size();
00195   this->joints_.resize(chain_size);
00196   for (unsigned int i = 0; i < chain_size; ++i)
00197   {
00198     this->joints_[i] = this->model_->GetJoint(trajectory->joint_names[i]);
00199   }
00200 
00201   unsigned int points_size = trajectory->points.size();
00202   this->points_.resize(points_size);
00203   for (unsigned int i = 0; i < points_size; ++i)
00204   {
00205     this->points_[i].positions.resize(chain_size);
00206     for (unsigned int j = 0; j < chain_size; ++j)
00207     {
00208       this->points_[i].positions[j] = trajectory->points[i].positions[j];
00209     }
00210   }
00211 
00212   // trajectory start time
00213   this->trajectory_start = gazebo::common::Time(trajectory->header.stamp.sec,
00214                                                 trajectory->header.stamp.nsec);
00215   common::Time cur_time = this->world_->GetSimTime();
00216   if (this->trajectory_start < cur_time)
00217     this->trajectory_start = cur_time;
00218 
00219   // update the joint trajectory to play
00220   this->has_trajectory_ = true;
00221   // reset trajectory_index to beginning of new trajectory
00222   this->trajectory_index = 0;
00223 
00224   if (this->disable_physics_updates_)
00225   {
00226     this->physics_engine_enabled_ = this->world_->GetEnablePhysicsEngine();
00227     this->world_->EnablePhysicsEngine(false);
00228   }
00229 }
00230 
00231 #ifdef ENABLE_SERVICE
00232 bool GazeboRosJointTrajectory::SetTrajectory(
00233   const gazebo_msgs::SetJointTrajectory::Request& req,
00234   const gazebo_msgs::SetJointTrajectory::Response& res)
00235 {
00236   boost::mutex::scoped_lock lock(this->update_mutex);
00237 
00238   this->model_pose_ = req.model_pose;
00239   this->set_model_pose_ = req.set_model_pose;
00240 
00241   this->reference_link_name_ = req.joint_trajectory.header.frame_id;
00242   // do this every time a new joint_trajectory is supplied,
00243   // use header.frame_id as the reference_link_name_
00244   if (this->reference_link_name_ != "world" &&
00245       this->reference_link_name_ != "/map" &&
00246       this->reference_link_name_ != "map")
00247   {
00248     physics::EntityPtr ent =
00249       this->world_->GetEntity(this->reference_link_name_);
00250     if (ent)
00251       this->reference_link_ = boost::shared_dynamic_cast<physics::Link>(ent);
00252     if (!this->reference_link_)
00253     {
00254       ROS_ERROR("ros_joint_trajectory plugin specified a reference link [%s]"
00255                 " that does not exist, aborting.\n",
00256                 this->reference_link_name_.c_str());
00257       ROS_DEBUG("will set model [%s] configuration, keeping model root link"
00258                 " stationary.", this->model_->GetName().c_str());
00259       return false;
00260     }
00261     else
00262       ROS_DEBUG("test: update model pose by keeping link [%s] stationary"
00263                 " inertially", this->reference_link_->GetName().c_str());
00264   }
00265 
00266   this->model_ =  this->world_->GetModel(req.model_name);
00267   if (!this->model_)  // look for it by frame_id name
00268   {
00269     this->model_ = this->reference_link_->GetParentModel();
00270     if (this->model_)
00271     {
00272       ROS_INFO("found model[%s] by link name specified in frame_id[%s]",
00273         this->model_->GetName().c_str(),
00274         req.joint_trajectory.header.frame_id.c_str());
00275     }
00276     else
00277     {
00278       ROS_WARN("no model found by link name specified in frame_id[%s],"
00279                "  aborting.", req.joint_trajectory.header.frame_id.c_str());
00280       return false;
00281     }
00282   }
00283 
00284   // copy joint configuration into a map
00285   this->joint_trajectory_ = req.joint_trajectory;
00286 
00287   // trajectory start time
00288   this->trajectory_start = gazebo::common::Time(
00289     req.joint_trajectory.header.stamp.sec,
00290     req.joint_trajectory.header.stamp.nsec);
00291 
00292   // update the joint_trajectory to play
00293   this->has_trajectory_ = true;
00294   // reset trajectory_index to beginning of new trajectory
00295   this->trajectory_index = 0;
00296   this->disable_physics_updates_ = req.disable_physics_updates;
00297   if (this->disable_physics_updates_)
00298   {
00299     this->physics_engine_enabled_ = this->world_->GetEnablePhysicsEngine();
00300     this->world_->EnablePhysicsEngine(false);
00301   }
00302 
00303   return true;
00304 }
00305 #endif
00306 
00308 // Play the trajectory, update states
00309 void GazeboRosJointTrajectory::UpdateStates()
00310 {
00311   boost::mutex::scoped_lock lock(this->update_mutex);
00312   if (this->has_trajectory_)
00313   {
00314     common::Time cur_time = this->world_->GetSimTime();
00315     // roll out trajectory via set model configuration
00316     // gzerr << "i[" << trajectory_index  << "] time "
00317     //       << trajectory_start << " now: " << cur_time << " : "<< "\n";
00318     if (cur_time >= this->trajectory_start)
00319     {
00320       // @todo:  consider a while loop until the trajectory
00321       // catches up to the current time
00322       // gzerr << trajectory_index << " : "  << this->points_.size() << "\n";
00323       if (this->trajectory_index < this->points_.size())
00324       {
00325         ROS_INFO("time [%f] updating configuration [%d/%lu]",
00326           cur_time.Double(), this->trajectory_index, this->points_.size());
00327 
00328         // get reference link pose before updates
00329         math::Pose reference_pose = this->model_->GetWorldPose();
00330         if (this->reference_link_)
00331         {
00332           reference_pose = this->reference_link_->GetWorldPose();
00333         }
00334 
00335         // trajectory roll-out based on time:
00336         //  set model configuration from trajectory message
00337         unsigned int chain_size = this->joints_.size();
00338         if (chain_size ==
00339           this->points_[this->trajectory_index].positions.size())
00340         {
00341           for (unsigned int i = 0; i < chain_size; ++i)
00342           {
00343             // this is not the most efficient way to set things
00344             if (this->joints_[i])
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           // set model pose
00354           if (this->reference_link_)
00355             this->model_->SetLinkWorldPose(reference_pose,
00356               this->reference_link_);
00357           else
00358             this->model_->SetWorldPose(reference_pose);
00359         }
00360         else
00361         {
00362           ROS_ERROR("point[%u] in JointTrajectory has different number of"
00363                     " joint names[%u] and positions[%lu].",
00364                     this->trajectory_index, chain_size,
00365                     this->points_[this->trajectory_index].positions.size());
00366         }
00367 
00368         // this->world_->SetPaused(is_paused);  // resume original pause-state
00369         gazebo::common::Time duration(
00370           this->points_[this->trajectory_index].time_from_start.sec,
00371           this->points_[this->trajectory_index].time_from_start.nsec);
00372 
00373         // reset start time for next trajectory point
00374         this->trajectory_start += duration;
00375         this->trajectory_index++;  // increment to next trajectory point
00376 
00377         // save last update time stamp
00378         this->last_time_ = cur_time;
00379       }
00380       else  // no more trajectory points
00381       {
00382         // trajectory finished
00383         this->reference_link_.reset();
00384         this->has_trajectory_ = false;
00385         if (this->disable_physics_updates_)
00386           this->world_->EnablePhysicsEngine(this->physics_engine_enabled_);
00387       }
00388     }
00389   }
00390 }
00391 
00393 // Put laser data to the interface
00394 void GazeboRosJointTrajectory::QueueThread()
00395 {
00396   static const double timeout = 0.01;
00397   while (this->rosnode_->ok())
00398   {
00399     this->queue_.callAvailable(ros::WallDuration(timeout));
00400   }
00401 }
00402 }


gazebo_plugins
Author(s): John Hsu
autogenerated on Fri Aug 28 2015 10:47:25