43 std::vector<std::size_t> violations;
45 const std::size_t count =
trajectory.points().size();
52 for (std::size_t i = 1; i + 1 < count; i++)
54 const Eigen::Vector2d incoming = step(
trajectory, i - 1);
55 const Eigen::Vector2d outgoing = step(
trajectory, i);
57 const double incomingLength = incoming.norm();
58 const double outgoingLength = outgoing.norm();
65 violations.push_back(i);
69 const double alignment = incoming.dot(outgoing) / (incomingLength * outgoingLength);
73 violations.push_back(i);
82 std::vector<std::size_t>& removed,
90 std::vector<std::size_t> originalIndices(
trajectory.points().size());
91 for (std::size_t i = 0; i < originalIndices.size(); i++)
93 originalIndices.at(i) = i;
100 constexpr int maxPasses = 8;
102 for (
int pass = 0; pass < maxPasses; pass++)
106 if (violations.empty())
119 std::vector<std::size_t> toRemove;
121 for (std::size_t runStart = 0; runStart < violations.size();)
123 std::size_t runEnd = runStart;
124 while (runEnd + 1 < violations.size() and
125 violations.at(runEnd + 1) == violations.at(runEnd) + 1)
130 const std::size_t first = violations.at(runStart);
131 const std::size_t last = violations.at(runEnd);
135 const std::size_t from = (first > 0) ? first - 1 : 0;
136 const std::size_t to = std::min(last + 1, repaired.
points().size() - 1);
138 std::size_t bestCandidate = last;
139 double bestLength = std::numeric_limits<double>::max();
140 double bestSpacingSpread = std::numeric_limits<double>::max();
142 for (std::size_t candidate = first; candidate <= last; candidate++)
144 std::vector<double> segments;
145 std::size_t previous = from;
147 for (std::size_t i = from + 1; i <= to; i++)
154 const auto& a = repaired.
points().at(previous).waypoint.pose.translation();
155 const auto& b = repaired.
points().at(i).waypoint.pose.translation();
156 segments.push_back(std::hypot(
static_cast<double>(b.x() - a.x()),
157 static_cast<double>(b.y() - a.y())));
162 for (
const double segment : segments)
172 double spacingSpread = 0.0;
173 if (not segments.empty())
175 const double mean = length /
static_cast<double>(segments.size());
176 for (
const double segment : segments)
178 spacingSpread += (segment -
mean) * (segment -
mean);
182 const double lengthTolerance = 1e-6 * std::max(1.0, bestLength);
183 const bool shorter = length < bestLength - lengthTolerance;
184 const bool sameLengthButMoreEven =
185 std::abs(length - bestLength) <= lengthTolerance and
186 spacingSpread < bestSpacingSpread;
188 if (shorter or sameLengthButMoreEven)
191 bestSpacingSpread = spacingSpread;
192 bestCandidate = candidate;
196 toRemove.push_back(bestCandidate);
197 runStart = runEnd + 1;
200 std::vector<core::GlobalTrajectoryPoint> kept;
201 std::vector<std::size_t> keptIndices;
202 kept.reserve(repaired.
points().size());
203 keptIndices.reserve(originalIndices.size());
205 for (std::size_t i = 0; i < repaired.
points().size(); i++)
207 const bool drop = std::find(toRemove.begin(), toRemove.end(), i) != toRemove.end();
211 removed.push_back(originalIndices.at(i));
215 kept.push_back(repaired.
points().at(i));
216 keptIndices.push_back(originalIndices.at(i));
226 originalIndices = keptIndices;
229 std::sort(removed.begin(), removed.end());