model_server.cpp
Go to the documentation of this file.
00001 #include "../include/model_server.h"
00002 #include <gazebo_msgs/SpawnModel.h>
00003 #include <gazebo_msgs/DeleteModel.h>
00004 #include <gazebo_msgs/GetWorldProperties.h>
00005 #include <urdf_interface/link.h>
00006 #include <urdf/model.h>
00007 #include <std_srvs/Empty.h>
00008 #include <iostream>
00009 #include <fstream>
00010 #include <pcl/ros/conversions.h>
00011 #include <Eigen/Core>
00012 #include <algorithm>
00013 #include <icr_msgs/SetObject.h>
00014 
00015 namespace ICR
00016 {
00017   ModelServer::ModelServer() : nh_private_("~"),pose_brc_(new PoseBroadcaster),obj_(new icr_msgs::Object),scale_(1.0),obj_loaded_(false)
00018 {
00019   std::string searched_param;
00020   std::string gazebo_prefix;
00021 
00022   nh_private_.searchParam("pose_source", searched_param);
00023   nh_private_.getParam(searched_param, pose_source_);
00024 
00025   nh_private_.searchParam("model_directory", searched_param);
00026   nh_private_.getParam(searched_param, model_dir_);
00027 
00028   nh_private_.searchParam("gazebo_prefix", searched_param);
00029   nh_private_.getParam(searched_param, gazebo_prefix);
00030 
00031   nh_private_.searchParam("object_scale", searched_param);
00032   nh_private_.getParam(searched_param, scale_);
00033 
00034   //read the client topics to be called from the parameter server
00035   XmlRpc::XmlRpcValue obj_client_topics;
00036   if (nh_private_.searchParam("obj_client_topics", searched_param))
00037     {
00038       nh_.getParam(searched_param,obj_client_topics);
00039       ROS_ASSERT(obj_client_topics.getType() == XmlRpc::XmlRpcValue::TypeArray); 
00040     
00041        for (int32_t i = 0; i < obj_client_topics.size(); ++i) 
00042         {    
00043           ROS_ASSERT(obj_client_topics[i].getType() == XmlRpc::XmlRpcValue::TypeString);
00044           
00045           //create a new client for each connected server
00046           boost::shared_ptr<ros::ServiceClient> obj_client(new ros::ServiceClient( nh_.serviceClient<icr_msgs::SetObject>((std::string)obj_client_topics[i])));
00047           set_obj_clts_.push_back(obj_client);
00048          }
00049     }
00050 
00051   gazebo_spawn_clt_ = nh_.serviceClient<gazebo_msgs::SpawnModel>(gazebo_prefix + "/spawn_urdf_model");
00052   gazebo_delete_clt_ = nh_.serviceClient<gazebo_msgs::DeleteModel>(gazebo_prefix + "/delete_model");
00053   gazebo_get_wp_clt_ = nh_.serviceClient<gazebo_msgs::GetWorldProperties>(gazebo_prefix + "/get_world_properties");
00054   gazebo_pause_clt_ = nh_.serviceClient<std_srvs::Empty>(gazebo_prefix + "/pause_physics");
00055   gazebo_unpause_clt_ = nh_.serviceClient<std_srvs::Empty>(gazebo_prefix + "/unpause_physics");
00056 
00057   //If Gazebo is the intended pose source, wait for Gazebo services to be available 
00058   if(!strcmp(pose_source_.c_str(),"gazebo"))
00059     {
00060       gazebo_delete_clt_.waitForExistence(); 
00061       gazebo_get_wp_clt_.waitForExistence();  
00062       gazebo_pause_clt_.waitForExistence();  
00063       gazebo_unpause_clt_.waitForExistence(); 
00064       gazebo_spawn_clt_.waitForExistence();
00065     }
00066   //Wait for the connected set_object services to be available
00067   for(unsigned int i=0;i<set_obj_clts_.size();i++)
00068     set_obj_clts_[i]->waitForExistence();
00069   
00070  load_obj_srv_ = nh_.advertiseService("load_object",&ModelServer::loadObject,this);
00071 }
00072   //--------------------------------------------------------------------------------
00073   bool ModelServer::loadObject(icr_msgs::LoadObject::Request  &req, icr_msgs::LoadObject::Response &res)
00074   {
00075     res.success=false;
00076 
00077     lock_.lock();
00078     obj_loaded_=false;
00079 
00080     //delete the previous model in Gazebo if Gazebo is the intended pose source
00081     if(!strcmp(pose_source_.c_str(),"gazebo"))  
00082       if(!gazeboDeleteModel(obj_name_))
00083         {
00084           lock_.unlock();
00085           return res.success;
00086         }
00087 
00088     //if a model is currently spawned in gazebo whichs name conforms to the file name in the
00089     //request, also delete it (this might be the case if there already was a model spawned in Gazebo
00090     //prior to the start of the model_server)
00091     if(!strcmp(pose_source_.c_str(),"gazebo"))  
00092       if(!gazeboDeleteModel(req.file))
00093         {
00094           lock_.unlock();
00095           return res.success;
00096         }
00097 
00098     //load the urdf model, extract obj_name_ and obj_frame_id_ from it and push it on the parameter server
00099     std::string serialized_model;
00100     if(!loadURDF(model_dir_+"/urdf/"+req.file+".urdf",serialized_model))
00101       {
00102         lock_.unlock();
00103         return res.success;
00104       }
00105 
00106     //Spawn the new model in Gazebo if Gazebo is the intended pose source
00107     if(!strcmp(pose_source_.c_str(),"gazebo"))  
00108       if(!gazeboSpawnModel(serialized_model,req.initial_pose))
00109         {
00110           lock_.unlock();
00111           return res.success;
00112         }
00113 
00114     //Load the according Wavefront .obj file
00115     pcl::PointCloud<pcl::PointNormal> obj_cloud;
00116     std::vector<std::vector<unsigned int> >  neighbors;
00117     if(!loadWavefrontObj(model_dir_+"/obj/"+req.file+".obj",obj_cloud,neighbors))
00118       {
00119         lock_.unlock();
00120         return res.success;
00121       }
00122 
00123     //Set the object in the Broadcaster
00124     pose_brc_->setObject(obj_cloud,obj_name_);
00125 
00126     //if pose should be taken from uc3m_objtracker then call it once here 
00127     if(pose_brc_->isPoseSourceUC3M() == true) 
00128       {
00129         if (!pose_brc_->getPoseUC3MObjtrack()) {
00130           ROS_WARN("uc3m_objtracker failed.");
00131         }
00132       }
00133 
00134     //Update the Object message
00135     obj_->name=obj_name_;
00136     pcl::toROSMsg(obj_cloud,obj_->points);
00137     icr_msgs::Neighbors ngb;
00138 
00139     obj_->neighbors.clear();
00140     for(unsigned int i=0;i<neighbors.size();i++)  
00141       {    
00142         ngb.indices.resize(neighbors[i].size());
00143         std::copy(neighbors[i].begin(),neighbors[i].end(),ngb.indices.begin());     
00144         obj_->neighbors.push_back(ngb);
00145       }
00146 
00147     obj_loaded_=true;
00148     res.success=true;
00149 
00150     //Send the object to the connected servers
00151     icr_msgs::SetObject set_obj;
00152     set_obj.request.object=(*obj_);
00153     for(unsigned int i=0; i<set_obj_clts_.size();i++)
00154       if(!set_obj_clts_[i]->call(set_obj))
00155         {
00156           ROS_ERROR("Could not send object to server number %d",i+1);
00157           res.success=false;
00158         }
00159  
00160     lock_.unlock();
00161 
00162     
00163     return res.success;
00164   }
00165 //--------------------------------------------------------------------------
00166 void ModelServer::spin()
00167 {
00168   //Broadcast the object's pose to tf
00169   if(obj_loaded_)
00170     pose_brc_->broadcastPose();
00171 
00172   ros::spinOnce();
00173 }
00174 //--------------------------------------------------------------------------
00175  bool ModelServer::loadURDF(std::string const & path,std::string & serialized_model)
00176   {
00177 
00178     serialized_model.clear();
00179   std::string line;
00180   std::ifstream file(path.c_str());
00181 
00182   if(!file.is_open()) 
00183     {
00184       ROS_ERROR("Could not open file %s",path.c_str());
00185       return false;
00186     }
00187   while(!file.eof()) // Parse the contents of the given urdf in a string
00188     {
00189       std::getline(file,line);
00190       serialized_model+=line;
00191     }
00192   file.close();
00193 
00194 
00195   //Parse the urdf in order to get the robot name and geometry
00196   urdf::Model urdf_model;
00197   if(!urdf_model.initString(serialized_model))
00198     {  
00199       ROS_ERROR("Could not parse urdf model %s",path.c_str());
00200       return false;
00201     }
00202 
00203   obj_name_=urdf_model.getName();
00204   obj_frame_id_="/"+urdf_model.getRoot()->name;//set the frame id to the base link name
00205 
00206   //Push the loaded file on the parameter server 
00207   nh_.setParam("icr_object",serialized_model);
00208 
00209   return true;
00210   }
00211 //--------------------------------------------------------------------------
00212 bool ModelServer::gazeboSpawnModel(std::string const & serialized_model,geometry_msgs::Pose const & initial_pose)
00213   {
00214 
00215   gazebo_msgs::SpawnModel spawn_model;
00216   std_srvs::Empty empty;
00217  
00218   spawn_model.request.model_name=obj_name_;
00219   spawn_model.request.model_xml=serialized_model;
00220   spawn_model.request.initial_pose=initial_pose;
00221   spawn_model.request.reference_frame="world"; //spawn the object in Gazebo's world frame
00222 
00223   gazebo_pause_clt_.call(empty);
00224   if (gazebo_spawn_clt_.call(spawn_model))
00225     ROS_INFO("Successfully spawned model %s in Gazebo",obj_name_.c_str());
00226   else
00227     {
00228       ROS_ERROR("Failed to spawn model %s in Gazebo",obj_name_.c_str());
00229       return false;
00230     }
00231 
00232   gazebo_unpause_clt_.call(empty);
00233 
00234   return true;
00235 }
00236 //--------------------------------------------------------------------------
00237   bool ModelServer::gazeboDeleteModel(std::string const & name)
00238   {
00239 
00240     gazebo_msgs::GetWorldProperties get_wp;
00241     gazebo_msgs::DeleteModel delete_model;
00242     std_srvs::Empty empty;
00243 
00244     if(!gazebo_get_wp_clt_.call(get_wp))
00245       {
00246         ROS_ERROR("Could not get world properties from Gazebo");
00247         return false;
00248       }
00249 
00250     delete_model.request.model_name=name;
00251 
00252     //see if a model with the obj_name_ is currently spawned, if yes delete it
00253     for(unsigned int i=0; i < get_wp.response.model_names.size();i++ )
00254       {
00255         if(!strcmp(get_wp.response.model_names[i].c_str(),name.c_str()))  
00256           {
00257             gazebo_pause_clt_.call(empty);
00258             if(!gazebo_delete_clt_.call(delete_model))
00259               {
00260                 ROS_WARN("Could not delete model %s",name.c_str());
00261               }
00262             gazebo_unpause_clt_.call(empty);
00263             ROS_INFO("Deleted model %s in Gazebo",name.c_str());
00264             break;
00265           }
00266       }
00267 
00268     return true;
00269   }
00270 //--------------------------------------------------------------------------
00271   bool ModelServer::loadWavefrontObj(std::string const & path, pcl::PointCloud<pcl::PointNormal> & cloud, std::vector<std::vector<unsigned int> > & neighbors )
00272 {
00273   ObjectLoader obj_loader; 
00274 
00275   obj_loader.loadObject(path.c_str() ,obj_name_);
00276 
00277   if(!((obj_loader.objectLoaded()) && (obj_loader.getObject()->getNumCp() > 0)))
00278     {
00279       ROS_INFO("Invalid Wavefront obj file: %s",path.c_str());
00280       return false;
00281     }
00282   obj_loader.getObject()->scaleObject(scale_);
00283   double xmax=0;
00284   pcl::PointNormal p;
00285   neighbors.resize(obj_loader.getObject()->getNumCp());
00286   for(unsigned int i=0; i<obj_loader.getObject()->getNumCp();i++)
00287     {
00288       Eigen::Vector3d const * v=obj_loader.getObject()->getContactPoint(i)->getVertex();
00289       Eigen::Vector3d const * vn=obj_loader.getObject()->getContactPoint(i)->getVertexNormal();
00290       neighbors[i].resize(obj_loader.getObject()->getContactPoint(i)->getNeighbors()->size());
00291       std::copy(obj_loader.getObject()->getContactPoint(i)->getNeighbors()->begin(),obj_loader.getObject()->getContactPoint(i)->getNeighbors()->end(),neighbors[i].begin()); 
00292       p.x=v->x(); p.y=v->y(); p.z=v->z(); 
00293       p.normal[0]=vn->x();  p.normal[1]=vn->y();  p.normal[2]=vn->z(); 
00294       p.curvature=0; //not estimated
00295       cloud.push_back(p);
00296       if(p.x > xmax)
00297         xmax=p.x;
00298 
00299 
00300     }
00301   cloud.header.frame_id=obj_frame_id_;
00302   cloud.header.stamp=ros::Time::now();
00303   cloud.width = cloud.size();
00304   cloud.height = 1;
00305   cloud.is_dense=true;
00306   std::cout<<"XMAX: "<<xmax<<std::endl;
00307   return true;
00308 }
00309 //--------------------------------------------------------------------------
00310 }//end namespace


icr
Author(s): Robert Krug
autogenerated on Mon Jan 6 2014 11:36:10