39 #include <costmap_cspace_msgs/CSpace3D.h> 40 #include <costmap_cspace_msgs/CSpace3DUpdate.h> 42 #include <geometry_msgs/PoseArray.h> 43 #include <nav_msgs/GetPlan.h> 44 #include <nav_msgs/Path.h> 45 #include <planner_cspace_msgs/PlannerStatus.h> 46 #include <sensor_msgs/PointCloud.h> 47 #include <std_srvs/Empty.h> 48 #include <trajectory_tracker_msgs/PathWithVelocity.h> 57 #include <move_base_msgs/MoveBaseAction.h> 95 std::shared_ptr<Planner3DActionServer>
act_;
100 Astar::Gridmap<char, 0x40>
cm_;
117 cost += powf(coef[i] * vc[i], 2.0);
120 vc.
cycle(cm_.size());
123 cost += fabs(coef[i] * vc[i]);
240 std_srvs::EmptyResponse& res)
242 ROS_WARN(
"Forgetting remembered costmap.");
249 nav_msgs::GetPlan::Response& res)
254 if (req.start.header.frame_id != map_header_.frame_id ||
255 req.goal.header.frame_id != map_header_.frame_id)
257 ROS_ERROR(
"Start [%s] and Goal [%s] poses must be in the map frame [%s].",
258 req.start.header.frame_id.c_str(),
259 req.goal.header.frame_id.c_str(),
260 map_header_.frame_id.c_str());
266 map_info_, s[0], s[1], s[2],
267 req.start.pose.position.x, req.start.pose.position.y,
tf2::getYaw(req.start.pose.orientation));
270 map_info_, e[0], e[1], e[2],
271 req.goal.pose.position.x, req.goal.pose.position.y,
tf2::getYaw(req.goal.pose.orientation));
274 if (!(cm_rough_.validate(s, range_) && cm_rough_.validate(e, range_)))
276 ROS_ERROR(
"Given start or goal is not on the map.");
279 else if (cm_rough_[s] == 100 || cm_rough_[e] == 100)
281 ROS_ERROR(
"Given start or goal is in Rock.");
287 const auto cb_cost = [
this, &euclid_cost_coef](
290 const bool hyst) ->
float 296 const auto cache_page = motion_cache_linear_.
find(0, d);
297 if (cache_page == motion_cache_linear_.
end(0))
299 const int num = cache_page->second.getMotion().size();
300 for (
const auto& pos_diff : cache_page->second.getMotion())
302 const Astar::Vec pos(s[0] + pos_diff[0], s[1] + pos_diff[1], 0);
303 const auto c = cm_rough_[pos];
308 const float distf = cache_page->second.getDistance();
309 cost += sum * map_info_.linear_resolution * distf * cc_.
weight_costmap_ / (100.0 * num);
313 const auto cb_cost_estim = [
this, &euclid_cost_coef](
317 const float cost =
euclidCost(d, euclid_cost_coef);
321 const auto cb_search = [
this](
327 const auto cb_progress = [](
const std::list<Astar::Vec>& path_grid)
332 const auto ts = boost::chrono::high_resolution_clock::now();
335 std::list<Astar::Vec> path_grid;
336 if (!as_.
search(s, e, path_grid,
338 std::placeholders::_1, std::placeholders::_2,
339 std::placeholders::_3, std::placeholders::_4,
false),
340 cb_cost_estim, cb_search, cb_progress,
345 ROS_WARN(
"Path plan failed (goal unreachable)");
348 const auto tnow = boost::chrono::high_resolution_clock::now();
350 boost::chrono::duration<float>(tnow - ts).count());
356 const std::list<Astar::Vecf> path_interpolated =
357 path_interpolator_.
interpolate(path_grid, 0.5, 0.0);
361 res.plan.poses.resize(path.poses.size());
362 for (
size_t i = 0; i < path.poses.size(); ++i)
364 res.plan.poses[i] = path.poses[i];
370 void cbGoal(
const geometry_msgs::PoseStamped::ConstPtr& msg)
372 if (act_->isActive())
374 ROS_ERROR(
"Setting new goal is ignored since planner_3d is proceeding the action.");
381 ROS_WARN(
"Preempting the current goal.");
382 act_->setPreempted(move_base_msgs::MoveBaseResult(),
"Preempted.");
384 status_.status = planner_cspace_msgs::PlannerStatus::DONE;
386 bool setGoal(
const geometry_msgs::PoseStamped& msg)
388 if (msg.header.frame_id != map_header_.frame_id)
390 ROS_ERROR(
"Goal [%s] pose must be in the map frame [%s].",
391 msg.header.frame_id.c_str(), map_header_.frame_id.c_str());
395 goal_raw_ = goal_ = msg;
398 goal_.pose.orientation.x * goal_.pose.orientation.x +
399 goal_.pose.orientation.y * goal_.pose.orientation.y +
400 goal_.pose.orientation.z * goal_.pose.orientation.z +
401 goal_.pose.orientation.w * goal_.pose.orientation.w;
402 if (fabs(len2 - 1.0) < 0.1)
412 status_.status = planner_cspace_msgs::PlannerStatus::DOING;
419 if (act_->isActive())
420 act_->setSucceeded(move_base_msgs::MoveBaseResult(),
"Goal cleared.");
426 Astar::Gridmap<float>& g,
431 std::vector<Astar::Vec> search_diffs;
435 const int range_rough = 4;
436 for (d[0] = -range_rough; d[0] <= range_rough; d[0]++)
438 for (d[1] = -range_rough; d[1] <= range_rough; d[1]++)
440 if (d[0] == 0 && d[1] == 0)
442 if (d.
sqlen() > range_rough * range_rough)
444 search_diffs.push_back(d);
454 std::vector<Astar::PriorityVec> centers;
455 for (
size_t i = 0; i < static_cast<size_t>(
num_task_); ++i)
459 const auto center = open.top();
461 if (center.p_raw_ > g[center.v_])
463 if (center.p_raw_ - ec_rough_[0] * (range_ + local_range_ + longcut_range_) > g[s_rough])
465 centers.push_back(center);
469 std::list<Astar::GridmapUpdate> updates;
471 #pragma omp for schedule(static) 472 for (
auto it = centers.cbegin(); it < centers.cend(); ++it)
475 const float c = it->p_raw_;
482 if (static_cast<size_t>(next[0]) >= static_cast<size_t>(map_info_.width) ||
483 static_cast<size_t>(next[1]) >= static_cast<size_t>(map_info_.height))
485 const float gnext = g[next];
492 float sum = 0, sum_hist = 0;
493 const float grid_to_len = d.gridToLenFactor();
494 const int dist = d.len();
495 const float dpx =
static_cast<float>(d[0]) / dist;
496 const float dpy =
static_cast<float>(d[1]) / dist;
497 Astar::Vec pos(static_cast<int>(p[0]), static_cast<int>(p[1]), 0);
499 for (; i < dist; i++)
501 const char c = cm_rough_[pos];
506 sum_hist += cm_hist_[pos];
513 (map_info_.linear_resolution * grid_to_len / 100.0) *
524 const float cost_next = c + cost;
525 if (gnext > cost_next)
526 updates.push_back(Astar::GridmapUpdate(p, next, cost_next, cost_next));
531 for (
const Astar::GridmapUpdate& u : updates)
533 if (g[u.getPos()] > u.getCost())
535 g[u.getPos()] = u.getCost();
536 open.push(u.getPriorityVec());
542 rough_cost_max_ = g[s_rough] + ec_rough_[0] * (range_ +
local_range_);
545 const int cost_acceptable = 50,
const int min_xy_range = 0)
547 ROS_DEBUG(
"%d, %d (%d,%d,%d)", xy_range, angle_range, s[0], s[1], s[2]);
549 float range_min = FLT_MAX;
552 for (d[2] = -angle_range; d[2] <= angle_range; d[2]++)
554 for (d[0] = -xy_range; d[0] <= xy_range; d[0]++)
556 for (d[1] = -xy_range; d[1] <= xy_range; d[1]++)
558 if (d[0] == 0 && d[1] == 0 && d[2] == 0)
560 if (d.
sqlen() > xy_range * xy_range)
562 if (d.
sqlen() < min_xy_range * min_xy_range)
566 if ((
unsigned int)s2[0] >= (
unsigned int)map_info_.width ||
567 (
unsigned int)s2[1] >= (
unsigned int)map_info_.height)
570 if (cm_[s2] >= cost_acceptable)
573 if (cost < range_min)
582 if (range_min == FLT_MAX)
584 if (cost_acceptable != 100)
592 ROS_DEBUG(
" (%d,%d,%d)", s[0], s[1], s[2]);
600 if (!has_map_ || !has_start_)
602 ROS_ERROR(
"Goal received, however map/goal/start are not ready. (%d/%d/%d)",
603 static_cast<int>(has_map_), static_cast<int>(has_goal_), static_cast<int>(has_start_));
609 map_info_, s[0], s[1], s[2],
610 start_.pose.position.x, start_.pose.position.y,
614 map_info_, e[0], e[1], e[2],
615 goal_.pose.position.x, goal_.pose.position.y,
621 "New goal received (%d, %d, %d)",
625 if (!cm_.validate(e, range_))
627 ROS_ERROR(
"Given goal is not on the map.");
630 if (!cm_.validate(s, range_))
632 ROS_ERROR(
"You are on the edge of the world.");
636 const auto ts = boost::chrono::high_resolution_clock::now();
639 cost_estim_cache_.
clear(FLT_MAX);
653 goal_.pose.position.x = x;
654 goal_.pose.position.y = y;
666 cost_estim_cache_[e] = -ec_rough_[0] * 0.5;
667 open.push(Astar::PriorityVec(cost_estim_cache_[e], cost_estim_cache_[e], e));
669 const auto tnow = boost::chrono::high_resolution_clock::now();
670 ROS_DEBUG(
"Cost estimation cache generated (%0.4f sec.)",
671 boost::chrono::duration<float>(tnow - ts).count());
672 cost_estim_cache_[e] = 0;
679 goal_updated_ =
true;
688 sensor_msgs::PointCloud debug;
693 for (p[1] = 0; p[1] < cost_estim_cache_.size()[1]; p[1]++)
695 for (p[0] = 0; p[0] < cost_estim_cache_.size()[0]; p[0]++)
700 geometry_msgs::Point32 point;
706 if (cost_estim_cache_[p] == FLT_MAX)
710 for (p[2] = 0; p[2] <
static_cast<int>(map_info_.angle); ++p[2])
711 point.z = std::min(static_cast<float>(cm_hyst_[p]), point.z);
716 if (cost_estim_cache_[p] == FLT_MAX)
718 point.z = cost_estim_cache_[p] / 500;
721 debug.points.push_back(point);
732 if (use_path_with_velocity_)
736 path, std::numeric_limits<double>::quiet_NaN()));
744 void cbMapUpdate(
const costmap_cspace_msgs::CSpace3DUpdate::ConstPtr& msg)
755 if (remember_updates_)
759 sensor_msgs::PointCloud pc;
761 pc.header.stamp = now;
763 for (p[1] = 0; p[1] < cm_hist_bbf_.size()[1]; p[1]++)
765 for (p[0] = 0; p[0] < cm_hist_bbf_.size()[0]; p[0]++)
771 geometry_msgs::Point32 point;
774 point.z = cm_hist_bbf_[p].getProbability();
775 pc.points.push_back(point);
783 for (p[1] = 0; p[1] < cm_hist_bbf_.size()[1]; p[1]++)
785 for (p[0] = 0; p[0] < cm_hist_bbf_.size()[0]; p[0]++)
788 cm_hist_[p] = lroundf(cm_hist_bbf_[p].getNormalizedProbability() * 100.0);
795 static_cast<int>(msg->width / 2), static_cast<int>(msg->height / 2), 0);
797 static_cast<int>(msg->x), static_cast<int>(msg->y), static_cast<int>(msg->yaw));
800 const int hist_ignore_range_max_sq =
803 for (p[0] = 0; p[0] <
static_cast<int>(msg->width); p[0]++)
805 for (p[1] = 0; p[1] <
static_cast<int>(msg->height); p[1]++)
808 for (p[2] = 0; p[2] <
static_cast<int>(msg->angle); p[2]++)
810 const size_t addr = ((p[2] * msg->height) + p[1]) * msg->width + p[0];
811 const char c = msg->data[addr];
816 if (cost_min > cm_rough_[gp_rough + p])
818 cm_rough_[gp_rough + p] = cost_min;
826 const float sqlen = p2.
sqlen();
827 if (sqlen > hist_ignore_range_sq &&
828 sqlen < hist_ignore_range_max_sq)
830 cm_hist_bbf_[pos].update(remember_hit_odds_);
833 else if (cost_min >= 0)
836 const float sqlen = p2.
sqlen();
837 if (sqlen < hist_ignore_range_max_sq)
839 cm_hist_bbf_[pos].update(remember_miss_odds_);
843 for (p[2] = 0; p[2] <
static_cast<int>(msg->angle); p[2]++)
845 const size_t addr = ((p[2] * msg->height) + p[1]) * msg->width + p[0];
846 const char c = msg->data[addr];
861 if (!has_goal_ || !has_start_)
864 if (!fast_map_update_)
872 map_info_, s[0], s[1], s[2],
873 start_.pose.position.x, start_.pose.position.y,
877 map_info_, e[0], e[1], e[2],
878 goal_.pose.position.x, goal_.pose.position.y,
890 const auto ts = boost::chrono::high_resolution_clock::now();
894 float cost_min = FLT_MAX;
895 for (p[1] = static_cast<int>(msg->y); p[1] < static_cast<int>(msg->y + msg->height); p[1]++)
897 for (p[0] = static_cast<int>(msg->x); p[0] < static_cast<int>(msg->x + msg->width); p[0]++)
899 if (cost_min > cost_estim_cache_[p])
902 cost_min = cost_estim_cache_[p];
909 open.
reserve(map_info_.width * map_info_.height / 2);
910 erase.
reserve(map_info_.width * map_info_.height / 2);
912 if (cost_min != FLT_MAX)
913 erase.push(Astar::PriorityVec(cost_min, cost_min, p_cost_min));
916 if (erase.size() < 1)
918 const Astar::PriorityVec center = erase.top();
922 if (cost_estim_cache_[p] == FLT_MAX)
924 cost_estim_cache_[p] = FLT_MAX;
928 for (d[0] = -1; d[0] <= 1; d[0]++)
930 for (d[1] = -1; d[1] <= 1; d[1]++)
932 if (!((d[0] == 0) ^ (d[1] == 0)))
936 if ((
unsigned int)next[0] >= (
unsigned int)map_info_.width ||
937 (
unsigned int)next[1] >= (
unsigned int)map_info_.height)
939 const float gn = cost_estim_cache_[next];
944 open.push(Astar::PriorityVec(gn, gn, next));
947 erase.push(Astar::PriorityVec(gn, gn, next));
951 if (open.size() == 0)
953 open.push(Astar::PriorityVec(-ec_rough_[0] * 0.5, -ec_rough_[0] * 0.5, e));
958 for (p[0] = 0; p[0] <
static_cast<int>(map_info_.width); p[0]++)
960 for (p[1] = 0; p[1] <
static_cast<int>(map_info_.height); p[1]++)
962 const auto& gp = cost_estim_cache_[p];
963 if (gp > rough_cost_max_)
965 open.push(Astar::PriorityVec(gp, gp, p));
972 const auto tnow = boost::chrono::high_resolution_clock::now();
973 ROS_DEBUG(
"Cost estimation cache updated (%0.4f sec.)",
974 boost::chrono::duration<float>(tnow - ts).count());
977 void cbMap(
const costmap_cspace_msgs::CSpace3D::ConstPtr& msg)
980 ROS_INFO(
" linear_resolution %0.2f x (%dx%d) px", msg->info.linear_resolution,
981 msg->info.width, msg->info.height);
982 ROS_INFO(
" angular_resolution %0.2f x %d px", msg->info.angular_resolution,
984 ROS_INFO(
" origin %0.3f m, %0.3f m, %0.3f rad",
985 msg->info.origin.position.x,
986 msg->info.origin.position.y,
992 const float ec_val[3] =
998 ec_ =
Astar::Vecf(ec_val[0], ec_val[1], ec_val[2]);
1001 if (map_info_.linear_resolution != msg->info.linear_resolution ||
1002 map_info_.angular_resolution != msg->info.angular_resolution)
1004 map_info_ = msg->info;
1006 range_ =
static_cast<int>(search_range_ / map_info_.linear_resolution);
1008 costmap_cspace_msgs::MapMetaData3D map_info_linear(map_info_);
1009 map_info_linear.angle = 1;
1010 motion_cache_linear_.
reset(
1011 map_info_linear.linear_resolution,
1012 map_info_linear.angular_resolution,
1014 cm_rough_.getAddressor());
1015 motion_cache_.
reset(
1016 map_info_.linear_resolution,
1017 map_info_.angular_resolution,
1019 cm_.getAddressor());
1021 search_list_.clear();
1022 for (d[0] = -range_; d[0] <=
range_; d[0]++)
1024 for (d[1] = -range_; d[1] <=
range_; d[1]++)
1028 for (d[2] = 0; d[2] <
static_cast<int>(map_info_.angle); d[2]++)
1030 search_list_.push_back(d);
1034 search_list_rough_.clear();
1035 for (d[0] = -range_; d[0] <=
range_; d[0]++)
1037 for (d[1] = -range_; d[1] <=
range_; d[1]++)
1042 search_list_rough_.push_back(d);
1045 ROS_DEBUG(
"Search list updated (range: ang %d, lin %d) %d",
1046 map_info_.angle, range_, static_cast<int>(search_list_.size()));
1048 rot_cache_.
reset(map_info_.linear_resolution, map_info_.angular_resolution, range_);
1049 path_interpolator_.
reset(map_info_.angular_resolution, range_);
1054 map_info_ = msg->info;
1056 map_header_ = msg->header;
1059 resolution_[0] = 1.0 / map_info_.linear_resolution;
1060 resolution_[1] = 1.0 / map_info_.linear_resolution;
1061 resolution_[2] = 1.0 / map_info_.angular_resolution;
1063 hist_ignore_range_ = lroundf(hist_ignore_range_f_ / map_info_.linear_resolution);
1064 hist_ignore_range_max_ = lroundf(hist_ignore_range_max_f_ / map_info_.linear_resolution);
1065 local_range_ = lroundf(local_range_f_ / map_info_.linear_resolution);
1066 longcut_range_ = lroundf(longcut_range_f_ / map_info_.linear_resolution);
1067 esc_range_ = lroundf(esc_range_f_ / map_info_.linear_resolution);
1068 esc_angle_ = map_info_.angle / 8;
1069 tolerance_range_ = lroundf(tolerance_range_f_ / map_info_.linear_resolution);
1070 tolerance_angle_ = lroundf(tolerance_angle_f_ / map_info_.angular_resolution);
1071 goal_tolerance_lin_ = lroundf(goal_tolerance_lin_f_ / map_info_.linear_resolution);
1072 goal_tolerance_ang_ = lroundf(goal_tolerance_ang_f_ / map_info_.angular_resolution);
1076 static_cast<int>(map_info_.width),
1077 static_cast<int>(map_info_.height),
1078 static_cast<int>(map_info_.angle)
1081 cm_.reset(
Astar::Vec(size[0], size[1], size[2]));
1082 cm_hyst_.reset(
Astar::Vec(size[0], size[1], size[2]));
1084 cost_estim_cache_.reset(
Astar::Vec(size[0], size[1], 1));
1085 cm_rough_.reset(
Astar::Vec(size[0], size[1], 1));
1086 cm_hist_.reset(
Astar::Vec(size[0], size[1], 1));
1087 cm_hist_bbf_.reset(
Astar::Vec(size[0], size[1], 1));
1090 for (p[0] = 0; p[0] <
static_cast<int>(map_info_.width); p[0]++)
1092 for (p[1] = 0; p[1] <
static_cast<int>(map_info_.height); p[1]++)
1095 for (p[2] = 0; p[2] <
static_cast<int>(map_info_.angle); p[2]++)
1097 const size_t addr = ((p[2] * size[1]) + p[1]) * size[0] + p[0];
1098 char c = msg->data[addr];
1106 cm_rough_[p] = cost_min;
1110 cm_hyst_.clear(100);
1123 move_base_msgs::MoveBaseGoalConstPtr goal = act_->acceptNewGoal();
1124 if (!
setGoal(goal->target_pose))
1125 act_->setAborted(move_base_msgs::MoveBaseResult(),
"Given goal is invalid.");
1130 geometry_msgs::PoseStamped start;
1133 start.pose.orientation.x = 0.0;
1134 start.pose.orientation.y = 0.0;
1135 start.pose.orientation.z = 0.0;
1136 start.pose.orientation.w = 1.0;
1137 start.pose.position.x = 0;
1138 start.pose.position.y = 0;
1139 start.pose.position.z = 0;
1142 geometry_msgs::TransformStamped trans =
1167 nh_,
"costmap_update",
1170 nh_,
"move_base_simple/goal",
1172 pub_debug_ = pnh_.
advertise<sensor_msgs::PointCloud>(
"debug", 1,
true);
1173 pub_hist_ = pnh_.
advertise<sensor_msgs::PointCloud>(
"remembered", 1,
true);
1174 pub_start_ = pnh_.
advertise<geometry_msgs::PoseStamped>(
"path_start", 1,
true);
1175 pub_end_ = pnh_.
advertise<geometry_msgs::PoseStamped>(
"path_end", 1,
true);
1176 pub_status_ = pnh_.
advertise<planner_cspace_msgs::PlannerStatus>(
"status", 1,
true);
1178 nh_,
"forget_planning_cost",
1186 pnh_.
param(
"use_path_with_velocity", use_path_with_velocity_,
false);
1187 if (use_path_with_velocity_)
1189 pub_path_velocity_ = nh_.
advertise<trajectory_tracker_msgs::PathWithVelocity>(
1190 "path_velocity", 1,
true);
1194 pub_path_ = neonavigation_common::compat::advertise<nav_msgs::Path>(
1196 pnh_,
"path", 1,
true);
1198 pub_path_poses_ = pnh_.
advertise<geometry_msgs::PoseArray>(
1199 "path_poses", 1,
true);
1201 pnh_.
param(
"freq", freq_, 4.0
f);
1202 pnh_.
param(
"freq_min", freq_min_, 2.0
f);
1203 pnh_.
param(
"search_range", search_range_, 0.4
f);
1205 double costmap_watchdog;
1206 pnh_.
param(
"costmap_watchdog", costmap_watchdog, 0.0);
1209 pnh_.
param(
"max_vel", max_vel_, 0.3
f);
1210 pnh_.
param(
"max_ang_vel", max_ang_vel_, 0.6
f);
1211 pnh_.
param(
"min_curve_raduis", min_curve_raduis_, 0.1
f);
1224 pnh_.
param(
"goal_tolerance_lin", goal_tolerance_lin_f_, 0.05);
1225 pnh_.
param(
"goal_tolerance_ang", goal_tolerance_ang_f_, 0.1);
1226 pnh_.
param(
"goal_tolerance_ang_finish", goal_tolerance_ang_finish_, 0.05);
1228 pnh_.
param(
"unknown_cost", unknown_cost_, 100);
1229 pnh_.
param(
"overwrite_cost", overwrite_cost_,
false);
1231 pnh_.
param(
"hist_ignore_range", hist_ignore_range_f_, 0.6);
1232 pnh_.
param(
"hist_ignore_range_max", hist_ignore_range_max_f_, 1.25);
1233 pnh_.
param(
"remember_updates", remember_updates_,
false);
1234 double remember_hit_prob, remember_miss_prob;
1235 pnh_.
param(
"remember_hit_prob", remember_hit_prob, 0.6);
1236 pnh_.
param(
"remember_miss_prob", remember_miss_prob, 0.3);
1240 pnh_.
param(
"local_range", local_range_f_, 2.5);
1241 pnh_.
param(
"longcut_range", longcut_range_f_, 0.0);
1242 pnh_.
param(
"esc_range", esc_range_f_, 0.25);
1243 pnh_.
param(
"tolerance_range", tolerance_range_f_, 0.25);
1244 pnh_.
param(
"tolerance_angle", tolerance_angle_f_, 0.0);
1246 pnh_.
param(
"sw_wait", sw_wait_, 2.0
f);
1247 pnh_.
param(
"find_best", find_best_,
true);
1249 pnh_.
param(
"robot_frame", robot_frame_, std::string(
"base_link"));
1251 double pos_jump, yaw_jump;
1252 std::string jump_detect_frame;
1253 pnh_.
param(
"pos_jump", pos_jump, 1.0);
1254 pnh_.
param(
"yaw_jump", yaw_jump, 1.5);
1255 pnh_.
param(
"jump_detect_frame", jump_detect_frame, std::string(
"base_link"));
1259 pnh_.
param(
"force_goal_orientation", force_goal_orientation_,
true);
1261 pnh_.
param(
"temporary_escape", temporary_escape_,
true);
1263 pnh_.
param(
"fast_map_update", fast_map_update_,
false);
1264 if (fast_map_update_)
1266 ROS_WARN(
"planner_3d: Experimental fast_map_update is enabled. ");
1268 std::string debug_mode;
1269 pnh_.
param(
"debug_mode", debug_mode, std::string(
"cost_estim"));
1270 if (debug_mode ==
"hyst")
1272 else if (debug_mode ==
"cost_estim")
1275 bool print_planning_duration;
1276 pnh_.
param(
"print_planning_duration", print_planning_duration,
false);
1277 if (print_planning_duration)
1285 pnh_.
param(
"max_retry_num", max_retry_num_, -1);
1287 int queue_size_limit;
1288 pnh_.
param(
"queue_size_limit", queue_size_limit, 0);
1292 pnh_.
param(
"num_threads", num_threads, 1);
1293 omp_set_num_threads(num_threads);
1295 pnh_.
param(
"num_search_task", num_task_, num_threads * 16);
1298 status_.status = planner_cspace_msgs::PlannerStatus::DONE;
1303 goal_updated_ =
false;
1333 if (!goal_updated_ && has_goal_)
1337 bool has_costmap(
false);
1340 if (last_costmap_ + costmap_watchdog_ < now)
1343 "Navigation is stopping since the costmap is too old (costmap: %0.3f)",
1344 last_costmap_.
toSec());
1345 status_.error = planner_cspace_msgs::PlannerStatus::DATA_MISSING;
1358 if (has_map_ && has_goal_ && has_start_ && has_costmap)
1360 if (act_->isActive())
1362 move_base_msgs::MoveBaseFeedback feedback;
1363 feedback.base_position =
start_;
1364 act_->publishFeedback(feedback);
1367 if (status_.status == planner_cspace_msgs::PlannerStatus::FINISHING)
1369 const float yaw_s =
tf2::getYaw(start_.pose.orientation);
1370 float yaw_g =
tf2::getYaw(goal_.pose.orientation);
1371 if (force_goal_orientation_)
1374 float yaw_diff = yaw_s - yaw_g;
1375 if (yaw_diff > M_PI)
1376 yaw_diff -= M_PI * 2.0;
1377 else if (yaw_diff < -M_PI)
1378 yaw_diff += M_PI * 2.0;
1379 if (fabs(yaw_diff) < goal_tolerance_ang_finish_)
1381 status_.status = planner_cspace_msgs::PlannerStatus::DONE;
1387 if (act_->isActive())
1388 act_->setSucceeded(move_base_msgs::MoveBaseResult(),
"Goal reached.");
1395 status_.error = planner_cspace_msgs::PlannerStatus::PATH_NOT_FOUND;
1397 else if (max_retry_num_ != -1 && cnt_stuck_ > max_retry_num_)
1399 status_.error = planner_cspace_msgs::PlannerStatus::PATH_NOT_FOUND;
1400 status_.status = planner_cspace_msgs::PlannerStatus::DONE;
1404 ROS_ERROR(
"Exceeded max_retry_num:%d", max_retry_num_);
1406 if (act_->isActive())
1408 move_base_msgs::MoveBaseResult(),
"Goal is in Rock");
1413 status_.error = planner_cspace_msgs::PlannerStatus::GOING_WELL;
1415 nav_msgs::Path path;
1417 path.header.stamp = now;
1418 makePlan(start_.pose, goal_.pose, path,
true);
1419 if (use_path_with_velocity_)
1434 ROS_INFO(
"Planned path has switchback");
1440 else if (!has_goal_)
1450 bool makePlan(
const geometry_msgs::Pose& gs,
const geometry_msgs::Pose& ge,
1451 nav_msgs::Path& path,
bool hyst)
1455 map_info_, s[0], s[1], s[2],
1456 gs.position.x, gs.position.y,
tf2::getYaw(gs.orientation));
1459 map_info_, e[0], e[1], e[2],
1460 ge.position.x, ge.position.y,
tf2::getYaw(ge.orientation));
1463 geometry_msgs::PoseStamped p;
1468 p.pose.position.x = x;
1469 p.pose.position.y = y;
1476 ROS_WARN(
"Oops! You are in Rock!");
1477 status_.error = planner_cspace_msgs::PlannerStatus::IN_ROCK;
1484 if (cost_estim_cache_[s_rough] == FLT_MAX)
1486 status_.error = planner_cspace_msgs::PlannerStatus::PATH_NOT_FOUND;
1488 if (!escaping_ && temporary_escape_)
1494 ROS_INFO(
"Temporary goal (%d, %d, %d)",
1499 goal_.pose.position.x = x;
1500 goal_.pose.position.y = y;
1511 p.pose.position.x = x;
1512 p.pose.position.y = y;
1516 diff.
cycle(map_info_.angle);
1517 if (diff.
sqlen() <= goal_tolerance_lin_ * goal_tolerance_lin_ &&
1520 path.poses.resize(1);
1521 path.poses[0].header = path.header;
1522 if (force_goal_orientation_)
1523 path.poses[0].pose = goal_raw_.pose;
1525 path.poses[0].pose = ge;
1536 status_.status = planner_cspace_msgs::PlannerStatus::FINISHING;
1542 const float range_limit = cost_estim_cache_[s_rough] - (local_range_ +
range_) * ec_[0];
1543 angle_resolution_aspect_ = 2.0 / tanf(map_info_.angular_resolution);
1545 const auto ts = boost::chrono::high_resolution_clock::now();
1548 std::list<Astar::Vec> path_grid;
1549 if (!as_.
search(s, e, path_grid,
1551 this, std::placeholders::_1, std::placeholders::_2,
1552 std::placeholders::_3, std::placeholders::_4, hyst),
1554 this, std::placeholders::_1, std::placeholders::_2),
1556 this, std::placeholders::_1,
1557 std::placeholders::_2, std::placeholders::_3),
1559 this, std::placeholders::_1),
1564 ROS_WARN(
"Path plan failed (goal unreachable)");
1565 status_.error = planner_cspace_msgs::PlannerStatus::PATH_NOT_FOUND;
1569 const auto tnow = boost::chrono::high_resolution_clock::now();
1571 boost::chrono::duration<float>(tnow - ts).count());
1573 geometry_msgs::PoseArray poses;
1574 poses.header = path.header;
1575 for (
const auto& p : path_grid)
1577 geometry_msgs::Pose pose;
1580 pose.position.x = x;
1581 pose.position.y = y;
1584 poses.poses.push_back(pose);
1586 pub_path_poses_.
publish(poses);
1588 const std::list<Astar::Vecf> path_interpolated =
1589 path_interpolator_.
interpolate(path_grid, 0.5, local_range_);
1594 const std::list<Astar::Vecf> path_interpolated =
1595 path_interpolator_.
interpolate(path_grid, 0.5, local_range_);
1597 std::unordered_map<Astar::Vec, bool, Astar::Vec> path_points;
1600 const int path_range = range_ + max_dist + expand_dist + 5;
1604 for (d[0] = -path_range; d[0] <= path_range; d[0]++)
1606 for (d[1] = -path_range; d[1] <= path_range; d[1]++)
1610 if ((
unsigned int)point[0] >= (
unsigned int)map_info_.width ||
1611 (
unsigned int)point[1] >= (
unsigned int)map_info_.height)
1613 path_points[point] =
true;
1618 cm_hyst_.clear(100);
1619 const auto ts = boost::chrono::high_resolution_clock::now();
1620 for (
auto& ps : path_points)
1623 float d_min = FLT_MAX;
1624 auto it_prev = path_interpolated.begin();
1625 for (
auto it = path_interpolated.begin(); it != path_interpolated.end(); it++)
1636 d_min = std::max(expand_dist, std::min(expand_dist + max_dist, d_min));
1637 cm_hyst_[p] = lroundf((d_min - expand_dist) * 100.0 / max_dist);
1639 const auto tnow = boost::chrono::high_resolution_clock::now();
1640 ROS_DEBUG(
"Hysteresis map generated (%0.4f sec.)",
1641 boost::chrono::duration<float>(tnow - ts).count());
1656 euclid_cost_coef_ =
ec_;
1673 float cost = cost_estim_cache_[s2];
1674 if (cost == FLT_MAX)
1678 if (s2[2] > static_cast<int>(map_info_.angle) / 2)
1679 s2[2] -= map_info_.angle;
1680 cost += ec_rough_[2] * fabs(s[2]);
1686 geometry_msgs::Pose p_prev;
1688 bool dir_set(
false);
1689 bool dir_prev(
false);
1690 for (
const auto& p : path.poses)
1694 const float len = hypotf(
1695 p.pose.position.y - p_prev.position.y,
1696 p.pose.position.x - p_prev.position.x);
1699 const float yaw =
tf2::getYaw(p.pose.orientation);
1700 const float vel_yaw = atan2f(
1701 p.pose.position.y - p_prev.position.y,
1702 p.pose.position.x - p_prev.position.x);
1703 const bool dir = (cosf(yaw) * cosf(vel_yaw) + sinf(yaw) * sinf(vel_yaw) < 0);
1705 if (dir_set && (dir_prev ^ dir))
1724 d_raw.
cycle(map_info_.angle);
1728 if (d[0] == 0 && d[1] == 0)
1732 const int dir = d[2] < 0 ? -1 : 1;
1734 for (
int i = 0; i <
abs(d[2]); i++)
1738 pos[2] += map_info_.angle;
1739 else if (pos[2] >= static_cast<int>(map_info_.angle))
1740 pos[2] -= map_info_.angle;
1741 const auto c = cm_[pos];
1748 sum * map_info_.angular_resolution * ec_[2] / ec_[0] +
1762 if (lroundf(motion_grid[0]) == 0 && lroundf(motion_grid[1]) != 0)
1768 if (fabs(motion[2]) >= 2.0 * M_PI / 4.0)
1775 const float dist = motion.
len();
1785 if (lroundf(motion_grid[0]) == 0)
1787 const float aspect = motion[0] / motion[1];
1788 if (fabs(aspect) < angle_resolution_aspect_)
1792 int sum = 0, sum_hyst = 0;
1796 const auto cache_page = motion_cache_.
find(s[2], d_index);
1797 if (cache_page == motion_cache_.
end(s[2]))
1799 const int num = cache_page->second.getMotion().size();
1800 for (
const auto& pos_diff : cache_page->second.getMotion())
1803 s[0] + pos_diff[0], s[1] + pos_diff[1], pos_diff[2]);
1804 const auto c = cm_[pos];
1810 sum_hyst += cm_hyst_[pos];
1812 const float distf = cache_page->second.getDistance();
1813 cost += sum * map_info_.linear_resolution * distf * cc_.
weight_costmap_ / (100.0 * num);
1814 cost += sum_hyst * map_info_.linear_resolution * distf * cc_.
weight_hysteresis_ / (100.0 * num);
1819 if (motion[0] * motion[1] * motion[2] < 0)
1822 if (d.
sqlen() < 3 * 3)
1825 const std::pair<float, float>& radiuses = rot_cache_.
getRadiuses(s[2], d2);
1826 const float r1 = radiuses.first;
1827 const float r2 = radiuses.second;
1830 if (fabs(r1 - r2) >= map_info_.linear_resolution * 1.5)
1836 const float curv_radius = (r1 + r2) / 2;
1849 int sum = 0, sum_hyst = 0;
1853 const auto cache_page = motion_cache_.
find(s[2], d_index);
1854 if (cache_page == motion_cache_.
end(s[2]))
1856 const int num = cache_page->second.getMotion().size();
1857 for (
const auto& pos_diff : cache_page->second.getMotion())
1860 s[0] + pos_diff[0], s[1] + pos_diff[1], pos_diff[2]);
1861 const auto c = cm_[pos];
1867 sum_hyst += cm_hyst_[pos];
1869 const float distf = cache_page->second.getDistance();
1870 cost += sum * map_info_.linear_resolution * distf * cc_.
weight_costmap_ / (100.0 * num);
1872 cost += sum_hyst * map_info_.linear_resolution * distf * cc_.
weight_hysteresis_ / (100.0 * num);
1881 switch (status_.error)
1883 case planner_cspace_msgs::PlannerStatus::GOING_WELL:
1884 stat.
summary(diagnostic_msgs::DiagnosticStatus::OK,
"Going well.");
1886 case planner_cspace_msgs::PlannerStatus::IN_ROCK:
1887 stat.
summary(diagnostic_msgs::DiagnosticStatus::ERROR,
"The robot is in rock.");
1889 case planner_cspace_msgs::PlannerStatus::PATH_NOT_FOUND:
1890 stat.
summary(diagnostic_msgs::DiagnosticStatus::ERROR,
"Path not found.");
1892 case planner_cspace_msgs::PlannerStatus::DATA_MISSING:
1893 stat.
summary(diagnostic_msgs::DiagnosticStatus::ERROR,
"Required data is missing.");
1895 case planner_cspace_msgs::PlannerStatus::INTERNAL_ERROR:
1896 stat.
summary(diagnostic_msgs::DiagnosticStatus::ERROR,
"Planner internal error.");
1899 stat.
summary(diagnostic_msgs::DiagnosticStatus::ERROR,
"Unknown error.");
1902 stat.
addf(
"status",
"%u", status_.status);
1903 stat.
addf(
"error",
"%u", status_.error);
int hist_ignore_range_max_
double goal_tolerance_ang_finish_
bool updateGoal(const bool goal_changed=true)
Astar::Gridmap< char, 0x80 > cm_hyst_
Astar::Vecf euclid_cost_coef_
diagnostic_updater::Updater diag_updater_
std::vector< Astar::Vec > search_list_
void cbMapUpdate(const costmap_cspace_msgs::CSpace3DUpdate::ConstPtr &msg)
ros::Duration costmap_watchdog_
Astar::Gridmap< char, 0x40 > cm_
void cycleUnsigned(const int res, const ArgList &...rest)
ROSCONSOLE_DECL void notifyLoggerLevelsChanged()
void publish(const boost::shared_ptr< M > &message) const
void reset(const float angular_resolution, const int range)
constexpr int getNoncyclic() const
geometry_msgs::PoseStamped start_
void summary(unsigned char lvl, const std::string s)
float cbCostEstim(const Astar::Vec &s, const Astar::Vec &e)
double tolerance_angle_f_
void setBaseFrame(const std::string &frame_id)
MotionCache motion_cache_
double tolerance_range_f_
bool force_goal_orientation_
float cbCost(const Astar::Vec &s, Astar::Vec &e, const Astar::Vec &v_goal, const Astar::Vec &v_start, const bool hyst)
void setHardwareID(const std::string &hwid)
void setSearchTaskNum(const size_t &search_task_num)
ros::Subscriber sub_map_update_
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
CyclicVecFloat< DIM, NONCYCLIC > Vecf
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
void add(const std::string &name, TaskFunction f)
void setMapFrame(const std::string &frame_id)
constexpr int getDim() const
void cbMap(const costmap_cspace_msgs::CSpace3D::ConstPtr &msg)
Astar::Gridmap< bbf::BinaryBayesFilter, 0x20 > cm_hist_bbf_
void setQueueSizeLimit(const size_t size)
ros::Subscriber subscribe(ros::NodeHandle &nh_new, const std::string &topic_new, ros::NodeHandle &nh_old, const std::string &topic_old, uint32_t queue_size, void(*fp)(M), const ros::TransportHints &transport_hints=ros::TransportHints())
geometry_msgs::PoseStamped goal_
const Cache::const_iterator end(const int start_yaw) const
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
void doTransform(const T &data_in, T &data_out, const geometry_msgs::TransformStamped &transform)
double hist_ignore_range_max_f_
const std::pair< float, float > & getRadiuses(const int start_angle, const CyclicVecInt< 3, 2 > &end) const
TFSIMD_FORCE_INLINE const tfScalar & y() const
bool makePlan(const geometry_msgs::Pose &gs, const geometry_msgs::Pose &ge, nav_msgs::Path &path, bool hyst)
int main(int argc, char *argv[])
const CyclicVecFloat< 3, 2 > & getMotion(const int start_angle, const CyclicVecInt< 3, 2 > &end) const
bool use_path_with_velocity_
void addf(const std::string &key, const char *format,...)
bool searchAvailablePos(Astar::Vec &s, const int xy_range, const int angle_range, const int cost_acceptable=50, const int min_xy_range=0)
bool cbMakePlan(nav_msgs::GetPlan::Request &req, nav_msgs::GetPlan::Response &res)
bool setGoal(const geometry_msgs::PoseStamped &msg)
const Cache::const_iterator find(const int start_yaw, const CyclicVecInt< 3, 2 > &goal) const
ros::Publisher pub_path_velocity_
ros::Subscriber sub_goal_
float euclidCost(const Astar::Vec &v, const Astar::Vecf coef) const
ros::ServiceServer advertiseService(ros::NodeHandle &nh_new, const std::string &service_new, ros::NodeHandle &nh_old, const std::string &service_old, bool(T::*srv_func)(MReq &, MRes &), T *obj)
bool cbForget(std_srvs::EmptyRequest &req, std_srvs::EmptyResponse &res)
ros::Publisher pub_debug_
Astar::Gridmap< char, 0x40 > cm_hist_
ros::ServiceServer srs_make_plan_
constexpr float probabilityToOdds(const float &p)
void cbGoal(const geometry_msgs::PoseStamped::ConstPtr &msg)
bool search(const Vec &s, const Vec &e, std::list< Vec > &path, std::function< float(const Vec &, Vec &, const Vec &, const Vec &)> cb_cost, std::function< float(const Vec &, const Vec &)> cb_cost_estim, std::function< std::vector< Vec > &(const Vec &, const Vec &, const Vec &)> cb_search, std::function< bool(const std::list< Vec > &)> cb_progress, const float cost_leave, const float progress_interval, const bool return_best=false)
#define ROS_WARN_THROTTLE(period,...)
ros::Publisher pub_path_poses_
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
void metric2Grid(const costmap_cspace_msgs::MapMetaData3D &map_info, int &x, int &y, int &yaw, const float gx, const float gy, const float gyaw)
double goal_tolerance_ang_f_
TFSIMD_FORCE_INLINE const tfScalar & x() const
double hist_ignore_range_f_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void fillCostmap(reservable_priority_queue< Astar::PriorityVec > &open, Astar::Gridmap< float > &g, const Astar::Vec &s, const Astar::Vec &e)
actionlib::SimpleActionServer< move_base_msgs::MoveBaseAction > Planner3DActionServer
void diagnoseStatus(diagnostic_updater::DiagnosticStatusWrapper &stat)
Astar::Gridmap< char, 0x40 > cm_base_
void setThresholds(const double pos_jump, const double yaw_jump)
std::list< CyclicVecFloat< 3, 2 > > interpolate(const std::list< CyclicVecInt< 3, 2 >> &path_grid, const float interval, const int local_range) const
double getYaw(const A &a)
bool cbProgress(const std::list< Astar::Vec > &path_grid)
void grid2Metric(const costmap_cspace_msgs::MapMetaData3D &map_info, const T x, const T y, const T yaw, float &gx, float &gy, float &gyaw)
geometry_msgs::PoseStamped goal_raw_
Astar::Gridmap< char, 0x80 > cm_rough_
float weight_costmap_turn_
costmap_cspace_msgs::MapMetaData3D map_info_
uint32_t getNumSubscribers() const
void reserve(const size_type capacity)
tf2_ros::TransformListener tfl_
INLINE Rall1d< T, V, S > abs(const Rall1d< T, V, S > &x)
ros::Publisher pub_start_
ros::Publisher pub_status_
void reset(const float linear_resolution, const float angular_resolution, const int range, const std::function< void(CyclicVecInt< 3, 2 >, size_t &, size_t &)> gm_addr)
ros::ServiceServer srs_forget_
std::vector< Astar::Vec > & cbSearch(const Astar::Vec &p, const Astar::Vec &s, const Astar::Vec &e)
void reset(const float linear_resolution, const float angular_resolution, const int range)
float hysteresis_max_dist_
PathInterpolator path_interpolator_
void reset(const Vec size)
Astar::Gridmap< float > cost_estim_cache_
ROSCONSOLE_DECL bool set_logger_level(const std::string &name, levels::Level level)
void grid2MetricPath(const costmap_cspace_msgs::MapMetaData3D &map_info, const STL_CONTAINER< CyclicVecFloat< 3, 2 >, std::allocator< CyclicVecFloat< 3, 2 >>> &path_grid, nav_msgs::Path &path)
bool switchDetect(const nav_msgs::Path &path)
std::shared_ptr< Planner3DActionServer > act_
std::vector< Astar::Vec > search_list_rough_
ROSCPP_DECL void spinOnce()
float angle_resolution_aspect_
MotionCache motion_cache_linear_
#define ROSCONSOLE_DEFAULT_NAME
planner_cspace_msgs::PlannerStatus status_
float euclidCost(const Astar::Vec &v) const
float remember_miss_odds_
PathWithVelocity toPathWithVelocity(const nav_msgs::Path &src, const double vel)
void cycle(const int res, const ArgList &...rest)
Astar::Gridmap< char, 0x80 > cm_rough_base_
std_msgs::Header map_header_
double goal_tolerance_lin_f_