159 <<
"AStarWithOrientation cannot be executed because there is no 3D costmap available";
160 const auto aStarParams =
161 aStarParamsOverride.has_value()
162 ? aStarParamsOverride.value()
168 smootherSeconds = 0.0;
171 const Eigen::Isometry3f root_T_used_root =
175 const core::Pose start = startRobotRoot * root_T_used_root;
176 const core::Pose goal = goalRobotRoot * root_T_used_root;
178 lastRecoveryOriginalStart.reset();
179 lastRecoveryPosition.reset();
185 const float startOrientationDeg =
costmap->rotationDegrees(start2D);
186 bool recovered =
false;
188 if (not
costmap->isFreeWithClearance(
189 Eigen::Vector2f{start2D.translation()}, startOrientationDeg, aStarParams.clearance))
191 ARMARX_WARNING <<
"Start position " << start2D.translation().transpose()
192 <<
" is in collision (within clearance=" << aStarParams.clearance
193 <<
" mm). Searching for recovery position within "
194 <<
generalConfig.inCollisionDistanceThresholdForRecovery <<
" mm...";
196 const auto recoveryVertex =
costmap->findClosestCollisionFreeVertex(
197 start2D.translation(),
200 aStarParams.clearance);
202 if (not recoveryVertex.has_value())
204 ARMARX_ERROR <<
"No valid recovery position found within threshold of "
205 <<
generalConfig.inCollisionDistanceThresholdForRecovery <<
" mm";
210 << recoveryVertex->position.transpose() <<
" (distance: "
211 << (recoveryVertex->position - start2D.translation()).norm()
212 <<
" mm). Prepending original start position to trajectory.";
214 lastRecoveryOriginalStart = start;
215 lastRecoveryPosition = recoveryVertex->position;
218 start2D.translation() = recoveryVertex->position;
226 std::vector<core::Pose2D>
plan;
227 const auto aStarStart = std::chrono::steady_clock::now();
232 std::chrono::duration<double>(std::chrono::steady_clock::now() - aStarStart)
234 expandedNodes = planner.lastExpandedNodes();
239 << start2D.translation().transpose() <<
" due to exception "
246 ARMARX_WARNING <<
"Could not calculate a path with orientation_aware A*";
250 std::vector<core::GlobalTrajectoryPoint>
trajectory;
252 std::vector<core::GlobalTrajectoryPoint> trajBeforeTransform;
253 trajBeforeTransform.reserve(
plan.size() + 2);
255 const Eigen::Isometry3f root_used_T_root = root_T_used_root.inverse();
257 trajectory.push_back({.waypoint = {effectiveStart * root_used_T_root}, .velocity = 300.F});
258 trajBeforeTransform.push_back({.waypoint = {effectiveStart}, .velocity = 300.F});
260 for (std::size_t i = 1; i <
plan.size(); ++i)
262 const auto& pose2d =
plan[i];
265 .waypoint = {
conv::to3D(pose2d) * root_used_T_root},
276 trajBeforeTransform.back().waypoint.pose = goal;
277 trajectory.back().waypoint.pose = goal * root_used_T_root;
287 const auto smoothingParams =
288 smoothingParamsOverride.has_value()
289 ? smoothingParamsOverride.value()
295 if (smoothingEnabled)
297 const auto smootherStart = std::chrono::steady_clock::now();
303 const auto optimizationResult = smoother.
optimize();
306 std::chrono::duration<double>(std::chrono::steady_clock::now() - smootherStart)
309 traj_smoothed = optimizationResult.trajectory.value();
310 lastPreprocessedTrajectory = optimizationResult.preprocessedTrajectory.value();
314 lastPreprocessedTrajectory = lastRawTrajectory;
316 lastSmoothedTrajectory = traj_smoothed;
318 auto traj_smoothed_converted = traj_smoothed.
mutablePoints() |
319 ranges::views::transform(
324 pt2.waypoint.pose * root_used_T_root;
331 auto checkResult = checker.check(traj_smoothed,
true);
332 lastPointsInCollision = checkResult.collisionPoints;
336 if (checkResult.collisionCount > 2 && !smoothingParams.always_return_smoothed)
338 ARMARX_WARNING <<
"Smoothed trajectory has " << checkResult.collisionCount
339 <<
" collision points; falling back to original A* trajectory.";
340 traj_to_use = lastRawTrajectory;
342 ranges::views::transform(
347 pt2.waypoint.pose * root_used_T_root;
354 if (!checkResult.isCollisionFree())
356 if (smoothingParams.always_return_smoothed)
358 ARMARX_WARNING <<
"Smoothed trajectory has " << checkResult.collisionCount
359 <<
" collision point(s); returning smoothed anyway because "
360 "alwaysReturnSmoothed is enabled.";
364 ARMARX_WARNING <<
"Smoothed trajectory has " << checkResult.collisionCount
365 <<
" minor collision(s); returning smoothed anyway.";
370 ARMARX_INFO <<
"Smoothed trajectory is collision-free.";
372 traj_to_use = traj_smoothed;
373 traj_converted = traj_smoothed_converted;
381 constexpr float maxRecoveryVelocity = 150.F;
384 const float recoveryVelocity =
385 std::min(trajectoryPoints.front().velocity, maxRecoveryVelocity);
386 trajectoryPoints.front().velocity = recoveryVelocity;
387 trajectoryPoints.insert(trajectoryPoints.begin(),
392 helperPoints.front().velocity = recoveryVelocity;
393 helperPoints.insert(helperPoints.begin(),
395 .velocity = recoveryVelocity});
398 auto& rawPoints = lastRawTrajectory.mutablePoints();
399 rawPoints.insert(rawPoints.begin(),
401 .velocity = recoveryVelocity});
405 .helperTrajectory = traj_to_use};
410 const std::string& vizLayerNamePrefix)
414 auto layer = vizClient.
layer(vizLayerNamePrefix +
"_raw");
417 .points(lastRawTrajectory.positions())
418 .
color(simox::Color::yellow()));
419 for (
const auto& [idx, tp] : lastRawTrajectory.points() | ranges::views::enumerate)
421 const Eigen::Vector3f target =
422 100.0F * tp.waypoint.pose.linear() * Eigen::Vector3f::UnitY();
423 layer.add(
viz::Arrow(
"theta_" + std::to_string(idx))
424 .fromTo(tp.waypoint.pose.translation(),
425 tp.waypoint.pose.translation() + target)
426 .
color(simox::Color::yellow()));
433 auto layer = vizClient.
layer(vizLayerNamePrefix +
"_preprocessed");
436 .points(lastPreprocessedTrajectory.positions())
437 .
color(simox::Color::green()));
438 for (
const auto& [idx, tp] : lastPreprocessedTrajectory.points()
439 | ranges::views::enumerate)
441 const Eigen::Vector3f target =
442 100.0F * tp.waypoint.pose.linear() * Eigen::Vector3f::UnitY();
443 layer.add(
viz::Arrow(
"theta_" + std::to_string(idx))
444 .fromTo(tp.waypoint.pose.translation(),
445 tp.waypoint.pose.translation() + target)
446 .
color(simox::Color::green()));
453 auto layer = vizClient.
layer(vizLayerNamePrefix +
"_smoothed");
460 std::vector<simox::color::Color> colors;
461 colors.reserve(lastSmoothedTrajectory.points().size());
462 for (
const auto& tp : lastSmoothedTrajectory.points())
464 double x = tp.waypoint.pose.translation().x();
465 double y = tp.waypoint.pose.translation().y();
466 double theta = std::atan2(tp.waypoint.pose.linear()(1, 0),
467 tp.waypoint.pose.linear()(0, 0));
469 wrapper(&
x, &y, &theta, &d_raw);
471 colors.push_back(simox::Color::red());
472 else if (d_raw < 200.0)
473 colors.push_back(simox::Color::yellow());
475 colors.push_back(simox::Color::green());
479 const auto positions = lastSmoothedTrajectory.positions();
480 for (std::size_t i = 0; i + 1 < positions.size(); ++i)
482 std::vector<Eigen::Vector3f> seg = {positions[i], positions[i + 1]};
484 auto color = (colors[i] == simox::Color::red() || colors[i + 1] == simox::Color::red())
485 ? simox::Color::red()
486 : (colors[i] == simox::Color::yellow()
487 || colors[i + 1] == simox::Color::yellow())
488 ? simox::Color::yellow()
489 : simox::Color::green();
490 layer.add(
viz::Path(
"segment_" + std::to_string(i)).points(seg).color(color));
493 for (
const auto& [idx, tp] : lastSmoothedTrajectory.points()
494 | ranges::views::enumerate)
496 const Eigen::Vector3f target =
497 100.0F * tp.waypoint.pose.linear() * Eigen::Vector3f::UnitY();
498 layer.add(
viz::Arrow(
"theta_" + std::to_string(idx))
499 .fromTo(tp.waypoint.pose.translation(),
500 tp.waypoint.pose.translation() + target)
501 .
color(colors[idx]));
507 .points(lastSmoothedTrajectory.positions())
508 .
color(simox::Color::blue()));
515 auto layer = vizClient.
layer(vizLayerNamePrefix +
"_recovery");
517 if (lastRecoveryOriginalStart.has_value() && lastRecoveryPosition.has_value())
519 const Eigen::Vector3f from = lastRecoveryOriginalStart->translation();
520 const Eigen::Vector3f to =
conv::to3D(lastRecoveryPosition.value());
522 .pose(Eigen::Isometry3f{Eigen::Translation3f{from}}.matrix())
523 .axisLengths(Eigen::Vector3f{30.F, 30.F, 30.F})
524 .
color(simox::Color::red()));
527 .color(simox::Color::red()));
534 auto layer = vizClient.
layer(vizLayerNamePrefix +
"_points_in_collision");
536 for (std::size_t i = 0; i < lastPointsInCollision.size(); ++i)
538 const auto& p = lastPointsInCollision[i];
539 std::stringstream ss;
540 ss <<
"point_in_collision_" << i;
544 Eigen::Isometry3f{Eigen::Translation3f{p.waypoint.pose.translation()}}
547 .color(simox::Color::red());
548 layer.add(ellipsoid);