first sparse steps
This commit is contained in:
parent
3810e64a5c
commit
24ca402f67
6 changed files with 139 additions and 12 deletions
|
|
@ -245,3 +245,67 @@ class CollisionEngine:
|
|||
if other_net_id != net_id and dynamic_prepared[obj_id].intersects(test_poly):
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def ray_cast(self, origin: Port, angle_deg: float, max_dist: float = 2000.0) -> float:
|
||||
"""
|
||||
Cast a ray and find the distance to the nearest static obstacle.
|
||||
|
||||
Args:
|
||||
origin: Starting port (x, y).
|
||||
angle_deg: Ray direction in degrees.
|
||||
max_dist: Maximum lookahead distance.
|
||||
|
||||
Returns:
|
||||
Distance to first collision, or max_dist if clear.
|
||||
"""
|
||||
import numpy
|
||||
from shapely.geometry import LineString
|
||||
|
||||
rad = numpy.radians(angle_deg)
|
||||
dx = max_dist * numpy.cos(rad)
|
||||
dy = max_dist * numpy.sin(rad)
|
||||
|
||||
# Ray geometry
|
||||
ray_line = LineString([(origin.x, origin.y), (origin.x + dx, origin.y + dy)])
|
||||
|
||||
# 1. Query R-Tree
|
||||
candidates = self.static_index.intersection(ray_line.bounds)
|
||||
|
||||
min_dist = max_dist
|
||||
|
||||
# 2. Check Intersections
|
||||
# Note: We intersect with DILATED obstacles to account for clearance
|
||||
for obj_id in candidates:
|
||||
obstacle = self.static_dilated[obj_id]
|
||||
# Fast check with prepared geom? intersects() is fast, intersection() gives point
|
||||
if self.static_prepared[obj_id].intersects(ray_line):
|
||||
# Calculate exact intersection distance
|
||||
intersection = ray_line.intersection(obstacle)
|
||||
if intersection.is_empty:
|
||||
continue
|
||||
|
||||
# Intersection could be MultiLineString or LineString or Point
|
||||
# We want the point closest to origin
|
||||
|
||||
# Helper to get dist
|
||||
def get_dist(geom):
|
||||
if hasattr(geom, 'geoms'): # Multi-part
|
||||
return min(get_dist(g) for g in geom.geoms)
|
||||
# For line string, the intersection is the segment INSIDE the obstacle.
|
||||
# The distance is the distance to the start of that segment.
|
||||
# Or if it's a touch (Point), distance to point.
|
||||
coords = geom.coords
|
||||
# Distance to the first point of the intersection geometry
|
||||
# (Assuming simple overlap, first point is entry)
|
||||
p1 = coords[0]
|
||||
return numpy.sqrt((p1[0] - origin.x)**2 + (p1[1] - origin.y)**2)
|
||||
|
||||
try:
|
||||
d = get_dist(intersection)
|
||||
# Subtract safety margin to be safe? No, let higher level handle margins.
|
||||
if d < min_dist:
|
||||
min_dist = d
|
||||
except Exception:
|
||||
pass # Robustness
|
||||
|
||||
return min_dist
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue