58 namespace r = ::ranges;
59 namespace rv = ::ranges::views;
64 {
return simox::math::mat4f_to_xyyaw(pt.waypoint.pose.matrix()).z(); };
68 std::vector<double> orientations =
69 trajectory.points() | ranges::views::transform(toYaw) | ranges::to_vector;
74 const std::vector<double> inMovementDir = orientations;
77 const double startOrientation = orientations.front();
78 const double goalOrientation = orientations.back();
83 const std::size_t nOrientationStartGoalInfluence = std::ceil(
84 (orientations.size() - 1) * params.startGoalDistanceThreshold / trajectory.length());
87 const double signedAngleDiff =
angleDiff(goalOrientation, startOrientation);
91 const double signedAngleDiffDesired = [&]() ->
double
93 switch (params.predefinedRotationDirection)
97 if (signedAngleDiff <= 0)
99 return signedAngleDiff;
101 return -2 *
M_PI + signedAngleDiff;
105 if (signedAngleDiff >= 0)
107 return signedAngleDiff;
109 return 2 *
M_PI + signedAngleDiff;
112 return signedAngleDiff;
117 if (orientations.size() < 2 * nOrientationStartGoalInfluence)
121 const double angleIncrement = signedAngleDiffDesired / (orientations.size() - 1);
125 const std::vector<double> equidistantOrientations = [&]
127 std::vector<double> vec{orientations.front()};
128 for (std::size_t i = 1; i < orientations.size() - 1; i++)
130 vec.push_back(startOrientation + angleIncrement * i);
132 vec.push_back(orientations.back());
135 orientations = equidistantOrientations;
143 const double signedAngleDiff =
angleDiff(
144 inMovementDir.at(nOrientationStartGoalInfluence - 1), startOrientation);
146 const double angleIncrement = signedAngleDiff / (nOrientationStartGoalInfluence);
148 for (std::size_t i = 1; i < nOrientationStartGoalInfluence; i++)
150 orientations.at(i) = startOrientation + angleIncrement * i;
156 for (std::size_t i = nOrientationStartGoalInfluence;
157 i < orientations.size() - nOrientationStartGoalInfluence;
160 orientations.at(i) = inMovementDir.at(i);
166 const double signedAngleDiff =
angleDiff(
168 inMovementDir.at(orientations.size() - nOrientationStartGoalInfluence));
170 const double angleIncrement = signedAngleDiff / (nOrientationStartGoalInfluence);
172 for (std::size_t i = 1; i < nOrientationStartGoalInfluence; i++)
174 orientations.at(orientations.size() - nOrientationStartGoalInfluence + i) =
175 goalOrientation - angleIncrement * (nOrientationStartGoalInfluence - i);
182 for (
const auto& ori : orientations)
191 const float movementDirWeightStep =
192 (params.movementDirWeightEnd - params.movementDirWeightStart) / (params.iterations - 1);
199 const float movementDirWeight = params.movementDirWeightEnd;
205 for (std::size_t i = 1; i < orientations.size() - 1; i++)
207 const float walkingDirAlpha = 0.2;
209 const Eigen::Vector2f vMovementDir =
211 (Eigen::Rotation2Df(inMovementDir.at(i)) * Eigen::Vector2f::UnitX());
213 const Eigen::Vector2f vStartGoal =
214 (1.0 - walkingDirAlpha) *
215 (Eigen::Rotation2Df(orientations.at(i)) * Eigen::Vector2f::UnitX());
217 const Eigen::Vector2f vCombined = [&]() -> Eigen::Vector2f
219 if (movementDirWeight > 0)
221 return vMovementDir + vStartGoal;
230 orientations.at(i) += VirtualRobot::RandomFloat(-0.05F, 0.05F);
237 const std::size_t nPoints = orientations.size();
239 ceres::Problem problem;
241 ARMARX_VERBOSE << orientations.size() - 2 <<
" orientations to optimize";
251 if (movementDirWeight > 0.F)
254 for (
size_t i = 1; i < (orientations.size() - 1); i++)
256 float actualMovementDirWeight = movementDirWeight;
262 actualMovementDirWeight *= i / 5.;
264 else if ((orientations.size() - i - 1) < 5)
266 actualMovementDirWeight *= (orientations.size() - i - 1) / 5.;
269 ceres::CostFunction* movementDirCostFunction =
271 actualMovementDirWeight);
273 ARMARX_DEBUG <<
"Adding OrientationPriorCostFunctor to optimize " << i;
274 problem.AddResidualBlock(
275 movementDirCostFunction,
nullptr, &orientations.at(i));
280 if (params.smoothnessWeight > 0.F)
283 for (
size_t i = 2; i < (orientations.size() - 2); i++)
285 ceres::CostFunction* smoothCostFunction =
288 ARMARX_DEBUG <<
"Addding SmoothOrientationCostFunctor to optimize " << i - 1
289 <<
", " << i <<
" and " << i + 1;
290 problem.AddResidualBlock(smoothCostFunction,
292 &orientations.at(i - 1),
294 &orientations.at(i + 1));
299 if (params.priorStartWeight > 0.F)
302 const auto connectedPointsInRangeStart =
303 trajectory.allConnectedPointsInRange(0, params.startGoalDistanceThreshold);
307 for (
const size_t i : connectedPointsInRangeStart)
310 if (i >= orientations.size() / 2)
316 inMovementDir.front(), params.priorStartWeight);
318 ARMARX_DEBUG <<
"Addding OrientationPriorCostFunctor(start) to optimize "
320 problem.AddResidualBlock(priorCostFunction,
nullptr, &orientations.at(i));
325 if (params.priorEndWeight > 0.F)
329 const auto connectedPointsInRangeGoal = trajectory.allConnectedPointsInRange(
330 trajectory.poses().size() - 1, params.startGoalDistanceThreshold);
334 for (
const size_t i : connectedPointsInRangeGoal)
337 if (i < orientations.size() / 2)
343 inMovementDir.back(), params.priorEndWeight);
345 ARMARX_DEBUG <<
"Addding OrientationPriorCostFunctor to optimize " << i;
346 problem.AddResidualBlock(priorCostFunction,
nullptr, &orientations.at(i));
352 if (params.smoothnessWeightStartGoal > 0.F and nPoints > 3)
356 ceres::CostFunction* smoothCostFunction =
358 params.smoothnessWeightStartGoal);
361 <<
"Addding SmoothOrientationFixedPreCostFunctor to optimize 1 and 2";
362 problem.AddResidualBlock(
363 smoothCostFunction,
nullptr, &orientations.at(1), &orientations.at(2));
367 if (params.smoothnessWeightStartGoal > 0.F and nPoints > 3)
371 ceres::CostFunction* smoothCostFunction =
373 params.smoothnessWeightStartGoal);
375 ARMARX_DEBUG <<
"Addding SmoothOrientationFixedPreCostFunctor to optimize "
376 << orientations.size() - 3 <<
" and " << orientations.size() - 2;
377 problem.AddResidualBlock(smoothCostFunction,
379 &orientations.at(orientations.size() - 3),
380 &orientations.at(orientations.size() - 2));
386 ceres::Solver::Options options;
387 options.linear_solver_type = ceres::DENSE_QR;
388 options.minimizer_progress_to_stdout =
true;
389 options.max_num_iterations = 100;
390 options.function_tolerance = 0.01;
396 ceres::Solver::Summary summary;
397 Solve(options, &problem, &summary);
403 if (not summary.IsSolutionUsable())
414 orientations.front() = startOrientation;
415 orientations.back() = goalOrientation;
418 for (
const auto& ori : orientations)
426 const float yaw = p.second;
429 Eigen::AngleAxisf(yaw, Eigen::Vector3f::UnitZ()).toRotationMatrix();
435 const auto modifiedTrajectory = rv::zip(trajectory.points(), orientations) |
436 rv::transform(applyOrientation) | r::to_vector;
439 .trajectory = modifiedTrajectory,