ppplanner_core.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2019, SEAOS, Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * * Neither the name of the <organization> nor the
16  * names of its contributors may be used to endorse or promote products
17  * derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * Author: t-ogata@seaos.co.jp
31  *********************************************************************/
34 #include <boost/tokenizer.hpp>
35 #include <boost/foreach.hpp>
36 #include <fstream>
37 #include <limits>
38 
39 #if MODE==MODE_GPU
40 #include <cuda.h>
41 #include <cuda_runtime.h>
42 #endif
43 
45 
46 #if MODE==MODE_GPU
47 int test_cuda(int a, int b);
48 //CUDA version calcPipeline function
49 //void calcPipeline_device(const int numcheckpoints,
50 //const double *stonex,const double *stoney,const bool isClose,
51 //const double *radii,const double *sradii,const double *eradii,
52 //const double origin_x,const double origin_y,
53 //const unsigned int costsizex,const unsigned int costsizey,
54 //const double resolution,int *data,const int nthreads);
55 void calling_device(const int numstones,const double *stonex,const double *stoney,
56 const double startx,const double starty,
57 const double *radius,const double *sradius,const double *eradius,
58 const unsigned int costsizex,const unsigned int costsizey,const double map_resolution,
59 const double origin_x,const double origin_y,const double *dist_from_centre,
60 const double centre_weight,
61 unsigned char lethal,
62 const int min_index_x,const int max_index_x,
63 const int min_index_y,const int max_index_y,
64 unsigned char *newCost,
65 const int nthreads,
66 const bool debug);
67 //a function for GPU calculation called from the function
68 //PipelinePlanner::VeilCostmap_cuda
69 void DistanceFromCentreCalling(const int numstones,
70 const double *stonex,const double *stoney,const double *stonedev,
71 const unsigned int costsizex,const unsigned int costsizey,
72 const double map_resolution, const double origin_x,const double origin_y,
73 double *dist_from_centre,
74 const int nthreads,
75 const bool debug);
76 #endif
77 
78 namespace pipeline_planner {
79 
81  initialized_(NULL),costmap_(NULL),navfn_planner_(NULL),lethal_cost_(253),debug(false),tolerance_(0.001),willDisplay_(false)
82 {
83 }
84 
85 PipelinePlanner::PipelinePlanner(std::string name, costmap_2d::Costmap2D* costmap, std::string frame_id):
86  initialized_(NULL),costmap_(NULL),navfn_planner_(NULL),lethal_cost_(253),debug(false),tolerance_(0.001),willDisplay_(false)
87 {
88  //initialisation
89  initialize(name,costmap,frame_id);
90 }
91 
93  //if(global_planner_)delete global_planner_;
96  if(dsrv_)delete dsrv_;
98 }
99 
100 void PipelinePlanner::initialize(std::string name, costmap_2d::Costmap2DROS* costmap_ros){
101  bool status;
102  if(!initialized_){
103  status=initialize(name,costmap_ros->getCostmap(),costmap_ros->getGlobalFrameID());
104  robot_status_.data=1;
105  if(status){
106  initialized_= true;
107  robot_status_.data=2;
108  std_msgs::Bool initialised;
109  initialised.data=true;
110  ros::Rate r1(1.0); ros::Rate r2(2.0);
111  r1.sleep();
112  pub_initialised_.publish(initialised);
113  r2.sleep();
114  } else {
115  return ;
116  };
117  };
118 }
119 
120 bool PipelinePlanner::initialize(std::string name, costmap_2d::Costmap2D* costmap, std::string frame_id){
121  if(initialized_){
122  ROS_WARN("This planner has already been initialized, you can't call it twice, doing nothing");
123  return false;
124  };
125 
126  gained_frame_id_=frame_id;
127  //global_planner_=new global_planner::GlobalPlanner(name,costmap,frame_id);
128  //global_planner_=new global_planner::GlobalPlanner("GlobalPlanner",costmap,frame_id);
130  //navfn_planner_=new navfn::NavfnROS("NavfnROS",costmap,frame_id);
131  navfn_planner_=new navfn::NavfnROS("NavfnROS",navfn_costmap_,frame_id);
132  costmap_=costmap;
133 
134  check_points_.clear();
135  segment_infos_.clear();
136  ros::NodeHandle nh1("~/"+name);
137  //sub_checkpoints_=nh1.subscribe<geometry_msgs::PoseArray>
138  // ("checkpoints",1,&PipelinePlanner::SubscribeCheckpoints,this);
139 
140  willDisplay_=false;
141  sub_movebase_goal_=nh1.subscribe<move_base_msgs::MoveBaseActionGoal>
142  ("/move_base/goal",1,&PipelinePlanner::callbackgoal,this);
143 
144  sub_robot_pose_=nh1.subscribe<geometry_msgs::Pose>
145  ("/robot_pose",1,&PipelinePlanner::callbackRobotPose,this);
146 
147  robot_position_.position.x=0.0;
148  robot_position_.position.y=0.0;
149  robot_position_.position.z=0.0;
150  robot_position_.orientation.x=0.0;
151  robot_position_.orientation.y=0.0;
152  robot_position_.orientation.z=0.0;
153  robot_position_.orientation.w=0.0;
154 
155  name_.clear();
156  name_=name;
157  read_status_.data=1;
158  pub_result_=nh1.advertise<std_msgs::UInt32>("read_checkpoints",1);
159  pub_status_=nh1.advertise<std_msgs::UInt32>("inform_status",1);
160  pub_plan_=nh1.advertise<nav_msgs::Path>("plan",1);
161  pub_robot_position_=nh1.advertise<pipeline_planner::RobotPosition>("robot_position",1);
162  pub_time_=nh1.advertise<std_msgs::Float32>("time",1);
163  pub_initialised_=nh1.advertise<std_msgs::Bool>("initialised",1,true);
164  pub_pipeline_=nh1.advertise<nav_msgs::OccupancyGrid>("visualise_pipeline",1,true);
166 
167  //nh1.param("fix_pipe_radius",fix_pipe_radius_,false);//TODO we will change default value as false
168 
177 
178  dsrv_=new dynamic_reconfigure::Server<pipeline_planner::PipelinePlannerConfig>(nh1);
179  dynamic_reconfigure::Server<pipeline_planner::PipelinePlannerConfig>::CallbackType cb=boost::bind(&PipelinePlanner::reconfigureCB,this,_1,_2);
180  dsrv_->setCallback(cb);
181 
182  //thread
183  thread_robot_position_=new boost::thread(boost::bind(&PipelinePlanner::informRobotPose,this));
184 
185  //wait for service
186  for(int i=0;i<10;i++){
187  bool come=ros::service::waitForService("/move_base/PipelinePlanner/receive_checkpoints",1000);
188  if(come){
189  ROS_INFO("Service /move_base/PipelinePlanner/receive_checkpoints has advertised.");
190  break;
191  } else {
192  };
193  if(i==9){
194  ROS_ERROR("Service /move_base/PipelinePlanner/receive_checkpoints preparation is not confirmed.");
195  };
196  };
197 
198  makePipeline();
199 
200  return true;
201 }
202 
203 void PipelinePlanner::reconfigureCB(pipeline_planner::PipelinePlannerConfig &config,uint32_t level){
204  setPipeRadius(config.pipe_radius);
205  setLethal(config.lethal_cost);
206  setWeight(config.centre_weight);
207 #if MODE==MODE_GPU
208  setNumThread(config.num_threads);
209 #endif
210  setStraight(config.use_straight);
211  setCharge(config.charge);
212  setTimeDisplay(config.time_display);
213  setTorchArea(config.use_torch,config.torch_area_x,config.torch_area_y);
214 }
215 
217  pipe_radius_=(double)radius;
218  if(read_status_.data==1)return; //before initialised
219  read_status_.data=2;
220  robot_status_.data=9;
222  int npoints=check_points_.size();
223  int endpoint=(openclose_==1)?npoints:npoints-1; // close or open
224  //costmap check
225  int flag=0;
226  flag=costCheck(endpoint);
227  bool legal;
228  //if(flag==1)pipe_radius_=-1.0;
229  if(flag==1){ legal=false;} else { legal=true;};
230  makePipeline(legal);
231  if(flag!=1){
232 #if MODE==MODE_GPU
233  DistanceFromCentre_cuda(endpoint);
234 #else
235  DistanceFromCentre(endpoint);
236 #endif
237  };
238 
239  if(flag==1){
240  ROS_ERROR_STREAM("The part of the route made by the check points is off the global costmap.");
241  read_status_.data=6;
242  robot_status_.data=9;
243  //pipe_radius_=(double)radius;
244  //check_points_.clear();
245  //makePipeline();
247  //res.read_status=read_status_.data;
248  } else if(flag==2){
249  ROS_INFO_STREAM("The route includes an obstacle.");
250  read_status_.data=5;
251  robot_status_.data=2;
253  //res.read_status=read_status_.data;
254  } else {
255  ROS_INFO_STREAM("The check points are received.");
256  read_status_.data=3;
257  robot_status_.data=2;
259  //res.read_status=read_status_.data;
260  };
261 
262 }
263 
264 bool PipelinePlanner::SetARadius(pipeline_planner::SetARadius::Request &req,pipeline_planner::SetARadius::Response &res){
265  //assertion of valid ID value
266  if(!(req.ID>=-1)){
267  res.result=1;
268  res.read_status=read_status_.data;
269  return true;
270  };
271  //assertion of valid radius value
272  if(!(req.radius==0||req.radius>=0.001&&req.radius<=50)){
273  res.result=2;
274  res.read_status=read_status_.data;
275  return true;
276  };
277  //assertion of non empty checkpoints
278  int ncheckpoints=check_points_.size();
279  if(check_points_.empty()){
280  res.result=3;
281  res.read_status=read_status_.data;
282  return true;
283  };
284  int nsegments=(openclose_==1)?ncheckpoints:ncheckpoints-1;
285  //all segments
286  if(req.ID==-1){
287  for(int i=0;i<nsegments;i++){
288  check_points_.at(i).pose.position.z=req.radius;
289  };
290  } else {//each segment
291  if(req.ID>nsegments-1){
292  res.result=4;
293  res.read_status=read_status_.data;
294  return true;
295  } else {
296  check_points_.at(req.ID).pose.position.z=req.radius;
297  };
298  };
299  res.result=0;
300  //generation of new pipeline and validation of that
301  read_status_.data=2;
302  robot_status_.data=9;
304  int flag=0;
305  flag=costCheck(nsegments);
306  bool legal;
307  if(flag==1){ legal=false;} else { legal=true;};
308  makePipeline(legal);
309  if(flag!=1){
310 #if MODE==MODE_GPU
311  DistanceFromCentre_cuda(nsegments);
312 #else
313  DistanceFromCentre(nsegments);
314 #endif
315  };
316 
317  if(flag==1){
318  ROS_ERROR_STREAM("The part of the route made by the check points is off the global costmap.");
319  read_status_.data=6;
320  robot_status_.data=9;
322  res.read_status=read_status_.data;
323  } else if(flag==2){
324  ROS_INFO_STREAM("The route includes an obstacle.");
325  read_status_.data=5;
326  robot_status_.data=2;
328  res.read_status=read_status_.data;
329  } else {
330  ROS_INFO_STREAM("The check points are received.");
331  read_status_.data=3;
332  robot_status_.data=2;
334  res.read_status=read_status_.data;
335  };
336 
337  return true;
338 }
339 
340 bool PipelinePlanner::SetARightshift(pipeline_planner::SetARightshift::Request &req,pipeline_planner::SetARightshift::Response &res){
341  //assertion of valid ID value
342  if(!(req.ID>=-1)){
343  res.result=1;
344  return true;
345  };
346  //assertion of non empty checkpoints
347  int ncheckpoints=check_points_.size();
348  if(check_points_.empty()){
349  res.result=3;
350  return true;
351  };
352  int nsegments=(openclose_==1)?ncheckpoints:ncheckpoints-1;
353  //all segments
354  if(req.ID==-1){
355  for(int i=0;i<nsegments;i++){
356  check_points_.at(i).pose.orientation.y=req.shift;
357  };
358  } else {//each segment
359  if(req.ID>nsegments-1){
360  res.result=4;
361  return true;
362  } else {
363  check_points_.at(req.ID).pose.orientation.y=req.shift;
364  };
365  };
366  res.result=0;
367  if(read_status_.data==3||read_status_.data==5){
368 #if MODE==MODE_GPU
369  DistanceFromCentre_cuda(nsegments);
370 #else
371  DistanceFromCentre(nsegments);
372 #endif
373  };
374  return true;
375 }
376 
377 bool PipelinePlanner::hasNoCross(const int endpoint,
378  const std::vector<geometry_msgs::PoseStamped> check_points){
379  bool hasCross=false;
380  int npoints=check_points.size();
381  double dbgPx,dbgPy,dbgQx,dbgQy,dbgRx,dbgRy,dbgSx,dbgSy;
382  for(int i=0;i<endpoint;i++){ //line segment PQ
383  int ci=i;
384  int ni=(i==npoints-1)?0:i+1;
385  double Px=check_points.at(ci).pose.position.x;
386  double Py=check_points.at(ci).pose.position.y;
387  double Qx=check_points.at(ni).pose.position.x;
388  double Qy=check_points.at(ni).pose.position.y;
389  for(int j=0;j<endpoint;j++){ //line segment RS
390  if((i==j)||abs(i-j)==1||abs(i-j)==npoints-1)continue;
391  int cj=j;
392  int nj=(j==npoints-1)?0:j+1;
393  double Rx=check_points.at(cj).pose.position.x;
394  double Ry=check_points.at(cj).pose.position.y;
395  double Sx=check_points.at(nj).pose.position.x;
396  double Sy=check_points.at(nj).pose.position.y;
397  // t(P-Q)=s(R-S)+(S-Q) for 0<=t<=1, 0<=s<=1 ... (1)
398  // (1) is crossing condition
399  // there are two cases, that is (P-Q)//(R-S) or not
400  double PQx=Qx-Px; double PQy=Qy-Py;
401  double RSx=Sx-Rx; double RSy=Sy-Ry;
402  double SQx=Qx-Sx; double SQy=Qy-Sy;
403  if(PQx*RSy==PQy*RSx){ // (P-Q)//(R-S)
404  if(!(PQx*SQy==PQy*SQx))continue; // assertion of (P-Q)//(S-Q)
405  // X={SQ,SP,RQ,RP} in PQ axis
406  // minX<= 0 <= maxX (condition for overlapping)
407  double SQ=SQx*PQx+SQy*PQy;
408  double SP=(Px-Sx)*PQx+(Py-Sy)*PQy;
409  double RQ=(Qx-Rx)*PQx+(Qy-Ry)*PQy;
410  double RP=(Px-Rx)*PQx+(Py-Ry)*PQy;
411  double minX=std::min(std::min(SQ,SP),std::min(RQ,RP));
412  double maxX=std::max(std::max(SQ,SP),std::max(RQ,RP));
413  if((minX<=0.0)&&(0.0<=maxX)){
414  hasCross=true;
415  dbgPx=Px;dbgPy=Py;dbgQx=Qx;dbgQy=Qy;
416  dbgRx=Rx;dbgRy=Ry;dbgSx=Sx;dbgSy=Sy;
417  break;
418  };
419  } else{ // not (P-Q)//(R-S)
420  // x: cross point
421  // x=tP+(1-t)Q=Q+tQP, x=sR+(1-s)S=S+sSR
422  // s=((Q-S)*n)/((R-S)*n), t=((S-Q)*m)/((P-Q)*m)
423  // 0<=s<=1, 0<=t<=1
424  // n: vector perpendicular to P-Q, m: vector perpendicular to R-S
425  double ppdPQx=-PQy; double ppdPQy=PQx; // n
426  double ppdRSx=-RSy; double ppdRSy=RSx; // m
427  double tmps=(SQx*ppdPQx+SQy*ppdPQy)/(-RSx*ppdPQx-RSy*ppdPQy);
428  double tmpt=(-SQx*ppdRSx-SQy*ppdRSy)/(-PQx*ppdRSx-PQy*ppdRSy);
429  if((0.0<=tmps)&&(tmps<=1.0)&&(0.0<=tmpt)&&(tmpt<=1.0)){
430  hasCross=true;
431  dbgPx=Px;dbgPy=Py;dbgQx=Qx;dbgQy=Qy;
432  dbgRx=Rx;dbgRy=Ry;dbgSx=Sx;dbgSy=Sy;
433  break;
434  };
435  };
436  };
437  if(hasCross)break;
438  };
439  if(hasCross){
440  ROS_ERROR_STREAM("SubscribeCheckpoints: received pipeline has a crossing ");
441  ROS_ERROR_STREAM("crossing segments");
442  ROS_ERROR_STREAM("(" << dbgPx << "," << dbgPy << ")-(" << dbgQx << "," << dbgQy << ")");
443  ROS_ERROR_STREAM("(" << dbgRx << "," << dbgRy << ")-(" << dbgSx << "," << dbgSy << ")");
444  };
445  bool hasnoCross=!hasCross;
446  return hasnoCross;
447 
448 }
449 
450 int PipelinePlanner::costCheck(int endpoint){
451  int flag=0;
452  int npoints=check_points_.size();
453  double map_resolution=costmap_->getResolution();
454  for(int i=0;i<endpoint;i++){
455  int ci=i;
456  int ni=(i==npoints-1)?0:i+1;
457  double pipe_radius;
458  //if(fix_pipe_radius_){
459  // pipe_radius=pipe_radius_;
460  //} else {
461  // if(check_points_.at(ci).pose.position.z==0.0){
462  // pipe_radius=pipe_radius_;
463  // } else {
464  // pipe_radius=check_points_.at(ci).pose.position.z;
465  // };
466  //};
467  pipe_radius=TakeSegmentRadius(check_points_.at(ci).pose.position.z);
468  //makeing a square
469  double cx=check_points_.at(ci).pose.position.x;
470  double cy=check_points_.at(ci).pose.position.y;
471  double nx=check_points_.at(ni).pose.position.x;
472  double ny=check_points_.at(ni).pose.position.y;
473  double minx=std::min(cx,nx)-pipe_radius;
474  double miny=std::min(cy,ny)-pipe_radius;
475  double maxx=std::max(cx,nx)+pipe_radius;
476  double maxy=std::max(cy,ny)+pipe_radius;
477 
478 if(debug){
479  ROS_INFO_STREAM("minx: " << minx << ", miny: " << miny);
480  ROS_INFO_STREAM("maxx: " << maxx << ", maxy: " << maxy);
481  double origx=costmap_->getOriginX();
482  double origy=costmap_->getOriginY();
483  ROS_INFO_STREAM("origx: " << origx);
484  ROS_INFO_STREAM("origy: " << origy);
485 };
486 
487  unsigned int minx_i,miny_i,maxx_i,maxy_i;
488  unsigned int uix1,uiy1,uix2,uiy2;
489  if(!(costmap_->worldToMap(minx,miny,uix1,uiy1))){
490  ROS_ERROR_STREAM("the point (" << minx << "," << miny << ") is off the global costmap");
491  flag=1;
492  break;
493  };
494  if(!(costmap_->worldToMap(maxx,maxy,uix2,uiy2))){
495  ROS_ERROR_STREAM("the point (" << maxx << "," << maxy << ") is off the global costmap");
496  flag=1;
497  break;
498  };
499  minx_i=std::min(uix1,uix2);
500  miny_i=std::min(uiy1,uiy2);
501  maxx_i=std::max(uix1,uix2);
502  maxy_i=std::max(uiy1,uiy2);
503 
504  double normv=std::sqrt((nx-cx)*(nx-cx)+(ny-cy)*(ny-cy));
505  double invnormv=1.0/normv;
506  double refper=cx*(ny-cy)-cy*(nx-cx); //reference value for perpendicular component
507  double difper=pipe_radius*invnormv*((ny-cy)*(ny-cy)-(-(nx-cx))*(nx-cx))
508  +map_resolution*(0.5* std::abs(ny-cy)+0.5* std::abs(nx-cx));
509  //reference value for parallel component
510  double refpll=(0.5*(nx+cx))*(nx-cx)+(0.5*(ny+cy))*(ny-cy);
511  //reference value for parallel component
512  double difpll=(0.5*(nx-cx))*(nx-cx)+(0.5*(ny-cy))*(ny-cy)
513  +map_resolution*(0.5*std::abs(nx-cx)+0.5*std::abs(ny-cy));
514 
515  //costmap cell loop in the square
516  for(int ix=minx_i;ix<maxx_i+1;ix++){
517  if((!debug)&&(flag!=0))break;
518  for(int iy=miny_i;iy<maxy_i+1;iy++){
519  //if(flag!=0)break;
520  //whether the cell overlap the pipe segment or not
521  double wx,wy; // centre of the costmap cell
522  costmap_->mapToWorld(ix,iy,wx,wy);
523  double curper=wx*(ny-cy)-wy*(nx-cx);
524  double curpll=wx*(nx-cx)+wy*(ny-cy);
525  //cost value
526  unsigned char c=costmap_->getCharMap()[costmap_->getIndex(ix,iy)];
527  //verification
528  if((std::abs(curper-refper)<difper)&&(std::abs(curpll-refpll)<difpll)&&(c>=lethal_cost_)){
529  if(debug){
530  ROS_WARN_STREAM("The centre of the costmap cell:" << wx << "," << wy);
531  ROS_WARN_STREAM("The costmap resolution: " << map_resolution);
532  };
533  flag=2;
534  if(!debug)break;
535  };
536  };};
537  //if(flag!=0)break;
538  };
539 
540  return flag;
541 }
542 
544  int npoints=check_points_.size();
545  unsigned int costsizex=costmap_->getSizeInCellsX();
546  unsigned int costsizey=costmap_->getSizeInCellsY();
547  unsigned int costsize=costsizex*costsizey;
548  dist_from_pipe_centre_.clear();
549  dist_from_pipe_centre_.resize(costsize);
550  for(unsigned int xi=0;xi<costsizex;xi++){
551  for(unsigned int yi=0;yi<costsizey;yi++){
552  unsigned int idx=costmap_->getIndex(xi,yi);
553 
554  //We only calculate distance of a point in the pipeline
555  if(pipeline_.data[idx]==100){
556  dist_from_pipe_centre_.at(idx)=100.0;
557  continue;
558  };
559 
560  double tmpdist,mindist;
561  double px,py;
562  costmap_->mapToWorld(xi,yi,px,py);
563  for(int i=0;i<endpoint;i++){
564  int ci=i;
565  int ni=(i==npoints-1)?0:i+1;
566  double cx=check_points_.at(ci).pose.position.x;
567  double cy=check_points_.at(ci).pose.position.y;
568  double nx=check_points_.at(ni).pose.position.x;
569  double ny=check_points_.at(ni).pose.position.y;
570  double cnx=nx-cx;double cny=ny-cy;
571  double leng_cn=sqrt(cnx*cnx+cny*cny);
572  double dirx=cnx/leng_cn; double diry=cny/leng_cn;
573  //directional component
574  double dcomp_c=cx*dirx+cy*diry;
575  double dcomp_n=nx*dirx+ny*diry;
576  double dcomp_p=px*dirx+py*diry;
577  //perpendicular component
578  double ppcx=ny-cy; double ppcy=-(nx-cx);
579  double leng_ppc=sqrt(ppcx*ppcx+ppcy*ppcy);
580  double perpx=ppcx/leng_ppc; double perpy=ppcy/leng_ppc;
581  //double tmpdist;
582  if(dcomp_p>dcomp_n){
583  //double npx=px-nx;double npy=py-ny;
584  double npx=px-(nx+perpx*check_points_.at(i).pose.orientation.y);
585  double npy=py-(nx+perpy*check_points_.at(i).pose.orientation.y);
586  tmpdist=sqrt(npx*npx+npy*npy);
587  } else if(dcomp_c>dcomp_p){
588  //double cpx=px-cx;double cpy=py-cy;
589  double cpx=px-(cx+perpx*check_points_.at(i).pose.orientation.y);
590  double cpy=py-(cy+perpy*check_points_.at(i).pose.orientation.y);
591  tmpdist=sqrt(cpx*cpx+cpy*cpy);
592  } else {
593 // //perpendicular component
594 // double ppcx=ny-cy; double ppcy=-(nx-cx);
595 // double leng_ppc=sqrt(ppcx*ppcx+ppcy*ppcy);
596 // double perpx=ppcx/leng_ppc; double perpy=ppcy/leng_ppc;
597  //double pcomp_c=cx*perpx+cy*perpy;
598  double pcomp_c=cx*perpx+cy*perpy+check_points_.at(i).pose.orientation.y;
599  double pcomp_p=px*perpx+py*perpy;
600  tmpdist=fabs(pcomp_c-pcomp_p);
601  };
602  if(i==0){
603  mindist=tmpdist;
604  } else {
605  if(tmpdist<mindist)mindist=tmpdist;
606  };
607  };
608  dist_from_pipe_centre_.at(idx)=mindist;
609  };};
610 
611  return true;
612 }
613 
614 #if MODE==MODE_GPU
616  //error task
617  ThreadNumberAdjusment(false);
618 
619  //preparation
620  cudaError_t error_allocation;
621  unsigned int costsizex=costmap_->getSizeInCellsX();
622  unsigned int costsizey=costmap_->getSizeInCellsY();
623  unsigned int costsize=costsizex*costsizey;
624 //void Costmap2D::mapToWorld(unsigned int mx, unsigned int my, double& wx, double& wy) const
625 //{
626 // wx = origin_x_ + (mx + 0.5) * resolution_;
627 // wy = origin_y_ + (my + 0.5) * resolution_;
628 //}
629  double origin_x=costmap_->getOriginX();
630  double origin_y=costmap_->getOriginY();
631  double map_resolution=costmap_->getResolution();
632  //coordinates for checkpoints, allocation for device and copy values to them.
633  double *stonex,*stoney;
634  double *stonedev;//deviation
635  if(debug){
636  error_allocation=cudaMallocManaged(&stonex,(endpoint+1)*sizeof(double));
637  ROS_INFO_STREAM("allocation stonex: " << error_allocation);//for debug
638  error_allocation=cudaMallocManaged(&stoney,(endpoint+1)*sizeof(double));
639  ROS_INFO_STREAM("allocation stonex: " << error_allocation);//for debug
640  error_allocation=cudaMallocManaged(&stonedev,(endpoint+1)*sizeof(double));
641  ROS_INFO_STREAM("allocation stonedev: " << error_allocation);//for debug
642  } else {
643  cudaMallocManaged(&stonex,(endpoint+1)*sizeof(double));
644  cudaMallocManaged(&stoney,(endpoint+1)*sizeof(double));
645  cudaMallocManaged(&stonedev,(endpoint+1)*sizeof(double));
646  };
647  int npoints=check_points_.size();
648  for(int i=0;i<endpoint;i++){
649  int ci=i;
650  int ni=(i==npoints-1)?0:i+1;
651  stonex[i]=check_points_.at(i).pose.position.x;
652  stoney[i]=check_points_.at(i).pose.position.y;
653  stonedev[i]=check_points_.at(i).pose.orientation.y;
654  if(i==endpoint-1){
655  int lastindex=(i==npoints-1)?0:i+1;
656  stonex[i+1]=check_points_.at(lastindex).pose.position.x;
657  stoney[i+1]=check_points_.at(lastindex).pose.position.y;
658  stonedev[i+1]=check_points_.at(lastindex).pose.orientation.y;
659  };
660  };
661  // allocation of device variable which corresponds dist_from_pipe_centre_
662  double *dist_from_centre;
663  if(debug){
664  error_allocation=cudaMallocManaged(&dist_from_centre,(costsize)*sizeof(double));
665  ROS_INFO_STREAM("allocation dist_from_centre: " << error_allocation);
666  } else {
667  cudaMallocManaged(&dist_from_centre,(costsize)*sizeof(double));
668  };
669 
670  //We only calculate distance of a point in the pipeline
671  for(int i=0;i<costsize;i++){
672  if(pipeline_.data[i]==100){
673  dist_from_centre[i]=100.0;//out of the pipeline
674  } else {
675  dist_from_centre[i]=0.0;//in the pipeline
676  };
677  };
678 
679  //calling device function
680  DistanceFromCentreCalling(endpoint,stonex,stoney,stonedev,costsizex,costsizey,
681  map_resolution,origin_x,origin_y,dist_from_centre,
683 
684 
685  //finalisation
686  //copying of variables
687  dist_from_pipe_centre_.clear();
688  dist_from_pipe_centre_.resize(costsize);
689  for(int xi=0;xi<costsizex;xi++){
690  for(int yi=0;yi<costsizey;yi++){
691  int index=yi*costsizex+xi;
692  dist_from_pipe_centre_.at(index)=dist_from_centre[index];
693  };};
694  //free allocated variables
695  cudaError_t error_free;
696  if(debug){
697  error_free=cudaFree(stonex);
698  ROS_INFO_STREAM("free stonex: " << error_free);
699  error_free=cudaFree(stoney);
700  ROS_INFO_STREAM("free stoney: " << error_free);
701  error_free=cudaFree(stonedev);
702  ROS_INFO_STREAM("free stonedev: " << error_free);
703  error_free=cudaFree(dist_from_centre);
704  ROS_INFO_STREAM("free dist_from_centre: " << error_free);
705  } else {
706  cudaFree(stonex);
707  cudaFree(stoney);
708  cudaFree(stonedev);
709  cudaFree(dist_from_centre);
710  };
711 
712 }
713 #endif
714 
716  int n=check_points_.size();
717  int last=(openclose_==1)?n:n-1;
718 
719  for(int i=0;i<last;i++){
720  pipeline_planner::SegmentInfo si;
721  int id,previd,nextid;
722  id=i;
723  if((openclose_==2)&&(i==0)){
724  previd=-1;
725  } else {
726  previd=(id-1+n)%n;
727  };
728  if((openclose_==2)&&(i==last-1)){
729  nextid=-1;
730  } else {
731  nextid=(id+1)%n;
732  };
733 
734  int cID=i;
735  int nID=(i+1)%n;
736  double cx=check_points_.at(cID).pose.position.x;
737  double cy=check_points_.at(cID).pose.position.y;
738  double nx=check_points_.at(nID).pose.position.x;
739  double ny=check_points_.at(nID).pose.position.y;
740  double dist=sqrt(pow(nx-cx,2.0)+pow(ny-cy,2.0));
741  if(dist<tolerance_){
742  ROS_ERROR_STREAM("two check points " << cID << "(" << cx << "," << cy << ")-(" << nx << "," << ny << ") are too close");
743  ROS_ERROR_STREAM(" distance: " << dist);
744  segment_infos_.clear();
745  return false;
746  };
747 
748  si.ID=id; si.prevID=previd; si.nextID=nextid;
749  si.length=dist;
750  si.start=false; si.end=false;
751 
752  segment_infos_.push_back(si);
753  };
754 
755  return true;
756 }
757 
758 void PipelinePlanner::PublishCheckpointsResult(std_msgs::UInt32 result){
759  pub_result_.publish(result);
760 }
761 
762 bool PipelinePlanner::InquireSegments(pipeline_planner::InquireSegments::Request &req,pipeline_planner::InquireSegments::Response &res){
763  res.num_segments=segment_infos_.size();
764  for(std::vector<pipeline_planner::SegmentInfo>::iterator it=segment_infos_.begin();it!=segment_infos_.end();it++){
765  pipeline_planner::SegmentInfo segmentinfo;
766  segmentinfo.ID=it->ID;
767  segmentinfo.prevID=it->prevID;
768  segmentinfo.nextID=it->nextID;
769  segmentinfo.length=it->length;
770  segmentinfo.start=it->start;
771  segmentinfo.end=it->end;
772 
773  res.sinfo.push_back(segmentinfo);
774  };
775  return true;
776 }
777 
778 bool PipelinePlanner::ReceiveCheckpoints(pipeline_planner::ReceiveCheckpoints::Request &req,pipeline_planner::ReceiveCheckpoints::Response &res){
779  check_points_.clear();
780  segment_infos_.clear();
781  makePipeline();
782 
783  read_status_.data=2;
784  robot_status_.data=9;
786  res.read_status=read_status_.data;
787  if(req.checkpoints.poses.empty()){
788  ROS_ERROR_STREAM("ReceiveCheckpoints: received checkpoint is empty");
789  read_status_.data=4;
790  robot_status_.data=9;
792  res.read_status=read_status_.data;
793  return true;
794  };
795 
796  int num_points=req.checkpoints.poses.size();
797  for(int i=0;i<num_points;i++){
798  geometry_msgs::PoseStamped tmpStm;
799  tmpStm.header.frame_id=gained_frame_id_;
800  tmpStm.pose.position.x = req.checkpoints.poses[i].position.x;
801  tmpStm.pose.position.y = req.checkpoints.poses[i].position.y;
802 // if(fix_pipe_radius_){
803 // tmpStm.pose.position.z = 0;
804 // } else {
805 // tmpStm.pose.position.z = req.checkpoints.poses[i].position.z;
816 // //assertion of validity
817 // if(!(tmpStm.pose.position.z>=0.001&&tmpStm.pose.position.z<=50)){
818 // tmpStm.pose.position.z=0.0;// This means the pipe_radius value.
819 // };
820 // };
821 
822  double aradius=req.checkpoints.poses[i].position.z;
823  if(!(aradius==0.0||aradius>=0.001&&aradius<=50)){
824  ROS_ERROR_STREAM("ReceiveCheckpoints: a radius of " << i+1 << "-th check point is not valid");
825  ROS_ERROR_STREAM("radius: " << tmpStm.pose.position.z);
826  read_status_.data=9;
827  robot_status_.data=9;
829  res.read_status=read_status_.data;
830  return true;
831  } else {
832  tmpStm.pose.position.z=aradius;
833  };
834 
835  tmpStm.pose.orientation.x = 0;
836  tmpStm.pose.orientation.y = req.checkpoints.poses[i].orientation.y;
837  tmpStm.pose.orientation.z = 0;
838  tmpStm.pose.orientation.w = 1;
839  check_points_.push_back(tmpStm);
840  };
841 
842  //status check
843  //empty
844  if(check_points_.empty()){
845  ROS_ERROR_STREAM("ReceiveCheckpoints: read of checkpoints failed");
846  read_status_.data=4;
847  robot_status_.data=9;
848  check_points_.clear();
850  res.read_status=read_status_.data;
851  return true;
852  };
853  //route overlaps an obstacle or a part of route is out of costmap
854  int npoints=check_points_.size();
855  double map_resolution=costmap_->getResolution();
856  int endpoint;
857  int openclose=std::atoi(req.checkpoints.header.frame_id.c_str());
858  openclose_=openclose;
859 if(debug){
860  ROS_INFO_STREAM("req.checkpoints.header.frame_id: " << req.checkpoints.header.frame_id);
861  ROS_INFO_STREAM("openclose_: " << openclose_);
862 };
863  if(!((openclose_==1)||(openclose_==2))){
864  ROS_ERROR_STREAM("The value for openclose flag is starnge.: " << req.checkpoints.header.frame_id);
865  ROS_ERROR_STREAM("It must be 1 or 2");
866  read_status_.data=7;
867  robot_status_.data=9;
868  check_points_.clear();
870  res.read_status=read_status_.data;
871  return true;
872  };
873  if(((openclose_==1)&&(check_points_.size()<3))||(check_points_.size()<2)){
874  ROS_ERROR_STREAM("ReceiveCheckpoints: The number of check points is " << check_points_.size());
875  if(openclose_==1){
876  ROS_ERROR_STREAM(" Checkpoints must be 3 or more");
877  } else {
878  ROS_ERROR_STREAM(" Checkpoints must be 2 or more");
879  };
880  read_status_.data=4;
881  robot_status_.data=9;
882  check_points_.clear();
884  res.read_status=read_status_.data;
885  return true;
886  };
887  //dump
888  ROS_INFO_STREAM("checkpoints from service");
889  //if(fix_pipe_radius_){
890  // ROS_INFO_STREAM("(x,y)");
891  // for(std::vector<geometry_msgs::PoseStamped>::iterator it=check_points_.begin();
892  // it!=check_points_.end();it++){
893  // ROS_INFO("(%f , %f)",(*it).pose.position.x, (*it).pose.position.y);
894  // };
895  //} else {
896  // ROS_INFO_STREAM("(x,y): pipe_radius");
897  // for(std::vector<geometry_msgs::PoseStamped>::iterator it=check_points_.begin();
898  // it!=check_points_.end();it++){
899  // double radius;
900  // if((*it).pose.position.z==0.0){
901  // radius=pipe_radius_;
902  // } else {
903  // radius=(*it).pose.position.z;
904  // };
905  // ROS_INFO("(%f , %f) : %f",(*it).pose.position.x, (*it).pose.position.y, radius);
906  // };
907  //};
908 
909  ROS_INFO_STREAM("(x,y): pipe_radius");
910  for(std::vector<geometry_msgs::PoseStamped>::iterator it=check_points_.begin();
911  it!=check_points_.end();it++){
912  double radius;
913  if((*it).pose.position.z==0.0){
914  radius=pipe_radius_;
915  } else {
916  radius=(*it).pose.position.z;
917  };
918  ROS_INFO("(%f , %f) : %f",(*it).pose.position.x, (*it).pose.position.y, radius);
919  };
920 
921  endpoint=(openclose_==1)?npoints:npoints-1; // close or open
922 
923  //calculation of pipe segments lengths
924  if(!InitSegInfo()){
925  ROS_ERROR_STREAM("some sequential checkpoints are too close.");
926  read_status_.data=10;
927  robot_status_.data=9;
928  check_points_.clear();
930  res.read_status=read_status_.data;
931  return true;
932  };
933 
934  //assertion for pipeline crossing
935  if(!hasNoCross(endpoint,check_points_)){
936  read_status_.data=8;
937  robot_status_.data=9;
938  check_points_.clear();
940  res.read_status=read_status_.data;
941  return true;
942  };
943 
944  //costmap check
945  int flag=0;
946  flag=costCheck(endpoint);
947 
948  //calculation of distance from centre
949  if(flag!=1){
950  makePipeline();
951 
952 #if MODE==MODE_GPU
953  DistanceFromCentre_cuda(endpoint);
954 #else
955  DistanceFromCentre(endpoint);
956 #endif
957  };
958 
959  if(flag==1){
960  ROS_ERROR_STREAM("The part of the route made by the check points is off the global costmap.");
961  read_status_.data=6;
962  robot_status_.data=9;
963  //check_points_.clear();
965  res.read_status=read_status_.data;
966  } else if(flag==2){
967  ROS_INFO_STREAM("The route includes an obstacle.");
968  read_status_.data=5;
969  robot_status_.data=2;
971  res.read_status=read_status_.data;
972  } else {
973  ROS_INFO_STREAM("The check points are received.");
974  read_status_.data=3;
975  robot_status_.data=2;
977  res.read_status=read_status_.data;
978  };
979 
980 #if MODE==MODE_GPU
981 test_cuda(2, 3);
982 #endif
983  return true;
984 }
985 
986 bool PipelinePlanner::makePlan(const geometry_msgs::PoseStamped& start,
987  const geometry_msgs::PoseStamped& goal,
988  std::vector<geometry_msgs::PoseStamped>& plan){
989  //for debug
990  ros::Time begin=ros::Time::now();
991  //to inform start of calculation into tablet through RMC
992  robot_status_.data=12;
994  if(!initialized_){
995  ROS_ERROR("This planner has not been initialized yet, but it is being used,"
996  " please call initialize() before use");
997  robot_status_.data=1;
999  return false;
1000  };
1001  if(!((read_status_.data==3)||(read_status_.data==5))){
1002  ROS_ERROR_STREAM("The planner didn't receive valid check points.");
1003  ROS_ERROR_STREAM("read_status_: " << read_status_.data);
1004  robot_status_.data=9;
1006  return false;
1007  };
1008 
1009  //verification of whether start and goal is in the pipeline or not
1010  bool inapipe=false;
1011  int lastpoint;
1012  lastpoint=(openclose_==1)?check_points_.size():check_points_.size()-1;
1013  std::vector<int> startids;
1014  startids.clear();
1015  for(int i=0;i<lastpoint;i++){
1016  int ci,ni,pi;
1017  bool inasegment;
1018  ci=i; ni=(i==check_points_.size()-1)?0:ci+1;
1019  double pipe_radius,sradius,eradius;
1020  //if(fix_pipe_radius_){
1021  // pipe_radius=pipe_radius_;
1022  // inasegment=InPipeSegment(start,pipe_radius,pipe_radius,pipe_radius,tolerance_,ci);
1023  //} else {
1024  pi=(ci==0)?check_points_.size()-1:ci-1;
1025  double crad=TakeSegmentRadius(check_points_.at(ci).pose.position.z);
1026  double prad=TakeSegmentRadius(check_points_.at(pi).pose.position.z);
1027  double nrad=TakeSegmentRadius(check_points_.at(ni).pose.position.z);
1028  //pipe_radius=check_points_.at(ci).pose.position.z;
1029  pipe_radius=crad;
1030  if(openclose_==2&&ci==0){
1031  sradius=pipe_radius;
1032  } else {
1033  //sradius=std::min(pipe_radius,check_points_.at(pi).pose.position.z);
1034  sradius=std::min(pipe_radius,prad);
1035  };
1036  if(openclose_==2&&ci==check_points_.size()-2){
1037  eradius=pipe_radius;
1038  } else {
1039  //eradius=std::min(pipe_radius,check_points_.at(ni).pose.position.z);
1040  eradius=std::min(pipe_radius,nrad);
1041  };
1042  inasegment=InPipeSegment(start,pipe_radius,sradius,eradius,tolerance_,ci);
1043  //};
1044  if(inasegment){
1045  startids.push_back(ci);
1046  inapipe=true;
1047  };
1048  };
1049  if(!inapipe){
1050  robot_status_.data=4;
1051  ROS_ERROR_STREAM("start point is out of pipeline");
1052  ROS_ERROR_STREAM("start point: " << start.pose.position.x << "," << start.pose.position.y);
1054  return false;
1055  };
1056  if(startids.size()>=check_points_.size()){
1057  robot_status_.data=5;
1058  ROS_ERROR_STREAM("All pipe segments include start point. It is strange.");
1060  return false;
1061  };
1062  inapipe=false;
1063  std::vector<int> goalids;
1064  goalids.clear();
1065  for(int i=0;i<lastpoint;i++){
1066  int ci,ni,pi;
1067  bool inasegment;
1068  ci=i; ni=(i==check_points_.size()-1)?0:ci+1;
1069  double pipe_radius,sradius,eradius;
1070  //if(fix_pipe_radius_){
1071  // pipe_radius=pipe_radius_;
1072  // inasegment=InPipeSegment(goal,pipe_radius,pipe_radius,pipe_radius,tolerance_,ci);
1073  //} else {
1074  pi=(ci==0)?check_points_.size()-1:ci-1;
1075  double crad=TakeSegmentRadius(check_points_.at(ci).pose.position.z);
1076  double prad=TakeSegmentRadius(check_points_.at(pi).pose.position.z);
1077  double nrad=TakeSegmentRadius(check_points_.at(ni).pose.position.z);
1078  //pipe_radius=check_points_.at(ci).pose.position.z;
1079  pipe_radius=crad;
1080  if(openclose_==2&&ci==0){
1081  sradius=pipe_radius;
1082  } else {
1083  //sradius=std::min(pipe_radius,check_points_.at(pi).pose.position.z);
1084  sradius=std::min(pipe_radius,prad);
1085  };
1086  if(openclose_==2&&ci==check_points_.size()-2){
1087  eradius=pipe_radius;
1088  } else {
1089  //eradius=std::min(pipe_radius,check_points_.at(ni).pose.position.z);
1090  eradius=std::min(pipe_radius,nrad);
1091  };
1092  inasegment=InPipeSegment(goal,pipe_radius,sradius,eradius,tolerance_,ci);
1093  //};
1094  if(inasegment){
1095  goalids.push_back(ci);
1096  inapipe=true;
1097  };
1098  };
1099  if(!inapipe){
1100  robot_status_.data=6;
1101  ROS_ERROR_STREAM("goal point is out of pipeline");
1102  ROS_ERROR_STREAM("goal point: " << goal.pose.position.x << "," << goal.pose.position.y);
1104  return false;
1105  };
1106  if(goalids.size()>=check_points_.size()){
1107  robot_status_.data=7;
1108  ROS_ERROR_STREAM("All pipe segments include goal point. It is strange.");
1110  return false;
1111  };
1112 
1113 if(debug){
1114 ROS_INFO_STREAM("indices which include start position");
1115 for(int i=0;i<startids.size();i++){
1116 int idx=startids.at(i);
1117 double x=check_points_.at(idx).pose.position.x;
1118 double y=check_points_.at(idx).pose.position.y;
1119 ROS_INFO_STREAM(idx << ": " << x << "," << y);
1120 };
1121 
1122 ROS_INFO_STREAM("indices which include goal position");
1123 for(int i=0;i<goalids.size();i++){
1124 int idx=goalids.at(i);
1125 double x=check_points_.at(idx).pose.position.x;
1126 double y=check_points_.at(idx).pose.position.y;
1127 ROS_INFO_STREAM(idx << ": " << x << "," << y);
1128 };
1129 };
1130 
1131  //start position and goal position
1132  int startindex;
1133  int nextindex,loopsize;
1134  startindex=startids.at(0);
1135  loopsize=startids.size();
1136  for(int i=0;i<loopsize;i++){
1137  bool next=false;
1138  if(!use_straight_){
1139  nextindex=(startindex==0)?check_points_.size()-1:startindex-1;
1140  } else {
1141  nextindex=(startindex==check_points_.size()-1)?0:startindex+1;
1142  };
1143  for(int j=0;j<loopsize;j++){
1144  if(startids.at(j)==nextindex){
1145  next=true; break;
1146  };
1147  };
1148  if(next){
1149  startindex=nextindex;
1150  } else {
1151  break;
1152  };
1153  };
1154 if(debug){
1155 ROS_INFO_STREAM("startindex: " << startindex);
1156 }
1157  int goalindex;
1158  goalindex=goalids.at(0);
1159  loopsize=goalids.size();
1160  for(int i=0;i<loopsize;i++){
1161  bool next=false;
1162  nextindex=(goalindex==check_points_.size()-1)?0:goalindex+1;
1163  for(int j=0;j<loopsize;j++){
1164  if(goalids.at(j)==nextindex){
1165  next=true; break;
1166  };
1167  };
1168  if(next){
1169  goalindex=nextindex;
1170  } else {
1171  break;
1172  };
1173  };
1174 if(debug){
1175 ROS_INFO_STREAM("goalindex: " << goalindex);
1176 };
1177  if((openclose_==2)&&(goalindex<startindex)){
1178  robot_status_.data=8;
1179  ROS_ERROR_STREAM("The goal point is behind a back position of the start point in the open route.");
1181  return false;
1182  };
1183  //avoidance to go backwards in one pipe segment
1184  if(startindex==goalindex){
1185  if(isBehindInaSegment(startindex,start,goal)){
1186  robot_status_.data=11;
1187  ROS_ERROR_STREAM("The goal point is behind a back position of the start point in a pipe segment.");
1189  return false;
1190  };
1191  };
1192 
1193  //selection of pipeline segments to use
1194  std::vector<int> segids;
1195  segids.clear();
1196  if(goalindex>=startindex){
1197  for(int i=startindex;i<=goalindex;i++){
1198  segids.push_back(i);
1199  };
1200  } else {
1201  for(int i=startindex;i<check_points_.size();i++){
1202  segids.push_back(i);
1203  };
1204  for(int i=0;i<=goalindex;i++){
1205  segids.push_back(i);
1206  };
1207  };
1208 if(debug){
1209 ROS_INFO_STREAM("segments to use");
1210 for(int i=0;i<segids.size();i++){
1211  int tmp01=segids.at(i);
1212  double d01x=check_points_.at(tmp01).pose.position.x;
1213  double d01y=check_points_.at(tmp01).pose.position.y;
1214  ROS_INFO_STREAM(tmp01 << ":" << d01x << "," << d01y);
1215 };
1216 };
1217 
1218  if(use_straight_){
1219  if(!(ConnectPoints(start,goal,segids,plan))){
1220  robot_status_.data=10;
1221  plan.clear();
1223  //double duration=ros::Time::now().toSec() - begin.toSec();
1224  //ROS_INFO_STREAM("Pipeline planner: makePlan duration time: " << duration);
1225  return false;
1226  } else {
1227  robot_status_.data=3;
1229  publishPlan(plan);
1230  double duration=ros::Time::now().toSec() - begin.toSec();
1231  if(willDisplay_){
1232  TimeDisplay(time_display_,duration);
1233  willDisplay_=false;
1234  };
1235  return true;
1236  };
1237  };
1238 
1239  //veiling of the space other than the pipeline segments
1240 #if MODE==MODE_GPU
1241  VeilCostmap_cuda(segids,startindex,goalindex,start);
1242 #else
1243  VeilCostmap(segids,startindex,goalindex,start);
1244 #endif
1245 
1246  geometry_msgs::PoseStamped local_global_goal;
1247  int err;
1248  if(use_torch_){
1249  if(!TakeLocalGoal(start,goal,local_global_goal,err)){
1250  robot_status_.data=13;
1252  return false;
1253  };
1254  };
1255 
1256  //calculation of the plan using global_planner
1257  //bool resultGlobalPlanner=global_planner_->makePlan(start,goal,plan);
1258  bool resultGlobalPlanner;
1259  if(use_torch_){
1260  resultGlobalPlanner=navfn_planner_->makePlan(start,local_global_goal,plan);
1261  } else {
1262  resultGlobalPlanner=navfn_planner_->makePlan(start,goal,plan);
1263  };
1264  if(resultGlobalPlanner==true){
1265  robot_status_.data=3;
1266  publishPlan(plan);
1267  } else if(resultGlobalPlanner==false){
1268  robot_status_.data=10;
1269  };
1270 
1272  //for debug
1273  double duration=ros::Time::now().toSec() - begin.toSec();
1274  if(willDisplay_){
1275  TimeDisplay(time_display_,duration);
1276  willDisplay_=false;
1277  };
1278  return resultGlobalPlanner;
1279 
1280 }
1281 
1282 bool PipelinePlanner::InPipeSegment(const geometry_msgs::PoseStamped& pose,
1283  double radius,double sradius,double eradius,double tolerance,int index){
1284  bool result; result=false;
1285  int ci,ni;
1286  ci=index; ni=(index==check_points_.size()-1)?0:ci+1;
1287  double cx=check_points_.at(ci).pose.position.x;
1288  double cy=check_points_.at(ci).pose.position.y;
1289  double nx=check_points_.at(ni).pose.position.x;
1290  double ny=check_points_.at(ni).pose.position.y;
1291  double px=pose.pose.position.x;
1292  double py=pose.pose.position.y;
1293  double normv=sqrt((nx-cx)*(nx-cx)+(ny-cy)*(ny-cy));
1294  if(normv<tolerance){
1295  ROS_ERROR_STREAM("The length of pipeline segment is too small."
1296  " length: " << normv);
1297  return false;
1298  };
1299  double invnormv=1.0/normv;
1300 
1301  double refper=cx*(ny-cy)-cy*(nx-cx);//reference value for perpendicular component
1302  double difper=radius*invnormv*((ny-cy)*(ny-cy)-(-(nx-cx))*(nx-cx));
1303  double sttpll=cx*(nx-cx)+cy*(ny-cy);//parallel component value for segment start
1304  double endpll=nx*(nx-cx)+ny*(ny-cy);//parallel component value for segment end
1305 
1306  double pper=px*(ny-cy)-py*(nx-cx);
1307  double ppll=px*(nx-cx)+py*(ny-cy);
1308  if((std::abs(pper-refper)<difper)&&((sttpll-ppll)*(endpll-ppll)<=0)){
1309  result=true;
1310  } else {
1311  result=false;
1312  };
1313  //start circle
1314  //TODO We need modification about condition.
1315  //We should assert if p < c < n.
1316  if(result==false){
1317  double dist_from_start=sqrt((px-cx)*(px-cx)+(py-cy)*(py-cy));
1318  if(dist_from_start<sradius)result=true;
1319  };
1320  //end circle
1321  if(result==false){
1322  double dist_from_end=sqrt((px-nx)*(px-nx)+(py-ny)*(py-ny));
1323  if(dist_from_end<eradius)result=true;
1324  };
1325  return result;
1326 }
1327 
1328 bool PipelinePlanner::knowRobotPosition(const geometry_msgs::Pose pose,
1329 int& ID,double& distance){
1330  ID=-1; distance=0.0;
1331  int npoints=check_points_.size();
1332  int lastpoint=(openclose_==1)?npoints:npoints-1;
1333  std::vector<double> radius,sradius,eradius;
1334  if(openclose_==1){
1335  radius.resize(npoints);
1336  sradius.resize(npoints);
1337  eradius.resize(npoints);
1338  } else {
1339  radius.resize(npoints-1);
1340  sradius.resize(npoints-1);
1341  eradius.resize(npoints-1);
1342  };
1343  //if(fix_pipe_radius_){
1344  // for(int i=0;i<sradius.size();i++){
1345  // radius.at(i)=pipe_radius_;
1346  // sradius.at(i)=pipe_radius_;
1347  // eradius.at(i)=pipe_radius_;
1348  // };
1349  //} else {
1350  for(int i=0;i<sradius.size();i++){
1351  int ci=i;
1352  int pi=(ci==0)?((openclose_==2)?0:npoints-1):ci-1;
1353  int ni=(ci==npoints-1)?((openclose_==2)?ci:0):ci+1;
1354  //double cr=check_points_.at(ci).pose.position.z;
1355  //double pr=check_points_.at(pi).pose.position.z;
1356  //double nr=check_points_.at(ni).pose.position.z;
1357  double cr=TakeSegmentRadius(check_points_.at(ci).pose.position.z);
1358  double pr=TakeSegmentRadius(check_points_.at(pi).pose.position.z);
1359  double nr=TakeSegmentRadius(check_points_.at(ni).pose.position.z);
1360  radius.at(i)=cr;
1361  sradius.at(i)=std::min(cr,pr);
1362  eradius.at(i)=std::min(cr,nr);
1363  };
1364  //};
1365  std::vector<int> insegments,nearsegments;
1366  std::vector<asegment> segments;
1367  insegments.clear(); nearsegments.clear(); segments.clear();
1368  for(int i=0;i<lastpoint;i++){
1369  int part;double dist;
1370  bool inasegment=whereInaPipeSegment(pose,i,radius.at(i),sradius.at(i),eradius.at(i),part,dist,tolerance_);
1371  asegment thesegment;
1372  thesegment.id=i; thesegment.part=part; thesegment.dist=dist;
1373  thesegment.in=inasegment;
1374  segments.push_back(thesegment);
1375  if(inasegment){
1376  nearsegments.push_back(i);
1377  if(part==1)insegments.push_back(i);
1378  };
1379  };
1380  //to know real id to take
1381  int nnseg=nearsegments.size();
1382  int mostfrontindex;
1383  if(nearsegments.empty()){
1384  //error task
1385  return false;
1386  } else if(nnseg==check_points_.size()) {
1387  ROS_ERROR("All pipe segments include the robot position. Its strange.");
1388  return false;
1389  } else {
1390  //recognition of the queue
1391  int currentindex=nearsegments.at(0);
1392  int nextindex;
1393  for(int i=0;i<nnseg;i++){
1394  bool isNext=false;
1395  nextindex=(currentindex==0)?check_points_.size()-1:currentindex-1;
1396  for(int j=0;j<nnseg;j++){
1397  if(nextindex==nearsegments.at(j)){
1398  isNext=true; break;
1399  };
1400  };
1401  if(isNext){
1402  currentindex=nextindex;
1403  } else {
1404  break;
1405  };
1406  };
1407  mostfrontindex=currentindex;
1408  if(!insegments.empty()){
1409  int niseg=insegments.size();
1410  currentindex=mostfrontindex;
1411  for(int i=0;i<check_points_.size();i++){
1412  if(segments.at(currentindex).part==1){
1413  break;
1414  } else {
1415  currentindex=(currentindex+1)%(check_points_.size());
1416  };
1417  };
1418  mostfrontindex=currentindex;
1419  };
1420  };
1421  ID=mostfrontindex;
1422  if(segments.at(ID).part==1){
1423  distance=segments.at(mostfrontindex).dist;
1424  } else if(segments.at(ID).part==2){
1425  distance=-segments.at(mostfrontindex).dist;
1426  } else if(segments.at(ID).part==3){
1427  //distance=segments.at(mostfrontindex).dist;
1428  int ci=ID;
1429  int ni=(ci==check_points_.size()-1)?0:ci+1;
1430  double cx=check_points_.at(ci).pose.position.x;
1431  double cy=check_points_.at(ci).pose.position.y;
1432  double nx=check_points_.at(ni).pose.position.x;
1433  double ny=check_points_.at(ni).pose.position.y;
1434  distance=sqrt(pow(nx-cx,2.0)+pow(ny-cy,2.0))+segments.at(mostfrontindex).dist;
1435  };
1436 
1437  return true;
1438 }
1439 
1440 bool PipelinePlanner::whereInaPipeSegment(const geometry_msgs::Pose pose,
1441 const int id,const double radius,const double sradius,const double eradius,
1442 int& part,double &dist,double tolerance){
1443  bool result=false;
1444  part=0;
1445  int ci=id;
1446  int ni=(id==check_points_.size()-1)?0:ci+1;
1447  double cx=check_points_.at(ci).pose.position.x;
1448  double cy=check_points_.at(ci).pose.position.y;
1449  double nx=check_points_.at(ni).pose.position.x;
1450  double ny=check_points_.at(ni).pose.position.y;
1451  double px=pose.position.x;
1452  double py=pose.position.y;
1453  double normv=sqrt((nx-cx)*(nx-cx)+(ny-cy)*(ny-cy));
1454  if(normv<tolerance){
1455  ROS_ERROR_STREAM("The length of pipeline segment is too small."
1456  " length: " << normv);
1457  return false;
1458  };
1459  double invnormv=1.0/normv;
1460 
1461  double refper=cx*(ny-cy)-cy*(nx-cx);//reference value for perpendicular component
1462  double difper=radius*invnormv*((ny-cy)*(ny-cy)-(-(nx-cx))*(nx-cx));
1463  double sttpll=cx*(nx-cx)+cy*(ny-cy);//parallel component value for segment start
1464  double endpll=nx*(nx-cx)+ny*(ny-cy);//parallel component value for segment end
1465 
1466  double pper=px*(ny-cy)-py*(nx-cx);
1467  double ppll=px*(nx-cx)+py*(ny-cy);
1468  if((std::abs(pper-refper)<difper)&&((sttpll-ppll)*(endpll-ppll)<=0)){
1469  result=true;
1470  part=1;
1471  dist=(ppll-sttpll)*invnormv;
1472  return result;
1473  } else {
1474  result=false;
1475  };
1476  //start circle
1477  if((sttpll-ppll)*(endpll-sttpll)>=0){
1478  double dist_from_start=sqrt((px-cx)*(px-cx)+(py-cy)*(py-cy));
1479  if(dist_from_start<sradius){
1480  result=true;
1481  part=2;
1482  dist=dist_from_start;
1483  return result;
1484  };
1485  };
1486  //end circle
1487  if((endpll-sttpll)*(ppll-endpll)>=0){
1488  double dist_from_end=sqrt((px-nx)*(px-nx)+(py-ny)*(py-ny));
1489  if(dist_from_end<eradius){
1490  result=true;
1491  part=3;
1492  dist=dist_from_end;
1493  return result;
1494  };
1495  };
1496  return false;
1497 
1498 }
1499 
1501  const geometry_msgs::PoseStamped& start,
1502  const geometry_msgs::PoseStamped& goal){
1503  int ci,ni;
1504  double cx,cy,nx,ny; double sx,sy,gx,gy;
1505  double poss,posg;
1506  bool result;
1507 
1508  ci=idx; ni=(ci==check_points_.size()-1)?0:ci+1;
1509  cx=check_points_.at(ci).pose.position.x;
1510  cy=check_points_.at(ci).pose.position.y;
1511  nx=check_points_.at(ni).pose.position.x;
1512  ny=check_points_.at(ni).pose.position.y;
1513  sx=start.pose.position.x;
1514  sy=start.pose.position.y;
1515  gx= goal.pose.position.x;
1516  gy= goal.pose.position.y;
1517 
1518  poss=(nx-cx)*sx+(ny-cy)*sy;
1519  posg=(nx-cx)*gx+(ny-cy)*gy;
1520  if(poss>posg){
1521  result=true;
1522  } else {
1523  result=false;
1524  };
1525  return result;
1526 };
1527 
1528 bool PipelinePlanner::VeilCostmap(const std::vector<int> segids,
1529  const int startindex,const int goalindex,const geometry_msgs::PoseStamped& start){
1530  unsigned int costsizex=costmap_->getSizeInCellsX();
1531  unsigned int costsizey=costmap_->getSizeInCellsY();
1532  int numsegids=segids.size();
1533  std::vector<int> daub;//bool
1534  daub.clear();
1535  daub.insert(daub.begin(),costsizex*costsizey,1);
1536  double map_resolution=costmap_->getResolution();
1537  //torch model
1538  double origin_x=costmap_->getOriginX();
1539  double origin_y=costmap_->getOriginY();
1540  const double robot_x=start.pose.position.x;
1541  const double robot_y=start.pose.position.y;
1542  int min_visible_x,min_visible_y,max_visible_x,max_visible_y;
1543  int min_index_x,max_index_x,min_index_y,max_index_y;
1544  if(use_torch_){
1545  min_visible_x=(int)((robot_x-torch_area_x_-origin_x)/map_resolution);
1546  max_visible_x=(int)((robot_x+torch_area_x_-origin_x)/map_resolution);
1547  min_visible_x=std::max(min_visible_x,0);
1548  max_visible_x=std::min(max_visible_x,(int)costsizex);
1549  min_visible_y=(int)((robot_y-torch_area_y_-origin_y)/map_resolution);
1550  max_visible_y=(int)((robot_y+torch_area_y_-origin_y)/map_resolution);
1551  min_visible_y=std::max(min_visible_y,0);
1552  max_visible_y=std::min(max_visible_y,(int)costsizey);
1553  min_index_x=min_visible_x; max_index_x=max_visible_x;
1554  min_index_y=min_visible_y; max_index_y=max_visible_y;
1555  } else {
1556  min_index_x=0; max_index_x=costsizex;
1557  min_index_y=0; max_index_y=costsizey;
1558  };
1559  //veil loop
1560  for(int i=0;i<numsegids;i++){
1561  double radius,sradius,eradius;
1562  int ci=segids.at(i);
1563  int ni=(ci==check_points_.size()-1)?0:ci+1;
1564  int pi;
1565  //if(fix_pipe_radius_){
1566  // radius=pipe_radius_;
1567  // sradius=pipe_radius_;
1568  // eradius=pipe_radius_;
1569  //} else {
1570  pi=(ci==0)?check_points_.size()-1:ci-1;
1571  double cr=TakeSegmentRadius(check_points_.at(ci).pose.position.z);
1572  double pr=TakeSegmentRadius(check_points_.at(pi).pose.position.z);
1573  double nr=TakeSegmentRadius(check_points_.at(ni).pose.position.z);
1574  //radius=check_points_.at(ci).pose.position.z;
1575  radius=cr;
1576  if(openclose_==2&&ci==0){
1577  sradius=radius;
1578  } else {
1579  //sradius=std::min(radius,check_points_.at(pi).pose.position.z);
1580  sradius=std::min(radius,pr);
1581  };
1582  if(openclose_==2&&ci==check_points_.size()-2){
1583  eradius=radius;
1584  } else {
1585  //eradius=std::min(radius,check_points_.at(ni).pose.position.z);
1586  eradius=std::min(radius,nr);
1587  };
1588  //};
1589  double cx=check_points_.at(ci).pose.position.x;
1590  double cy=check_points_.at(ci).pose.position.y;
1591  double nx=check_points_.at(ni).pose.position.x;
1592  double ny=check_points_.at(ni).pose.position.y;
1593 
1594  double normv=std::sqrt((nx-cx)*(nx-cx)+(ny-cy)*(ny-cy));
1595  double invnormv=1.0/normv;
1596  double refper=cx*(ny-cy)-cy*(nx-cx); //reference value for perpendicular component
1597  double difper=radius*invnormv*((ny-cy)*(ny-cy)-(-(nx-cx))*(nx-cx))
1598  +map_resolution*(0.5* std::abs(ny-cy)+0.5* std::abs(nx-cx));
1599  double refpll=(0.5*(nx+cx))*(nx-cx)+(0.5*(ny+cy))*(ny-cy);//reference value for parallel component
1600  //reference value for parallel component
1601  double difpll=(0.5*(nx-cx))*(nx-cx)+(0.5*(ny-cy))*(ny-cy)
1602  +map_resolution*(0.5*std::abs(nx-cx)+0.5*std::abs(ny-cy));
1603  double sedgepll,eedgepll,startpll,respll;
1604  int start_area=0;
1605  if(ci==startindex){
1606  sedgepll=(cx)*(nx-cx)+(cy)*(ny-cy);//parallel component for the start edge
1607  eedgepll=(nx)*(nx-cx)+(ny)*(ny-cy);//parallel component for the end edge
1608  startpll=(start.pose.position.x)*(nx-cx)+(start.pose.position.y)*(ny-cy);//parallel component for the start point
1609  //respll=map_resolution*(0.5*std::abs(nx-cx)+0.5*std::abs(ny-cy));
1610  if((sedgepll-startpll)*(eedgepll-sedgepll)>0){
1611  start_area=1;//start point is out from start edge
1612  } else if((startpll-sedgepll)*(eedgepll-startpll)>0){
1613  start_area=2;//start point is in the first pipe segment
1614  } else {
1615  start_area=3;//start point is out from end edge
1616  };
1617  };
1618  //for(unsigned int xi=0;xi<costsizex;xi++)
1619  //for(unsigned int yi=0;yi<costsizey;yi++)
1620  for(unsigned int xi=min_index_x;xi<max_index_x;xi++){
1621  for(unsigned int yi=min_index_y;yi<max_index_y;yi++){
1622  int index=yi*costsizex+xi;
1623  if(daub.at(index)==2)continue;
1624  if(pipeline_.data[index]==100){
1625  daub.at(index)=2;continue;
1626  };
1627  double wx,wy;
1628  costmap_->mapToWorld(xi,yi,wx,wy);
1629  //pipeline rectangular
1630  double curper=wx*(ny-cy)-wy*(nx-cx);
1631  double curpll=wx*(nx-cx)+wy*(ny-cy);
1632  if((std::abs(curper-refper) < difper)&&(std::abs(curpll-refpll) < difpll)){
1633  if((ci==startindex)&&((start_area==2
1634  &&((curpll-sedgepll)*(startpll-curpll)>0)
1635  &&(std::abs(curpll-startpll)>0.1))
1636  ||(start_area==3))){
1637  //plug of start pipesegment
1638  //daub.at(costmap_->getIndex(xi,yi))=1;
1639  daub.at(index)=2;
1640  continue;
1641  } else {
1642  //daub.at(costmap_->getIndex(xi,yi))=0;
1643  daub.at(index)=0;
1644  };
1645  };
1646  //pipelince connection circle
1647  double distancefromconnection; double startfromconnection;
1648  //start edge circle
1649  distancefromconnection=sqrt((wx-cx)*(wx-cx)+(wy-cy)*(wy-cy));
1650  if(distancefromconnection<sradius+map_resolution*(0.5*sqrt(2.0))){
1651  //we should set condition to plug start circle
1652  startfromconnection=sqrt((start.pose.position.x-cx)*(start.pose.position.x-cx)+
1653  (start.pose.position.y-cy)*(start.pose.position.y-cy));
1654  if((ci==startindex)&&start_area==1
1655  &&((sedgepll-curpll)*(eedgepll-sedgepll)>0)
1656  &&(distancefromconnection>(startfromconnection+sradius)*0.5)){
1657  //daub.at(costmap_->getIndex(xi,yi))=2;
1658  daub.at(index)=2;
1659  continue;
1660  } else {
1661  daub.at(index)=0;
1662  };
1663  };
1664  //end edge circle
1665  distancefromconnection=sqrt((wx-nx)*(wx-nx)+(wy-ny)*(wy-ny));
1666  if(distancefromconnection<eradius+map_resolution*(0.5*sqrt(2.0))){
1667  daub.at(index)=0;
1668  };
1669  };
1670  };
1671  };
1672 
1673  //preservation of old costmap and replacement of costmap
1674  for(unsigned int xi=0;xi<costsizex;xi++){
1675  for(unsigned int yi=0;yi<costsizey;yi++){
1676  unsigned int idx=costmap_->getIndex(xi,yi);
1677  unsigned char curr_cost=costmap_->getCost(xi,yi);
1678  bool notVisible=(xi<min_index_x)||(max_index_x<=xi)||(yi<min_index_y)||(max_index_y<=yi);
1679  if(notVisible){
1680  navfn_costmap_->setCost(xi,yi,curr_cost);
1681  } else if((daub.at(idx)==1)||(daub.at(idx)==2)){
1683  } else {
1684  unsigned char new_cost;
1685  if((curr_cost!=253)&&(curr_cost!=254)&&(curr_cost!=255)){
1686  //new_cost=(unsigned char)(curr_cost
1687  // +centre_weight_*dist_from_pipe_centre_.at(idx));
1688  new_cost=std::min(lethal_cost_,(unsigned char)(curr_cost
1690  } else {
1691  new_cost=curr_cost;
1692  };
1693  navfn_costmap_->setCost(xi,yi,new_cost);
1694  };
1695  };};
1696 
1697  return true;
1698 }
1699 
1700 #if MODE==MODE_GPU
1701 bool PipelinePlanner::VeilCostmap_cuda(const std::vector<int> segids,
1702  const int startindex,const int goalindex,const geometry_msgs::PoseStamped& start){
1703  ThreadNumberAdjusment(false);
1704 
1705  //preparations
1706  cudaError_t error_allocation;
1707  //stones
1708  int numstones=segids.size();
1709  double *stonex,*stoney;
1710  //stonex=new double[numstones+1];
1711  //stoney=new double[numstones+1];
1712  if(debug){
1713  error_allocation=cudaMallocManaged(&stonex,(numstones+1)*sizeof(double));
1714  ROS_INFO_STREAM("error stonex: " << error_allocation);//for debug
1715  error_allocation=cudaMallocManaged(&stoney,(numstones+1)*sizeof(double));
1716  ROS_INFO_STREAM("error stoney: " << error_allocation);//for debug
1717  } else {
1718  cudaMallocManaged(&stonex,(numstones+1)*sizeof(double));
1719  cudaMallocManaged(&stoney,(numstones+1)*sizeof(double));
1720  };
1721  for(int i=0;i<numstones;i++){
1722  int index=segids.at(i);
1723  stonex[i]=check_points_.at(index).pose.position.x;
1724  stoney[i]=check_points_.at(index).pose.position.y;
1725  if(i==numstones-1){
1726  int lastindex=(index==check_points_.size()-1)?0:index+1;
1727  stonex[i+1]=check_points_.at(lastindex).pose.position.x;
1728  stoney[i+1]=check_points_.at(lastindex).pose.position.y;
1729  };
1730  };
1731  double *radius, *sradius, *eradius;
1732  if(debug){
1733  error_allocation=cudaMallocManaged(&radius,(numstones)*sizeof(double));
1734  ROS_INFO_STREAM("error radius: " << error_allocation);//for debug
1735  error_allocation=cudaMallocManaged(&sradius,(numstones)*sizeof(double));
1736  ROS_INFO_STREAM("error sradius: " << error_allocation);//for debug
1737  error_allocation=cudaMallocManaged(&eradius,(numstones)*sizeof(double));
1738  ROS_INFO_STREAM("error eradius: " << error_allocation);//for debug
1739  } else {
1740  cudaMallocManaged(&radius,(numstones)*sizeof(double));
1741  cudaMallocManaged(&sradius,(numstones)*sizeof(double));
1742  cudaMallocManaged(&eradius,(numstones)*sizeof(double));
1743  };
1744  //if(fix_pipe_radius_){
1745  // for(int i=0;i<numstones;i++){
1746  // radius[i]=pipe_radius_;
1747  // sradius[i]=pipe_radius_;
1748  // eradius[i]=pipe_radius_;
1749  // };
1750  //} else {
1751  for(int i=0;i<numstones;i++){
1752  int ci=segids.at(i);
1753  int ni=(ci==check_points_.size()-1)?0:ci+1;
1754  int pi=(ci==0)?check_points_.size()-1:ci-1;
1755  double cr=TakeSegmentRadius(check_points_.at(ci).pose.position.z);
1756  double pr=TakeSegmentRadius(check_points_.at(pi).pose.position.z);
1757  double nr=TakeSegmentRadius(check_points_.at(ni).pose.position.z);
1758  //radius[i]=check_points_.at(ci).pose.position.z;
1759  //sradius[i]=(openclose_==2&&ci==0)?
1760  // radius[i]:std::min(radius[i],check_points_.at(pi).pose.position.z);
1761  //eradius[i]=(openclose_==2&&ci==check_points_.size()-2)?
1762  // radius[i]:std::min(radius[i],check_points_.at(ni).pose.position.z);
1763  radius[i]=cr;
1764  sradius[i]=(openclose_==2&&ci==0)?
1765  radius[i]:std::min(radius[i],pr);
1766  eradius[i]=(openclose_==2&&ci==check_points_.size()-2)?
1767  radius[i]:std::min(radius[i],nr);
1768  };
1769  //};
1770  //start position
1771  double startx=start.pose.position.x;
1772  double starty=start.pose.position.y;
1773  //radius
1774  //double radius=pipe_radius_;
1775  //size and resolution of costmap
1776  unsigned int costsizex=costmap_->getSizeInCellsX();
1777  unsigned int costsizey=costmap_->getSizeInCellsY();
1778  double map_resolution=costmap_->getResolution();
1779  //origin
1780  double origin_x=costmap_->getOriginX();
1781  double origin_y=costmap_->getOriginY();
1782 
1783  //torch model
1784  int min_visible_x,min_visible_y,max_visible_x,max_visible_y;
1785  int min_index_x,max_index_x,min_index_y,max_index_y;
1786  if(use_torch_){
1787  min_visible_x=(int)((startx-torch_area_x_-origin_x)/map_resolution);
1788  max_visible_x=(int)((startx+torch_area_x_-origin_x)/map_resolution);
1789  min_visible_x=std::max(min_visible_x,0);
1790  max_visible_x=std::min(max_visible_x,(int)costsizex);
1791  min_visible_y=(int)((starty-torch_area_y_-origin_y)/map_resolution);
1792  max_visible_y=(int)((starty+torch_area_y_-origin_y)/map_resolution);
1793  min_visible_y=std::max(min_visible_y,0);
1794  max_visible_y=std::min(max_visible_y,(int)costsizey);
1795  min_index_x=min_visible_x; max_index_x=max_visible_x;
1796  min_index_y=min_visible_y; max_index_y=max_visible_y;
1797  } else {
1798  min_index_x=0; max_index_x=costsizex;
1799  min_index_y=0; max_index_y=costsizey;
1800  };
1801 
1802  //new cost array
1803  unsigned char *newCost;
1804  if(debug){
1805  error_allocation=cudaMallocManaged(&newCost,(costsizex*costsizey)*sizeof(unsigned char));
1806  ROS_INFO_STREAM("error newCost: " << error_allocation);//for debug
1807  ROS_INFO_STREAM("07 costsizex*costsizey: " << costsizex*costsizey);//for debug
1808  } else {
1809  cudaMallocManaged(&newCost,(costsizex*costsizey)*sizeof(unsigned char));
1810  };
1811  for(int xi=0;xi<costsizex;xi++){
1812  for(int yi=0;yi<costsizey;yi++){
1813  int index=yi*costsizex+xi;
1814  //newCost[index]=costmap_->getCost(xi,yi);
1815  unsigned char c=costmap_->getCost(xi,yi);
1816  newCost[index]=c;
1817  };};
1818  //dist_from_pipe_centre
1819  double *dist_from_centre;
1820  if(debug){
1821  error_allocation=cudaMallocManaged(&dist_from_centre,(costsizex*costsizey)*sizeof(double));
1822  ROS_INFO_STREAM("error dist from centre: " << error_allocation);//for debug
1823  } else {
1824  cudaMallocManaged(&dist_from_centre,(costsizex*costsizey)*sizeof(double));
1825  };
1826  //for(int xi=0;xi<costsizex;xi++)
1827  //for(int yi=0;yi<costsizey;yi++)
1828  for(int xi=min_index_x;xi<max_index_x;xi++){
1829  for(int yi=min_index_y;yi<max_index_y;yi++){
1830  int index=yi*costsizex+xi;
1831  dist_from_centre[index]=dist_from_pipe_centre_.at(index);
1832  };};
1833 
1834  //call of cuda function
1835  //using num_threads_
1836  calling_device(numstones,stonex,stoney,startx,starty,radius,sradius,eradius,
1837  costsizex,costsizey,map_resolution,origin_x,origin_y,dist_from_centre,
1838  centre_weight_,lethal_cost_,min_index_x,max_index_x,min_index_y,max_index_y,
1839  newCost,num_threads_,debug);
1840 
1841  //replacement of costmap
1842  for(int xi=0;xi<costsizex;xi++){
1843  for(int yi=0;yi<costsizey;yi++){
1844  //int idx=costmap_->getIndex(xi,yi);
1845  int idx=yi*costsizex+xi;
1846  //costmap_->setCost(xi,yi,newCost[idx]);
1847  navfn_costmap_->setCost(xi,yi,newCost[idx]);
1848  };};
1849 
1850  //free allocated variables
1851  cudaError_t error_free;
1852  if(debug){
1853  error_free=cudaFree(stonex);
1854  ROS_INFO_STREAM("free stonex: " << error_free);
1855  error_free=cudaFree(stoney);
1856  ROS_INFO_STREAM("free stoney: " << error_free);
1857  error_free=cudaFree(newCost);
1858  ROS_INFO_STREAM("free newCost: " << error_free);
1859  error_free=cudaFree(dist_from_centre);
1860  ROS_INFO_STREAM("free dist_from_centre: " << error_free);
1861  } else {
1862  cudaFree(stonex);
1863  cudaFree(stoney);
1864  cudaFree(newCost);
1865  cudaFree(dist_from_centre);
1866  };
1867 
1868 cudaError_t last_error;
1869 last_error=cudaGetLastError();
1870 if(last_error!=cudaSuccess){
1871  ROS_ERROR_STREAM("cudaGetLastError : " << last_error);
1872 } else if(debug){
1873  ROS_INFO_STREAM("cudaGetLastError : " << last_error);
1874 };
1875 
1876  return true;
1877 }
1878 #endif
1879 
1880 bool PipelinePlanner::ConnectPoints(const geometry_msgs::PoseStamped& start,
1881  const geometry_msgs::PoseStamped& goal, const std::vector<int> segids,
1882  std::vector<geometry_msgs::PoseStamped>& plan){
1883  geometry_msgs::PoseStamped astone;
1884  ros::Time plan_time;
1885  //if(!fix_pipe_radius_){
1886  plan_time = ros::Time::now();
1887  astone.header.stamp = plan_time;
1888  astone.header.frame_id = gained_frame_id_;
1889  astone.pose.position.x=0.0;//x
1890  astone.pose.position.y=0.0;//y
1891  astone.pose.position.z=0.0;
1892  astone.pose.orientation.x=0.0;
1893  astone.pose.orientation.y=0.0;
1894  astone.pose.orientation.z=0.0;
1895  astone.pose.orientation.w=1.0;
1896  //};
1897  plan.clear();
1898  if(segids.size()==1){
1899  plan.push_back(start);
1900  if(!(DrawOpenSegment(start, goal, plan))){return false;};
1901  plan.push_back(goal);
1902  return true;
1903  };
1904  plan.push_back(start);
1905  if(!(DrawOpenSegment(start, check_points_.at(segids.at(1)), plan))){return false;};
1906  for(int i=1;i<segids.size()-1;i++){
1907  //if(fix_pipe_radius_){
1908  // astone=check_points_.at(segids.at(i));
1909  //} else {
1910  astone.pose.position.x=check_points_.at(segids.at(i)).pose.position.x;
1911  astone.pose.position.y=check_points_.at(segids.at(i)).pose.position.y;
1912  //};
1913  plan.push_back(astone);
1914  if(!(DrawOpenSegment(check_points_.at(segids.at(i)),
1915  check_points_.at(segids.at(i+1)), plan))){return false;};
1916  };
1917  //if(fix_pipe_radius_){
1918  // astone=check_points_.at(segids.at(segids.size()-1));
1919  //} else {
1920  astone.pose.position.x=check_points_.at(segids.at(segids.size()-1)).pose.position.x;
1921  astone.pose.position.y=check_points_.at(segids.at(segids.size()-1)).pose.position.y;
1922  //};
1923  plan.push_back(astone);
1924  if(!(DrawOpenSegment(check_points_.at(segids.at(segids.size()-1)),
1925  goal, plan))){return false;};
1926  plan.push_back(goal);
1927 
1928  return true;
1929 }
1930 
1931 bool PipelinePlanner::DrawOpenSegment(const geometry_msgs::PoseStamped init_point,
1932  const geometry_msgs::PoseStamped end_point,
1933  std::vector<geometry_msgs::PoseStamped>& plan){
1934  double map_resolution=costmap_->getResolution();
1935  double l=map_resolution*2.0;
1936  double ix=init_point.pose.position.x;
1937  double iy=init_point.pose.position.y;
1938  double ex=end_point.pose.position.x;
1939  double ey=end_point.pose.position.y;
1940 
1941  double diff_ie=sqrt((ex-ix)*(ex-ix)+(ey-iy)*(ey-iy));
1942  int num=(int) (diff_ie/l);
1943  if(num==0)return true;
1944  double dx=(ex-ix)/(num+1.0);
1945  double dy=(ey-iy)/(num+1.0);
1946 
1947  ros::Time plan_time = ros::Time::now();
1948 
1949  for(int i=1;i<num+1;i++){
1950  geometry_msgs::PoseStamped astone;
1951  double x=ix+dx*i;
1952  double y=iy+dy*i;
1953  unsigned int px,py;
1954  if(!(costmap_->worldToMap(x,y,px,py))){
1955  ROS_ERROR_STREAM("out of map: (" << x << "," << y << ")");
1956  return false;
1957  };
1958  if(!charge_){
1959  unsigned char curr_cost=costmap_->getCost(px,py);
1960  if(curr_cost >= lethal_cost_){
1961  ROS_ERROR_STREAM("point (" << x << "," << y << ") is lethal");
1962  return false;
1963  };
1964  };
1965 
1966  astone.header.stamp = plan_time;
1967  astone.header.frame_id = gained_frame_id_;
1968  astone.pose.position.x=x;
1969  astone.pose.position.y=y;
1970  astone.pose.position.z=0.0;
1971  astone.pose.orientation.x=0.0;
1972  astone.pose.orientation.y=0.0;
1973  astone.pose.orientation.z=0.0;
1974  astone.pose.orientation.w=1.0;
1975  plan.push_back(astone);
1976  };
1977  return true;
1978 }
1979 
1980 void PipelinePlanner::publishPlan(const std::vector<geometry_msgs::PoseStamped>& path){
1981  nav_msgs::Path path_publish;
1982  path_publish.poses.resize(path.size());
1983 
1984  if(!path.empty()){
1985  path_publish.header.frame_id = path[0].header.frame_id;
1986  path_publish.header.stamp = path[0].header.stamp;
1987  };
1988  for(int i=0;i<path.size();i++){
1989  path_publish.poses[i]=path[i];
1990  };
1991  pub_plan_.publish(path_publish);
1992 
1993 }
1994 
1996  makePipeline(true);
1997 }
1998 
1999 
2001  const int costsizex=costmap_->getSizeInCellsX();
2002  const int costsizey=costmap_->getSizeInCellsY();
2003  const double map_resolution=costmap_->getResolution();
2004  const double origin_x=costmap_->getOriginX();
2005  const double origin_y=costmap_->getOriginY();
2006 
2007  //nav_msgs::OccupancyGrid pipeline_;
2008  pipeline_.header.stamp=ros::Time::now();
2009  pipeline_.header.frame_id=gained_frame_id_;
2010  pipeline_.info.resolution=map_resolution;
2011  pipeline_.info.width=costsizex;
2012  pipeline_.info.height=costsizey;
2013  pipeline_.info.origin.position.x=origin_x;
2014  pipeline_.info.origin.position.y=origin_y;
2015  pipeline_.info.origin.position.z=0.0;
2016  pipeline_.info.origin.orientation.w=1.0;
2017  pipeline_.data.resize(pipeline_.info.width*pipeline_.info.height);
2018 
2019  if(legal==false){
2020  for(int i=0;i<costsizex*costsizey;i++){
2021  pipeline_.data[i]=100;
2022  };
2024  return;
2025  };
2026 
2027  int numchecks=check_points_.size();
2028  int numsegids=(openclose_==1)?numchecks:numchecks-1;
2029 
2030  if(numchecks<2){
2031  for(int i=0;i<costsizex*costsizey;i++){
2032  pipeline_.data[i]=100;
2033  };
2035  return;
2036  };
2037 
2038  double *stonex,*stoney,*radii,*sradii,*eradii;
2039  int *data;
2040  bool isClose;
2041  isClose=(openclose_==1)?true:false;
2042  //GPU mode
2043  //cudaMallocManaged(&stonex,(numchecks)*sizeof(double));
2044  //cudaMallocManaged(&stoney,(numchecks)*sizeof(double));
2045  //cudaMallocManaged(&radii,(numsegids)*sizeof(double));
2046  //cudaMallocManaged(&sradii,(numsegids)*sizeof(double));
2047  //cudaMallocManaged(&eradii,(numsegids)*sizeof(double));
2048  //cudaMallocManaged(&data,(costsizex*costsizey)*sizeof(int));
2049  //CPU mode
2050  stonex=new double[numchecks];
2051  stoney=new double[numchecks];
2052  radii=new double[numsegids];
2053  sradii=new double[numsegids];
2054  eradii=new double[numsegids];
2055  data=new int[costsizex*costsizey];
2056 
2057  for(int i=0;i<numchecks;i++){
2058  stonex[i]=check_points_.at(i).pose.position.x;
2059  stoney[i]=check_points_.at(i).pose.position.y;
2060  };
2061  //if(fix_pipe_radius_){
2062  // for(int i=0;i<numsegids;i++){
2063  // radii[i]=pipe_radius_;sradii[i]=pipe_radius_;eradii[i]=pipe_radius_;
2064  // };
2065  //} else {
2066  for(int i=0;i<numsegids;i++){
2067  int ci=i;
2068  int pi=(ci==0)?numchecks-1:ci-1;
2069  int ni=(ci==numchecks-1)?0:ci+1;
2070  double cr=TakeSegmentRadius(check_points_.at(ci).pose.position.z);
2071  double pr=TakeSegmentRadius(check_points_.at(pi).pose.position.z);
2072  double nr=TakeSegmentRadius(check_points_.at(ni).pose.position.z);
2073  //radii[i]=check_points_.at(i).pose.position.z;
2074  radii[ci]=cr;
2075  if(openclose_==2&&ci==0){
2076  sradii[ci]=radii[ci];
2077  } else {
2078  //sradii[ci]=std::min(radii[ci],check_points_.at(pi).pose.position.z);
2079  sradii[ci]=std::min(radii[ci],pr);
2080  };
2081  if(openclose_==2&&ci==numchecks-2){
2082  eradii[ci]=radii[ci];
2083  } else {
2084  //eradii[ci]=std::min(radii[ci],check_points_.at(ni).pose.position.z);
2085  eradii[ci]=std::min(radii[ci],nr);
2086  };
2087  };
2088  //};
2089  //GPU
2090 // calcPipeline_device(numchecks,stonex,stoney,isClose,radii,sradii,eradii,
2091 // origin_x,origin_y,costsizex,costsizey,map_resolution,data,num_threads_);
2092  //CPU
2093  calcPipeline(numchecks,stonex,stoney,isClose,radii,sradii,eradii,
2094  origin_x,origin_y,costsizex,costsizey,map_resolution,data);
2095  for(int i=0;i<costsizex*costsizey;i++){
2096  pipeline_.data[i]=data[i];
2097  };
2098  //termination
2099  //GPU
2100  //cudaFree(stonex);
2101  //cudaFree(stoney);
2102  //cudaFree(radii);
2103  //cudaFree(sradii);
2104  //cudaFree(eradii);
2105  //cudaFree(data);
2106  //CPU
2107  delete[] stonex;
2108  delete[] stoney;
2109  delete[] radii;
2110  delete[] sradii;
2111  delete[] eradii;
2112  delete[] data;
2113 
2115 }
2116 
2117 void PipelinePlanner::calcPipeline(const int numcheckpoints,
2118 const double *stonex,const double *stoney,const bool isClose,
2119 const double *radii,const double *sradii,const double *eradii,
2120 const double origin_x,const double origin_y,
2121 const unsigned int costsizex,const unsigned int costsizey,
2122 const double resolution,int *data){
2123  //initialisation
2124  for(int i=0;i<costsizex*costsizey;i++){
2125  data[i]=100;
2126  };
2127  int numsegids=(isClose==true)?numcheckpoints:numcheckpoints-1;
2128  //calculation
2129  for(int i=0;i<numsegids;i++){
2130  int ci=i;
2131  int ni=(ci==numcheckpoints-1)?0:ci+1;
2132  const double cx=stonex[ci];
2133  const double cy=stoney[ci];
2134  const double nx=stonex[ni];
2135  const double ny=stoney[ni];
2136  const double normv=std::sqrt((nx-cx)*(nx-cx)+(ny-cy)*(ny-cy));
2137  const double invnormv=1.0/normv;
2138  const double refper=cx*(ny-cy)-cy*(nx-cx); //reference value for perpendicular component
2139  const double difper=radii[i]*invnormv*((ny-cy)*(ny-cy)-(-(nx-cx))*(nx-cx))
2140  +resolution*(0.5* std::abs(ny-cy)+0.5* std::abs(nx-cx));
2141  const double refpll=(0.5*(nx+cx))*(nx-cx)+(0.5*(ny+cy))*(ny-cy);//reference value for parallel component
2142  const double difpll=(0.5*(nx-cx))*(nx-cx)+(0.5*(ny-cy))*(ny-cy)
2143  +resolution*(0.5*std::abs(nx-cx)+0.5*std::abs(ny-cy));
2144 
2145  //restrict region for fast calculation
2146  int min_index_x,min_index_y,max_index_x,max_index_y;
2147  double min_x,min_y,max_x,max_y;
2148 
2149  min_x=std::min(std::min(cx-radii[i],cx-sradii[i]),std::min(nx-radii[i],nx-eradii[i]));
2150  min_index_x=std::max(0,(int)((min_x-origin_x)/resolution));
2151  max_x=std::max(std::max(cx+radii[i],cx+sradii[i]),std::max(nx+radii[i],nx+eradii[i]));
2152  max_index_x=std::min((int)costsizex,(int)((max_x-origin_x)/resolution));
2153 
2154  min_y=std::min(std::min(cy-radii[i],cy-sradii[i]),std::min(ny-radii[i],ny-eradii[i]));
2155  min_index_y=std::max(0,(int)((min_y-origin_y)/resolution));
2156  max_y=std::max(std::max(cy+radii[i],cy+sradii[i]),std::max(ny+radii[i],ny+eradii[i]));
2157  max_index_y=std::min((int)costsizey,(int)((max_y-origin_y)/resolution));
2158 
2159  //ROS_INFO_STREAM("x: " << min_index_x << "," << max_index_x << ", y: " << min_index_y << "," << max_index_y);
2160  //min_index_x=0;min_index_y=0;
2161  //max_index_x=costsizex;max_index_y=costsizey;
2162 
2163  //for(int xi=0;xi<costsizex;xi++)
2164  //for(int yi=0;yi<costsizey;yi++)
2165  for(int xi=min_index_x;xi<max_index_x;xi++){
2166  for(int yi=min_index_y;yi<max_index_y;yi++){
2167  int index=yi*costsizex+xi;
2168  if(data[index]==0)continue;
2169  const double wx=origin_x+(xi+0.5)*resolution;
2170  const double wy=origin_y+(yi+0.5)*resolution;
2171  const double curper=wx*(ny-cy)-wy*(nx-cx);
2172  const double curpll=wx*(nx-cx)+wy*(ny-cy);
2173  //rectangular region
2174  if((std::abs(curper-refper)<difper)&&(std::abs(curpll-refpll)<difpll)){
2175  data[index]=0;
2176  continue;
2177  } else {
2178  //start circle region
2179  const double distfromstart=sqrt(pow(wx-cx,2.0)+pow(wy-cy,2.0));
2180  if(distfromstart<sradii[i]+resolution*0.5*sqrt(2.0)){
2181  data[index]=0;
2182  continue;
2183  };
2184  //end circle region
2185  const double distfromend=sqrt(pow(wx-nx,2.0)+pow(wy-ny,2.0));
2186  if(distfromend<eradii[i]+resolution*0.5*sqrt(2.0)){
2187  data[index]=0;
2188  };
2189  };
2190  };};
2191  };
2192 }
2193 
2194 void PipelinePlanner::callbackgoal(const move_base_msgs::MoveBaseActionGoal::ConstPtr& goal){
2195  willDisplay_=true;
2196 }
2197 
2198 void PipelinePlanner::callbackRobotPose(const geometry_msgs::Pose::ConstPtr& pose){
2199  boost::mutex::scoped_lock lock(mutex_robot_position_);
2200  robot_position_.position.x=pose->position.x;
2201  robot_position_.position.y=pose->position.y;
2202 
2203 }
2204 
2206  ros::NodeHandle nh;
2207  ros::Rate r(1.0);
2208  ROS_INFO("Pipeline planner: informRobotPose loop started");
2209  while(ros::ok()){
2210  bool in; int id; double distance;
2211  pipeline_planner::RobotPosition position;
2212  if(read_status_.data==5||read_status_.data==3){
2213  in=knowRobotPosition(robot_position_,id,distance);
2214  position.in=in;
2215  position.id=id;
2216  position.startdist=distance;
2217  position.previd=-1;
2218  position.nextid=-1;
2219  position.enddist=0.0;
2220  if(in){
2221  for(std::vector<pipeline_planner::SegmentInfo>::iterator it=segment_infos_.begin(); it!=segment_infos_.end();it++){
2222  if(it->ID == id){
2223  position.previd=it->prevID;
2224  position.nextid=it->nextID;
2225  position.enddist= it->length - distance;
2226  };
2227  };
2228  };
2229  } else {
2230  position.in=false;
2231  position.id=-1;
2232  position.previd=-1;
2233  position.nextid=-1;
2234  position.startdist=0.0;
2235  position.enddist=0.0;
2236  };
2237  for(std::vector<pipeline_planner::SegmentInfo>::iterator it=segment_infos_.begin();it!=segment_infos_.end();it++){
2238  if(it->ID == position.id){it->start=true;}else{it->start=false;};
2239  if(it->nextID == position.id){it->end=true;}else{it->end=false;};
2240  };
2241  pub_robot_position_.publish(position);
2242  r.sleep();
2243  };
2244 
2245 }
2246 
2247 void PipelinePlanner::TimeDisplay(const bool time_display,const double duration){
2248  if(time_display){
2249  ROS_WARN_STREAM("/ ** ** ");
2250  ROS_WARN_STREAM(" Pipeline planner ");
2251  ROS_WARN_STREAM(" makePlan duration time ");
2252  ROS_WARN_STREAM(" " << duration);
2253  ROS_WARN_STREAM(" ** ** /");
2254  };
2255  consumed_time_.data=duration;
2257 }
2258 
2259 bool PipelinePlanner::TakeLocalGoal(const geometry_msgs::PoseStamped& start,
2260 const geometry_msgs::PoseStamped& goal,geometry_msgs::PoseStamped& local_goal,
2261 int& err){
2262  err=0;
2263  //to assert we use torch model
2264  if(!use_torch_){
2265  ROS_ERROR("we only use TakeLocalGoal function on torch model");
2266  err=1;
2267  return false;
2268  };
2269  //preparation
2270  bool in; int sid,gid; double sdistance,gdistance;
2271  geometry_msgs::Pose pose;
2272  int nextid;
2273  double sx,sy,gx,gy;//start and goal
2274  sx=start.pose.position.x; sy=start.pose.position.y;
2275  gx=goal.pose.position.x; gy=goal.pose.position.y;
2276  double cx,cy,nx,ny; double lenseg;
2277  double pseusx,pseusy,pseugx,pseugy;//pseudo-start and pseudo-goal
2278  double crossx,crossy;//cross point
2279  int result;
2280  int numid;
2281  int numcp=check_points_.size();
2282  //to determine pseudo-start
2283  pose.position.x=sx;
2284  pose.position.y=sy;
2285  in=knowRobotPosition(pose,sid,sdistance);
2286  if(!in){
2287  ROS_ERROR("start position is out of pipeline");
2288  err=2;
2289  return false;
2290  };
2291  //to determine pseudo-goal
2292  pose.position.x=gx;
2293  pose.position.y=gy;
2294  in=knowRobotPosition(pose,gid,gdistance);
2295  if(!in){
2296  ROS_ERROR("goal position is out of pipeline");
2297  err=3;
2298  return false;
2299  };
2300  //substitution of pseudo-start and pseudo-end values
2301  //nextid=(sid==check_points_.size()-1)?0:sid+1;
2302  nextid=(sid+1)%numcp;
2303  cx=check_points_.at(sid).pose.position.x;
2304  cy=check_points_.at(sid).pose.position.y;
2305  nx=check_points_.at(nextid).pose.position.x;
2306  ny=check_points_.at(nextid).pose.position.y;
2307  lenseg=sqrt(pow(nx-cx,2)+pow(ny-cy,2));
2308  if(lenseg<tolerance_){
2309  ROS_ERROR_STREAM("the length of pipe segment " << sid << " is too short: " << lenseg);
2310  err=4;
2311  return false;
2312  };
2313  pseusx=(nx-cx)*sdistance/lenseg+cx;
2314  pseusy=(ny-cy)*sdistance/lenseg+cy;
2315  nextid=(gid+1)%numcp;
2316  cx=check_points_.at(gid).pose.position.x;
2317  cy=check_points_.at(gid).pose.position.y;
2318  nx=check_points_.at(nextid).pose.position.x;
2319  ny=check_points_.at(nextid).pose.position.y;
2320  lenseg=sqrt(pow(nx-cx,2)+pow(ny-cy,2));
2321  if(lenseg<tolerance_){
2322  ROS_ERROR_STREAM("the length of pipe segment " << sid << " is too short: " << lenseg);
2323  err=4;
2324  return false;
2325  };
2326  pseugx=(nx-cx)*gdistance/lenseg+cx;
2327  pseugy=(ny-cy)*gdistance/lenseg+cy;
2328  //to check whether pipe segment crosses the torch area for each pipe segment
2329  if(sid<=gid){ numid=gid-sid;}else{numid=gid-sid+numcp;};
2330  for(int i=sid;i<sid+numid+1;i++){
2331  int ID=i%numcp; int nID=(i+1)%numcp;
2332  if(i==sid){
2333  cx=pseusx; cy=pseusy;
2334  } else {
2335  cx=check_points_.at(ID).pose.position.x;
2336  cy=check_points_.at(ID).pose.position.y;
2337  };
2338  if(i==sid+numid){
2339  nx=pseugx; ny=pseugy;
2340  } else {
2341  nx=check_points_.at(nID).pose.position.x;
2342  ny=check_points_.at(nID).pose.position.y;
2343  };
2344  result=CrossTorchArea(sx,sy,cx,cy,nx,ny,crossx,crossy);
2345  if(result<0){
2346  ROS_ERROR("unexpected error, torch area might be too narrow with respect to the pipeline radius");
2347  ROS_ERROR("please adjust torch_area_x and torch_area_y");
2348  err=5;
2349  return false;
2350  } else if(result==1){
2351  ROS_ERROR("pseudo-start position is out of torch area");
2352  err=6;
2353  return false;
2354  } else if(result==2){
2355  //substitution of local goal and return true
2356  local_goal.header.seq=goal.header.seq;
2357  local_goal.header.stamp=goal.header.stamp;
2358  local_goal.header.frame_id=goal.header.frame_id;
2359  local_goal.pose.position.z=goal.pose.position.z;
2360  local_goal.pose.orientation.x=goal.pose.orientation.x;
2361  local_goal.pose.orientation.y=goal.pose.orientation.y;
2362  local_goal.pose.orientation.z=goal.pose.orientation.z;
2363  local_goal.pose.orientation.w=goal.pose.orientation.w;
2364  //main difference
2365  local_goal.pose.position.x=crossx;
2366  local_goal.pose.position.y=crossy;
2367  return true;
2368  };
2369  };
2370  //case in that the path from pseudo-start to pseudo-goal is in the torch area
2371  local_goal.header.seq=goal.header.seq;
2372  local_goal.header.stamp=goal.header.stamp;
2373  local_goal.header.frame_id=goal.header.frame_id;
2374  local_goal.pose.position.z=goal.pose.position.z;
2375  local_goal.pose.orientation.x=goal.pose.orientation.x;
2376  local_goal.pose.orientation.y=goal.pose.orientation.y;
2377  local_goal.pose.orientation.z=goal.pose.orientation.z;
2378  local_goal.pose.orientation.w=goal.pose.orientation.w;
2379  //main difference
2380  local_goal.pose.position.x=gx;
2381  local_goal.pose.position.y=gy;
2382  return true;
2383 }
2384 
2385 int PipelinePlanner::CrossTorchArea(const double tx,const double ty,
2386 const double sx,const double sy,const double ex,const double ey,
2387 double& bx,double& by){
2388  // b=c+(n-c)*t, |bx-sx|=ax, |by-sy|=ay, 0<t<1 (condition to cross the boundary)
2389  //whether start point is in torch area or not
2390  if(!(std::abs(sx-tx)<=torch_area_x_&&std::abs(sy-ty)<=torch_area_y_)){
2391  return 1;
2392  };
2393  //whether end point is in torch area or not
2394  if(std::abs(ex-tx)<=torch_area_x_&&std::abs(ey-ty)<=torch_area_y_){
2395  return 0;
2396  };
2397  //assertion of valid length of line segment
2398  double len=sqrt(pow(ex-sx,2)+pow(ey-sy,2));
2399  if(len<tolerance_){
2400  return -2;
2401  };
2402  //calculation of the cross point
2403  //b=s+(e-s)*u, 0<u<1, |bx-tx|=ax or |by-ty|=ay (cross condition)
2404  double uxp,uxm,uyp,uym; double minu;
2405  if(std::abs(ex-sx)<tolerance_){
2406  uxp=2.0; uxm=2.0;
2407  } else {
2408  uxp=(tx-sx+torch_area_x_)/(ex-sx); uxm=(tx-sx-torch_area_x_)/(ex-sx);
2409  if(uxp<0.0)uxp=2.0; if(uxm<0.0)uxm=2.0;
2410  };
2411  if(std::abs(ey-sy)<tolerance_){
2412  uyp=2.0; uym=2.0;
2413  } else {
2414  uyp=(ty-sy+torch_area_y_)/(ey-sy); uym=(ty-sy-torch_area_y_)/(ey-sy);
2415  if(uyp<0.0)uyp=2.0; if(uym<0.0)uym=2.0;
2416  };
2417  minu=std::min(std::min(uxp,uxm),std::min(uyp,uym));
2418  if(minu>1.0){
2419  return -1;
2420  };
2421  bx=sx+(ex-sx)*minu; by=sy+(ey-sy)*minu;
2422 
2423  return 2;
2424 }
2425 
2426 double PipelinePlanner::TakeSegmentRadius(const double contained_radius){
2427  double radius;
2428  if(contained_radius==0.0){
2429  radius=pipe_radius_;
2430  } else {
2431  radius=contained_radius;
2432  };
2433  return radius;
2434 }
2435 
2436 #if MODE==MODE_GPU
2438  cudaDeviceProp prop;
2439  int device=0;
2440  cudaError_t device_property_error;
2441  device_property_error=cudaGetDeviceProperties(&prop,device);
2442  if(device_property_error!=cudaSuccess){
2443  ROS_ERROR_STREAM("cudaGetDeviceProperties error: " << device_property_error);
2444  };
2445  if(debug){
2446  ROS_INFO_STREAM("max thread per block: " << prop.maxThreadsPerBlock);
2447  };
2448  if(num_threads_>prop.maxThreadsPerBlock){
2449  ROS_WARN("the number of thead you set is larger than maximum thread size");
2450  ROS_WARN_STREAM("the number of threads you set: " << num_threads_);
2451  ROS_WARN_STREAM("the maximum size of thread for this device: " << prop.maxThreadsPerBlock);
2452 
2453  num_threads_=prop.maxThreadsPerBlock;
2454  ROS_WARN_STREAM("we force to set the number of threads: " << num_threads_);
2455  ros::NodeHandle nh("~");
2456  nh.setParam("/move_base/PipelinePlanner/num_threads",prop.maxThreadsPerBlock);
2457  };
2458 }
2459 #endif
2460 
2461 
2462 } // end namespace
void makePipeline()
To make a pipeline and publish it as a topic Pipeline is constructed from check_points_. Validity of checkpoints_ must be checked in advance. Publication data values 0:in the pipeline, 100:out of the pipeline.
std::vector< pipeline_planner::SegmentInfo > segment_infos_
Definition: ppplanner.h:508
void setCost(unsigned int mx, unsigned int my, unsigned char cost)
bool ReceiveCheckpoints(pipeline_planner::ReceiveCheckpoints::Request &req, pipeline_planner::ReceiveCheckpoints::Response &res)
Reception of checkpoints.
bool DistanceFromCentre_cuda(int endpoint)
Calculation of cell&#39;s distance from pipe centre.
void initialize(std::string name, costmap_2d::Costmap2DROS *costmap_ros)
Initialisation function for the Planner.
bool VeilCostmap_cuda(const std::vector< int > segids, const int startindex, const int goalindex, const geometry_msgs::PoseStamped &start)
To veil costmap other than that in pipeline segments.
bool InitSegInfo()
Initialisation of segment info.
void TimeDisplay(const bool time_display, const double duration)
Display consumed time on makePlan function.
bool getRobotStatus(pipeline_planner::GetRobotStatus::Request &req, pipeline_planner::GetRobotStatus::Response &res)
Get the status of a robot.
Definition: ppplanner.h:194
void publish(const boost::shared_ptr< M > &message) const
int CrossTorchArea(const double tx, const double ty, const double sx, const double sy, const double ex, const double ey, double &bx, double &by)
Whether the line segment crosses the torch area boundary or not.
void mapToWorld(unsigned int mx, unsigned int my, double &wx, double &wy) const
ros::ServiceServer set_a_radius_srv_
Definition: ppplanner.h:550
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void setLethal(unsigned char lethal_cost)
Definition: ppplanner.h:124
void callbackgoal(const move_base_msgs::MoveBaseActionGoal::ConstPtr &goal)
Callback function for reception of actionlib goal.
nav_msgs::OccupancyGrid pipeline_
Definition: ppplanner.h:506
bool isBehindInaSegment(int idx, const geometry_msgs::PoseStamped &start, const geometry_msgs::PoseStamped &goal)
Whether the goal point is behind the start point in a pipe segment.
void setNumThread(float num_threads)
Definition: ppplanner.h:133
void setStraight(bool use_straight)
Definition: ppplanner.h:138
void informRobotPose()
loop for informing the robot position by a thread
ros::ServiceServer set_a_rightshift_srv_
Definition: ppplanner.h:551
std_msgs::UInt32 robot_status_
Definition: ppplanner.h:530
std::string getGlobalFrameID()
PLUGINLIB_EXPORT_CLASS(BAGReader, nodelet::Nodelet)
ros::ServiceServer receive_checkpoints_srv_
Definition: ppplanner.h:549
double getOriginX() const
ros::ServiceServer read_state_srv_
Definition: ppplanner.h:544
ros::ServiceServer get_checkpoints_srv_
Definition: ppplanner.h:546
std_msgs::Float32 consumed_time_
Definition: ppplanner.h:562
void callbackRobotPose(const geometry_msgs::Pose::ConstPtr &pose)
Callback function for reception of robot position.
void publishPlan(const std::vector< geometry_msgs::PoseStamped > &path)
To publish a path.
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
bool hasNoCross(const int endpoint, const std::vector< geometry_msgs::PoseStamped > check_points)
To check whether a sequence of checkpoints has a crossing or not.
Provides a global planner that will make a route along check points gained from topic. This planner uses global_planner.
Definition: ppplanner.h:75
bool makePlan(const geometry_msgs::PoseStamped &start, const geometry_msgs::PoseStamped &goal, std::vector< geometry_msgs::PoseStamped > &plan)
TFSIMD_FORCE_INLINE const tfScalar & y() const
#define ROS_WARN(...)
ros::ServiceServer robot_state_srv_
Definition: ppplanner.h:545
ros::Publisher pub_robot_position_
Definition: ppplanner.h:534
unsigned char * getCharMap() const
navfn::NavfnROS * navfn_planner_
Definition: ppplanner.h:512
void reconfigureCB(pipeline_planner::PipelinePlannerConfig &config, uint32_t level)
Callback function for dynamic reconfiguration.
bool DrawOpenSegment(const geometry_msgs::PoseStamped init_point, const geometry_msgs::PoseStamped end_point, std::vector< geometry_msgs::PoseStamped > &plan)
To substitute the plan along two points.
bool InquireSegments(pipeline_planner::InquireSegments::Request &req, pipeline_planner::InquireSegments::Response &res)
Inquiring segments information.
void DistanceFromCentreCalling(const int numstones, const double *stonex, const double *stoney, const double *stonedev, const unsigned int costsizex, const unsigned int costsizey, const double map_resolution, const double origin_x, const double origin_y, double *dist_from_centre, const int nthreads, const bool debug)
costmap_2d::Costmap2D * navfn_costmap_
Definition: ppplanner.h:513
unsigned char getCost(unsigned int mx, unsigned int my) const
bool knowRobotPosition(const geometry_msgs::Pose pose, int &ID, double &distance)
To know the position of a robot in the pipeline.
double distance(double x0, double y0, double x1, double y1)
bool ConnectPoints(const geometry_msgs::PoseStamped &start, const geometry_msgs::PoseStamped &goal, const std::vector< int > segids, std::vector< geometry_msgs::PoseStamped > &plan)
To substitute plan by connecting start point, checkpoints and goal point.
void setPipeRadius(float radius)
substitute pipe_radius_ value when it is called from dynamic reconfigure
boost::thread * thread_robot_position_
Definition: ppplanner.h:552
#define ROS_INFO(...)
bool makePlan(const geometry_msgs::PoseStamped &start, const geometry_msgs::PoseStamped &goal, std::vector< geometry_msgs::PoseStamped > &plan)
Given a goal pose in the world, compute a plan.
int test_cuda(int a, int b)
PipelinePlanner()
Constructor for the PipelinePlanner.
ros::ServiceServer inquire_segments_srv_
Definition: ppplanner.h:548
void PublishCheckpointsResult(std_msgs::UInt32 result)
Callback function for subscription of checkpoints data from topic.
dynamic_reconfigure::Server< pipeline_planner::PipelinePlannerConfig > * dsrv_
Definition: ppplanner.h:377
ROSCPP_DECL bool ok()
geometry_msgs::Pose robot_position_
Definition: ppplanner.h:564
int costCheck(int endpoint)
To check received checkpoints whether it has a problem on costmap or not.
costmap_2d::Costmap2D * costmap_
Definition: ppplanner.h:504
bool getReadStatus(pipeline_planner::GetReadStatus::Request &req, pipeline_planner::GetReadStatus::Response &res)
Get the status of reading checkpoints.
Definition: ppplanner.h:183
TFSIMD_FORCE_INLINE const tfScalar & x() const
double getOriginY() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
unsigned int getSizeInCellsY() const
ros::Subscriber sub_movebase_goal_
Definition: ppplanner.h:568
#define ROS_WARN_STREAM(args)
void calcPipeline(const int numcheckpoints, const double *stonex, const double *stoney, const bool isClose, const double *radii, const double *sradii, const double *eradii, const double origin_x, const double origin_y, const unsigned int costsizex, const unsigned int costsizey, const double resolution, int *data)
To calculate the pipeline without GPU.
bool sleep()
bool getNumofCheckpoints(pipeline_planner::GetNumofCheckpoints::Request &req, pipeline_planner::GetNumofCheckpoints::Response &res)
Get the status of reading checkpoints.
Definition: ppplanner.h:228
ros::ServiceServer get_numof_checkpoints_srv_
Definition: ppplanner.h:547
std::vector< geometry_msgs::PoseStamped > check_points_
Definition: ppplanner.h:505
unsigned int getSizeInCellsX() const
#define ROS_INFO_STREAM(args)
void setTorchArea(bool use_torch, float torch_area_x, float torch_area_y)
Definition: ppplanner.h:150
bool InPipeSegment(const geometry_msgs::PoseStamped &pose, double radius, double start_edge_radius, double end_edge_radius, double tolerance, int index)
Verification of whether the position is in the pipeline segment or not.
static Time now()
bool SetARadius(pipeline_planner::SetARadius::Request &req, pipeline_planner::SetARadius::Response &res)
Service to set a pipeline segment radius.
bool VeilCostmap(const std::vector< int > segids, const int startindex, const int goalindex, const geometry_msgs::PoseStamped &start)
To veil costmap other than that in pipeline segments.
bool DistanceFromCentre(int endpoint)
Calculation of cell&#39;s distance from pipe centre.
bool getCheckpoints(pipeline_planner::GetCheckpoints::Request &req, pipeline_planner::GetCheckpoints::Response &res)
Get check points.
Definition: ppplanner.h:205
bool whereInaPipeSegment(const geometry_msgs::Pose pose, const int id, const double radius, const double sradius, const double eradius, int &part, double &dist, double tolerance)
To know the position of a robot in a pipe segment.
double getResolution() const
Costmap2D * getCostmap()
#define ROS_ERROR_STREAM(args)
void setTimeDisplay(bool time_display)
Definition: ppplanner.h:146
double TakeSegmentRadius(const double contained_radius)
Taking pipline radius in a given pipeline segment.
bool TakeLocalGoal(const geometry_msgs::PoseStamped &start, const geometry_msgs::PoseStamped &goal, geometry_msgs::PoseStamped &local_goal, int &err)
To make local goal on torch model.
void setWeight(float centre_weight)
Definition: ppplanner.h:128
#define ROS_ERROR(...)
void setParam(const std::string &key, const XmlRpc::XmlRpcValue &v) const
bool worldToMap(double wx, double wy, unsigned int &mx, unsigned int &my) const
bool SetARightshift(pipeline_planner::SetARightshift::Request &req, pipeline_planner::SetARightshift::Response &res)
Service to set a right shift value for a pipeline segment.
std::vector< double > dist_from_pipe_centre_
Definition: ppplanner.h:375
unsigned int getIndex(unsigned int mx, unsigned int my) const
~PipelinePlanner()
Destructor for the planner.
ROSCPP_DECL bool waitForService(const std::string &service_name, int32_t timeout)
void calling_device(const int numstones, const double *stonex, const double *stoney, const double startx, const double starty, const double *radius, const double *sradius, const double *eradius, const unsigned int costsizex, const unsigned int costsizey, const double map_resolution, const double origin_x, const double origin_y, const double *dist_from_centre, const double centre_weight, unsigned char lethal, const int min_index_x, const int max_index_x, const int min_index_y, const int max_index_y, unsigned char *newCost, const int nthreads, const bool debug)


pipeline_planner
Author(s): seaos
autogenerated on Thu Jul 4 2019 19:55:39