Skip to content

User/rnar17/new update collision zones#822

Open
rnar17 wants to merge 2 commits intomainfrom
user/rnar17/new-update-collision-zones
Open

User/rnar17/new update collision zones#822
rnar17 wants to merge 2 commits intomainfrom
user/rnar17/new-update-collision-zones

Conversation

@rnar17
Copy link
Contributor

@rnar17 rnar17 commented Feb 23, 2026

Description

  • Resolves Updating the Boat Collision Zone's Size #458
  • Implemented triangular collision zone for boats with non‑zero ROT. Added collision zone case for if there is no collision possible between AIS ship and Sailbot.
  • Triangle is defined by:
    • A: current bow position
    • B: projected collision point at current heading
    • C: projected collision point after applying ROT over a 5‑second horizon
  • Added rot_to_rad_per_sec() helper in coordinate systems since its logic is used in a few places
image The boat on the left has ROT > 0, and _calculate_projected_distance() predicts a future intersection with the Sailbot. In this case, the collision zone is generated using the turning‑motion method described above, producing a triangular swept region. The region naturally fans outward as it extends away from the AIS ship. This is more realistic since a turning ship can sweep through a larger lateral area the farther out you go from its current position.

Verification

  • Created unit tests in test_obstacles.py that verify collision zone creation and geometry for no collision case, straight line case (ROT=0), and turning motion case (ROT>0)
  • Created unit tests in test_coord_systems.py for rot_to_rad_per_sec()

Copy link
Contributor

@raghumanimehta raghumanimehta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @rnar17 !! This task was indeed quite complicated.

I have pointed a couple of changes, and I have also requested a review on coordinate systems given PATH's troubles with it. I am in the process of updating the documentation in code and confluence. I will notify you when that's done.

Please use that to verify the coordinates on this PR. You can start working on the other changes I have requested on this PR.

return [latlon_to_xy(reference=reference_latlon, latlon=pos) for pos in lat_lon_list]


def rot_to_rad_per_sec(rot: int) -> float:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of Magic number violations. You don't need to make all of them constants, but can you explain some of the calculations you are doing here? Wherever it makes sense to you, please repalce magic numbers with appropriately named constants.

self.ais_ship = ais_ship

projected_distance = self._calculate_projected_distance()
# Calculate ROT in radians per second
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment not needed

cog_rad = math.radians(self.ais_ship.cog.heading)
x, y = cs.latlon_to_xy(self.reference, self.ais_ship.lat_lon)
projected_distance = self._calculate_projected_distance(cog_rad)
bow_y = self.length / 2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does bow_y do?


if projected_distance == PROJ_DISTANCE_NO_COLLISION:
# If no collision detected, create small collision zone around the boat
RADIUS_MULTIPLIER = 5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did you come up with 5?

radius, resolution=16
)
raw = self._translate_collision_zone(boat_collision_zone)
self._raw_collision_zone = raw
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest assigning self._raw_collision_zone directly.

[-collision_zone_width, self.length / 2 + projected_distance],
[collision_zone_width, self.length / 2 + projected_distance],
[self.width / 2, -self.length / 2],
elif abs(rot_rps) < 1e-4:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did you come up with this threshold? + Magic number

[self.width / 2, -self.length / 2],
elif abs(rot_rps) < 1e-4:
# Straight line
collision_zone_width = projected_distance * COLLISION_ZONE_STRETCH_FACTOR * self.width
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is same as earlier, right?

if abs(rot) == 127:
rot_dpm = 10.0
else:
rot_dpm = (abs(rot) / 4.733) ** 2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: why not remove the abs? It seems that we are first computing the magnitude then multiplying the direction on line 264 (correct me if i am wrong). Doesn't it make sense to just do

Suggested change
rot_dpm = (abs(rot) / 4.733) ** 2
rot_dpm = (rot / 4.733) ** 2

This now encodes direction directly. I am not sure if this would produce the correct result, please verify this change through testing.

prepared.prep(self.collision_zone)
else:
# Turning motion
R = speed_kmps / abs(rot_rps)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add the units of R to the variable name please?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is how much the boat translates per radian right?

turn_angle = rot_rps * dt

# Center of rotation in world frame
cx = x - R * math.sin(cog_rad) * math.copysign(1, rot_rps)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't verified this but, could you please check if cog is in the right coordinate system for our applicaiton? Remember, our coordinate systems were a mess and this file was written before we discovered the mess. Please take a look whenever you have time.

Please note the documentaiton might be wrong in places; i appologize for that. I am in the process of fixing it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will also point out that i had discovered that math.sin() and other trigonometric functions might need to be flipped to be used correctly. Please look into that as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, can you please explain the math here. Especially why does cx = x - R ... whereas cy = y + R...? That is, why is there a discrepency in the signs of those calculations. It is not immediately obvious to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

path Pathfinding team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Updating the Boat Collision Zone's Size

3 participants