42 #include <nav_msgs/Path.h>
43 #include <geometry_msgs/PoseArray.h>
44 #include <mbf_msgs/MoveBaseAction.h>
45 #include <mbf_abstract_nav/MoveBaseFlexConfig.h>
66 return static_cast<std::string
>(value[tag]);
86 throw std::runtime_error(
"No parameter " + resource);
89 if (raw.
getType() != XmlRpcValue::TypeArray)
90 throw std::runtime_error(resource +
" must be an XmlRpcValue::TypeArray");
95 mapping[
"global"] = global_costmap_ptr;
96 mapping[
"local"] = local_costmap_ptr;
98 const int size = raw.
size();
99 for (
int ii = 0; ii != size; ++ii)
104 if (element.
getType() != XmlRpcValue::TypeStruct)
119 output[name] = mapping.at(costmap);
125 catch (
const std::out_of_range& _ex)
127 ROS_ERROR_STREAM(
"Unknown costmap name. It must be either 'local' or 'global'");
149 catch (
const std::exception& _ex)
157 AbstractNavigationServer(tf_listener_ptr),
158 recovery_plugin_loader_(
"mbf_costmap_core",
"mbf_costmap_core::CostmapRecovery"),
159 nav_core_recovery_plugin_loader_(
"nav_core",
"nav_core::RecoveryBehavior"),
160 controller_plugin_loader_(
"mbf_costmap_core",
"mbf_costmap_core::CostmapController"),
161 nav_core_controller_plugin_loader_(
"nav_core",
"nav_core::BaseLocalPlanner"),
162 planner_plugin_loader_(
"mbf_costmap_core",
"mbf_costmap_core::CostmapPlanner"),
163 nav_core_planner_plugin_loader_(
"nav_core",
"nav_core::BaseGlobalPlanner"),
164 global_costmap_ptr_(new
CostmapWrapper(
"global_costmap", tf_listener_ptr_)),
165 local_costmap_ptr_(new
CostmapWrapper(
"local_costmap", tf_listener_ptr_)),
166 setup_reconfigure_(false)
207 template <
typename Key,
typename Value>
208 const Value&
findWithDefault(
const boost::unordered_map<Key, Value>& map,
const Key& key,
const Value& default_value)
210 typedef boost::unordered_map<Key, Value> MapType;
211 typename MapType::const_iterator iter = map.find(key);
212 if (iter == map.end())
218 const std::string &plugin_name,
223 return boost::make_shared<mbf_costmap_nav::CostmapPlannerExecution>(
224 plugin_name, boost::static_pointer_cast<mbf_costmap_core::CostmapPlanner>(plugin_ptr),
tf_listener_ptr_,
229 const std::string &plugin_name,
234 return boost::make_shared<mbf_costmap_nav::CostmapControllerExecution>(
235 plugin_name, boost::static_pointer_cast<mbf_costmap_core::CostmapController>(plugin_ptr),
vel_pub_,
goal_pub_,
240 const std::string &plugin_name,
243 return boost::make_shared<mbf_costmap_nav::CostmapRecoveryExecution>(
245 boost::static_pointer_cast<mbf_costmap_core::CostmapRecovery>(plugin_ptr),
257 planner_ptr = boost::static_pointer_cast<mbf_abstract_core::AbstractPlanner>(
260 ROS_DEBUG_STREAM(
"mbf_costmap_core-based planner plugin " << planner_name <<
" loaded.");
264 ROS_DEBUG_STREAM(
"Failed to load the " << planner_type <<
" planner as a mbf_costmap_core-based plugin."
265 <<
" Try to load as a nav_core-based plugin. " << ex_mbf_core.what());
270 planner_ptr = boost::make_shared<mbf_nav_core_wrapper::WrapperGlobalPlanner>(nav_core_planner_ptr);
272 ROS_DEBUG_STREAM(
"nav_core-based planner plugin " << planner_name <<
" loaded");
276 ROS_FATAL_STREAM(
"Failed to load the " << planner_type <<
" planner, are you sure it's properly registered"
277 <<
" and that the containing library is built? " << ex_mbf_core.what() <<
" " << ex_nav_core.what());
285 const std::string &name,
290 = boost::static_pointer_cast<mbf_costmap_core::CostmapPlanner>(planner_ptr);
301 costmap_planner_ptr->initialize(name, costmap_ptr.get());
313 ROS_DEBUG_STREAM(
"mbf_costmap_core-based controller plugin " << controller_name <<
" loaded.");
317 ROS_DEBUG_STREAM(
"Failed to load the " << controller_type <<
" controller as a mbf_costmap_core-based plugin;"
318 <<
" we will retry to load as a nav_core-based plugin. " << ex_mbf_core.what());
324 controller_ptr = boost::make_shared<mbf_nav_core_wrapper::WrapperLocalPlanner>(nav_core_controller_ptr);
326 ROS_DEBUG_STREAM(
"nav_core-based controller plugin " << controller_name <<
" loaded.");
330 ROS_FATAL_STREAM(
"Failed to load the " << controller_type <<
" controller, are you sure it's properly registered"
331 <<
" and that the containing library is built? " << ex_mbf_core.what() <<
" " << ex_nav_core.what());
334 return controller_ptr;
338 const std::string &name,
358 = boost::static_pointer_cast<mbf_costmap_core::CostmapController>(controller_ptr);
359 costmap_controller_ptr->initialize(name,
tf_listener_ptr_.get(), costmap_ptr.get());
365 const std::string &recovery_type)
371 recovery_ptr = boost::static_pointer_cast<mbf_abstract_core::AbstractRecovery>(
374 ROS_DEBUG_STREAM(
"mbf_costmap_core-based recovery behavior plugin " << recovery_name <<
" loaded.");
378 ROS_DEBUG_STREAM(
"Failed to load the " << recovery_type <<
" recovery behavior as a mbf_costmap_core-based plugin;"
379 <<
" Retry to load as a nav_core-based plugin. " << ex_mbf_core.what());
386 recovery_ptr = boost::make_shared<mbf_nav_core_wrapper::WrapperRecoveryBehavior>(nav_core_recovery_ptr);
388 ROS_DEBUG_STREAM(
"nav_core-based recovery behavior plugin " << recovery_name <<
" loaded.");
393 ROS_FATAL_STREAM(
"Failed to load the " << recovery_type <<
" recovery behavior, are you sure it's properly registered"
394 <<
" and that the containing library is built? " << ex_mbf_core.what() <<
" " << ex_nav_core.what());
402 const std::string &name,
426 boost::static_pointer_cast<mbf_costmap_core::CostmapRecovery>(behavior_ptr);
428 ROS_DEBUG_STREAM(
"Recovery behavior plugin \"" << name <<
"\" initialized.");
435 AbstractNavigationServer::stop();
450 if (config.restore_defaults)
454 config.restore_defaults =
false;
458 mbf_abstract_nav::MoveBaseFlexConfig abstract_config;
459 abstract_config.planner_frequency = config.planner_frequency;
460 abstract_config.planner_patience = config.planner_patience;
461 abstract_config.planner_max_retries = config.planner_max_retries;
462 abstract_config.controller_frequency = config.controller_frequency;
463 abstract_config.controller_patience = config.controller_patience;
464 abstract_config.controller_max_retries = config.controller_max_retries;
465 abstract_config.recovery_enabled = config.recovery_enabled;
466 abstract_config.recovery_patience = config.recovery_patience;
467 abstract_config.oscillation_timeout = config.oscillation_timeout;
468 abstract_config.oscillation_distance = config.oscillation_distance;
469 abstract_config.restore_defaults = config.restore_defaults;
473 local_costmap_ptr_->reconfigure(config.shutdown_costmaps, config.shutdown_costmaps_delay);
474 global_costmap_ptr_->reconfigure(config.shutdown_costmaps, config.shutdown_costmaps_delay);
480 mbf_msgs::CheckPoint::Response &response)
484 std::string costmap_name;
485 switch (request.costmap)
487 case mbf_msgs::CheckPoint::Request::LOCAL_COSTMAP:
489 costmap_name =
"local costmap";
491 case mbf_msgs::CheckPoint::Request::GLOBAL_COSTMAP:
493 costmap_name =
"global costmap";
497 << mbf_msgs::CheckPoint::Request::LOCAL_COSTMAP <<
": local costmap, "
498 << mbf_msgs::CheckPoint::Request::GLOBAL_COSTMAP <<
": global costmap");
503 std::string costmap_frame = costmap->getGlobalFrameID();
505 geometry_msgs::PointStamped point;
508 ROS_ERROR_STREAM(
"Transform target point to " << costmap_name <<
" frame '" << costmap_frame <<
"' failed");
512 double x = point.point.x;
513 double y = point.point.y;
516 costmap->checkActivate();
518 if (!costmap->getCostmap()->worldToMap(x, y, mx, my))
521 response.state =
static_cast<uint8_t
>(mbf_msgs::CheckPoint::Response::OUTSIDE);
527 boost::unique_lock<costmap_2d::Costmap2D::mutex_t> lock(*(costmap->getCostmap()->getMutex()));
530 response.cost = costmap->getCostmap()->getCost(mx, my);
534 response.state =
static_cast<uint8_t
>(mbf_msgs::CheckPoint::Response::UNKNOWN);
538 response.state =
static_cast<uint8_t
>(mbf_msgs::CheckPoint::Response::LETHAL);
542 response.state =
static_cast<uint8_t
>(mbf_msgs::CheckPoint::Response::INSCRIBED);
546 response.state =
static_cast<uint8_t
>(mbf_msgs::CheckPoint::Response::FREE);
552 costmap->checkDeactivate();
557 mbf_msgs::CheckPose::Response &response)
561 std::string costmap_name;
562 switch (request.costmap)
564 case mbf_msgs::CheckPose::Request::LOCAL_COSTMAP:
566 costmap_name =
"local costmap";
568 case mbf_msgs::CheckPose::Request::GLOBAL_COSTMAP:
570 costmap_name =
"global costmap";
574 << mbf_msgs::CheckPose::Request::LOCAL_COSTMAP <<
": local costmap, "
575 << mbf_msgs::CheckPose::Request::GLOBAL_COSTMAP <<
": global costmap");
580 std::string costmap_frame = costmap->getGlobalFrameID();
582 geometry_msgs::PoseStamped pose;
583 if (request.current_pose)
587 ROS_ERROR_STREAM(
"Get robot pose on " << costmap_name <<
" frame '" << costmap_frame <<
"' failed");
595 ROS_ERROR_STREAM(
"Transform target pose to " << costmap_name <<
" frame '" << costmap_frame <<
"' failed");
600 double x = pose.pose.position.x;
601 double y = pose.pose.position.y;
602 double yaw =
tf::getYaw(pose.pose.orientation);
605 costmap->checkActivate();
608 std::vector<geometry_msgs::Point> footprint = costmap->getUnpaddedRobotFootprint();
612 std::vector<Cell> footprint_cells =
614 response.state = mbf_msgs::CheckPose::Response::FREE;
615 if (footprint_cells.empty())
618 response.state = std::max(
response.state,
static_cast<uint8_t
>(mbf_msgs::CheckPose::Response::OUTSIDE));
623 boost::unique_lock<costmap_2d::Costmap2D::mutex_t> lock(*(costmap->getCostmap()->getMutex()));
626 for (
int i = 0; i < footprint_cells.size(); ++i)
628 unsigned char cost = costmap->getCostmap()->getCost(footprint_cells[i].x, footprint_cells[i].y);
632 response.state = std::max(
response.state,
static_cast<uint8_t
>(mbf_msgs::CheckPose::Response::UNKNOWN));
633 response.cost += cost * (request.unknown_cost_mult ? request.unknown_cost_mult : 1.0);
636 response.state = std::max(
response.state,
static_cast<uint8_t
>(mbf_msgs::CheckPose::Response::LETHAL));
637 response.cost += cost * (request.lethal_cost_mult ? request.lethal_cost_mult : 1.0);
640 response.state = std::max(
response.state,
static_cast<uint8_t
>(mbf_msgs::CheckPose::Response::INSCRIBED));
641 response.cost += cost * (request.inscrib_cost_mult ? request.inscrib_cost_mult : 1.0);
653 case mbf_msgs::CheckPose::Response::OUTSIDE:
655 <<
"; safety distance = " << request.safety_dist <<
")");
657 case mbf_msgs::CheckPose::Response::UNKNOWN:
659 <<
"; safety distance = " << request.safety_dist <<
")");
661 case mbf_msgs::CheckPose::Response::LETHAL:
663 <<
"; safety distance = " << request.safety_dist <<
")");
665 case mbf_msgs::CheckPose::Response::INSCRIBED:
667 <<
"; safety distance = " << request.safety_dist <<
")");
669 case mbf_msgs::CheckPose::Response::FREE:
671 <<
"; safety distance = " << request.safety_dist <<
")");
675 costmap->checkDeactivate();
680 mbf_msgs::CheckPath::Response &response)
684 std::string costmap_name;
685 switch (request.costmap)
687 case mbf_msgs::CheckPath::Request::LOCAL_COSTMAP:
689 costmap_name =
"local costmap";
691 case mbf_msgs::CheckPath::Request::GLOBAL_COSTMAP:
693 costmap_name =
"global costmap";
697 << mbf_msgs::CheckPath::Request::LOCAL_COSTMAP <<
": local costmap, "
698 << mbf_msgs::CheckPath::Request::GLOBAL_COSTMAP <<
": global costmap");
703 costmap->checkActivate();
706 std::string costmap_frame = costmap->getGlobalFrameID();
708 std::vector<geometry_msgs::Point> footprint;
709 if (!request.path_cells_only)
713 footprint = costmap->getUnpaddedRobotFootprint();
718 boost::unique_lock<costmap_2d::Costmap2D::mutex_t> lock(*(costmap->getCostmap()->getMutex()));
720 geometry_msgs::PoseStamped pose;
722 response.state = mbf_msgs::CheckPath::Response::FREE;
724 for (
int i = 0; i < request.path.poses.size(); ++i)
730 ROS_ERROR_STREAM(
"Transform target pose to " << costmap_name <<
" frame '" << costmap_frame <<
"' failed");
734 double x = pose.pose.position.x;
735 double y = pose.pose.position.y;
736 double yaw =
tf::getYaw(pose.pose.orientation);
737 std::vector<Cell> cells_to_check;
738 if (request.path_cells_only)
741 if (costmap->getCostmap()->worldToMap(x, y, cell.
x, cell.
y))
743 cells_to_check.push_back(cell);
752 if (cells_to_check.empty())
756 response.state = std::max(
response.state,
static_cast<uint8_t
>(mbf_msgs::CheckPath::Response::OUTSIDE));
762 for (
int j = 0; j < cells_to_check.size(); ++j)
764 unsigned char cost = costmap->getCostmap()->getCost(cells_to_check[j].x, cells_to_check[j].y);
768 response.state = std::max(
response.state,
static_cast<uint8_t
>(mbf_msgs::CheckPose::Response::UNKNOWN));
769 response.cost += cost * (request.unknown_cost_mult ? request.unknown_cost_mult : 1.0);
772 response.state = std::max(
response.state,
static_cast<uint8_t
>(mbf_msgs::CheckPath::Response::LETHAL));
773 response.cost += cost * (request.lethal_cost_mult ? request.lethal_cost_mult : 1.0);
776 response.state = std::max(
response.state,
static_cast<uint8_t
>(mbf_msgs::CheckPath::Response::INSCRIBED));
777 response.cost += cost * (request.inscrib_cost_mult ? request.inscrib_cost_mult : 1.0);
785 if (request.return_on &&
response.state >= request.return_on)
790 case mbf_msgs::CheckPath::Response::OUTSIDE:
791 ROS_DEBUG_STREAM(
"At pose " << i <<
" [" << x <<
", " << y <<
", " << yaw <<
"] path goes outside the map "
792 <<
"(cost = " <<
response.cost <<
"; safety distance = " << request.safety_dist <<
")");
794 case mbf_msgs::CheckPath::Response::UNKNOWN:
795 ROS_DEBUG_STREAM(
"At pose " << i <<
" [" << x <<
", " << y <<
", " << yaw <<
"] path goes in unknown space! "
796 <<
"(cost = " <<
response.cost <<
"; safety distance = " << request.safety_dist <<
")");
798 case mbf_msgs::CheckPath::Response::LETHAL:
799 ROS_DEBUG_STREAM(
"At pose " << i <<
" [" << x <<
", " << y <<
", " << yaw <<
"] path goes in collision! "
800 <<
"(cost = " <<
response.cost <<
"; safety distance = " << request.safety_dist <<
")");
802 case mbf_msgs::CheckPath::Response::INSCRIBED:
803 ROS_DEBUG_STREAM(
"At pose " << i <<
" [" << x <<
", " << y <<
", " << yaw <<
"] path goes near an obstacle "
804 <<
"(cost = " <<
response.cost <<
"; safety distance = " << request.safety_dist <<
")");
806 case mbf_msgs::CheckPath::Response::FREE:
808 <<
response.cost <<
"; safety distance = " << request.safety_dist <<
")");
815 i += request.skip_poses;
818 costmap->checkDeactivate();
823 std_srvs::Empty::Response &response)