SBPLPlanner2D.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2013 Armin Hornung, University of Freiburg
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the University of Freiburg nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
30 
32  : nh_(),
33  robot_radius_(0.25),
34  start_received_(false), goal_received_(false),
35  path_costs_(0.0)
36 {
37 
38  // private NodeHandle for parameters:
39  ros::NodeHandle nh_private("~");
40  nh_private.param("planner_type", planner_type_, std::string("ARAPlanner"));
41  nh_private.param("search_until_first_solution", search_until_first_solution_, false);
42  nh_private.param("allocated_time", allocated_time_, 7.0);
43  nh_private.param("forward_search", forward_search_, false);
44  nh_private.param("initial_epsilon", initial_epsilon_, 3.0);
45  nh_private.param("robot_radius", robot_radius_, robot_radius_);
46 
47  path_pub_ = nh_.advertise<nav_msgs::Path>("path", 0);
48 
49  // subscriptions in SBPLPlanner2DNode
50 }
51 
53 
54 }
55 
56 void SBPLPlanner2D::goalCallback(const geometry_msgs::PoseStampedConstPtr& goal_pose){
57  // set goal:
58  goal_pose_ = goal_pose->pose;
59  goal_received_ = true;
60  ROS_DEBUG("Received goal: %f %f", goal_pose_.position.x, goal_pose_.position.y);
61 
62  if (goal_pose->header.frame_id != map_->getFrameID()){
63  ROS_WARN("Goal pose frame id \"%s\" different from map frame id \"%s\"", goal_pose->header.frame_id.c_str(), map_->getFrameID().c_str());
64  }
65 
66  // planning?
67  if (start_received_)
68  plan();
69 }
70 
71 void SBPLPlanner2D::startCallback(const geometry_msgs::PoseWithCovarianceStampedConstPtr& start_pose){
72  // set start:
73  start_pose_ = start_pose->pose.pose;
74  start_received_ = true;
75  ROS_DEBUG("Received start: %f %f", start_pose_.position.x, start_pose_.position.y);
76 
77  if (start_pose->header.frame_id != map_->getFrameID()){
78  ROS_WARN("Start pose frame id \"%s\" different from map frame id \"%s\"", start_pose->header.frame_id.c_str(), map_->getFrameID().c_str());
79  }
80 
81  // planning?
82  if (goal_received_)
83  plan();
84 }
85 
86 bool SBPLPlanner2D::plan(const geometry_msgs::Pose& start, const geometry_msgs::Pose& goal){
87  start_pose_ = start;
88  goal_pose_ = goal;
89 
90  start_received_ = true;
91  goal_received_ = true;
92 
93  return plan();
94 }
95 
96 bool SBPLPlanner2D::plan(double startX, double startY, double goalX, double goalY){
97  start_pose_.position.x = startX;
98  start_pose_.position.y = startY;
99 
100  goal_pose_.position.x = goalX;
101  goal_pose_.position.y = goalY;
102 
103  start_received_ = true;
104  goal_received_ = true;
105 
106  return plan();
107 }
108 
110  path_.poses.clear();
111 
112  if (!map_){
113  ROS_ERROR("Map not set");
114  return false;
115  }
116 
117  unsigned start_x, start_y, goal_x, goal_y;
118  if (!map_->worldToMap(start_pose_.position.x, start_pose_.position.y, start_x, start_y)){
119  ROS_ERROR("Start coordinates out of map bounds");
120  return false;
121  }
122  if (!map_->worldToMap(goal_pose_.position.x, goal_pose_.position.y, goal_x, goal_y)){
123  ROS_ERROR("Goal coordinates out of map bounds");
124  return false;
125  }
126 
127  if (map_->isOccupiedAtCell(start_x, start_y)){
128  ROS_ERROR("Start coordinate (%f %f) is occupied in map", start_pose_.position.x, start_pose_.position.y);
129  return false;
130  }
131  if (map_->isOccupiedAtCell(goal_x, goal_y)){
132  ROS_ERROR("Goal coordinate (%f %f) is occupied in map", goal_pose_.position.x, goal_pose_.position.y);
133  return false;
134  }
135 
136  int start_id = planner_environment_->SetStart(start_x, start_y);
137  int goal_id = planner_environment_->SetGoal(goal_x, goal_y);
138 
139  if (start_id < 0 || planner_->set_start(start_id) == 0){
140  ROS_ERROR("Failed to set start state");
141  return false;
142  }
143 
144  if (goal_id < 0 || planner_->set_goal(goal_id) == 0){
145  ROS_ERROR("Failed to set goal state");
146  return false;
147  }
148 
149  // set planner params:
150  planner_->set_initialsolution_eps(initial_epsilon_);
151  planner_->set_search_mode(search_until_first_solution_);
152  std::vector<int> solution_stateIDs;
153  int solution_cost;
154 
155 
156  if(planner_->replan(allocated_time_, &solution_stateIDs, &solution_cost))
157  ROS_DEBUG("Solution found. Costs: %d; final eps: %f", solution_cost, planner_->get_final_epsilon());
158  else{
159  ROS_INFO("Solution not found");
160  return false;
161  }
162 
163  // scale costs (SBPL uses mm and does not know map res)
164  path_costs_ = double(solution_cost) / ENVNAV2D_COSTMULT * map_->getResolution();
165 
166  // extract / publish path:
167  path_.poses.reserve(solution_stateIDs.size());
168  path_.header.frame_id = map_->getFrameID();
169  path_.header.stamp = ros::Time::now();
170 
171  geometry_msgs::PoseStamped pose;
172  pose.header = path_.header;
173  for (size_t i = 0; i < solution_stateIDs.size(); i++) {
174  int mx, my;
175  planner_environment_->GetCoordFromState(solution_stateIDs[i], mx, my);
176  //ROS_INFO("p: %d - [%d %d]", solution_stateIDs[i], mx, my);
177  double wx,wy;
178  map_->mapToWorld(mx,my,wx,wy);
179 
180 
181  pose.pose.position.x = wx;
182  pose.pose.position.y = wy;
183  pose.pose.position.z = 0.0;
184  path_.poses.push_back(pose);
185  }
186 
188 
189  return true;
190 }
191 
192 void SBPLPlanner2D::mapCallback(const nav_msgs::OccupancyGridConstPtr& occupancy_map){
193  gridmap_2d::GridMap2DPtr map(new gridmap_2d::GridMap2D(occupancy_map));
194  updateMap(map);
195 }
196 
198  planner_environment_.reset(new EnvironmentNAV2D());
199  planner_environment_->InitializeEnv(int(map->getInfo().width), int(map->getInfo().height), 0, OBSTACLE_COST);
200  // environment is set up, reset planner:
201  setPlanner();
202 
203  // store local copy:
204  map_.reset(new gridmap_2d::GridMap2D(*map));
205  map_->inflateMap(robot_radius_);
206 
207 
208  for(unsigned int j = 0; j < map_->getInfo().height; ++j){
209  for(unsigned int i = 0; i < map_->getInfo().width; ++i){
210  if (map_->isOccupiedAtCell(i,j))
211  planner_environment_->UpdateCost(i, j, OBSTACLE_COST);
212  else
213  planner_environment_->UpdateCost(i,j,0);
214 
215  }
216  }
217 
218  ROS_DEBUG("Map set");
219 
220  return true;
221 }
222 
224  if (planner_type_ == "ARAPlanner"){
225  planner_.reset(new ARAPlanner(planner_environment_.get(),forward_search_));
226  } else if (planner_type_ == "ADPlanner"){
227  planner_.reset(new ADPlanner(planner_environment_.get(),forward_search_));
228  } else if (planner_type_ == "RSTARPlanner"){
229  planner_.reset(new RSTARPlanner(planner_environment_.get(),forward_search_));
230  }
231 }
232 
233 
nav_msgs::Path path_
Definition: SBPLPlanner2D.h:99
void publish(const boost::shared_ptr< M > &message) const
void goalCallback(const geometry_msgs::PoseStampedConstPtr &goal)
Set goal and plan when start was already set.
geometry_msgs::Pose goal_pose_
Definition: SBPLPlanner2D.h:98
bool forward_search_
Definition: SBPLPlanner2D.h:94
virtual ~SBPLPlanner2D()
double robot_radius_
Definition: SBPLPlanner2D.h:95
double initial_epsilon_
Definition: SBPLPlanner2D.h:92
ros::Publisher path_pub_
Definition: SBPLPlanner2D.h:85
#define ROS_WARN(...)
bool search_until_first_solution_
Definition: SBPLPlanner2D.h:93
double allocated_time_
Definition: SBPLPlanner2D.h:91
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
void setPlanner()
(re)sets the planner
static const unsigned char OBSTACLE_COST
void mapCallback(const nav_msgs::OccupancyGridConstPtr &occupancy_map)
calls updateMap()
std::string planner_type_
Definition: SBPLPlanner2D.h:90
bool start_received_
Definition: SBPLPlanner2D.h:97
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool updateMap(gridmap_2d::GridMap2DPtr map)
Setup the internal map representation and initialize the SBPL planning environment.
boost::shared_ptr< EnvironmentNAV2D > planner_environment_
Definition: SBPLPlanner2D.h:87
boost::shared_ptr< SBPLPlanner > planner_
Definition: SBPLPlanner2D.h:86
double path_costs_
void startCallback(const geometry_msgs::PoseWithCovarianceStampedConstPtr &start)
Set start and plan when goal was already set.
static Time now()
geometry_msgs::Pose start_pose_
Definition: SBPLPlanner2D.h:98
gridmap_2d::GridMap2DPtr map_
Definition: SBPLPlanner2D.h:88
ros::NodeHandle nh_
Definition: SBPLPlanner2D.h:83
#define ROS_ERROR(...)
#define ROS_DEBUG(...)


humanoid_planner_2d
Author(s): Armin Hornung
autogenerated on Mon Jun 10 2019 13:38:35