158 <<
"AStarWithOrientation cannot be executed because there is no 3D costmap available";
159 const auto aStarParams =
164 const Eigen::Isometry3f root_T_used_root =
168 const core::Pose start = startRobotRoot * root_T_used_root;
169 const core::Pose goal = goalRobotRoot * root_T_used_root;
171 lastRecoveryOriginalStart.reset();
172 lastRecoveryPosition.reset();
178 const float startOrientationDeg =
costmap->rotationDegrees(start2D);
179 bool recovered =
false;
181 if (not
costmap->isFreeWithClearance(
182 Eigen::Vector2f{start2D.translation()}, startOrientationDeg, aStarParams.clearance))
184 ARMARX_WARNING <<
"Start position " << start2D.translation().transpose()
185 <<
" is in collision (within clearance=" << aStarParams.clearance
186 <<
" mm). Searching for recovery position within "
187 <<
generalConfig.inCollisionDistanceThresholdForRecovery <<
" mm...";
189 const auto recoveryVertex =
costmap->findClosestCollisionFreeVertex(
190 start2D.translation(),
193 aStarParams.clearance);
195 if (not recoveryVertex.has_value())
197 ARMARX_ERROR <<
"No valid recovery position found within threshold of "
198 <<
generalConfig.inCollisionDistanceThresholdForRecovery <<
" mm";
203 << recoveryVertex->position.transpose() <<
" (distance: "
204 << (recoveryVertex->position - start2D.translation()).norm()
205 <<
" mm). Prepending original start position to trajectory.";
207 lastRecoveryOriginalStart = start;
208 lastRecoveryPosition = recoveryVertex->position;
211 start2D.translation() = recoveryVertex->position;
219 std::vector<core::Pose2D>
plan;
227 << start2D.translation().transpose() <<
" due to exception "
234 ARMARX_WARNING <<
"Could not calculate a path with orientation_aware A*";
238 std::vector<core::GlobalTrajectoryPoint>
trajectory;
240 std::vector<core::GlobalTrajectoryPoint> trajBeforeTransform;
241 trajBeforeTransform.reserve(
plan.size() + 2);
243 const Eigen::Isometry3f root_used_T_root = root_T_used_root.inverse();
245 trajectory.push_back({.waypoint = {effectiveStart * root_used_T_root}, .velocity = 300.F});
246 trajBeforeTransform.push_back({.waypoint = {effectiveStart}, .velocity = 300.F});
248 for (std::size_t i = 1; i <
plan.size(); ++i)
250 const auto& pose2d =
plan[i];
253 .waypoint = {
conv::to3D(pose2d) * root_used_T_root},
264 trajBeforeTransform.back().waypoint.pose = goal;
265 trajectory.back().waypoint.pose = goal * root_used_T_root;
275 const auto smoothingParams =
281 const auto optimizationResult = smoother.
optimize();
282 auto traj_smoothed = optimizationResult.
trajectory.value();
283 lastPreprocessedTrajectory = optimizationResult.preprocessedTrajectory.value();
284 lastSmoothedTrajectory = traj_smoothed;
286 auto traj_smoothed_converted = traj_smoothed.mutablePoints() |
287 ranges::views::transform(
292 pt2.waypoint.pose * root_used_T_root;
299 auto checkResult = checker.check(traj_smoothed,
true);
300 lastPointsInCollision = checkResult.collisionPoints;
304 if (checkResult.collisionCount > 2 && !smoothingParams.always_return_smoothed)
306 ARMARX_WARNING <<
"Smoothed trajectory has " << checkResult.collisionCount
307 <<
" collision points; falling back to original A* trajectory.";
308 traj_to_use = lastRawTrajectory;
310 ranges::views::transform(
315 pt2.waypoint.pose * root_used_T_root;
322 if (!checkResult.isCollisionFree())
324 if (smoothingParams.always_return_smoothed)
326 ARMARX_WARNING <<
"Smoothed trajectory has " << checkResult.collisionCount
327 <<
" collision point(s); returning smoothed anyway because "
328 "alwaysReturnSmoothed is enabled.";
332 ARMARX_WARNING <<
"Smoothed trajectory has " << checkResult.collisionCount
333 <<
" minor collision(s); returning smoothed anyway.";
338 ARMARX_INFO <<
"Smoothed trajectory is collision-free.";
340 traj_to_use = traj_smoothed;
341 traj_converted = traj_smoothed_converted;
349 constexpr float maxRecoveryVelocity = 150.F;
352 const float recoveryVelocity =
353 std::min(trajectoryPoints.front().velocity, maxRecoveryVelocity);
354 trajectoryPoints.front().velocity = recoveryVelocity;
355 trajectoryPoints.insert(trajectoryPoints.begin(),
360 helperPoints.front().velocity = recoveryVelocity;
361 helperPoints.insert(helperPoints.begin(),
363 .velocity = recoveryVelocity});
366 auto& rawPoints = lastRawTrajectory.mutablePoints();
367 rawPoints.insert(rawPoints.begin(),
369 .velocity = recoveryVelocity});
373 .helperTrajectory = traj_to_use};
378 const std::string& vizLayerNamePrefix)
382 auto layer = vizClient.
layer(vizLayerNamePrefix +
"_raw");
385 .points(lastRawTrajectory.positions())
386 .
color(simox::Color::yellow()));
387 for (
const auto& [idx, tp] : lastRawTrajectory.points() | ranges::views::enumerate)
389 const Eigen::Vector3f target =
390 100.0F * tp.waypoint.pose.linear() * Eigen::Vector3f::UnitY();
391 layer.add(
viz::Arrow(
"theta_" + std::to_string(idx))
392 .fromTo(tp.waypoint.pose.translation(),
393 tp.waypoint.pose.translation() + target)
394 .
color(simox::Color::yellow()));
401 auto layer = vizClient.
layer(vizLayerNamePrefix +
"_preprocessed");
404 .points(lastPreprocessedTrajectory.positions())
405 .
color(simox::Color::green()));
406 for (
const auto& [idx, tp] : lastPreprocessedTrajectory.points()
407 | ranges::views::enumerate)
409 const Eigen::Vector3f target =
410 100.0F * tp.waypoint.pose.linear() * Eigen::Vector3f::UnitY();
411 layer.add(
viz::Arrow(
"theta_" + std::to_string(idx))
412 .fromTo(tp.waypoint.pose.translation(),
413 tp.waypoint.pose.translation() + target)
414 .
color(simox::Color::green()));
421 auto layer = vizClient.
layer(vizLayerNamePrefix +
"_smoothed");
428 std::vector<simox::color::Color> colors;
429 colors.reserve(lastSmoothedTrajectory.points().size());
430 for (
const auto& tp : lastSmoothedTrajectory.points())
432 double x = tp.waypoint.pose.translation().x();
433 double y = tp.waypoint.pose.translation().y();
434 double theta = std::atan2(tp.waypoint.pose.linear()(1, 0),
435 tp.waypoint.pose.linear()(0, 0));
437 wrapper(&
x, &y, &theta, &d_raw);
439 colors.push_back(simox::Color::red());
440 else if (d_raw < 200.0)
441 colors.push_back(simox::Color::yellow());
443 colors.push_back(simox::Color::green());
447 const auto positions = lastSmoothedTrajectory.positions();
448 for (std::size_t i = 0; i + 1 < positions.size(); ++i)
450 std::vector<Eigen::Vector3f> seg = {positions[i], positions[i + 1]};
452 auto color = (colors[i] == simox::Color::red() || colors[i + 1] == simox::Color::red())
453 ? simox::Color::red()
454 : (colors[i] == simox::Color::yellow()
455 || colors[i + 1] == simox::Color::yellow())
456 ? simox::Color::yellow()
457 : simox::Color::green();
458 layer.add(
viz::Path(
"segment_" + std::to_string(i)).points(seg).color(color));
461 for (
const auto& [idx, tp] : lastSmoothedTrajectory.points()
462 | ranges::views::enumerate)
464 const Eigen::Vector3f target =
465 100.0F * tp.waypoint.pose.linear() * Eigen::Vector3f::UnitY();
466 layer.add(
viz::Arrow(
"theta_" + std::to_string(idx))
467 .fromTo(tp.waypoint.pose.translation(),
468 tp.waypoint.pose.translation() + target)
469 .
color(colors[idx]));
475 .points(lastSmoothedTrajectory.positions())
476 .
color(simox::Color::blue()));
483 auto layer = vizClient.
layer(vizLayerNamePrefix +
"_recovery");
485 if (lastRecoveryOriginalStart.has_value() && lastRecoveryPosition.has_value())
487 const Eigen::Vector3f from = lastRecoveryOriginalStart->translation();
488 const Eigen::Vector3f to =
conv::to3D(lastRecoveryPosition.value());
490 .pose(Eigen::Isometry3f{Eigen::Translation3f{from}}.matrix())
491 .axisLengths(Eigen::Vector3f{30.F, 30.F, 30.F})
492 .
color(simox::Color::red()));
495 .color(simox::Color::red()));
502 auto layer = vizClient.
layer(vizLayerNamePrefix +
"_points_in_collision");
504 for (std::size_t i = 0; i < lastPointsInCollision.size(); ++i)
506 const auto& p = lastPointsInCollision[i];
507 std::stringstream ss;
508 ss <<
"point_in_collision_" << i;
512 Eigen::Isometry3f{Eigen::Translation3f{p.waypoint.pose.translation()}}
515 .color(simox::Color::red());
516 layer.add(ellipsoid);