Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <nav_2d_utils/path_ops.h>
00036 #include <nav_2d_utils/geometry_help.h>
00037 #include <cmath>
00038 #include <vector>
00039
00040 namespace nav_2d_utils
00041 {
00042
00043 double poseDistance(const geometry_msgs::Pose2D& pose0, const geometry_msgs::Pose2D& pose1)
00044 {
00045 return hypot(pose0.x - pose1.x, pose0.y - pose1.y);
00046 }
00047
00048 double getPlanLength(const nav_2d_msgs::Path2D& plan, const unsigned int start_index)
00049 {
00050 double length = 0.0;
00051 for (unsigned int i = start_index + 1; i < plan.poses.size(); i++)
00052 {
00053 length += poseDistance(plan.poses[i - 1], plan.poses[i]);
00054 }
00055 return length;
00056 }
00057
00058 double getPlanLength(const nav_2d_msgs::Path2D& plan, const geometry_msgs::Pose2D& query_pose)
00059 {
00060 if (plan.poses.size() == 0) return 0.0;
00061
00062 unsigned int closest_index = 0;
00063 double closest_distance = poseDistance(plan.poses[0], query_pose);
00064 for (unsigned int i = 1; i < plan.poses.size(); i++)
00065 {
00066 double distance = poseDistance(plan.poses[i], query_pose);
00067 if (closest_distance > distance)
00068 {
00069 closest_index = i;
00070 closest_distance = distance;
00071 }
00072 }
00073 return getPlanLength(plan, closest_index);
00074 }
00075
00076 nav_2d_msgs::Path2D adjustPlanResolution(const nav_2d_msgs::Path2D& global_plan_in, double resolution)
00077 {
00078 nav_2d_msgs::Path2D global_plan_out;
00079 global_plan_out.header = global_plan_in.header;
00080 if (global_plan_in.poses.size() == 0)
00081 {
00082 return global_plan_out;
00083 }
00084
00085 geometry_msgs::Pose2D last = global_plan_in.poses[0];
00086 global_plan_out.poses.push_back(last);
00087
00088 double sq_resolution = resolution * resolution;
00089
00090 for (unsigned int i = 1; i < global_plan_in.poses.size(); ++i)
00091 {
00092 geometry_msgs::Pose2D loop = global_plan_in.poses[i];
00093 double sq_dist = (loop.x - last.x) * (loop.x - last.x) + (loop.y - last.y) * (loop.y - last.y);
00094 if (sq_dist > sq_resolution)
00095 {
00096
00097 double diff = sqrt(sq_dist) - resolution;
00098 double steps_double = ceil(diff / resolution) + 1.0;
00099 int steps = static_cast<int>(steps_double);
00100
00101 double delta_x = (loop.x - last.x) / steps_double;
00102 double delta_y = (loop.y - last.y) / steps_double;
00103 double delta_t = (loop.theta - last.theta) / steps_double;
00104
00105 for (int j = 1; j < steps; ++j)
00106 {
00107 geometry_msgs::Pose2D pose;
00108 pose.x = last.x + j * delta_x;
00109 pose.y = last.y + j * delta_y;
00110 pose.theta = last.theta + j * delta_t;
00111 global_plan_out.poses.push_back(pose);
00112 }
00113 }
00114 global_plan_out.poses.push_back(global_plan_in.poses[i]);
00115 last.x = loop.x;
00116 last.y = loop.y;
00117 }
00118 return global_plan_out;
00119 }
00120
00121 using PoseList = std::vector<geometry_msgs::Pose2D>;
00122
00134 PoseList compressPlan(const PoseList& input, unsigned int start_index, unsigned int end_index, double epsilon)
00135 {
00136
00137 if (end_index - start_index <= 1)
00138 {
00139 PoseList::const_iterator first = input.begin() + start_index;
00140 PoseList::const_iterator last = input.begin() + end_index + 1;
00141 return PoseList(first, last);
00142 }
00143
00144
00145 const geometry_msgs::Pose2D& start = input[start_index],
00146 end = input[end_index];
00147 double max_distance = 0.0;
00148 unsigned int max_index = 0;
00149 for (unsigned int i = start_index + 1; i < end_index; i++)
00150 {
00151 const geometry_msgs::Pose2D& pose = input[i];
00152 double d = distanceToLine(pose.x, pose.y, start.x, start.y, end.x, end.y);
00153 if (d > max_distance)
00154 {
00155 max_index = i;
00156 max_distance = d;
00157 }
00158 }
00159
00160
00161 if (max_distance <= epsilon)
00162 {
00163 PoseList outer;
00164 outer.push_back(start);
00165 outer.push_back(end);
00166 return outer;
00167 }
00168
00169
00170 PoseList first_part = compressPlan(input, start_index, max_index, epsilon);
00171 PoseList second_part = compressPlan(input, max_index, end_index, epsilon);
00172 first_part.insert(first_part.end(), second_part.begin() + 1, second_part.end());
00173 return first_part;
00174 }
00175
00176 nav_2d_msgs::Path2D compressPlan(const nav_2d_msgs::Path2D& input_path, double epsilon)
00177 {
00178 nav_2d_msgs::Path2D results;
00179 results.header = input_path.header;
00180 results.poses = compressPlan(input_path.poses, 0, input_path.poses.size() - 1, epsilon);
00181 return results;
00182 }
00183
00184 void addPose(nav_2d_msgs::Path2D& path, double x, double y, double theta)
00185 {
00186 geometry_msgs::Pose2D pose;
00187 pose.x = x;
00188 pose.y = y;
00189 pose.theta = theta;
00190 path.poses.push_back(pose);
00191 }
00192 }