6#define M_PIf 3.14159265358979323846f
15 return std::atan2(std::sin(a), std::cos(a));
22 bool TrajectoryChecker::isInCollisionBilinear(
float x,
float y,
float theta_rad)
const
25 const auto localPosition = costmap_.
origin().inverse() * Eigen::Vector2f{
x, y};
29 if (localPosition.x() < bounds.min.x() || localPosition.x() > bounds.max.x() ||
30 localPosition.y() < bounds.min.y() || localPosition.y() > bounds.max.y())
43 const float vX_shift = vX - 0.01f;
44 const float vY_shift = vY - 0.01f;
46 int iXlow =
static_cast<int>(std::floor(vX_shift));
47 int iXhigh =
static_cast<int>(std::ceil(vX_shift));
48 int iYlow =
static_cast<int>(std::floor(vY_shift));
49 int iYhigh =
static_cast<int>(std::ceil(vY_shift));
51 const auto size = costmap_.
getSize();
52 iXlow = std::clamp(iXlow, 0, size.x() - 1);
53 iXhigh = std::clamp(iXhigh, 0, size.x() - 1);
54 iYlow = std::clamp(iYlow, 0, size.y() - 1);
55 iYhigh = std::clamp(iYhigh, 0, size.y() - 1);
58 (
static_cast<float>(iXhigh) - vX) * (
static_cast<float>(iYhigh) - vY);
60 (vX -
static_cast<float>(iXlow)) * (
static_cast<float>(iYhigh) - vY);
62 (
static_cast<float>(iXhigh) - vX) * (vY -
static_cast<float>(iYlow));
64 (vX -
static_cast<float>(iXlow)) * (vY -
static_cast<float>(iYlow));
68 auto gridVal = [&](
int ix,
int iy) ->
float {
72 float interpolated = w00 * gridVal(iXlow, iYlow) + w10 * gridVal(iXhigh, iYlow) +
73 w01 * gridVal(iXlow, iYhigh) + w11 * gridVal(iXhigh, iYhigh);
75 return interpolated <= 10.0f;
82 struct Point {
double x, y, theta; };
83 std::vector<Point> points;
87 const auto& R = gp.waypoint.pose.rotation();
89 gp.waypoint.pose.translation().x(),
90 gp.waypoint.pose.translation().y(),
91 std::atan2(R(1, 0), R(0, 0))
96 for (std::size_t i = 0; i < points.size(); ++i)
98 if (isInCollisionBilinear(
static_cast<float>(points[i].
x),
99 static_cast<float>(points[i].y),
100 static_cast<float>(points[i].theta)))
106 ARMARX_INFO <<
"Collision detected at waypoint " << i;
112 constexpr float segmentResolution = 50.0f;
113 for (std::size_t i = 0; i + 1 < points.size(); ++i)
115 double dx = points[i + 1].x - points[i].x;
116 double dy = points[i + 1].y - points[i].y;
117 double dist = std::hypot(dx, dy);
118 int numSamples =
static_cast<int>(std::ceil(dist / segmentResolution));
122 for (
int s = 1; s < numSamples; ++s)
124 double t =
static_cast<double>(s) / numSamples;
125 double sampleX = points[i].x + t * dx;
126 double sampleY = points[i].y + t * dy;
127 double dtheta =
normalizeAngle(points[i + 1].theta - points[i].theta);
128 double sampleTheta =
normalizeAngle(points[i].theta + t * dtheta);
130 if (isInCollisionBilinear(
static_cast<float>(sampleX),
131 static_cast<float>(sampleY),
132 static_cast<float>(sampleTheta)))
137 Eigen::Translation3f{Eigen::Vector3f(
static_cast<float>(sampleX),
138 static_cast<float>(sampleY),
140 Eigen::AngleAxisf{
static_cast<float>(sampleTheta), Eigen::Vector3f::UnitZ()};
144 ARMARX_INFO <<
"Collision detected on segment between waypoints " << i <<
" and " << i + 1;
const core::Pose2D & origin() const
const SceneBounds & getLocalSceneBounds() const noexcept
Rotation closestRotationFromDegrees(RotationDegrees degrees) const
const Parameters & params() const noexcept
float value_ignore_mask(const Index &index, const RotationIndex rot_index) const
TrajectoryChecker(const Costmap3D &costmap)
TrajectoryCollisionCheckResult check(const core::GlobalTrajectory &trajectory, bool logDetails=false) const
#define ARMARX_INFO
The normal logging level.
This file is part of ArmarX.
This file is part of ArmarX.
double normalizeAngle(double a)
This file offers overloads of toIce() and fromIce() functions for STL container types.
float cellSize
How big each cell is in the uniform grid.
std::vector< core::GlobalTrajectoryPoint > collisionPoints