RAPP Platform  v0.6.0
RAPP Platform is a collection of ROS nodes and back-end processes that aim to deliver ready-to-use generic services to robots
 All Classes Namespaces Files Functions Variables Macros
path_planning.cpp
Go to the documentation of this file.
2 #include <iostream>
3 #include <string>
4 
5 // Required by for routine
6 #include <sys/stat.h>
7 #include <sys/types.h>
8 #include <unistd.h>
9 #include <algorithm>
10 #include <stdlib.h> // Declaration for exit()
11 #include <boost/filesystem.hpp> // find_file
12 #include <cmath>
13 
14 bool input_poses_correct(geometry_msgs::PoseStamped &start, geometry_msgs::PoseStamped &goal){
15 
16  //ToDo
17  // check if pose coordinate is grater then map size
18 
19  bool status = false;
20  if (start.pose.position.x != 0){
21  if (goal.pose.position.x != 0){
22  if (goal.pose.position.y != 0){
23  if (start.pose.position.y != 0){
24 
25  status = true;
26 
27  }}}}
28 
29  return status;
30 }
32  //int i = 0;
33  for (int i = 0; i < MS_pIDs.size();i++){
34  ROS_DEBUG_STREAM("KILLING GP: "<< GP_pIDs.at(i) );
35  kill(MS_pIDs.at(i),SIGKILL);
36  kill(GP_pIDs.at(i),SIGKILL);
37  }
38 }
39 
40 
41 bool exists_file (const std::string& name) {
42  struct stat buffer;
43  return (stat (name.c_str(), &buffer) == 0);
44 }
45 
47  pid_t tf_broadcaster_pID = fork();
48  if (tf_broadcaster_pID == 0)
49  {
50  ROS_DEBUG("starting tf_broadcaster_pID");
51 
52  execl("/opt/ros/indigo/bin/rosrun","/opt/ros/indigo/bin/rosrun","tf", "static_transform_publisher", "0.066", "1.7", "0.54", "0.49999984", "0.49960184", "0.49999984","0.50039816","map","base_link","100", (char *)0);
53  }
54  else if (tf_broadcaster_pID < 0)
55  {
56  std::cout << "Failed to fork tf_broadcaster_pID" << std::endl;
57  exit(1);
58 
59  }
60  else{
61  return true;
62  }
63  return false;
64 
65 }
66 
67 pid_t start_map_servers(std::string node_nr_str){
68 
69  pid_t map_server_pID = fork();
70  if (map_server_pID == 0)
71  {
72  ROS_DEBUG_STREAM("starting map_server node: "<< node_nr_str);
73 
74  std:: string execute_param_1_string = "__name:=map_server"+node_nr_str;
75  const char* execute_param_1 = execute_param_1_string.c_str();
76  ROS_DEBUG_STREAM("map_server name:\n" << node_nr_str );
77 
78  // set map path
79  std:: string execute_param_2_string = ros::package::getPath("rapp_map_server")+"/maps/empty.yaml";
80  const char* execute_param_2 = execute_param_2_string.c_str();
81  // remap map publication topic
82  std:: string execute_param_3_string = "/map:=/map_server"+node_nr_str+"/map";
83  const char* execute_param_3 = execute_param_3_string.c_str();
84  execl("/opt/ros/indigo/bin/rosrun", "/opt/ros/indigo/bin/rosrun", "rapp_map_server", "rapp_map_server", execute_param_1, execute_param_2, execute_param_3, (char *)0);
85  }
86  else if (map_server_pID < 0)
87  {
88  std::cout << "Failed to fork map_server node: "<<node_nr_str << std::endl;
89  exit(1);
90 
91  }
92  else{
93  return true;
94  }
95  return false;
96 
97 }
98 pid_t start_global_planners(std::string node_nr_str){
99  const char* execute_command = "/opt/ros/indigo/bin/rosparam";
100  pid_t load_configs_costmap_pID = fork();
101  if (load_configs_costmap_pID == 0)
102  {
103  ROS_DEBUG_STREAM("starting load_configs_costmap_pID for sequence: "<< node_nr_str);
104 
105  std::string robot_type = "NAO";
106  std::string costmap_file = robot_type+".yaml";
107  std::string load_configs_pkg_path = ros::package::getPath("rapp_path_planning");
108  // set yaml file path
109  std:: string execute_param_1_string = load_configs_pkg_path+"/cfg/costmap/"+costmap_file;
110  const char* execute_param_1 = execute_param_1_string.c_str();
111  ROS_DEBUG_STREAM("costmap file path:\n"<< execute_param_1_string);
112 
113  // set params namespace
114  std:: string execute_param_2_string = "/global_planner"+node_nr_str+"/costmap/";
115  const char* execute_param_2 = execute_param_2_string.c_str();
116  //nh_.setParam("/global_planner"+node_nr_str+"/costmap/map_service", "/map_server"+node_nr_str+"/getMap");
117 
118  execl(execute_command,execute_command,"load", execute_param_1,execute_param_2 , (char *)0);
119  }
120  else if (load_configs_costmap_pID < 0)
121  {
122  std::cout << "Failed to fork load_configs" << std::endl;
123  return false;
124  exit(1);
125 
126  }
127  else{
128  pid_t load_configs_planner_pID = fork();
129  if (load_configs_planner_pID == 0)
130  {
131  ROS_DEBUG_STREAM("starting load_configs_planner_pID for sequence: "<< node_nr_str);
132 
133  std::string algorithm = "dijkstra";
134  std::string algorithm_file = algorithm+".yaml";
135  std::string load_configs_pkg_path = ros::package::getPath("rapp_path_planning");
136  // set yaml file path
137  std:: string execute_param_1_string = load_configs_pkg_path+"/cfg/planner/"+algorithm_file;
138  const char* execute_param_1 = execute_param_1_string.c_str();
139  // set params namespace
140  std:: string execute_param_2_string = "/global_planner"+node_nr_str+"/planner/";
141  const char* execute_param_2 = execute_param_2_string.c_str();
142  execl(execute_command,execute_command,"load", execute_param_1,execute_param_2 , (char *)0);
143  }
144  else if (load_configs_planner_pID < 0)
145  {
146  ROS_ERROR("Failed to fork load_configs");
147  return false;
148  exit(1);
149 
150  }
151  else{
152  pid_t global_planner_pID = fork();
153  if (global_planner_pID == 0)
154  {
155  ROS_DEBUG_STREAM("starting global_planner node: "<< node_nr_str);
156 
157  // ROS node name
158  std:: string execute_param_1_string = "__name:=global_planner"+node_nr_str;
159  const char* execute_param_1 = execute_param_1_string.c_str();
160  // remap map subscribtion topic
161  std:: string execute_param_2_string = "/map:=/map_server"+node_nr_str+"/map";
162  const char* execute_param_2 = execute_param_2_string.c_str();
163 
164  execl("/opt/ros/indigo/bin/rosrun","/opt/ros/indigo/bin/rosrun","global_planner", "planner", execute_param_1, execute_param_2, (char *)0);
165 
166  }
167  else if (global_planner_pID < 0)
168  {
169  ROS_ERROR("Failed to fork global_planner");
170  exit(1);
171  }
172  else{
173  return true;
174 
175  }
176  }
177  }
178  return false;
179 }
180 
182 {
183  if ((homedir = getenv("HOME")) == NULL) {
184  homedir = getpwuid(getuid())->pw_dir;
185  }
186  if(!nh_.getParam("/rapp_path_planning_plan_path_topic", pathPlanningTopic_))
187  {
188  ROS_WARN("Path planning topic param does not exist. Setting to: /rapp/rapp_path_planning/plan_path");
189  pathPlanningTopic_ = "/rapp/rapp_path_planning/plan_path";
190  }
191  if(!nh_.getParam("/rapp_path_planning_threads", pathPlanningThreads_))
192  {
193  ROS_WARN("Path planning threads param does not exist. Setting 5 threads.");
195  }
197  pid_t MS_pID;
198  pid_t GP_pID;
199  // if (tf_status){
200  for (int node_nr=1;node_nr<pathPlanningThreads_+1;node_nr++)
201  {
202  std::string node_nr_str = boost::lexical_cast<std::string>(node_nr);
203 
204 
205  MS_pID = start_map_servers(node_nr_str);
206  GP_pID = start_global_planners(node_nr_str);
207  MS_pIDs.push_back(MS_pID);
208  GP_pIDs.push_back(GP_pID);
209  //bool config_status = path_planner_.configureSequence(node_nr_str, "/home/rapp/rapp_platform/rapp-platform-catkin-ws/src/rapp-platform/rapp_map_server/maps/empty.yaml", "NAO", "dijkstra", nh_);
210 
211  }
212  uint32_t serv_port;
213  std::string serv_node_name, serv_name;
214  ros::ServiceManager srv_manager;
215  // char *serv_name_char;
216  // sprintf(serv_name_char, "/global_planner%d/make_plan", pathPlanningThreads_);
217  std::string threads_str = boost::lexical_cast<std::string>(pathPlanningThreads_);
218  serv_name = "/global_planner"+threads_str+"/make_plan";
219  bool serv_active = srv_manager.lookupService(serv_name.c_str() ,serv_node_name,serv_port);
220  int i=0;
221  while (!serv_active && i <= 20){
222  ROS_DEBUG_STREAM("Waiting for:"<<" /global_planner"<<pathPlanningThreads_<<"/make_plan" << " service ");
223  serv_active = srv_manager.lookupService(serv_name.c_str(),serv_node_name,serv_port);
224  ros::Duration(1).sleep();
225  i+=1;
226  }
227  // }
228  if(!nh_.getParam("/rapp_path_planning_upload_map_topic", uploadMapTopic_))
229  {
230  ROS_WARN("Upload map topic param does not exist. Setting to: /rapp/rapp_path_planning/upload_map");
231  pathPlanningTopic_ = "/rapp/rapp_path_planning/upload_map";
232  }
233 
234  // Creating the service server concerning the path planning functionality
235  pathPlanningService_ = nh_.advertiseService(pathPlanningTopic_,
237  uploadMapService_ = nh_.advertiseService(uploadMapTopic_,
239 }
240 
241 
242 bool PathPlanning::uploadMapCallback(rapp_platform_ros_communications::MapServerUploadMapRosSrv::Request &req,
243  rapp_platform_ros_communications::MapServerUploadMapRosSrv::Response &res){
244 
245  std::string seq_nr_str = path_planner_.setSequenceNR(nh_, pathPlanningThreads_);
246  ros::ServiceClient upload_map_client = nh_.serviceClient<rapp_platform_ros_communications::MapServerUploadMapRosSrv>("/map_server"+seq_nr_str+"/upload_map");
247  rapp_platform_ros_communications::MapServerUploadMapRosSrv upload_map_srv;
248  upload_map_srv.request = req;
249  if(upload_map_client.call(upload_map_srv)){
250  res = upload_map_srv.response;
251  return true;
252  }else{
253  ROS_ERROR_STREAM("FAILED to call service:\n/map_server"<< seq_nr_str << "/upload_map");
254  return false;
255  }
256 
257 }
258 
259 std::vector<geometry_msgs::PoseStamped> setPoseDist(double pose_dist, std::vector<geometry_msgs::PoseStamped> input_path){
260  geometry_msgs::PoseStamped last_pose;
261  geometry_msgs::PoseStamped next_pose;
262  std::vector<geometry_msgs::PoseStamped> new_path;
263 
264  double dist_now = 0;
265  last_pose.pose.position.x = input_path[0].pose.position.x;
266  last_pose.pose.position.y = input_path[0].pose.position.y;
267  new_path.push_back(input_path[0]);
268  //std::cout <<"input_path = "<<input_path.size()<<std::endl;
269 
270  for(int i=0; i < (int) floor(input_path.size()/5) ; i+=1){
271 
272  next_pose.pose.position.x = input_path[i*5].pose.position.x;
273  next_pose.pose.position.y = input_path[i*5].pose.position.y;
274 
275 
276  dist_now = sqrt((last_pose.pose.position.x - next_pose.pose.position.x)*(last_pose.pose.position.x - next_pose.pose.position.x)+(last_pose.pose.position.y - next_pose.pose.position.y)*(last_pose.pose.position.y - next_pose.pose.position.y));
277  //std::cout <<"dist_now = "<<dist_now<<std::endl;
278  if (dist_now >= pose_dist){
279  next_pose.pose.position.z = input_path[i*5].pose.position.z;
280  next_pose.pose.orientation.x = input_path[i*5].pose.orientation.x;
281  next_pose.pose.orientation.y = input_path[i*5].pose.orientation.y;
282  next_pose.pose.orientation.z = input_path[i*5].pose.orientation.z;
283  next_pose.pose.orientation.w = input_path[i*5].pose.orientation.w;
284  next_pose.header.seq = input_path[i*5].header.seq;
285  next_pose.header.stamp = input_path[i*5].header.stamp;
286  // next_pose.pose.header = input_path[i*5].pose.header;
287  next_pose.header.frame_id = input_path[i*5].header.frame_id;
288  new_path.push_back(next_pose);
289  last_pose.pose.position.x = next_pose.pose.position.x;
290  last_pose.pose.position.y = next_pose.pose.position.y;
291 
292  }
293  }
294 
295  int nr_iter = (int) floor(input_path.size()/5);
296  if (nr_iter < input_path.size())
297  new_path.push_back(input_path[input_path.size()-1]);
298  //std::cout <<"next_pose = "<<new_path.size()<<std::endl;
299 
300  return new_path;
301 }
303  rapp_platform_ros_communications::PathPlanningRosSrv::Request& req,
304  rapp_platform_ros_communications::PathPlanningRosSrv::Response& res)
305 {
306  std::string homedir_str = homedir;
307 
308  std::string map_path = homedir_str+"/rapp_platform_files/maps/"+req.user_name+"/"+req.map_name+".yaml";
309  std::string costmap_file_path = ros::package::getPath("rapp_path_planning")+"/cfg/costmap/"+req.robot_type+".yaml";
310  std::string algorithm_file_path = ros::package::getPath("rapp_path_planning")+"/cfg/planner/"+req.algorithm+".yaml";
311  navfn::MakeNavPlanResponse response;
312  if (input_poses_correct(req.start, req.goal)){
313  if (exists_file(algorithm_file_path)){
314  if (exists_file(costmap_file_path)){
315  if (exists_file(map_path)){
316  ROS_DEBUG("NEW <<Path_planning>> SERVICE STARTED");
317  std::string seq_nr_str = path_planner_.setSequenceNR(nh_, pathPlanningThreads_);
318  ROS_DEBUG_STREAM("SEQ-NR is: " << seq_nr_str);
319  bool config_status = path_planner_.configureSequence(seq_nr_str, map_path, req.robot_type, req.algorithm, nh_);
320 
321  response = path_planner_.startSequence(seq_nr_str, req.start, req.goal, nh_);
322 
323  res.plan_found = response.plan_found;
324 
325  res.error_message = response.error_message;
326 
327  new_path.clear();
328  if (res.plan_found == 1){
329  nh_.param<double>("rapp_path_planning_pose_distance", pose_dist_, 0.15);
330 
331  new_path = setPoseDist(pose_dist_, response.path);
332  }
333 
334  res.path = new_path;
335 
336  nh_.setParam("/rapp/rapp_path_planning/seq_"+seq_nr_str+"/busy", false);
337  }else{
338  res.plan_found = 2;
339  res.error_message = "Input map does not exist";
340  ROS_ERROR("Input map does not exist");
341  }
342  }else{
343  res.plan_found = 3;
344  res.error_message = "Input robot_type does not exist";
345 
346  ROS_ERROR("Input robot_type does not exist");
347 
348  }
349  }else{
350  res.plan_found = 4;
351  res.error_message = "Input algorithm does not exist";
352 
353  ROS_ERROR("Input algorithm does not exist");
354 
355  }
356  }else{
357  res.plan_found = 5;
358  res.error_message = "Robot pose can NOT be placed at the map border";
359 
360  ROS_ERROR("Robot pose can NOT be placed at the map border");
361 
362  }
363  return true;
364 
365 }
366 
367 
std::vector< pid_t > GP_pIDs
Definition: path_planning.h:74
std::string uploadMapTopic_
Definition: path_planning.h:79
std::vector< geometry_msgs::PoseStamped > new_path
Definition: path_planning.h:82
bool exists_file(const std::string &name)
std::string setSequenceNR(ros::NodeHandle &nh_, int pathPlanningThreads_)
Determines next planning seqence (which global_planner and map_server should be used) ...
Definition: path_planner.cpp:9
bool pathPlanningCallback(rapp_platform_ros_communications::PathPlanningRosSrv::Request &req, rapp_platform_ros_communications::PathPlanningRosSrv::Response &res)
Determines next planning seqence (which global_planner and map_server should be used) ...
int pathPlanningThreads_
Definition: path_planning.h:80
bool uploadMapCallback(rapp_platform_ros_communications::MapServerUploadMapRosSrv::Request &req, rapp_platform_ros_communications::MapServerUploadMapRosSrv::Response &res)
Upload map to RAPP Platform.
bool input_poses_correct(geometry_msgs::PoseStamped &start, geometry_msgs::PoseStamped &goal)
std::vector< geometry_msgs::PoseStamped > setPoseDist(double pose_dist, std::vector< geometry_msgs::PoseStamped > input_path)
pid_t start_global_planners(std::string node_nr_str)
double pose_dist_
Definition: path_planning.h:81
pid_t start_map_servers(std::string node_nr_str)
std::string pathPlanningTopic_
Definition: path_planning.h:78
bool configureSequence(std::string seq_nr, std::string map_path, std::string robot_type, std::string algorithm, ros::NodeHandle &nh_)
Configures sequence. Sets map, approprate costmap parameters for specified robot type, sets global_planner to use detemined algorithm.
ros::NodeHandle nh_
Definition: path_planning.h:67
pid_t start_tf_publisher()
navfn::MakeNavPlanResponse startSequence(std::string seq_nr, geometry_msgs::PoseStamped request_start, geometry_msgs::PoseStamped request_goal, ros::NodeHandle &nh_)
Starts planning service of determined planning sequence.
PathPlanner path_planner_
Definition: path_planning.h:83
ros::ServiceServer uploadMapService_
Definition: path_planning.h:72
PathPlanning(void)
Default constructor.
std::vector< pid_t > MS_pIDs
Definition: path_planning.h:75
const char * homedir
Definition: path_planning.h:69
ros::ServiceServer pathPlanningService_
Definition: path_planning.h:71