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++) {