environment_server.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  *
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2008, Willow Garage, Inc.
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the Willow Garage nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  *  \author Sachin Chitta, Ioan Sucan
00036  *********************************************************************/
00037 
00038 #include "planning_environment/monitors/planning_monitor.h"
00039 
00040 #include <arm_navigation_msgs/GetRobotState.h>
00041 #include <arm_navigation_msgs/GetStateValidity.h>
00042 #include <arm_navigation_msgs/GetPlanningScene.h>
00043 #include <arm_navigation_msgs/SetPlanningSceneDiff.h>
00044 #include <ros/package.h>
00045 #include <std_srvs/Empty.h>
00046 #include <arm_navigation_msgs/SyncPlanningSceneAction.h>
00047 #include <actionlib/client/simple_action_client.h>
00048 #include <planning_environment/models/model_utils.h>
00049 
00050 static const std::string SYNC_PLANNING_SCENE_NAME ="sync_planning_scene";
00051 static const unsigned int UNSUCCESSFUL_REPLY_LIMIT = 5;
00052 static const ros::Duration PLANNING_SCENE_CLIENT_TIMEOUT(5.0);
00053 
00054 namespace planning_environment
00055 {
00056 class EnvironmentServer
00057 {
00058 public: 
00059   EnvironmentServer() :
00060   private_handle_("~")
00061   {
00062     private_handle_.param<bool>("use_monitor", use_monitor_, true);
00063     private_handle_.param<bool>("use_collision_map", use_collision_map_, false);
00064 
00065     std::string robot_description_name = root_handle_.resolveName("robot_description", true);
00066 
00067     collision_models_ = new planning_environment::CollisionModels(robot_description_name);
00068     if(use_monitor_) {
00069       planning_monitor_ = new planning_environment::PlanningMonitor(collision_models_, &tf_);
00070       planning_monitor_->setUseCollisionMap(use_collision_map_);
00071 
00072       planning_monitor_->waitForState();
00073       planning_monitor_->startEnvironmentMonitor();
00074       bool printed = false;
00075       while(root_handle_.ok() && use_collision_map_ && !planning_monitor_->haveMap()){
00076         ros::Duration().fromSec(1.0).sleep();
00077         if(!printed) {
00078           ROS_INFO_STREAM("Waiting for collision map");
00079           printed = true;
00080         }
00081       }
00082     } else {
00083       planning_monitor_ = NULL;
00084     }
00085     
00086     register_planning_scene_service_ = root_handle_.advertiseService("register_planning_scene", &EnvironmentServer::registerPlanningScene, this);
00087     get_robot_state_service_ = private_handle_.advertiseService("get_robot_state", &EnvironmentServer::getRobotState, this);
00088     get_planning_scene_service_ = private_handle_.advertiseService("get_planning_scene", &EnvironmentServer::getPlanningScene, this);
00089     set_planning_scene_diff_service_ = private_handle_.advertiseService("set_planning_scene_diff", &EnvironmentServer::setPlanningSceneDiff, this);
00090 
00091     ROS_INFO("Environment server started");
00092   }
00093         
00094   virtual ~EnvironmentServer()
00095   {
00096     for(std::map<std::string, actionlib::SimpleActionClient<arm_navigation_msgs::SyncPlanningSceneAction>* >::iterator it = sync_planning_scene_clients_.begin();
00097         it != sync_planning_scene_clients_.end();
00098         it++) {
00099       delete it->second;
00100     }
00101     delete collision_models_;
00102     if(planning_monitor_) {
00103       delete planning_monitor_;
00104     }
00105   }
00106         
00107 private:
00108   
00109   bool registerPlanningScene(std_srvs::Empty::Request &req,
00110                              std_srvs::Empty::Response &res)
00111   {
00112     register_lock_.lock();
00113     if(req.__connection_header->find("callerid") == req.__connection_header->end()) {
00114       ROS_ERROR_STREAM("Request has no callerid");
00115       return false;
00116     }
00117     std::string callerid = req.__connection_header->find("callerid")->second;
00118     if(sync_planning_scene_clients_.find(callerid) != sync_planning_scene_clients_.end()) {
00119       delete sync_planning_scene_clients_[callerid];
00120     }
00121     sync_planning_scene_clients_[callerid] = new actionlib::SimpleActionClient<arm_navigation_msgs::SyncPlanningSceneAction>(callerid+"/"+SYNC_PLANNING_SCENE_NAME, true);
00122     if(!sync_planning_scene_clients_[callerid]->waitForServer(ros::Duration(10.0))) {
00123       ROS_INFO_STREAM("Couldn't connect back to action server for " << callerid << ". Removing from list");
00124       delete sync_planning_scene_clients_[callerid];
00125       sync_planning_scene_clients_.erase(callerid);
00126       register_lock_.unlock();
00127       return false;
00128     } 
00129     ROS_INFO_STREAM("Successfully connected to planning scene action server for " << callerid);
00130     register_lock_.unlock();
00131     return true;
00132   }
00133                 
00134   bool getRobotState(arm_navigation_msgs::GetRobotState::Request &req, 
00135                      arm_navigation_msgs::GetRobotState::Response &res)
00136   {
00137     planning_monitor_->getCurrentRobotState(res.robot_state);
00138     return true;    
00139   }
00140 
00141   bool getPlanningScene(arm_navigation_msgs::GetPlanningScene::Request &req, 
00142                         arm_navigation_msgs::GetPlanningScene::Response &res) 
00143   {
00144     if(use_monitor_) {
00145       planning_monitor_->getCompletePlanningScene(req.planning_scene_diff,
00146                                                   req.operations,
00147                                                   res.planning_scene);
00148     } else {
00149       res.planning_scene = req.planning_scene_diff;
00150     }
00151     return true;
00152   }
00153 
00154   bool setPlanningSceneDiff(arm_navigation_msgs::SetPlanningSceneDiff::Request &req, 
00155                             arm_navigation_msgs::SetPlanningSceneDiff::Response &res) 
00156   {
00157     ros::WallTime s1 = ros::WallTime::now();
00158     if(use_monitor_) {
00159       planning_monitor_->getCompletePlanningScene(req.planning_scene_diff,
00160                                                   req.operations,
00161                                                   res.planning_scene);
00162     } else {
00163       res.planning_scene = req.planning_scene_diff;
00164       if(req.operations.collision_operations.size() > 0) {
00165         std::vector<std::string> o_strings;
00166         for(unsigned int i = 0; i < req.planning_scene_diff.collision_objects.size(); i++) {
00167           o_strings.push_back(req.planning_scene_diff.collision_objects[i].id);
00168         }
00169         if(req.planning_scene_diff.collision_map.boxes.size() > 0) {
00170           o_strings.push_back(COLLISION_MAP_NAME);
00171         }
00172         std::vector<std::string> a_strings;
00173         for(unsigned int i = 0; i < req.planning_scene_diff.attached_collision_objects.size(); i++) {
00174           a_strings.push_back(req.planning_scene_diff.attached_collision_objects[i].object.id);
00175         }
00176         res.planning_scene.allowed_collision_matrix = 
00177           applyOrderedCollisionOperationsToCollisionsModel(collision_models_,
00178                                                            req.operations, 
00179                                                            o_strings,
00180                                                            a_strings);
00181       }
00182     }
00183     arm_navigation_msgs::SyncPlanningSceneGoal planning_scene_goal;
00184     planning_scene_goal.planning_scene = res.planning_scene;
00185     for(std::map<std::string, actionlib::SimpleActionClient<arm_navigation_msgs::SyncPlanningSceneAction>* >::iterator it = sync_planning_scene_clients_.begin();
00186         it != sync_planning_scene_clients_.end();
00187         it++) {
00188       it->second->sendGoal(planning_scene_goal);
00189     }
00190     std::vector<std::string> bad_list;
00191     for(std::map<std::string, actionlib::SimpleActionClient<arm_navigation_msgs::SyncPlanningSceneAction>* >::iterator it = sync_planning_scene_clients_.begin();
00192         it != sync_planning_scene_clients_.end();
00193         it++) {
00194       if(!it->second->waitForResult(PLANNING_SCENE_CLIENT_TIMEOUT)) {
00195         unsuccessful_planning_scene_client_replies_[it->first]++;
00196         ROS_INFO_STREAM("Did not get reply from planning scene client " << it->first 
00197                         << ".  Incrementing counter to " << unsuccessful_planning_scene_client_replies_[it->first]);
00198         if(unsuccessful_planning_scene_client_replies_[it->first] > UNSUCCESSFUL_REPLY_LIMIT) {
00199           ROS_WARN_STREAM("Failed to get reply from planning scene client " << it->first << " for " 
00200                           << UNSUCCESSFUL_REPLY_LIMIT << " consecutive tries.  Removing");
00201           bad_list.push_back(it->first);
00202         } 
00203         continue;
00204       } 
00205       unsuccessful_planning_scene_client_replies_[it->first] = 0;
00206     }
00207 
00208     for(unsigned int i = 0; i < bad_list.size(); i++) {
00209       delete sync_planning_scene_clients_[bad_list[i]];
00210       sync_planning_scene_clients_.erase(bad_list[i]);
00211     }
00212     ROS_DEBUG_STREAM("Setting planning scene diff took " << (ros::WallTime::now()-s1).toSec());
00213     return true;
00214   }
00215 
00216 private:
00217 
00218   boost::mutex register_lock_;
00219   ros::NodeHandle root_handle_, private_handle_;
00220   planning_environment::CollisionModels *collision_models_;
00221   planning_environment::PlanningMonitor *planning_monitor_;
00222   tf::TransformListener tf_;    
00223 
00224   bool use_monitor_;
00225   bool use_collision_map_;
00226 
00227   ros::ServiceServer get_robot_state_service_;
00228   ros::ServiceServer get_planning_scene_service_;
00229   ros::ServiceServer set_planning_scene_diff_service_;
00230 
00231   ros::ServiceServer register_planning_scene_service_;
00232   std::map<std::string, unsigned int> unsuccessful_planning_scene_client_replies_;
00233   std::map<std::string, actionlib::SimpleActionClient<arm_navigation_msgs::SyncPlanningSceneAction>* > sync_planning_scene_clients_;
00234 };    
00235 }
00236 
00237 int main(int argc, char** argv)
00238 {
00239   ros::init(argc, argv, "environment_server");
00240   //figuring out whether robot_description has been remapped
00241 
00242   ros::AsyncSpinner spinner(1); 
00243   spinner.start();
00244   planning_environment::EnvironmentServer environment_monitor;
00245   ros::waitForShutdown();
00246   return 0;
00247 }


planning_environment
Author(s): Ioan Sucan
autogenerated on Mon Dec 2 2013 12:34:43