planner_3d.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2019, the neonavigation authors
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <algorithm>
31 #include <limits>
32 #include <list>
33 #include <string>
34 #include <utility>
35 #include <vector>
36 
37 #include <ros/ros.h>
38 
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>
50 
51 #include <ros/console.h>
52 #include <tf2/utils.h>
55 
57 #include <move_base_msgs/MoveBaseAction.h>
58 
60 
61 #include <planner_cspace/bbf.h>
68 
69 #include <omp.h>
70 
72 {
73 public:
75 
76 protected:
78 
94 
95  std::shared_ptr<Planner3DActionServer> act_;
98 
100  Astar::Gridmap<char, 0x40> cm_;
101  Astar::Gridmap<bbf::BinaryBayesFilter, 0x20> cm_hist_bbf_;
102  Astar::Gridmap<char, 0x40> cm_hist_;
103  Astar::Gridmap<char, 0x80> cm_rough_;
104  Astar::Gridmap<char, 0x40> cm_base_;
105  Astar::Gridmap<char, 0x80> cm_rough_base_;
106  Astar::Gridmap<char, 0x80> cm_hyst_;
107  Astar::Gridmap<float> cost_estim_cache_;
108 
110 
111  float euclidCost(const Astar::Vec& v, const Astar::Vecf coef) const
112  {
113  Astar::Vec vc = v;
114  float cost = 0;
115  for (int i = 0; i < as_.getNoncyclic(); i++)
116  {
117  cost += powf(coef[i] * vc[i], 2.0);
118  }
119  cost = sqrtf(cost);
120  vc.cycle(cm_.size());
121  for (int i = as_.getNoncyclic(); i < as_.getDim(); i++)
122  {
123  cost += fabs(coef[i] * vc[i]);
124  }
125  return cost;
126  }
127  float euclidCost(const Astar::Vec& v) const
128  {
129  return euclidCost(v, euclid_cost_coef_);
130  }
131 
134 
135  costmap_cspace_msgs::MapMetaData3D map_info_;
136  std_msgs::Header map_header_;
137  float max_vel_;
139  float freq_;
140  float freq_min_;
142  int range_;
149  double esc_range_f_;
156  bool has_map_;
157  bool has_goal_;
162  std::vector<Astar::Vec> search_list_;
163  std::vector<Astar::Vec> search_list_rough_;
173 
175  std::string robot_frame_;
176 
178 
180 
181  // Cost weights
182  class CostCoeff
183  {
184  public:
195  };
197 
198  geometry_msgs::PoseStamped start_;
199  geometry_msgs::PoseStamped goal_;
200  geometry_msgs::PoseStamped goal_raw_;
210 
212  {
215  };
217 
218  planner_cspace_msgs::PlannerStatus status_;
219 
221  float sw_wait_;
222 
224  bool rough_;
225 
227 
228  bool escaping_;
229 
231 
234 
238 
239  bool cbForget(std_srvs::EmptyRequest& req,
240  std_srvs::EmptyResponse& res)
241  {
242  ROS_WARN("Forgetting remembered costmap.");
243  if (has_map_)
244  cm_hist_bbf_.clear(bbf::BinaryBayesFilter(bbf::MIN_ODDS));
245 
246  return true;
247  }
248  bool cbMakePlan(nav_msgs::GetPlan::Request& req,
249  nav_msgs::GetPlan::Response& res)
250  {
251  if (!has_map_)
252  return false;
253 
254  if (req.start.header.frame_id != map_header_.frame_id ||
255  req.goal.header.frame_id != map_header_.frame_id)
256  {
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());
261  return false;
262  }
263 
264  Astar::Vec s, e;
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));
268  s[2] = 0;
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));
272  e[2] = 0;
273 
274  if (!(cm_rough_.validate(s, range_) && cm_rough_.validate(e, range_)))
275  {
276  ROS_ERROR("Given start or goal is not on the map.");
277  return false;
278  }
279  else if (cm_rough_[s] == 100 || cm_rough_[e] == 100)
280  {
281  ROS_ERROR("Given start or goal is in Rock.");
282  return false;
283  }
284 
285  const Astar::Vecf euclid_cost_coef = ec_rough_;
286 
287  const auto cb_cost = [this, &euclid_cost_coef](
288  const Astar::Vec& s, const Astar::Vec& e,
289  const Astar::Vec& v_goal, const Astar::Vec& v_start,
290  const bool hyst) -> float
291  {
292  const Astar::Vec d = e - s;
293  float cost = euclidCost(d, euclid_cost_coef);
294 
295  int sum = 0;
296  const auto cache_page = motion_cache_linear_.find(0, d);
297  if (cache_page == motion_cache_linear_.end(0))
298  return -1;
299  const int num = cache_page->second.getMotion().size();
300  for (const auto& pos_diff : cache_page->second.getMotion())
301  {
302  const Astar::Vec pos(s[0] + pos_diff[0], s[1] + pos_diff[1], 0);
303  const auto c = cm_rough_[pos];
304  if (c > 99)
305  return -1;
306  sum += c;
307  }
308  const float distf = cache_page->second.getDistance();
309  cost += sum * map_info_.linear_resolution * distf * cc_.weight_costmap_ / (100.0 * num);
310 
311  return cost;
312  };
313  const auto cb_cost_estim = [this, &euclid_cost_coef](
314  const Astar::Vec& s, const Astar::Vec& e)
315  {
316  const Astar::Vec d = e - s;
317  const float cost = euclidCost(d, euclid_cost_coef);
318 
319  return cost;
320  };
321  const auto cb_search = [this](
322  const Astar::Vec& p,
323  const Astar::Vec& s, const Astar::Vec& e) -> std::vector<Astar::Vec>&
324  {
325  return search_list_rough_;
326  };
327  const auto cb_progress = [](const std::list<Astar::Vec>& path_grid)
328  {
329  return true;
330  };
331 
332  const auto ts = boost::chrono::high_resolution_clock::now();
333  // ROS_INFO("Planning from (%d, %d, %d) to (%d, %d, %d)",
334  // s[0], s[1], s[2], e[0], e[1], e[2]);
335  std::list<Astar::Vec> path_grid;
336  if (!as_.search(s, e, path_grid,
337  std::bind(cb_cost,
338  std::placeholders::_1, std::placeholders::_2,
339  std::placeholders::_3, std::placeholders::_4, false),
340  cb_cost_estim, cb_search, cb_progress,
341  0,
342  1.0f / freq_min_,
343  find_best_))
344  {
345  ROS_WARN("Path plan failed (goal unreachable)");
346  return false;
347  }
348  const auto tnow = boost::chrono::high_resolution_clock::now();
349  ROS_INFO("Path found (%0.4f sec.)",
350  boost::chrono::duration<float>(tnow - ts).count());
351 
352  nav_msgs::Path path;
353  path.header = map_header_;
354  path.header.stamp = ros::Time::now();
355 
356  const std::list<Astar::Vecf> path_interpolated =
357  path_interpolator_.interpolate(path_grid, 0.5, 0.0);
358  grid_metric_converter::grid2MetricPath(map_info_, path_interpolated, path);
359 
360  res.plan.header = map_header_;
361  res.plan.poses.resize(path.poses.size());
362  for (size_t i = 0; i < path.poses.size(); ++i)
363  {
364  res.plan.poses[i] = path.poses[i];
365  }
366 
367  return true;
368  }
369 
370  void cbGoal(const geometry_msgs::PoseStamped::ConstPtr& msg)
371  {
372  if (act_->isActive())
373  {
374  ROS_ERROR("Setting new goal is ignored since planner_3d is proceeding the action.");
375  return;
376  }
377  setGoal(*msg);
378  }
379  void cbPreempt()
380  {
381  ROS_WARN("Preempting the current goal.");
382  act_->setPreempted(move_base_msgs::MoveBaseResult(), "Preempted.");
383  has_goal_ = false;
384  status_.status = planner_cspace_msgs::PlannerStatus::DONE;
385  }
386  bool setGoal(const geometry_msgs::PoseStamped& msg)
387  {
388  if (msg.header.frame_id != map_header_.frame_id)
389  {
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());
392  return false;
393  }
394 
395  goal_raw_ = goal_ = msg;
396 
397  const double len2 =
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)
403  {
404  escaping_ = false;
405  has_goal_ = true;
406  cnt_stuck_ = 0;
407  if (!updateGoal())
408  {
409  has_goal_ = false;
410  return false;
411  }
412  status_.status = planner_cspace_msgs::PlannerStatus::DOING;
413  pub_status_.publish(status_);
414  diag_updater_.update();
415  }
416  else
417  {
418  has_goal_ = false;
419  if (act_->isActive())
420  act_->setSucceeded(move_base_msgs::MoveBaseResult(), "Goal cleared.");
421  }
422  return true;
423  }
426  Astar::Gridmap<float>& g,
427  const Astar::Vec& s, const Astar::Vec& e)
428  {
429  const Astar::Vec s_rough(s[0], s[1], 0);
430 
431  std::vector<Astar::Vec> search_diffs;
432  {
433  Astar::Vec d;
434  d[2] = 0;
435  const int range_rough = 4;
436  for (d[0] = -range_rough; d[0] <= range_rough; d[0]++)
437  {
438  for (d[1] = -range_rough; d[1] <= range_rough; d[1]++)
439  {
440  if (d[0] == 0 && d[1] == 0)
441  continue;
442  if (d.sqlen() > range_rough * range_rough)
443  continue;
444  search_diffs.push_back(d);
445  }
446  }
447  }
448 
449  while (true)
450  {
451  if (open.size() < 1)
452  break;
453 
454  std::vector<Astar::PriorityVec> centers;
455  for (size_t i = 0; i < static_cast<size_t>(num_task_); ++i)
456  {
457  if (open.size() < 1)
458  break;
459  const auto center = open.top();
460  open.pop();
461  if (center.p_raw_ > g[center.v_])
462  continue;
463  if (center.p_raw_ - ec_rough_[0] * (range_ + local_range_ + longcut_range_) > g[s_rough])
464  continue;
465  centers.push_back(center);
466  }
467 #pragma omp parallel
468  {
469  std::list<Astar::GridmapUpdate> updates;
470 
471 #pragma omp for schedule(static)
472  for (auto it = centers.cbegin(); it < centers.cend(); ++it)
473  {
474  const Astar::Vec p = it->v_;
475  const float c = it->p_raw_;
476 
477  for (const Astar::Vec& d : search_diffs)
478  {
479  Astar::Vec next = p + d;
480  next.cycleUnsigned(map_info_.angle);
481 
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))
484  continue;
485  const float gnext = g[next];
486  if (gnext < 0)
487  continue;
488 
489  float cost = 0;
490 
491  {
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);
498  int i = 0;
499  for (; i < dist; i++)
500  {
501  const char c = cm_rough_[pos];
502  if (c > 99)
503  break;
504  sum += c;
505 
506  sum_hist += cm_hist_[pos];
507  pos[0] += dpx;
508  pos[1] += dpy;
509  }
510  if (i != dist)
511  continue;
512  cost +=
513  (map_info_.linear_resolution * grid_to_len / 100.0) *
514  (sum * cc_.weight_costmap_ + sum_hist * cc_.weight_remembered_);
515 
516  if (cost < 0)
517  {
518  cost = 0;
519  ROS_WARN_THROTTLE(1.0, "Negative cost value is detected. Limited to zero.");
520  }
521  }
522  cost += euclidCost(d, ec_rough_);
523 
524  const float cost_next = c + cost;
525  if (gnext > cost_next)
526  updates.push_back(Astar::GridmapUpdate(p, next, cost_next, cost_next));
527  }
528  }
529 #pragma omp critical
530  {
531  for (const Astar::GridmapUpdate& u : updates)
532  {
533  if (g[u.getPos()] > u.getCost())
534  {
535  g[u.getPos()] = u.getCost();
536  open.push(u.getPriorityVec());
537  }
538  }
539  } // omp critical
540  } // omp parallel
541  }
542  rough_cost_max_ = g[s_rough] + ec_rough_[0] * (range_ + local_range_);
543  }
544  bool searchAvailablePos(Astar::Vec& s, const int xy_range, const int angle_range,
545  const int cost_acceptable = 50, const int min_xy_range = 0)
546  {
547  ROS_DEBUG("%d, %d (%d,%d,%d)", xy_range, angle_range, s[0], s[1], s[2]);
548 
549  float range_min = FLT_MAX;
550  Astar::Vec s_out;
551  Astar::Vec d;
552  for (d[2] = -angle_range; d[2] <= angle_range; d[2]++)
553  {
554  for (d[0] = -xy_range; d[0] <= xy_range; d[0]++)
555  {
556  for (d[1] = -xy_range; d[1] <= xy_range; d[1]++)
557  {
558  if (d[0] == 0 && d[1] == 0 && d[2] == 0)
559  continue;
560  if (d.sqlen() > xy_range * xy_range)
561  continue;
562  if (d.sqlen() < min_xy_range * min_xy_range)
563  continue;
564 
565  Astar::Vec s2 = s + d;
566  if ((unsigned int)s2[0] >= (unsigned int)map_info_.width ||
567  (unsigned int)s2[1] >= (unsigned int)map_info_.height)
568  continue;
569  s2.cycleUnsigned(map_info_.angle);
570  if (cm_[s2] >= cost_acceptable)
571  continue;
572  const auto cost = euclidCost(d, ec_);
573  if (cost < range_min)
574  {
575  range_min = cost;
576  s_out = s2;
577  }
578  }
579  }
580  }
581 
582  if (range_min == FLT_MAX)
583  {
584  if (cost_acceptable != 100)
585  {
586  return searchAvailablePos(s, xy_range, angle_range, 100);
587  }
588  return false;
589  }
590  s = s_out;
591  s.cycleUnsigned(map_info_.angle);
592  ROS_DEBUG(" (%d,%d,%d)", s[0], s[1], s[2]);
593  return true;
594  }
595  bool updateGoal(const bool goal_changed = true)
596  {
597  if (!has_goal_)
598  return true;
599 
600  if (!has_map_ || !has_start_)
601  {
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_));
604  return true;
605  }
606 
607  Astar::Vec s, e;
609  map_info_, s[0], s[1], s[2],
610  start_.pose.position.x, start_.pose.position.y,
611  tf2::getYaw(start_.pose.orientation));
612  s.cycleUnsigned(map_info_.angle);
614  map_info_, e[0], e[1], e[2],
615  goal_.pose.position.x, goal_.pose.position.y,
616  tf2::getYaw(goal_.pose.orientation));
617  e.cycleUnsigned(map_info_.angle);
618  if (goal_changed)
619  {
620  ROS_INFO(
621  "New goal received (%d, %d, %d)",
622  e[0], e[1], e[2]);
623  }
624 
625  if (!cm_.validate(e, range_))
626  {
627  ROS_ERROR("Given goal is not on the map.");
628  return false;
629  }
630  if (!cm_.validate(s, range_))
631  {
632  ROS_ERROR("You are on the edge of the world.");
633  return false;
634  }
635 
636  const auto ts = boost::chrono::high_resolution_clock::now();
638 
639  cost_estim_cache_.clear(FLT_MAX);
640  if (cm_[e] == 100)
641  {
642  if (!searchAvailablePos(e, tolerance_range_, tolerance_angle_))
643  {
644  ROS_WARN("Oops! Goal is in Rock!");
645  ++cnt_stuck_;
646  return true;
647  }
648  ROS_INFO("Goal moved (%d, %d, %d)",
649  e[0], e[1], e[2]);
650  float x, y, yaw;
651  grid_metric_converter::grid2Metric(map_info_, e[0], e[1], e[2], x, y, yaw);
652  goal_.pose.orientation = tf2::toMsg(tf2::Quaternion(tf2::Vector3(0.0, 0.0, 1.0), yaw));
653  goal_.pose.position.x = x;
654  goal_.pose.position.y = y;
655  }
656  if (cm_[s] == 100)
657  {
658  if (!searchAvailablePos(s, tolerance_range_, tolerance_angle_))
659  {
660  ROS_WARN("Oops! You are in Rock!");
661  return true;
662  }
663  }
664 
665  e[2] = 0;
666  cost_estim_cache_[e] = -ec_rough_[0] * 0.5; // Decrement to reduce calculation error
667  open.push(Astar::PriorityVec(cost_estim_cache_[e], cost_estim_cache_[e], e));
668  fillCostmap(open, cost_estim_cache_, s, 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;
673 
674  if (goal_changed)
675  cm_hyst_.clear(100);
676 
677  publishCostmap();
678 
679  goal_updated_ = true;
680 
681  return true;
682  }
684  {
685  if (pub_debug_.getNumSubscribers() == 0)
686  return;
687 
688  sensor_msgs::PointCloud debug;
689  debug.header = map_header_;
690  debug.header.stamp = ros::Time::now();
691  {
692  Astar::Vec p;
693  for (p[1] = 0; p[1] < cost_estim_cache_.size()[1]; p[1]++)
694  {
695  for (p[0] = 0; p[0] < cost_estim_cache_.size()[0]; p[0]++)
696  {
697  p[2] = 0;
698  float x, y, yaw;
699  grid_metric_converter::grid2Metric(map_info_, p[0], p[1], p[2], x, y, yaw);
700  geometry_msgs::Point32 point;
701  point.x = x;
702  point.y = y;
703  switch (debug_out_)
704  {
705  case DEBUG_HYSTERESIS:
706  if (cost_estim_cache_[p] == FLT_MAX)
707  continue;
708 
709  point.z = 100;
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);
712 
713  point.z *= 0.01;
714  break;
715  case DEBUG_COST_ESTIM:
716  if (cost_estim_cache_[p] == FLT_MAX)
717  continue;
718  point.z = cost_estim_cache_[p] / 500;
719  break;
720  }
721  debug.points.push_back(point);
722  }
723  }
724  }
725  pub_debug_.publish(debug);
726  }
728  {
729  nav_msgs::Path path;
730  path.header.frame_id = robot_frame_;
731  path.header.stamp = ros::Time::now();
732  if (use_path_with_velocity_)
733  {
734  pub_path_velocity_.publish(
736  path, std::numeric_limits<double>::quiet_NaN()));
737  }
738  else
739  {
740  pub_path_.publish(path);
741  }
742  }
743 
744  void cbMapUpdate(const costmap_cspace_msgs::CSpace3DUpdate::ConstPtr& msg)
745  {
746  if (!has_map_)
747  return;
748  ROS_DEBUG("Map updated");
749 
750  const ros::Time now = ros::Time::now();
751  last_costmap_ = now;
752 
753  cm_ = cm_base_;
754  cm_rough_ = cm_rough_base_;
755  if (remember_updates_)
756  {
757  if (pub_hist_.getNumSubscribers() > 0)
758  {
759  sensor_msgs::PointCloud pc;
760  pc.header = map_header_;
761  pc.header.stamp = now;
762  Astar::Vec p;
763  for (p[1] = 0; p[1] < cm_hist_bbf_.size()[1]; p[1]++)
764  {
765  for (p[0] = 0; p[0] < cm_hist_bbf_.size()[0]; p[0]++)
766  {
767  if (cm_hist_bbf_[p].get() > bbf::probabilityToOdds(0.1))
768  {
769  float x, y, yaw;
770  grid_metric_converter::grid2Metric(map_info_, p[0], p[1], p[2], x, y, yaw);
771  geometry_msgs::Point32 point;
772  point.x = x;
773  point.y = y;
774  point.z = cm_hist_bbf_[p].getProbability();
775  pc.points.push_back(point);
776  }
777  }
778  }
779  pub_hist_.publish(pc);
780  }
781  Astar::Vec p;
782  cm_hist_.clear(0);
783  for (p[1] = 0; p[1] < cm_hist_bbf_.size()[1]; p[1]++)
784  {
785  for (p[0] = 0; p[0] < cm_hist_bbf_.size()[0]; p[0]++)
786  {
787  p[2] = 0;
788  cm_hist_[p] = lroundf(cm_hist_bbf_[p].getNormalizedProbability() * 100.0);
789  }
790  }
791  }
792 
793  {
794  const Astar::Vec center(
795  static_cast<int>(msg->width / 2), static_cast<int>(msg->height / 2), 0);
796  const Astar::Vec gp(
797  static_cast<int>(msg->x), static_cast<int>(msg->y), static_cast<int>(msg->yaw));
798  const Astar::Vec gp_rough(gp[0], gp[1], 0);
799  const int hist_ignore_range_sq = hist_ignore_range_ * hist_ignore_range_;
800  const int hist_ignore_range_max_sq =
801  hist_ignore_range_max_ * hist_ignore_range_max_;
802  Astar::Vec p;
803  for (p[0] = 0; p[0] < static_cast<int>(msg->width); p[0]++)
804  {
805  for (p[1] = 0; p[1] < static_cast<int>(msg->height); p[1]++)
806  {
807  int cost_min = 100;
808  for (p[2] = 0; p[2] < static_cast<int>(msg->angle); p[2]++)
809  {
810  const size_t addr = ((p[2] * msg->height) + p[1]) * msg->width + p[0];
811  const char c = msg->data[addr];
812  if (c < cost_min)
813  cost_min = c;
814  }
815  p[2] = 0;
816  if (cost_min > cm_rough_[gp_rough + p])
817  {
818  cm_rough_[gp_rough + p] = cost_min;
819  }
820 
821  Astar::Vec pos = gp + p;
822  pos[2] = 0;
823  if (cost_min == 100)
824  {
825  const Astar::Vec p2 = p - center;
826  const float sqlen = p2.sqlen();
827  if (sqlen > hist_ignore_range_sq &&
828  sqlen < hist_ignore_range_max_sq)
829  {
830  cm_hist_bbf_[pos].update(remember_hit_odds_);
831  }
832  }
833  else if (cost_min >= 0)
834  {
835  const Astar::Vec p2 = p - center;
836  const float sqlen = p2.sqlen();
837  if (sqlen < hist_ignore_range_max_sq)
838  {
839  cm_hist_bbf_[pos].update(remember_miss_odds_);
840  }
841  }
842 
843  for (p[2] = 0; p[2] < static_cast<int>(msg->angle); p[2]++)
844  {
845  const size_t addr = ((p[2] * msg->height) + p[1]) * msg->width + p[0];
846  const char c = msg->data[addr];
847  if (overwrite_cost_)
848  {
849  if (c >= 0)
850  cm_[gp + p] = c;
851  }
852  else
853  {
854  if (cm_[gp + p] < c)
855  cm_[gp + p] = c;
856  }
857  }
858  }
859  }
860  }
861  if (!has_goal_ || !has_start_)
862  return;
863 
864  if (!fast_map_update_)
865  {
866  updateGoal(false);
867  return;
868  }
869 
870  Astar::Vec s, e;
872  map_info_, s[0], s[1], s[2],
873  start_.pose.position.x, start_.pose.position.y,
874  tf2::getYaw(start_.pose.orientation));
875  s.cycleUnsigned(map_info_.angle);
877  map_info_, e[0], e[1], e[2],
878  goal_.pose.position.x, goal_.pose.position.y,
879  tf2::getYaw(goal_.pose.orientation));
880  e.cycleUnsigned(map_info_.angle);
881 
882  if (cm_[e] == 100)
883  {
884  updateGoal(false);
885  return;
886  }
887 
888  e[2] = 0;
889 
890  const auto ts = boost::chrono::high_resolution_clock::now();
891 
892  Astar::Vec p, p_cost_min;
893  p[2] = 0;
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]++)
896  {
897  for (p[0] = static_cast<int>(msg->x); p[0] < static_cast<int>(msg->x + msg->width); p[0]++)
898  {
899  if (cost_min > cost_estim_cache_[p])
900  {
901  p_cost_min = p;
902  cost_min = cost_estim_cache_[p];
903  }
904  }
905  }
906 
909  open.reserve(map_info_.width * map_info_.height / 2);
910  erase.reserve(map_info_.width * map_info_.height / 2);
911 
912  if (cost_min != FLT_MAX)
913  erase.push(Astar::PriorityVec(cost_min, cost_min, p_cost_min));
914  while (true)
915  {
916  if (erase.size() < 1)
917  break;
918  const Astar::PriorityVec center = erase.top();
919  const Astar::Vec p = center.v_;
920  erase.pop();
921 
922  if (cost_estim_cache_[p] == FLT_MAX)
923  continue;
924  cost_estim_cache_[p] = FLT_MAX;
925 
926  Astar::Vec d;
927  d[2] = 0;
928  for (d[0] = -1; d[0] <= 1; d[0]++)
929  {
930  for (d[1] = -1; d[1] <= 1; d[1]++)
931  {
932  if (!((d[0] == 0) ^ (d[1] == 0)))
933  continue;
934  Astar::Vec next = p + d;
935  next.cycleUnsigned(map_info_.angle);
936  if ((unsigned int)next[0] >= (unsigned int)map_info_.width ||
937  (unsigned int)next[1] >= (unsigned int)map_info_.height)
938  continue;
939  const float gn = cost_estim_cache_[next];
940  if (gn == FLT_MAX)
941  continue;
942  if (gn < cost_min)
943  {
944  open.push(Astar::PriorityVec(gn, gn, next));
945  continue;
946  }
947  erase.push(Astar::PriorityVec(gn, gn, next));
948  }
949  }
950  }
951  if (open.size() == 0)
952  {
953  open.push(Astar::PriorityVec(-ec_rough_[0] * 0.5, -ec_rough_[0] * 0.5, e));
954  }
955  {
956  Astar::Vec p;
957  p[2] = 0;
958  for (p[0] = 0; p[0] < static_cast<int>(map_info_.width); p[0]++)
959  {
960  for (p[1] = 0; p[1] < static_cast<int>(map_info_.height); p[1]++)
961  {
962  const auto& gp = cost_estim_cache_[p];
963  if (gp > rough_cost_max_)
964  {
965  open.push(Astar::PriorityVec(gp, gp, p));
966  }
967  }
968  }
969  }
970 
971  fillCostmap(open, cost_estim_cache_, s, e);
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());
975  publishCostmap();
976  }
977  void cbMap(const costmap_cspace_msgs::CSpace3D::ConstPtr& msg)
978  {
979  ROS_INFO("Map received");
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,
983  msg->info.angle);
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,
987  tf2::getYaw(msg->info.origin.orientation));
988 
989  // Stop robot motion until next planning step
991 
992  const float ec_val[3] =
993  {
994  1.0f / max_vel_,
995  1.0f / max_vel_,
996  1.0f * cc_.weight_ang_vel_ / max_ang_vel_
997  };
998  ec_ = Astar::Vecf(ec_val[0], ec_val[1], ec_val[2]);
999  ec_rough_ = Astar::Vecf(ec_val[0], ec_val[1], 0);
1000 
1001  if (map_info_.linear_resolution != msg->info.linear_resolution ||
1002  map_info_.angular_resolution != msg->info.angular_resolution)
1003  {
1004  map_info_ = msg->info;
1005  Astar::Vec d;
1006  range_ = static_cast<int>(search_range_ / map_info_.linear_resolution);
1007 
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,
1013  range_,
1014  cm_rough_.getAddressor());
1015  motion_cache_.reset(
1016  map_info_.linear_resolution,
1017  map_info_.angular_resolution,
1018  range_,
1019  cm_.getAddressor());
1020 
1021  search_list_.clear();
1022  for (d[0] = -range_; d[0] <= range_; d[0]++)
1023  {
1024  for (d[1] = -range_; d[1] <= range_; d[1]++)
1025  {
1026  if (d.sqlen() > range_ * range_)
1027  continue;
1028  for (d[2] = 0; d[2] < static_cast<int>(map_info_.angle); d[2]++)
1029  {
1030  search_list_.push_back(d);
1031  }
1032  }
1033  }
1034  search_list_rough_.clear();
1035  for (d[0] = -range_; d[0] <= range_; d[0]++)
1036  {
1037  for (d[1] = -range_; d[1] <= range_; d[1]++)
1038  {
1039  if (d.sqlen() > range_ * range_)
1040  continue;
1041  d[2] = 0;
1042  search_list_rough_.push_back(d);
1043  }
1044  }
1045  ROS_DEBUG("Search list updated (range: ang %d, lin %d) %d",
1046  map_info_.angle, range_, static_cast<int>(search_list_.size()));
1047 
1048  rot_cache_.reset(map_info_.linear_resolution, map_info_.angular_resolution, range_);
1049  path_interpolator_.reset(map_info_.angular_resolution, range_);
1050  ROS_DEBUG("Rotation cache generated");
1051  }
1052  else
1053  {
1054  map_info_ = msg->info;
1055  }
1056  map_header_ = msg->header;
1057  jump_.setMapFrame(map_header_.frame_id);
1058 
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;
1062 
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);
1073 
1074  const int size[3] =
1075  {
1076  static_cast<int>(map_info_.width),
1077  static_cast<int>(map_info_.height),
1078  static_cast<int>(map_info_.angle)
1079  };
1080  as_.reset(Astar::Vec(size[0], size[1], size[2]));
1081  cm_.reset(Astar::Vec(size[0], size[1], size[2]));
1082  cm_hyst_.reset(Astar::Vec(size[0], size[1], size[2]));
1083 
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));
1088 
1089  Astar::Vec p;
1090  for (p[0] = 0; p[0] < static_cast<int>(map_info_.width); p[0]++)
1091  {
1092  for (p[1] = 0; p[1] < static_cast<int>(map_info_.height); p[1]++)
1093  {
1094  int cost_min = 100;
1095  for (p[2] = 0; p[2] < static_cast<int>(map_info_.angle); p[2]++)
1096  {
1097  const size_t addr = ((p[2] * size[1]) + p[1]) * size[0] + p[0];
1098  char c = msg->data[addr];
1099  if (c < 0)
1100  c = unknown_cost_;
1101  cm_[p] = c;
1102  if (c < cost_min)
1103  cost_min = c;
1104  }
1105  p[2] = 0;
1106  cm_rough_[p] = cost_min;
1107  }
1108  }
1109  ROS_DEBUG("Map copied");
1110  cm_hyst_.clear(100);
1111 
1112  has_map_ = true;
1113 
1114  cm_rough_base_ = cm_rough_;
1115  cm_base_ = cm_;
1116  cm_hist_bbf_.clear(bbf::BinaryBayesFilter(bbf::MIN_ODDS));
1117  cm_hist_.clear(0);
1118 
1119  updateGoal();
1120  }
1121  void cbAction()
1122  {
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.");
1126  }
1127 
1129  {
1130  geometry_msgs::PoseStamped start;
1131  start.header.frame_id = robot_frame_;
1132  start.header.stamp = ros::Time(0);
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;
1140  try
1141  {
1142  geometry_msgs::TransformStamped trans =
1143  tfbuf_.lookupTransform(map_header_.frame_id, robot_frame_, ros::Time(), ros::Duration(0.1));
1144  tf2::doTransform(start, start, trans);
1145  }
1146  catch (tf2::TransformException& e)
1147  {
1148  has_start_ = false;
1149  return;
1150  }
1151  start_ = start;
1152  has_start_ = true;
1153  }
1154 
1155 public:
1157  : nh_()
1158  , pnh_("~")
1159  , tfl_(tfbuf_)
1160  , jump_(tfbuf_)
1161  {
1164  nh_, "costmap",
1165  pnh_, "costmap", 1, &Planner3dNode::cbMap, this);
1166  sub_map_update_ = neonavigation_common::compat::subscribe(
1167  nh_, "costmap_update",
1168  pnh_, "costmap_update", 1, &Planner3dNode::cbMapUpdate, this);
1170  nh_, "move_base_simple/goal",
1171  pnh_, "goal", 1, &Planner3dNode::cbGoal, this);
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",
1179  pnh_, "forget", &Planner3dNode::cbForget, this);
1180  srs_make_plan_ = pnh_.advertiseService("make_plan", &Planner3dNode::cbMakePlan, this);
1181 
1182  act_.reset(new Planner3DActionServer(ros::NodeHandle(), "move_base", false));
1183  act_->registerGoalCallback(boost::bind(&Planner3dNode::cbAction, this));
1184  act_->registerPreemptCallback(boost::bind(&Planner3dNode::cbPreempt, this));
1185 
1186  pnh_.param("use_path_with_velocity", use_path_with_velocity_, false);
1187  if (use_path_with_velocity_)
1188  {
1189  pub_path_velocity_ = nh_.advertise<trajectory_tracker_msgs::PathWithVelocity>(
1190  "path_velocity", 1, true);
1191  }
1192  else
1193  {
1194  pub_path_ = neonavigation_common::compat::advertise<nav_msgs::Path>(
1195  nh_, "path",
1196  pnh_, "path", 1, true);
1197  }
1198  pub_path_poses_ = pnh_.advertise<geometry_msgs::PoseArray>(
1199  "path_poses", 1, true);
1200 
1201  pnh_.param("freq", freq_, 4.0f);
1202  pnh_.param("freq_min", freq_min_, 2.0f);
1203  pnh_.param("search_range", search_range_, 0.4f);
1204 
1205  double costmap_watchdog;
1206  pnh_.param("costmap_watchdog", costmap_watchdog, 0.0);
1207  costmap_watchdog_ = ros::Duration(costmap_watchdog);
1208 
1209  pnh_.param("max_vel", max_vel_, 0.3f);
1210  pnh_.param("max_ang_vel", max_ang_vel_, 0.6f);
1211  pnh_.param("min_curve_raduis", min_curve_raduis_, 0.1f);
1212 
1213  pnh_.param("weight_decel", cc_.weight_decel_, 50.0f);
1214  pnh_.param("weight_backward", cc_.weight_backward_, 0.9f);
1215  pnh_.param("weight_ang_vel", cc_.weight_ang_vel_, 1.0f);
1216  pnh_.param("weight_costmap", cc_.weight_costmap_, 50.0f);
1217  pnh_.param("weight_costmap_turn", cc_.weight_costmap_turn_, 0.0f);
1218  pnh_.param("weight_remembered", cc_.weight_remembered_, 1000.0f);
1219  pnh_.param("cost_in_place_turn", cc_.in_place_turn_, 30.0f);
1220  pnh_.param("hysteresis_max_dist", cc_.hysteresis_max_dist_, 0.1f);
1221  pnh_.param("hysteresis_expand", cc_.hysteresis_expand_, 0.1f);
1222  pnh_.param("weight_hysteresis", cc_.weight_hysteresis_, 5.0f);
1223 
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);
1227 
1228  pnh_.param("unknown_cost", unknown_cost_, 100);
1229  pnh_.param("overwrite_cost", overwrite_cost_, false);
1230 
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);
1237  remember_hit_odds_ = bbf::probabilityToOdds(remember_hit_prob);
1238  remember_miss_odds_ = bbf::probabilityToOdds(remember_miss_prob);
1239 
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);
1245 
1246  pnh_.param("sw_wait", sw_wait_, 2.0f);
1247  pnh_.param("find_best", find_best_, true);
1248 
1249  pnh_.param("robot_frame", robot_frame_, std::string("base_link"));
1250 
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"));
1256  jump_.setBaseFrame(jump_detect_frame);
1257  jump_.setThresholds(pos_jump, yaw_jump);
1258 
1259  pnh_.param("force_goal_orientation", force_goal_orientation_, true);
1260 
1261  pnh_.param("temporary_escape", temporary_escape_, true);
1262 
1263  pnh_.param("fast_map_update", fast_map_update_, false);
1264  if (fast_map_update_)
1265  {
1266  ROS_WARN("planner_3d: Experimental fast_map_update is enabled. ");
1267  }
1268  std::string debug_mode;
1269  pnh_.param("debug_mode", debug_mode, std::string("cost_estim"));
1270  if (debug_mode == "hyst")
1271  debug_out_ = DEBUG_HYSTERESIS;
1272  else if (debug_mode == "cost_estim")
1273  debug_out_ = DEBUG_COST_ESTIM;
1274 
1275  bool print_planning_duration;
1276  pnh_.param("print_planning_duration", print_planning_duration, false);
1277  if (print_planning_duration)
1278  {
1280  {
1282  }
1283  }
1284 
1285  pnh_.param("max_retry_num", max_retry_num_, -1);
1286 
1287  int queue_size_limit;
1288  pnh_.param("queue_size_limit", queue_size_limit, 0);
1289  as_.setQueueSizeLimit(queue_size_limit);
1290 
1291  int num_threads;
1292  pnh_.param("num_threads", num_threads, 1);
1293  omp_set_num_threads(num_threads);
1294 
1295  pnh_.param("num_search_task", num_task_, num_threads * 16);
1296  as_.setSearchTaskNum(num_task_);
1297 
1298  status_.status = planner_cspace_msgs::PlannerStatus::DONE;
1299 
1300  has_map_ = false;
1301  has_goal_ = false;
1302  has_start_ = false;
1303  goal_updated_ = false;
1304 
1305  escaping_ = false;
1306  cnt_stuck_ = 0;
1307 
1308  diag_updater_.setHardwareID("none");
1309  diag_updater_.add("Path Planner Status", this, &Planner3dNode::diagnoseStatus);
1310 
1311  act_->start();
1312  }
1313  void spin()
1314  {
1315  ros::Rate wait(freq_);
1316  ROS_DEBUG("Initialized");
1317 
1318  while (ros::ok())
1319  {
1320  wait.sleep();
1321  ros::spinOnce();
1322 
1323  const ros::Time now = ros::Time::now();
1324 
1325  if (has_map_)
1326  {
1327  updateStart();
1328  if (jump_.detectJump())
1329  {
1330  cm_hist_bbf_.clear(bbf::BinaryBayesFilter(bbf::MIN_ODDS));
1331  }
1332 
1333  if (!goal_updated_ && has_goal_)
1334  updateGoal();
1335  }
1336 
1337  bool has_costmap(false);
1338  if (costmap_watchdog_ > ros::Duration(0))
1339  {
1340  if (last_costmap_ + costmap_watchdog_ < now)
1341  {
1342  ROS_WARN(
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;
1346  publishEmptyPath();
1347  }
1348  else
1349  {
1350  has_costmap = true;
1351  }
1352  }
1353  else
1354  {
1355  has_costmap = true;
1356  }
1357 
1358  if (has_map_ && has_goal_ && has_start_ && has_costmap)
1359  {
1360  if (act_->isActive())
1361  {
1362  move_base_msgs::MoveBaseFeedback feedback;
1363  feedback.base_position = start_;
1364  act_->publishFeedback(feedback);
1365  }
1366 
1367  if (status_.status == planner_cspace_msgs::PlannerStatus::FINISHING)
1368  {
1369  const float yaw_s = tf2::getYaw(start_.pose.orientation);
1370  float yaw_g = tf2::getYaw(goal_.pose.orientation);
1371  if (force_goal_orientation_)
1372  yaw_g = tf2::getYaw(goal_raw_.pose.orientation);
1373 
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_)
1380  {
1381  status_.status = planner_cspace_msgs::PlannerStatus::DONE;
1382  has_goal_ = false;
1383  // Don't publish empty path here in order a path follower
1384  // to minimize the error to the desired final pose
1385  ROS_INFO("Path plan finished");
1386 
1387  if (act_->isActive())
1388  act_->setSucceeded(move_base_msgs::MoveBaseResult(), "Goal reached.");
1389  }
1390  }
1391  else
1392  {
1393  if (escaping_)
1394  {
1395  status_.error = planner_cspace_msgs::PlannerStatus::PATH_NOT_FOUND;
1396  }
1397  else if (max_retry_num_ != -1 && cnt_stuck_ > max_retry_num_)
1398  {
1399  status_.error = planner_cspace_msgs::PlannerStatus::PATH_NOT_FOUND;
1400  status_.status = planner_cspace_msgs::PlannerStatus::DONE;
1401  has_goal_ = false;
1402 
1403  publishEmptyPath();
1404  ROS_ERROR("Exceeded max_retry_num:%d", max_retry_num_);
1405 
1406  if (act_->isActive())
1407  act_->setAborted(
1408  move_base_msgs::MoveBaseResult(), "Goal is in Rock");
1409  continue;
1410  }
1411  else
1412  {
1413  status_.error = planner_cspace_msgs::PlannerStatus::GOING_WELL;
1414  }
1415  nav_msgs::Path path;
1416  path.header = map_header_;
1417  path.header.stamp = now;
1418  makePlan(start_.pose, goal_.pose, path, true);
1419  if (use_path_with_velocity_)
1420  {
1421  // NaN velocity means that don't care the velocity
1422  pub_path_velocity_.publish(
1423  trajectory_tracker_msgs::toPathWithVelocity(path, std::numeric_limits<double>::quiet_NaN()));
1424  }
1425  else
1426  {
1427  pub_path_.publish(path);
1428  }
1429 
1430  if (sw_wait_ > 0.0)
1431  {
1432  if (switchDetect(path))
1433  {
1434  ROS_INFO("Planned path has switchback");
1435  ros::Duration(sw_wait_).sleep();
1436  }
1437  }
1438  }
1439  }
1440  else if (!has_goal_)
1441  {
1442  publishEmptyPath();
1443  }
1444  pub_status_.publish(status_);
1445  diag_updater_.force_update();
1446  }
1447  }
1448 
1449 protected:
1450  bool makePlan(const geometry_msgs::Pose& gs, const geometry_msgs::Pose& ge,
1451  nav_msgs::Path& path, bool hyst)
1452  {
1453  Astar::Vec s, e;
1455  map_info_, s[0], s[1], s[2],
1456  gs.position.x, gs.position.y, tf2::getYaw(gs.orientation));
1457  s.cycleUnsigned(map_info_.angle);
1459  map_info_, e[0], e[1], e[2],
1460  ge.position.x, ge.position.y, tf2::getYaw(ge.orientation));
1461  e.cycleUnsigned(map_info_.angle);
1462 
1463  geometry_msgs::PoseStamped p;
1464  p.header = map_header_;
1465  float x, y, yaw;
1466  grid_metric_converter::grid2Metric(map_info_, e[0], e[1], e[2], x, y, yaw);
1467  p.pose.orientation = tf2::toMsg(tf2::Quaternion(tf2::Vector3(0.0, 0.0, 1.0), yaw));
1468  p.pose.position.x = x;
1469  p.pose.position.y = y;
1470  pub_end_.publish(p);
1471 
1472  if (cm_[s] == 100)
1473  {
1474  if (!searchAvailablePos(s, tolerance_range_, tolerance_angle_))
1475  {
1476  ROS_WARN("Oops! You are in Rock!");
1477  status_.error = planner_cspace_msgs::PlannerStatus::IN_ROCK;
1478  return false;
1479  }
1480  ROS_INFO("Start moved");
1481  }
1482  const Astar::Vec s_rough(s[0], s[1], 0);
1483 
1484  if (cost_estim_cache_[s_rough] == FLT_MAX)
1485  {
1486  status_.error = planner_cspace_msgs::PlannerStatus::PATH_NOT_FOUND;
1487  ROS_WARN("Goal unreachable.");
1488  if (!escaping_ && temporary_escape_)
1489  {
1490  e = s;
1491  if (searchAvailablePos(e, esc_range_, esc_angle_, 50, esc_range_ / 2))
1492  {
1493  escaping_ = true;
1494  ROS_INFO("Temporary goal (%d, %d, %d)",
1495  e[0], e[1], e[2]);
1496  float x, y, yaw;
1497  grid_metric_converter::grid2Metric(map_info_, e[0], e[1], e[2], x, y, yaw);
1498  goal_.pose.orientation = tf2::toMsg(tf2::Quaternion(tf2::Vector3(0.0, 0.0, 1.0), yaw));
1499  goal_.pose.position.x = x;
1500  goal_.pose.position.y = y;
1501 
1502  updateGoal();
1503  return false;
1504  }
1505  }
1506  return false;
1507  }
1508 
1509  grid_metric_converter::grid2Metric(map_info_, s[0], s[1], s[2], x, y, yaw);
1510  p.pose.orientation = tf2::toMsg(tf2::Quaternion(tf2::Vector3(0.0, 0.0, 1.0), yaw));
1511  p.pose.position.x = x;
1512  p.pose.position.y = y;
1513  pub_start_.publish(p);
1514 
1515  Astar::Vec diff = s - e;
1516  diff.cycle(map_info_.angle);
1517  if (diff.sqlen() <= goal_tolerance_lin_ * goal_tolerance_lin_ &&
1518  abs(diff[2]) <= goal_tolerance_ang_)
1519  {
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;
1524  else
1525  path.poses[0].pose = ge;
1526 
1527  if (escaping_)
1528  {
1529  goal_ = goal_raw_;
1530  escaping_ = false;
1531  updateGoal();
1532  ROS_INFO("Escaped");
1533  }
1534  else
1535  {
1536  status_.status = planner_cspace_msgs::PlannerStatus::FINISHING;
1537  ROS_INFO("Path plan finishing");
1538  }
1539  return true;
1540  }
1541 
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);
1544 
1545  const auto ts = boost::chrono::high_resolution_clock::now();
1546  // ROS_INFO("Planning from (%d, %d, %d) to (%d, %d, %d)",
1547  // s[0], s[1], s[2], e[0], e[1], e[2]);
1548  std::list<Astar::Vec> path_grid;
1549  if (!as_.search(s, e, path_grid,
1550  std::bind(&Planner3dNode::cbCost,
1551  this, std::placeholders::_1, std::placeholders::_2,
1552  std::placeholders::_3, std::placeholders::_4, hyst),
1553  std::bind(&Planner3dNode::cbCostEstim,
1554  this, std::placeholders::_1, std::placeholders::_2),
1555  std::bind(&Planner3dNode::cbSearch,
1556  this, std::placeholders::_1,
1557  std::placeholders::_2, std::placeholders::_3),
1558  std::bind(&Planner3dNode::cbProgress,
1559  this, std::placeholders::_1),
1560  range_limit,
1561  1.0f / freq_min_,
1562  true))
1563  {
1564  ROS_WARN("Path plan failed (goal unreachable)");
1565  status_.error = planner_cspace_msgs::PlannerStatus::PATH_NOT_FOUND;
1566  if (!find_best_)
1567  return false;
1568  }
1569  const auto tnow = boost::chrono::high_resolution_clock::now();
1570  ROS_DEBUG("Path found (%0.4f sec.)",
1571  boost::chrono::duration<float>(tnow - ts).count());
1572 
1573  geometry_msgs::PoseArray poses;
1574  poses.header = path.header;
1575  for (const auto& p : path_grid)
1576  {
1577  geometry_msgs::Pose pose;
1578  float x, y, yaw;
1579  grid_metric_converter::grid2Metric(map_info_, p[0], p[1], p[2], x, y, yaw);
1580  pose.position.x = x;
1581  pose.position.y = y;
1582  pose.orientation =
1583  tf2::toMsg(tf2::Quaternion(tf2::Vector3(0.0, 0.0, 1.0), yaw));
1584  poses.poses.push_back(pose);
1585  }
1586  pub_path_poses_.publish(poses);
1587 
1588  const std::list<Astar::Vecf> path_interpolated =
1589  path_interpolator_.interpolate(path_grid, 0.5, local_range_);
1590  grid_metric_converter::grid2MetricPath(map_info_, path_interpolated, path);
1591 
1592  if (hyst)
1593  {
1594  const std::list<Astar::Vecf> path_interpolated =
1595  path_interpolator_.interpolate(path_grid, 0.5, local_range_);
1596 
1597  std::unordered_map<Astar::Vec, bool, Astar::Vec> path_points;
1598  const float max_dist = cc_.hysteresis_max_dist_ / map_info_.linear_resolution;
1599  const float expand_dist = cc_.hysteresis_expand_ / map_info_.linear_resolution;
1600  const int path_range = range_ + max_dist + expand_dist + 5;
1601  for (const Astar::Vecf& p : path_interpolated)
1602  {
1603  Astar::Vec d;
1604  for (d[0] = -path_range; d[0] <= path_range; d[0]++)
1605  {
1606  for (d[1] = -path_range; d[1] <= path_range; d[1]++)
1607  {
1608  Astar::Vec point = p + d;
1609  point.cycleUnsigned(map_info_.angle);
1610  if ((unsigned int)point[0] >= (unsigned int)map_info_.width ||
1611  (unsigned int)point[1] >= (unsigned int)map_info_.height)
1612  continue;
1613  path_points[point] = true;
1614  }
1615  }
1616  }
1617 
1618  cm_hyst_.clear(100);
1619  const auto ts = boost::chrono::high_resolution_clock::now();
1620  for (auto& ps : path_points)
1621  {
1622  const Astar::Vec& p = ps.first;
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++)
1626  {
1627  if (it != it_prev)
1628  {
1629  const float d =
1630  CyclicVecFloat<3, 2>(p).distLinestrip2d(*it_prev, *it);
1631  if (d < d_min)
1632  d_min = d;
1633  }
1634  it_prev = it;
1635  }
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);
1638  }
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());
1642  publishCostmap();
1643  }
1644 
1645  return true;
1646  }
1647  std::vector<Astar::Vec>& cbSearch(
1648  const Astar::Vec& p,
1649  const Astar::Vec& s, const Astar::Vec& e)
1650  {
1651  const Astar::Vec ds = s - p;
1652 
1653  if (ds.sqlen() < local_range_ * local_range_)
1654  {
1655  rough_ = false;
1656  euclid_cost_coef_ = ec_;
1657  return search_list_;
1658  }
1659  rough_ = true;
1660  euclid_cost_coef_ = ec_rough_;
1661  return search_list_rough_;
1662  }
1663  bool cbProgress(const std::list<Astar::Vec>& path_grid)
1664  {
1665  publishEmptyPath();
1666  ROS_WARN("Search timed out");
1667  return true;
1668  }
1669 
1670  float cbCostEstim(const Astar::Vec& s, const Astar::Vec& e)
1671  {
1672  Astar::Vec s2(s[0], s[1], 0);
1673  float cost = cost_estim_cache_[s2];
1674  if (cost == FLT_MAX)
1675  return FLT_MAX;
1676  if (!rough_)
1677  {
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]);
1681  }
1682  return cost;
1683  }
1684  bool switchDetect(const nav_msgs::Path& path)
1685  {
1686  geometry_msgs::Pose p_prev;
1687  bool first(true);
1688  bool dir_set(false);
1689  bool dir_prev(false);
1690  for (const auto& p : path.poses)
1691  {
1692  if (!first)
1693  {
1694  const float len = hypotf(
1695  p.pose.position.y - p_prev.position.y,
1696  p.pose.position.x - p_prev.position.x);
1697  if (len > 0.001)
1698  {
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);
1704 
1705  if (dir_set && (dir_prev ^ dir))
1706  {
1707  return true;
1708  }
1709  dir_prev = dir;
1710  dir_set = true;
1711  }
1712  }
1713  first = false;
1714  p_prev = p.pose;
1715  }
1716  return false;
1717  }
1718  float cbCost(const Astar::Vec& s, Astar::Vec& e,
1719  const Astar::Vec& v_goal,
1720  const Astar::Vec& v_start,
1721  const bool hyst)
1722  {
1723  Astar::Vec d_raw = e - s;
1724  d_raw.cycle(map_info_.angle);
1725  const Astar::Vec d = d_raw;
1726  float cost = euclidCost(d);
1727 
1728  if (d[0] == 0 && d[1] == 0)
1729  {
1730  // In-place turn
1731  int sum = 0;
1732  const int dir = d[2] < 0 ? -1 : 1;
1733  Astar::Vec pos = s;
1734  for (int i = 0; i < abs(d[2]); i++)
1735  {
1736  pos[2] += dir;
1737  if (pos[2] < 0)
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];
1742  if (c > 99)
1743  return -1;
1744  sum += c;
1745  }
1746 
1747  const float cost =
1748  sum * map_info_.angular_resolution * ec_[2] / ec_[0] +
1749  sum * map_info_.angular_resolution * cc_.weight_costmap_turn_ / 100.0;
1750  // simplified from sum * map_info_.angular_resolution * abs(d[2]) * cc_.weight_costmap_turn_ / (100.0 * abs(d[2]))
1751  return cc_.in_place_turn_ + cost;
1752  }
1753 
1754  Astar::Vec d2;
1755  d2[0] = d[0] + range_;
1756  d2[1] = d[1] + range_;
1757  d2[2] = e[2];
1758 
1759  const Astar::Vecf motion = rot_cache_.getMotion(s[2], d2);
1760  const Astar::Vecf motion_grid = motion * resolution_;
1761 
1762  if (lroundf(motion_grid[0]) == 0 && lroundf(motion_grid[1]) != 0)
1763  {
1764  // Not non-holonomic
1765  return -1;
1766  }
1767 
1768  if (fabs(motion[2]) >= 2.0 * M_PI / 4.0)
1769  {
1770  // Over 90 degree turn
1771  // must be separated into two curves
1772  return -1;
1773  }
1774 
1775  const float dist = motion.len();
1776 
1777  if (motion[0] < 0)
1778  {
1779  // Going backward
1780  cost *= 1.0 + cc_.weight_backward_;
1781  }
1782 
1783  if (d[2] == 0)
1784  {
1785  if (lroundf(motion_grid[0]) == 0)
1786  return -1; // side slip
1787  const float aspect = motion[0] / motion[1];
1788  if (fabs(aspect) < angle_resolution_aspect_)
1789  return -1; // large y offset
1790 
1791  // Go-straight
1792  int sum = 0, sum_hyst = 0;
1793  Astar::Vec d_index(d[0], d[1], e[2]);
1794  d_index.cycleUnsigned(map_info_.angle);
1795 
1796  const auto cache_page = motion_cache_.find(s[2], d_index);
1797  if (cache_page == motion_cache_.end(s[2]))
1798  return -1;
1799  const int num = cache_page->second.getMotion().size();
1800  for (const auto& pos_diff : cache_page->second.getMotion())
1801  {
1802  const Astar::Vec pos(
1803  s[0] + pos_diff[0], s[1] + pos_diff[1], pos_diff[2]);
1804  const auto c = cm_[pos];
1805  if (c > 99)
1806  return -1;
1807  sum += c;
1808 
1809  if (hyst)
1810  sum_hyst += cm_hyst_[pos];
1811  }
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);
1815  }
1816  else
1817  {
1818  // Curve
1819  if (motion[0] * motion[1] * motion[2] < 0)
1820  return -1;
1821 
1822  if (d.sqlen() < 3 * 3)
1823  return -1;
1824 
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;
1828 
1829  // curveture at the start_ pose and the end pose must be same
1830  if (fabs(r1 - r2) >= map_info_.linear_resolution * 1.5)
1831  {
1832  // Drifted
1833  return -1;
1834  }
1835 
1836  const float curv_radius = (r1 + r2) / 2;
1837  if (std::abs(curv_radius) < min_curve_raduis_)
1838  return -1;
1839 
1840  if (fabs(max_vel_ / r1) > max_ang_vel_)
1841  {
1842  const float vel = fabs(curv_radius) * max_ang_vel_;
1843 
1844  // Curve deceleration penalty
1845  cost += dist * fabs(vel / max_vel_) * cc_.weight_decel_;
1846  }
1847 
1848  {
1849  int sum = 0, sum_hyst = 0;
1850  Astar::Vec d_index(d[0], d[1], e[2]);
1851  d_index.cycleUnsigned(map_info_.angle);
1852 
1853  const auto cache_page = motion_cache_.find(s[2], d_index);
1854  if (cache_page == motion_cache_.end(s[2]))
1855  return -1;
1856  const int num = cache_page->second.getMotion().size();
1857  for (const auto& pos_diff : cache_page->second.getMotion())
1858  {
1859  const Astar::Vec pos(
1860  s[0] + pos_diff[0], s[1] + pos_diff[1], pos_diff[2]);
1861  const auto c = cm_[pos];
1862  if (c > 99)
1863  return -1;
1864  sum += c;
1865 
1866  if (hyst)
1867  sum_hyst += cm_hyst_[pos];
1868  }
1869  const float distf = cache_page->second.getDistance();
1870  cost += sum * map_info_.linear_resolution * distf * cc_.weight_costmap_ / (100.0 * num);
1871  cost += sum * map_info_.angular_resolution * abs(d[2]) * cc_.weight_costmap_turn_ / (100.0 * num);
1872  cost += sum_hyst * map_info_.linear_resolution * distf * cc_.weight_hysteresis_ / (100.0 * num);
1873  }
1874  }
1875 
1876  return cost;
1877  }
1878 
1880  {
1881  switch (status_.error)
1882  {
1883  case planner_cspace_msgs::PlannerStatus::GOING_WELL:
1884  stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Going well.");
1885  break;
1886  case planner_cspace_msgs::PlannerStatus::IN_ROCK:
1887  stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "The robot is in rock.");
1888  break;
1889  case planner_cspace_msgs::PlannerStatus::PATH_NOT_FOUND:
1890  stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Path not found.");
1891  break;
1892  case planner_cspace_msgs::PlannerStatus::DATA_MISSING:
1893  stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Required data is missing.");
1894  break;
1895  case planner_cspace_msgs::PlannerStatus::INTERNAL_ERROR:
1896  stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Planner internal error.");
1897  break;
1898  default:
1899  stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Unknown error.");
1900  break;
1901  }
1902  stat.addf("status", "%u", status_.status);
1903  stat.addf("error", "%u", status_.error);
1904  }
1905 };
1906 
1907 int main(int argc, char* argv[])
1908 {
1909  ros::init(argc, argv, "planner_3d");
1910 
1911  Planner3dNode jy;
1912  jy.spin();
1913 
1914  return 0;
1915 }
d
int hist_ignore_range_max_
Definition: planner_3d.cpp:167
double goal_tolerance_ang_finish_
Definition: planner_3d.cpp:206
bool updateGoal(const bool goal_changed=true)
Definition: planner_3d.cpp:595
Astar::Gridmap< char, 0x80 > cm_hyst_
Definition: planner_3d.cpp:106
double longcut_range_f_
Definition: planner_3d.cpp:146
Astar::Vecf euclid_cost_coef_
Definition: planner_3d.cpp:109
diagnostic_updater::Updater diag_updater_
Definition: planner_3d.cpp:235
std::vector< Astar::Vec > search_list_
Definition: planner_3d.cpp:162
void cbPreempt()
Definition: planner_3d.cpp:379
bool temporary_escape_
Definition: planner_3d.cpp:168
bool fast_map_update_
Definition: planner_3d.cpp:161
void cbMapUpdate(const costmap_cspace_msgs::CSpace3DUpdate::ConstPtr &msg)
Definition: planner_3d.cpp:744
ros::Duration costmap_watchdog_
Definition: planner_3d.cpp:236
Chain d2()
Astar::Gridmap< char, 0x40 > cm_
Definition: planner_3d.cpp:100
void cycleUnsigned(const int res, const ArgList &...rest)
Definition: cyclic_vec.h:279
double esc_range_f_
Definition: planner_3d.cpp:149
Astar::Vecf resolution_
Definition: planner_3d.cpp:203
ROSCONSOLE_DECL void notifyLoggerLevelsChanged()
void publish(const boost::shared_ptr< M > &message) const
void reset(const float angular_resolution, const int range)
f
constexpr int getNoncyclic() const
Definition: grid_astar.h:127
ros::Subscriber sub_map_
Definition: planner_3d.cpp:81
geometry_msgs::PoseStamped start_
Definition: planner_3d.cpp:198
void summary(unsigned char lvl, const std::string s)
float cbCostEstim(const Astar::Vec &s, const Astar::Vec &e)
double tolerance_angle_f_
Definition: planner_3d.cpp:153
void setBaseFrame(const std::string &frame_id)
Definition: jump_detector.h:70
MotionCache motion_cache_
Definition: planner_3d.cpp:232
double tolerance_range_f_
Definition: planner_3d.cpp:152
bool force_goal_orientation_
Definition: planner_3d.cpp:226
float cbCost(const Astar::Vec &s, Astar::Vec &e, const Astar::Vec &v_goal, const Astar::Vec &v_start, const bool hyst)
ros::Time last_costmap_
Definition: planner_3d.cpp:237
void setHardwareID(const std::string &hwid)
void setSearchTaskNum(const size_t &search_task_num)
Definition: grid_astar.h:131
XmlRpcServer s
bool sleep() const
ros::Subscriber sub_map_update_
Definition: planner_3d.cpp:82
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
Definition: grid_astar.h:55
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)
Definition: jump_detector.h:66
void publishCostmap()
Definition: planner_3d.cpp:683
constexpr int getDim() const
Definition: grid_astar.h:123
void cbMap(const costmap_cspace_msgs::CSpace3D::ConstPtr &msg)
Definition: planner_3d.cpp:977
Astar::Gridmap< bbf::BinaryBayesFilter, 0x20 > cm_hist_bbf_
Definition: planner_3d.cpp:101
void setQueueSizeLimit(const size_t size)
Definition: grid_astar.h:153
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())
std::string robot_frame_
Definition: planner_3d.cpp:175
geometry_msgs::PoseStamped goal_
Definition: planner_3d.cpp:199
const Cache::const_iterator end(const int start_yaw) const
Definition: motion_cache.h:74
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
T sqlen() const
Definition: cyclic_vec.h:230
void doTransform(const T &data_in, T &data_out, const geometry_msgs::TransformStamped &transform)
double hist_ignore_range_max_f_
Definition: planner_3d.cpp:166
const std::pair< float, float > & getRadiuses(const int start_angle, const CyclicVecInt< 3, 2 > &end) const
TFSIMD_FORCE_INLINE const tfScalar & y() const
float len() const
Definition: cyclic_vec.h:239
bool makePlan(const geometry_msgs::Pose &gs, const geometry_msgs::Pose &ge, nav_msgs::Path &path, bool hyst)
#define ROS_WARN(...)
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_
Definition: planner_3d.cpp:171
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)
Definition: planner_3d.cpp:544
DebugMode debug_out_
Definition: planner_3d.cpp:216
bool cbMakePlan(nav_msgs::GetPlan::Request &req, nav_msgs::GetPlan::Response &res)
Definition: planner_3d.cpp:248
ros::NodeHandle pnh_
Definition: planner_3d.cpp:80
bool setGoal(const geometry_msgs::PoseStamped &msg)
Definition: planner_3d.cpp:386
const Cache::const_iterator find(const int start_yaw, const CyclicVecInt< 3, 2 > &goal) const
Definition: motion_cache.h:65
ros::Publisher pub_path_velocity_
Definition: planner_3d.cpp:85
RotationCache rot_cache_
Definition: planner_3d.cpp:132
ros::Subscriber sub_goal_
Definition: planner_3d.cpp:83
float euclidCost(const Astar::Vec &v, const Astar::Vecf coef) const
Definition: planner_3d.cpp:111
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)
Definition: planner_3d.cpp:239
ros::Publisher pub_debug_
Definition: planner_3d.cpp:87
bool detectJump()
Definition: jump_detector.h:79
Astar::Gridmap< char, 0x40 > cm_hist_
Definition: planner_3d.cpp:102
ros::ServiceServer srs_make_plan_
Definition: planner_3d.cpp:93
constexpr float probabilityToOdds(const float &p)
Definition: bbf.h:40
void cbGoal(const geometry_msgs::PoseStamped::ConstPtr &msg)
Definition: planner_3d.cpp:370
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)
Definition: grid_astar.h:158
#define ROS_WARN_THROTTLE(period,...)
float search_range_
Definition: planner_3d.cpp:141
ros::Publisher pub_path_poses_
Definition: planner_3d.cpp:86
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_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)
Astar::Vecf ec_rough_
Definition: planner_3d.cpp:202
double goal_tolerance_ang_f_
Definition: planner_3d.cpp:205
bool overwrite_cost_
Definition: planner_3d.cpp:155
ROSCPP_DECL bool ok()
float remember_hit_odds_
Definition: planner_3d.cpp:169
float rough_cost_max_
Definition: planner_3d.cpp:223
TFSIMD_FORCE_INLINE const tfScalar & x() const
double hist_ignore_range_f_
Definition: planner_3d.cpp:164
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
const float MIN_ODDS
Definition: bbf.h:47
float min_curve_raduis_
Definition: planner_3d.cpp:172
void fillCostmap(reservable_priority_queue< Astar::PriorityVec > &open, Astar::Gridmap< float > &g, const Astar::Vec &s, const Astar::Vec &e)
Definition: planner_3d.cpp:424
ros::Publisher pub_hist_
Definition: planner_3d.cpp:88
actionlib::SimpleActionServer< move_base_msgs::MoveBaseAction > Planner3DActionServer
Definition: planner_3d.cpp:77
void diagnoseStatus(diagnostic_updater::DiagnosticStatusWrapper &stat)
Astar::Gridmap< char, 0x40 > cm_base_
Definition: planner_3d.cpp:104
void setThresholds(const double pos_jump, const double yaw_jump)
Definition: jump_detector.h:74
std::list< CyclicVecFloat< 3, 2 > > interpolate(const std::list< CyclicVecInt< 3, 2 >> &path_grid, const float interval, const int local_range) const
bool remember_updates_
Definition: planner_3d.cpp:160
bool sleep()
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)
B toMsg(const A &a)
geometry_msgs::PoseStamped goal_raw_
Definition: planner_3d.cpp:200
Astar::Gridmap< char, 0x80 > cm_rough_
Definition: planner_3d.cpp:103
ros::Publisher pub_end_
Definition: planner_3d.cpp:90
int goal_tolerance_ang_
Definition: planner_3d.cpp:208
JumpDetector jump_
Definition: planner_3d.cpp:174
costmap_cspace_msgs::MapMetaData3D map_info_
Definition: planner_3d.cpp:135
ros::Publisher pub_path_
Definition: planner_3d.cpp:84
uint32_t getNumSubscribers() const
tf2_ros::Buffer tfbuf_
Definition: planner_3d.cpp:96
void reserve(const size_type capacity)
int hist_ignore_range_
Definition: planner_3d.cpp:165
tf2_ros::TransformListener tfl_
Definition: planner_3d.cpp:97
INLINE Rall1d< T, V, S > abs(const Rall1d< T, V, S > &x)
ros::Publisher pub_start_
Definition: planner_3d.cpp:89
float max_ang_vel_
Definition: planner_3d.cpp:138
int goal_tolerance_lin_
Definition: planner_3d.cpp:207
ros::Publisher pub_status_
Definition: planner_3d.cpp:91
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_
Definition: planner_3d.cpp:92
std::vector< Astar::Vec > & cbSearch(const Astar::Vec &p, const Astar::Vec &s, const Astar::Vec &e)
static Time now()
void reset(const float linear_resolution, const float angular_resolution, const int range)
double local_range_f_
Definition: planner_3d.cpp:144
PathInterpolator path_interpolator_
Definition: planner_3d.cpp:133
void reset(const Vec size)
Definition: grid_astar.h:136
Astar::Vecf ec_
Definition: planner_3d.cpp:201
Astar::Gridmap< float > cost_estim_cache_
Definition: planner_3d.cpp:107
ROSCONSOLE_DECL bool set_logger_level(const std::string &name, levels::Level level)
void publishEmptyPath()
Definition: planner_3d.cpp:727
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_
Definition: planner_3d.cpp:95
std::vector< Astar::Vec > search_list_rough_
Definition: planner_3d.cpp:163
ROSCPP_DECL void spinOnce()
#define ROS_ERROR(...)
float angle_resolution_aspect_
Definition: planner_3d.cpp:209
MotionCache motion_cache_linear_
Definition: planner_3d.cpp:233
#define ROSCONSOLE_DEFAULT_NAME
planner_cspace_msgs::PlannerStatus status_
Definition: planner_3d.cpp:218
void updateStart()
float euclidCost(const Astar::Vec &v) const
Definition: planner_3d.cpp:127
float remember_miss_odds_
Definition: planner_3d.cpp:170
PathWithVelocity toPathWithVelocity(const nav_msgs::Path &src, const double vel)
void cycle(const int res, const ArgList &...rest)
Definition: cyclic_vec.h:272
Astar::Gridmap< char, 0x80 > cm_rough_base_
Definition: planner_3d.cpp:105
CostCoeff cc_
Definition: planner_3d.cpp:196
ros::NodeHandle nh_
Definition: planner_3d.cpp:79
#define ROS_DEBUG(...)
std_msgs::Header map_header_
Definition: planner_3d.cpp:136
double goal_tolerance_lin_f_
Definition: planner_3d.cpp:204


planner_cspace
Author(s): Atsushi Watanabe
autogenerated on Tue Jul 9 2019 05:00:13