Skip to content

Commit

Permalink
Provide function that checks if a line segment intersects a door
Browse files Browse the repository at this point in the history
Signed-off-by: Michael X. Grey <[email protected]>
  • Loading branch information
mxgrey committed Nov 24, 2023
1 parent 2412365 commit 388355d
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 0 deletions.
6 changes: 6 additions & 0 deletions rmf_traffic/include/rmf_traffic/agv/Graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ class Graph
/// Get the name of the map that this door is on.
const std::string& map() const;

/// Check if the line formed by p0 -> p1 intersects this door.
bool intersects(
Eigen::Vector2d p0,
Eigen::Vector2d p1,
double envelope = 0.0) const;

/// Constructor
DoorProperties(
std::string name,
Expand Down
71 changes: 71 additions & 0 deletions rmf_traffic/src/rmf_traffic/agv/Graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,77 @@ const std::string& Graph::DoorProperties::map() const
return _pimpl->map;
}

//==============================================================================
namespace {
double distance_from_point_to_segment(
Eigen::Vector2d q,
Eigen::Vector2d p0,
Eigen::Vector2d p1)
{
const double endpoint_distance = std::min((q - p0).norm(), (q - p1).norm());
const auto L = (p1 - p0).norm();
if (L < 1e-3)
{
return endpoint_distance;
}

const Eigen::Vector2d n = (p1 - p0) / L;
const Eigen::Vector2d v = q - p0;
const Eigen::Vector2d q_proj = (v.dot(n)) * n;
const double ortho_distance = (q - q_proj).norm();
return std::min(ortho_distance, endpoint_distance);
}
} // anonymous namespace

//==============================================================================
bool Graph::DoorProperties::intersects(
Eigen::Vector2d p0,
Eigen::Vector2d p1,
double envelope) const
{
const auto q0 = _pimpl->start;
const auto q1 = _pimpl->end;
for (const auto test : std::vector<std::function<double()>>{
[&]{ return distance_from_point_to_segment(p0, q0, q1); },
[&]{ return distance_from_point_to_segment(p1, q0, q1); },
[&]{ return distance_from_point_to_segment(q0, p0, p1); },
[&]{ return distance_from_point_to_segment(_pimpl->end, p0, p1); }
})
{
const double distance = test();
if (distance <= envelope)
return true;
}

// If none of the endpoints are within range of the other lines, then the only
// way for an intersection to exist is if the lines truly cross each other.
const double det = (p0.x() - p1.x()) * (q0.y() - q1.y())
- (p0.y() - p1.y()) * (q0.x() - q1.x());

if (std::abs(det) < 1e-8)
{
// The lines are essentially parallel and their endpoints aren't close
// enough, so there is no intersection.
return false;
}

const double t = ( (p0.x() - q0.x()) * (q0.y() - q1.y())
- (p0.y() - q0.y()) * (q0.x() - q1.x()) )
/ det;

if (t < 0.0 || 1.0 < t)
return false;

const double u = ( (p0.x() - q0.x()) * (p0.y() - p1.y())
- (p0.y() - q0.y()) * (p0.x() - p1.x()) )
/ det;

if (u < 0.0 || 1.0 < u)
return false;

return true;
}

//==============================================================================
Graph::DoorProperties::DoorProperties(
std::string name,
Expand Down

0 comments on commit 388355d

Please sign in to comment.