36 namespace mnm = marti_nav_msgs;
43 const std::string &target_frame)
45 for (
auto &point : route.
points) {
46 point.setPosition(
transform*point.position());
47 point.setOrientation(
transform*point.orientation());
49 route.
header.frame_id = target_frame;
54 for (
auto &point : route.
points) {
55 point.position().setZ(0.0);
64 if (route.
points.size() < 2) {
68 std::vector<size_t> degenerate_orientations;
70 for (
size_t i = 0; i < route.
points.size(); ++i) {
75 tf::Vector3 v_forward;
78 v_forward = route.
points[i+1].position() - route.
points[i+0].position();
79 }
else if (i+1 == route.
points.size()) {
81 v_forward = route.
points[i+0].position() - route.
points[i-1].position();
83 v_forward = route.
points[i+1].position() - route.
points[i-1].position();
86 v_forward.normalize();
89 tf::Vector3 v_left = up.cross(v_forward);
96 if (std::isnan(v_left.x()))
100 degenerate_orientations.push_back(i);
108 tf::Vector3 v_up = v_forward.cross(v_left);
116 v_forward.x(), v_left.x(), v_up.x(),
117 v_forward.y(), v_left.y(), v_up.y(),
118 v_forward.z(), v_left.z(), v_up.z());
124 route.
points[i].setOrientation(orientation);
131 for (
size_t i = 0; i < degenerate_orientations.size(); ++i)
133 size_t d_idx = degenerate_orientations[i];
134 bool repaired_orientation =
false;
135 for (
size_t j = 1; j < route.
points.size(); ++j)
137 size_t up_idx = d_idx + j;
138 int64_t down_idx = (int64_t)d_idx - (int64_t)j;
139 if (up_idx < route.
points.size())
141 if (std::find(degenerate_orientations.begin(), degenerate_orientations.end(), up_idx) == degenerate_orientations.end())
144 route.
points[d_idx].setOrientation(route.
points[up_idx].orientation());
145 repaired_orientation =
true;
152 if (std::find(degenerate_orientations.begin(), degenerate_orientations.end(), down_idx) == degenerate_orientations.end())
155 route.
points[d_idx].setOrientation(route.
points[down_idx].orientation());
156 repaired_orientation =
true;
162 if (!repaired_orientation)
165 "orientation. The route may be malformed.");
170 "orientation. Note that the source route may contain "
184 double &min_distance_from_line,
185 double &min_distance_on_line,
186 const tf::Vector3 &p0,
187 const tf::Vector3 &p1,
188 const tf::Vector3 &p,
189 bool extrapolate_start,
190 bool extrapolate_end)
192 tf::Vector3 v = p1 - p0;
193 const double v_len_sq = v.dot(v);
198 if (v_len_sq > 1e-6) {
199 s = v.dot(p - p0) / v_len_sq;
208 if (!extrapolate_start &&
s < 0.0) {
210 }
else if (!extrapolate_end &&
s > 1.0) {
214 tf::Vector3 x_nearest = p0 +
s*v;
216 min_distance_from_line = x_nearest.distance(p);
217 min_distance_on_line =
s*std::sqrt(v_len_sq);
222 const tf::Vector3 &point,
223 bool extrapolate_before_start,
224 bool extrapolate_past_end)
226 if (route.
points.size() == 0) {
231 if (route.
points.size() == 1) {
233 position.route_id = route.
guid();
234 position.id = route.
points[0].id();
235 position.distance = 0.0;
241 double min_distance_from_line = std::numeric_limits<double>::infinity();
242 double min_distance_on_line = std::numeric_limits<double>::infinity();
243 size_t min_segment_index = 0;
245 for (
size_t i = 0; i+1 < route.
points.size(); ++i) {
246 double distance_from_line;
247 double distance_on_line;
251 route.
points[i+0].position(),
252 route.
points[i+1].position(),
256 if (distance_from_line <= min_distance_from_line) {
257 min_segment_index = i;
258 min_distance_on_line = distance_on_line;
259 min_distance_from_line = distance_from_line;
268 if (extrapolate_before_start && min_segment_index == 0) {
271 min_distance_on_line,
272 route.
points[i+0].position(),
273 route.
points[i+1].position(),
276 }
else if (min_segment_index + 2 == route.
points.size()) {
282 size_t i = min_segment_index;
284 min_distance_on_line,
285 route.
points[i+0].position(),
286 route.
points[i+1].position(),
290 double last_length = (route.
points[i+1].position() - route.
points[i+0].position()).
length();
291 if (min_distance_on_line > last_length) {
293 min_distance_on_line -= last_length;
296 if (!extrapolate_past_end) {
297 min_distance_on_line = 0.0;
301 position.route_id = route.
guid();
302 position.id = route.
points[min_segment_index].id();
303 position.distance = min_distance_on_line;
308 mnm::RoutePosition &position,
310 const tf::Vector3 &point,
311 const mnm::RoutePosition &window_start,
312 const mnm::RoutePosition &window_end)
314 if (route.
points.size() < 2) {
320 mnm::RoutePosition
start;
324 mnm::RoutePosition end;
331 if (
start.id == end.id &&
start.distance == end.distance) {
332 position.route_id = route.
guid();
345 if ((end_index < start_index) ||
346 (start_index == end_index && end.distance <
start.distance)) {
347 std::swap(end,
start);
348 std::swap(start_index, end_index);
354 if (start_index+1 == route.
points.size()) {
357 start.distance += (route.
points[start_index+1].position() -
360 if (end_index+1 == route.
points.size()) {
362 end.id = route.
points[end_index].id();
363 end.distance += (route.
points[end_index+1].position() -
370 if (start_index == end_index) {
371 double distance_from_line;
372 double distance_on_line;
376 route.
points[start_index+0].position(),
377 route.
points[start_index+1].position(),
381 if (distance_on_line <
start.distance) {
382 distance_on_line =
start.distance;
383 }
else if (distance_on_line > end.distance) {
384 distance_on_line = end.distance;
387 mnm::RoutePosition denormal_position;
388 denormal_position.id =
start.id;
389 denormal_position.distance = distance_on_line;
394 position.route_id = route.
guid();
400 double min_distance_from_line = std::numeric_limits<double>::infinity();
401 double min_distance_on_line = std::numeric_limits<double>::infinity();
402 size_t min_segment_index = 0;
404 for (
size_t i = start_index; i <= end_index; ++i) {
405 double distance_from_line;
406 double distance_on_line;
410 route.
points[i+0].position(),
411 route.
points[i+1].position(),
415 if (distance_from_line <= min_distance_from_line) {
416 min_segment_index = i;
417 min_distance_on_line = distance_on_line;
418 min_distance_from_line = distance_from_line;
424 if (min_segment_index == start_index) {
426 min_distance_on_line,
427 route.
points[min_segment_index+0].position(),
428 route.
points[min_segment_index+1].position(),
431 if (min_distance_on_line <
start.distance) {
432 min_distance_on_line =
start.distance;
434 }
else if (min_segment_index == end_index) {
436 min_distance_on_line,
437 route.
points[min_segment_index+0].position(),
438 route.
points[min_segment_index+1].position(),
441 if (min_distance_on_line > end.distance) {
442 min_distance_on_line = end.distance;
446 mnm::RoutePosition denormal_position;
447 denormal_position.id = route.
points[min_segment_index].id();
448 denormal_position.distance = min_distance_on_line;
453 position.route_id = route.
guid();
476 }
else if (distance > 1) {
494 const mnm::RoutePosition &position)
501 double distance = position.distance;
502 while (distance < 0.0) {
510 distance += (route.
points[index-0].position() -
515 while (distance > 0.0) {
517 if (index+1 == route.
points.size()) {
521 double segment_length = (route.
points[index+0].position() -
523 if (distance > segment_length) {
526 distance -= segment_length;
535 normalized_position.route_id = position.route_id;
536 normalized_position.distance = distance;
537 normalized_position.id = route.
points[index].id();
544 const mnm::RoutePosition &position,
545 bool allow_extrapolation)
547 mnm::RoutePosition norm_position;
557 if (index == 0 && norm_position.distance < 0.0) {
558 if (!allow_extrapolation) {
562 if (route.
points.size() < 2) {
571 norm_position.distance);
576 if (index+1 == route.
points.size() && norm_position.distance > 0.0) {
577 if (!allow_extrapolation) {
580 if (route.
points.size() < 2) {
593 norm_position.distance + extra_dist);
600 norm_position.distance);
606 const mnm::RoutePosition &start,
607 const mnm::RoutePosition &end,
620 size_t min_index = std::min(start_index, end_index);
621 size_t max_index = std::max(start_index, end_index);
624 if (route.
header.frame_id == stu::_wgs84_frame) {
625 for (
size_t i = min_index; i < max_index; i++) {
626 d += stu::GreatCircleDistance(route.
points[i+1].position(), route.
points[i].position());
629 for (
size_t i = min_index; i < max_index; i++) {
634 if (end_index < start_index) {
638 distance =
d + end.distance -
start.distance;
643 std::vector<double> &distances,
644 const mnm::RoutePosition &start,
645 const std::vector<mnm::RoutePosition> &ends,
656 size_t min_index = start_index;
657 size_t max_index = start_index;
658 std::vector<int> indices;
659 indices.resize(ends.size());
660 for (
size_t i = 0; i < ends.size(); ++i) {
663 indices[i] = pt_index;
664 min_index = std::min(min_index, pt_index);
665 max_index = std::max(max_index, pt_index);
672 const size_t roi_start_index = start_index - min_index;
677 std::vector<double> arc_lengths;
678 arc_lengths.resize(max_index-min_index+1);
680 arc_lengths[roi_start_index] = 0.0;
681 if (route.
header.frame_id == stu::_wgs84_frame) {
683 for (
size_t rev_i = 1; rev_i <= roi_start_index; ++rev_i) {
684 const size_t i = roi_start_index - rev_i;
685 const tf::Vector3 pt1 = route.
points[min_index+i].position();
686 const tf::Vector3 pt2 = route.
points[min_index+i+1].position();
687 arc_lengths[i] = arc_lengths[i+1] - stu::GreatCircleDistance(pt1, pt2);
690 for (
size_t i = roi_start_index+1; i < arc_lengths.size(); ++i) {
691 const tf::Vector3 pt1 = route.
points[min_index+i].position();
692 const tf::Vector3 pt2 = route.
points[min_index+i-1].position();
693 arc_lengths[i] = arc_lengths[i-1] + stu::GreatCircleDistance(pt1, pt2);
698 for (
size_t rev_i = 1; rev_i <= roi_start_index; ++rev_i) {
699 const size_t i = roi_start_index - rev_i;
700 const tf::Vector3 pt1 = route.
points[min_index+i].position();
701 const tf::Vector3 pt2 = route.
points[min_index+i+1].position();
702 arc_lengths[i] = arc_lengths[i+1] - (pt2-pt1).
length();
705 for (
size_t i = roi_start_index+1; i < arc_lengths.size(); ++i) {
706 const tf::Vector3 pt1 = route.
points[min_index+i].position();
707 const tf::Vector3 pt2 = route.
points[min_index+i-1].position();
708 arc_lengths[i] = arc_lengths[i-1] + (pt2-pt1).
length();
713 distances.resize(ends.size());
714 for (
size_t i = 0; i < distances.size(); ++i) {
715 if (indices[i] < 0) {
716 distances[i] = std::numeric_limits<double>::quiet_NaN();
720 const size_t cache_index = indices[i]-min_index;
721 distances[i] = arc_lengths[cache_index] + ends[i].distance -
start.distance;
730 const marti_nav_msgs::RoutePosition &start,
731 const marti_nav_msgs::RoutePosition &end)
738 mnm::RoutePosition norm_start;
743 mnm::RoutePosition norm_end;
757 if (norm_end.distance > 0.0) {
764 end_index = std::min(end_index, route.
points.size());
766 if (end_index <= start_index)
773 sub_route.
points.reserve(end_index - start_index);
774 for (
size_t i = start_index; i < end_index; i++) {